summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2011-07-02 22:08:51 +0200
committerSergei Golubchik <sergii@pisem.net>2011-07-02 22:08:51 +0200
commit9809f05199aeb0b67991fac41bd86f38730768dc (patch)
treefa2792ff86d0da014b535d743759810612338042 /storage
parent0accbd0364e0333e0b119aa9ce93e34ded9df6cb (diff)
parent5a0e7394a5ae0c7b6a1ea35b7ea3a8985325987a (diff)
downloadmariadb-git-9809f05199aeb0b67991fac41bd86f38730768dc.tar.gz
5.5-merge
Diffstat (limited to 'storage')
-rw-r--r--storage/Makefile.am22
-rw-r--r--storage/archive/Makefile.am104
-rw-r--r--storage/archive/azio.c9
-rw-r--r--storage/archive/ha_archive.cc38
-rw-r--r--storage/archive/ha_archive.h4
-rw-r--r--storage/archive/plug.in4
-rw-r--r--storage/blackhole/Makefile.am83
-rw-r--r--storage/blackhole/ha_blackhole.cc10
-rw-r--r--storage/blackhole/ha_blackhole.h1
-rw-r--r--storage/blackhole/plug.in6
-rw-r--r--storage/csv/Makefile.am64
-rw-r--r--storage/csv/ha_tina.h3
-rw-r--r--storage/csv/plug.in5
-rw-r--r--storage/example/Makefile.am82
-rw-r--r--storage/example/ha_example.cc95
-rw-r--r--storage/example/ha_example.h1
-rw-r--r--storage/example/plug.in3
-rw-r--r--storage/federated/Makefile.am84
-rw-r--r--storage/federated/ha_federated.cc10
-rw-r--r--storage/federated/ha_federated.h4
-rw-r--r--storage/federated/plug.in5
-rw-r--r--storage/federatedx/plug.in5
-rw-r--r--storage/heap/Makefile.am73
-rw-r--r--storage/heap/ha_heap.cc11
-rw-r--r--storage/heap/ha_heap.h3
-rw-r--r--storage/heap/heapdef.h7
-rw-r--r--storage/heap/hp_block.c2
-rw-r--r--storage/heap/hp_create.c4
-rw-r--r--storage/heap/hp_delete.c2
-rw-r--r--storage/heap/hp_open.c2
-rw-r--r--storage/heap/hp_static.c4
-rw-r--r--storage/heap/hp_test2.c8
-rw-r--r--storage/heap/plug.in7
-rw-r--r--storage/ibmdb2i/CMakeLists.txt39
-rw-r--r--storage/ibmdb2i/Makefile.am52
-rw-r--r--storage/ibmdb2i/db2i_blobCollection.cc107
-rw-r--r--storage/ibmdb2i/db2i_blobCollection.h151
-rw-r--r--storage/ibmdb2i/db2i_charsetSupport.cc826
-rw-r--r--storage/ibmdb2i/db2i_charsetSupport.h65
-rw-r--r--storage/ibmdb2i/db2i_collationSupport.cc355
-rw-r--r--storage/ibmdb2i/db2i_collationSupport.h48
-rw-r--r--storage/ibmdb2i/db2i_constraints.cc672
-rw-r--r--storage/ibmdb2i/db2i_conversion.cc1459
-rw-r--r--storage/ibmdb2i/db2i_errors.cc297
-rw-r--r--storage/ibmdb2i/db2i_errors.h93
-rw-r--r--storage/ibmdb2i/db2i_file.cc553
-rw-r--r--storage/ibmdb2i/db2i_file.h446
-rw-r--r--storage/ibmdb2i/db2i_global.h138
-rw-r--r--storage/ibmdb2i/db2i_iconv.h51
-rw-r--r--storage/ibmdb2i/db2i_ileBridge.cc1342
-rw-r--r--storage/ibmdb2i/db2i_ileBridge.h499
-rw-r--r--storage/ibmdb2i/db2i_ioBuffers.cc332
-rw-r--r--storage/ibmdb2i/db2i_ioBuffers.h416
-rw-r--r--storage/ibmdb2i/db2i_misc.h129
-rw-r--r--storage/ibmdb2i/db2i_myconv.cc1498
-rw-r--r--storage/ibmdb2i/db2i_myconv.h3201
-rw-r--r--storage/ibmdb2i/db2i_rir.cc686
-rw-r--r--storage/ibmdb2i/db2i_safeString.h98
-rw-r--r--storage/ibmdb2i/db2i_sqlStatementStream.cc86
-rw-r--r--storage/ibmdb2i/db2i_sqlStatementStream.h151
-rw-r--r--storage/ibmdb2i/db2i_validatedPointer.h162
-rw-r--r--storage/ibmdb2i/ha_ibmdb2i.cc3374
-rw-r--r--storage/ibmdb2i/ha_ibmdb2i.h822
-rw-r--r--storage/ibmdb2i/plug.in12
-rw-r--r--storage/innobase/CMakeLists.txt60
-rw-r--r--storage/innobase/COPYING351
-rw-r--r--storage/innobase/COPYING.Sun_Microsystems31
-rw-r--r--storage/innobase/Doxyfile2
-rw-r--r--storage/innobase/Makefile.am339
-rw-r--r--storage/innobase/btr/btr0btr.c578
-rw-r--r--storage/innobase/btr/btr0cur.c645
-rw-r--r--storage/innobase/btr/btr0sea.c6
-rw-r--r--storage/innobase/buf/buf0buddy.c4
-rw-r--r--storage/innobase/buf/buf0buf.c598
-rw-r--r--storage/innobase/buf/buf0flu.c135
-rw-r--r--storage/innobase/buf/buf0lru.c157
-rw-r--r--storage/innobase/buf/buf0rea.c21
-rwxr-xr-xstorage/innobase/compile-innodb2
-rw-r--r--storage/innobase/data/data0data.c8
-rw-r--r--storage/innobase/dict/dict0crea.c17
-rw-r--r--storage/innobase/dict/dict0dict.c369
-rw-r--r--storage/innobase/dict/dict0load.c162
-rw-r--r--storage/innobase/dict/dict0mem.c65
-rw-r--r--storage/innobase/fil/fil0fil.c135
-rw-r--r--storage/innobase/fsp/fsp0fsp.c60
-rw-r--r--storage/innobase/handler/ha_innodb.cc1533
-rw-r--r--storage/innobase/handler/ha_innodb.h23
-rw-r--r--storage/innobase/handler/handler0alter.cc362
-rw-r--r--storage/innobase/handler/i_s.cc1655
-rw-r--r--storage/innobase/handler/i_s.h9
-rw-r--r--storage/innobase/handler/mysql_addons.cc42
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c979
-rw-r--r--storage/innobase/include/btr0btr.h134
-rw-r--r--storage/innobase/include/btr0btr.ic38
-rw-r--r--storage/innobase/include/btr0cur.h107
-rw-r--r--storage/innobase/include/btr0pcur.h40
-rw-r--r--storage/innobase/include/btr0pcur.ic45
-rw-r--r--storage/innobase/include/btr0types.h125
-rw-r--r--storage/innobase/include/buf0buddy.h2
-rw-r--r--storage/innobase/include/buf0buddy.ic4
-rw-r--r--storage/innobase/include/buf0buf.h161
-rw-r--r--storage/innobase/include/buf0buf.ic77
-rw-r--r--storage/innobase/include/buf0flu.h32
-rw-r--r--storage/innobase/include/buf0lru.h12
-rw-r--r--storage/innobase/include/buf0rea.h8
-rw-r--r--storage/innobase/include/data0data.h11
-rw-r--r--storage/innobase/include/data0data.ic22
-rw-r--r--storage/innobase/include/data0type.h9
-rw-r--r--storage/innobase/include/db0err.h14
-rw-r--r--storage/innobase/include/dict0dict.h68
-rw-r--r--storage/innobase/include/dict0dict.ic56
-rw-r--r--storage/innobase/include/dict0load.h12
-rw-r--r--storage/innobase/include/dict0mem.h91
-rw-r--r--storage/innobase/include/dict0types.h19
-rw-r--r--storage/innobase/include/fil0fil.h8
-rw-r--r--storage/innobase/include/ha_prototypes.h20
-rw-r--r--storage/innobase/include/ibuf0ibuf.h78
-rw-r--r--storage/innobase/include/ibuf0ibuf.ic40
-rw-r--r--storage/innobase/include/lock0lock.h7
-rw-r--r--storage/innobase/include/lock0lock.ic6
-rw-r--r--storage/innobase/include/log0log.ic2
-rw-r--r--storage/innobase/include/mem0mem.ic12
-rw-r--r--storage/innobase/include/mtr0mtr.h14
-rw-r--r--storage/innobase/include/mtr0mtr.ic15
-rw-r--r--storage/innobase/include/mysql_addons.h33
-rw-r--r--storage/innobase/include/os0file.h2
-rw-r--r--storage/innobase/include/os0sync.h27
-rw-r--r--storage/innobase/include/os0thread.h33
-rw-r--r--storage/innobase/include/page0page.h27
-rw-r--r--storage/innobase/include/page0page.ic23
-rw-r--r--storage/innobase/include/page0zip.h2
-rw-r--r--storage/innobase/include/rem0cmp.h4
-rw-r--r--storage/innobase/include/rem0cmp.ic2
-rw-r--r--storage/innobase/include/rem0rec.h31
-rw-r--r--storage/innobase/include/rem0rec.ic51
-rw-r--r--storage/innobase/include/rem0types.h20
-rw-r--r--storage/innobase/include/row0ext.h13
-rw-r--r--storage/innobase/include/row0ext.ic9
-rw-r--r--storage/innobase/include/row0ins.h5
-rw-r--r--storage/innobase/include/row0mysql.h4
-rw-r--r--storage/innobase/include/row0row.h32
-rw-r--r--storage/innobase/include/row0row.ic36
-rw-r--r--storage/innobase/include/row0upd.h45
-rw-r--r--storage/innobase/include/srv0srv.h65
-rw-r--r--storage/innobase/include/sync0arr.h7
-rw-r--r--storage/innobase/include/sync0rw.h4
-rw-r--r--storage/innobase/include/sync0sync.h43
-rw-r--r--storage/innobase/include/thr0loc.h90
-rw-r--r--storage/innobase/include/thr0loc.ic24
-rw-r--r--storage/innobase/include/trx0i_s.h3
-rw-r--r--storage/innobase/include/trx0purge.h22
-rw-r--r--storage/innobase/include/trx0rseg.h16
-rw-r--r--storage/innobase/include/trx0sys.h10
-rw-r--r--storage/innobase/include/trx0sys.ic12
-rw-r--r--storage/innobase/include/trx0trx.h37
-rw-r--r--storage/innobase/include/trx0undo.h11
-rw-r--r--storage/innobase/include/univ.i77
-rw-r--r--storage/innobase/include/ut0auxconf.h14
-rw-r--r--storage/innobase/include/ut0bh.h152
-rw-r--r--storage/innobase/include/ut0bh.ic125
-rw-r--r--storage/innobase/include/ut0dbg.h7
-rw-r--r--storage/innobase/include/ut0rbt.h2
-rw-r--r--storage/innobase/include/ut0ut.h29
-rw-r--r--storage/innobase/include/ut0vec.h19
-rw-r--r--storage/innobase/include/ut0vec.ic29
-rw-r--r--storage/innobase/lock/lock0lock.c233
-rw-r--r--storage/innobase/log/log0log.c107
-rw-r--r--storage/innobase/log/log0recv.c6
-rw-r--r--storage/innobase/mem/mem0dbg.c15
-rw-r--r--storage/innobase/mem/mem0mem.c2
-rw-r--r--storage/innobase/mtr/mtr0log.c2
-rw-r--r--storage/innobase/mtr/mtr0mtr.c14
-rw-r--r--storage/innobase/mysql-test/patches/README30
-rw-r--r--storage/innobase/mysql-test/patches/index_merge_innodb-explain.diff31
-rw-r--r--storage/innobase/mysql-test/patches/information_schema.diff124
-rw-r--r--storage/innobase/mysql-test/patches/innodb_change_buffering_basic.diff60
-rw-r--r--storage/innobase/mysql-test/patches/innodb_file_per_table.diff47
-rw-r--r--storage/innobase/mysql-test/patches/innodb_lock_wait_timeout.diff55
-rw-r--r--storage/innobase/mysql-test/patches/innodb_thread_concurrency_basic.diff31
-rw-r--r--storage/innobase/mysql-test/patches/partition_innodb.diff59
-rw-r--r--storage/innobase/os/os0file.c295
-rw-r--r--storage/innobase/os/os0sync.c211
-rw-r--r--storage/innobase/os/os0thread.c93
-rw-r--r--storage/innobase/page/page0cur.c10
-rw-r--r--storage/innobase/page/page0page.c131
-rw-r--r--storage/innobase/page/page0zip.c26
-rw-r--r--storage/innobase/plug.in233
-rw-r--r--storage/innobase/rem/rem0cmp.c14
-rw-r--r--storage/innobase/rem/rem0rec.c8
-rw-r--r--storage/innobase/row/row0ext.c19
-rw-r--r--storage/innobase/row/row0ins.c13
-rw-r--r--storage/innobase/row/row0merge.c76
-rw-r--r--storage/innobase/row/row0mysql.c85
-rw-r--r--storage/innobase/row/row0purge.c68
-rw-r--r--storage/innobase/row/row0row.c48
-rw-r--r--storage/innobase/row/row0sel.c148
-rw-r--r--storage/innobase/row/row0umod.c44
-rw-r--r--storage/innobase/row/row0upd.c403
-rw-r--r--storage/innobase/row/row0vers.c28
-rw-r--r--storage/innobase/srv/srv0srv.c408
-rw-r--r--storage/innobase/srv/srv0start.c475
-rw-r--r--storage/innobase/sync/sync0arr.c73
-rw-r--r--storage/innobase/sync/sync0rw.c35
-rw-r--r--storage/innobase/sync/sync0sync.c450
-rw-r--r--storage/innobase/thr/thr0loc.c285
-rw-r--r--storage/innobase/trx/trx0i_s.c61
-rw-r--r--storage/innobase/trx/trx0purge.c399
-rw-r--r--storage/innobase/trx/trx0rec.c64
-rw-r--r--storage/innobase/trx/trx0roll.c8
-rw-r--r--storage/innobase/trx/trx0rseg.c52
-rw-r--r--storage/innobase/trx/trx0sys.c57
-rw-r--r--storage/innobase/trx/trx0trx.c366
-rw-r--r--storage/innobase/trx/trx0undo.c43
-rw-r--r--storage/innobase/ut/ut0auxconf_atomic_pthread_t_gcc.c43
-rw-r--r--storage/innobase/ut/ut0auxconf_atomic_pthread_t_solaris.c54
-rw-r--r--storage/innobase/ut/ut0auxconf_have_gcc_atomics.c61
-rw-r--r--storage/innobase/ut/ut0auxconf_have_solaris_atomics.c39
-rw-r--r--storage/innobase/ut/ut0auxconf_pause.c32
-rw-r--r--storage/innobase/ut/ut0auxconf_sizeof_pthread_t.c35
-rw-r--r--storage/innobase/ut/ut0bh.c164
-rw-r--r--storage/innobase/ut/ut0dbg.c11
-rw-r--r--storage/innobase/ut/ut0ut.c17
-rw-r--r--storage/myisam/Makefile.am169
-rw-r--r--storage/myisam/ft_boolean_search.c2
-rw-r--r--storage/myisam/ft_stopwords.c4
-rwxr-xr-xstorage/myisam/ftbench/Ecompare.pl15
-rwxr-xr-xstorage/myisam/ftbench/Ecreate.pl15
-rwxr-xr-xstorage/myisam/ftbench/Ereport.pl15
-rwxr-xr-xstorage/myisam/ftbench/ft-test-run.sh17
-rw-r--r--storage/myisam/ha_myisam.cc35
-rw-r--r--storage/myisam/ha_myisam.h3
-rw-r--r--storage/myisam/mi_check.c11
-rw-r--r--storage/myisam/mi_close.c2
-rw-r--r--storage/myisam/mi_create.c2
-rw-r--r--storage/myisam/mi_delete.c3
-rw-r--r--storage/myisam/mi_delete_all.c2
-rw-r--r--storage/myisam/mi_dynrec.c5
-rw-r--r--storage/myisam/mi_log.c4
-rw-r--r--storage/myisam/mi_open.c6
-rw-r--r--storage/myisam/mi_static.c2
-rw-r--r--storage/myisam/mi_statrec.c3
-rwxr-xr-xstorage/myisam/mi_test_all.sh18
-rw-r--r--storage/myisam/mi_update.c11
-rw-r--r--storage/myisam/mi_write.c6
-rw-r--r--storage/myisam/myisamchk.c8
-rw-r--r--storage/myisam/myisamdef.h14
-rw-r--r--storage/myisam/myisampack.c2
-rw-r--r--storage/myisam/plug.in7
-rw-r--r--storage/myisam/rt_index.c2
-rw-r--r--storage/myisam/sort.c2
-rw-r--r--storage/myisammrg/Makefile.am62
-rw-r--r--storage/myisammrg/ha_myisammrg.cc47
-rw-r--r--storage/myisammrg/ha_myisammrg.h3
-rw-r--r--storage/myisammrg/myrg_def.h2
-rw-r--r--storage/myisammrg/myrg_open.c8
-rw-r--r--storage/myisammrg/plug.in6
-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/ndb_configure.m4349
-rw-r--r--storage/ndb/plug.in2
-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/lgman.cpp16
-rw-r--r--storage/ndb/src/libndb.ver.in15
-rw-r--r--storage/ndb/src/mgmsrv/InitConfigFileParser.cpp2
-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/run-test/setup.cpp4
-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/perfschema/Makefile.am76
-rw-r--r--storage/perfschema/ha_perfschema.cc40
-rw-r--r--storage/perfschema/ha_perfschema.h7
-rw-r--r--storage/perfschema/pfs_engine_table.cc111
-rw-r--r--storage/perfschema/pfs_global.h16
-rw-r--r--storage/perfschema/pfs_instr.cc25
-rw-r--r--storage/perfschema/pfs_instr.h1
-rw-r--r--storage/perfschema/pfs_instr_class.cc70
-rw-r--r--storage/perfschema/pfs_instr_class.h2
-rw-r--r--storage/perfschema/pfs_lock.h20
-rw-r--r--storage/perfschema/plug.in26
-rw-r--r--storage/perfschema/table_events_waits.cc27
-rw-r--r--storage/perfschema/table_events_waits_summary.cc4
-rw-r--r--storage/perfschema/table_ews_global_by_event_name.cc2
-rw-r--r--storage/perfschema/table_file_instances.cc2
-rw-r--r--storage/perfschema/table_file_summary.cc4
-rw-r--r--storage/perfschema/table_performance_timers.cc2
-rw-r--r--storage/perfschema/table_setup_consumers.cc3
-rw-r--r--storage/perfschema/table_setup_instruments.cc3
-rw-r--r--storage/perfschema/table_setup_timers.cc3
-rw-r--r--storage/perfschema/table_sync_instances.cc6
-rw-r--r--storage/perfschema/table_threads.cc13
-rw-r--r--storage/perfschema/table_threads.h4
-rw-r--r--storage/perfschema/unittest/Makefile.am58
-rw-r--r--storage/perfschema/unittest/pfs-t.cc3
-rw-r--r--storage/perfschema/unittest/pfs_instr-oom-t.cc5
-rw-r--r--storage/perfschema/unittest/pfs_instr-t.cc6
-rw-r--r--storage/perfschema/unittest/pfs_instr_class-oom-t.cc5
-rw-r--r--storage/perfschema/unittest/pfs_instr_class-t.cc6
-rw-r--r--storage/perfschema/unittest/pfs_timer-t.cc4
-rw-r--r--storage/perfschema/unittest/stub_server_misc.h21
389 files changed, 10619 insertions, 30298 deletions
diff --git a/storage/Makefile.am b/storage/Makefile.am
deleted file mode 100644
index a188d8967be..00000000000
--- a/storage/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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 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
-
-# Process this file with automake to create Makefile.in
-
-AUTOMAKE_OPTIONS = foreign
-
-# These are built from source in the Docs directory
-SUBDIRS = @mysql_se_dirs@
-DIST_SUBDIRS = @mysql_se_distdirs@
diff --git a/storage/archive/Makefile.am b/storage/archive/Makefile.am
deleted file mode 100644
index 14fcde4108b..00000000000
--- a/storage/archive/Makefile.am
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright (C) 2005-2006 MySQL AB
-# Copyright (C) 2009 SUN Microsystems
-#
-# 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
-
-#called from the top level Makefile
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-pkgplugindir = $(pkglibdir)/plugin
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir) @ZLIB_INCLUDES@
-WRAPLIBS=
-
-LDADD =
-
-DEFS = @DEFS@
-
-noinst_HEADERS = ha_archive.h azlib.h
-noinst_PROGRAMS = archive_test archive_reader
-
-EXTRA_LTLIBRARIES = ha_archive.la
-pkgplugin_LTLIBRARIES = @plugin_archive_shared_target@
-ha_archive_la_LDFLAGS = -module -rpath $(pkgplugindir)
-ha_archive_la_CXXFLAGS= -shared $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_archive_la_CFLAGS = -shared $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_archive_la_SOURCES = ha_archive.cc azio.c
-
-
-EXTRA_LIBRARIES = libarchive.a
-noinst_LIBRARIES = @plugin_archive_static_target@
-libarchive_a_CXXFLAGS = $(AM_CXXFLAGS)
-libarchive_a_CFLAGS = $(AM_CFLAGS)
-libarchive_a_SOURCES = ha_archive.cc azio.c
-
-
-archive_test_SOURCES = archive_test.c azio.c
-archive_test_CFLAGS = $(AM_CFLAGS)
-archive_test_LDADD = $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a \
- @ZLIB_LIBS@
-archive_test_LDFLAGS = @NOINST_LDFLAGS@
-
-archive_reader_SOURCES = archive_reader.c azio.c
-archive_reader_CFLAGS = $(AM_CFLAGS)
-archive_reader_LDADD = $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a \
- @ZLIB_LIBS@
-archive_reader_LDFLAGS = @NOINST_LDFLAGS@
-
-
-EXTRA_DIST = CMakeLists.txt plug.in
-
-if HAVE_DTRACE_DASH_G
-# The object for static and dynamic linking of archive differ
-# For static linkage of archive to mysqld
-
-libarchive_a_LIBADD = probes_mysql.o
-libarchive_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-# For archive as shared library
-ha_archive_la_LIBADD = probes_sh_mysql.o
-# Hack: We "depend" on ".libs/" but have no rule for it,
-# but it is created as a byproduct of the ".lo"
-DTRACESHAREDDEPS = ha_archive_la-ha_archive.lo
-DTRACESHAREDFILES = ha_archive_la-ha_archive.o
-DTRACEPROVIDER = probes_mysql.d
-ha_archive_la_DEPENDENCIES = probes_sh_mysql.o $(DTRACESHAREDDEPS) dtrace_providers
-
-CLEANFILES = $(DTRACEPROVIDER) dtrace_files dtrace_providers $(DTRACESHAREDFILES)
-DTRACEFILES = libarchive_a-ha_archive.o
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_sh_mysql.o: $(DTRACEPROVIDER) $(DTRACESHAREDDEPS)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACESHAREDFILES) -o $@
- $(CP) $(DTRACESHAREDFILES) .libs
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-
-endif
diff --git a/storage/archive/azio.c b/storage/archive/azio.c
index 936a179b5b4..8fc85965cf0 100644
--- a/storage/archive/azio.c
+++ b/storage/archive/azio.c
@@ -116,6 +116,15 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd)
errno = 0;
s->file = fd < 0 ? my_open(path, Flags, MYF(0)) : fd;
+ DBUG_EXECUTE_IF("simulate_archive_open_failure",
+ {
+ if (s->file >= 0)
+ {
+ my_close(s->file, MYF(0));
+ s->file= -1;
+ my_errno= EMFILE;
+ }
+ });
if (s->file < 0 )
{
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 8144ea5f319..2e001efc1dc 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -1,17 +1,19 @@
-/* Copyright (C) 2003 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
+ 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.
+ 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 */
+ 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 */
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation // gcc: Class implementation
@@ -20,6 +22,7 @@
#include "sql_priv.h"
#include "probes_mysql.h"
#include "sql_class.h" // SSV
+#include "sql_table.h"
#include <myisam.h>
#include "ha_archive.h"
@@ -256,7 +259,7 @@ int archive_discover(handlerton *hton, THD* thd, const char *db,
char *frm_ptr;
MY_STAT file_stat;
- fn_format(az_file, name, db, ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
+ build_table_filename(az_file, sizeof(az_file) - 1, db, name, ARZ, 0);
if (!(my_stat(az_file, &file_stat, MYF(0))))
goto err;
@@ -934,7 +937,7 @@ int ha_archive::write_row(uchar *buf)
*/
azflush(&(share->archive_write), Z_SYNC_FLUSH);
/*
- Set the position of the local read thread to the beginning postion.
+ Set the position of the local read thread to the beginning position.
*/
if (read_data_header(&archive))
{
@@ -1190,7 +1193,7 @@ int ha_archive::unpack_row(azio_stream *file_to_read, uchar *record)
ptr+= table->s->null_bytes;
for (Field **field=table->field ; *field ; field++)
{
- if (!((*field)->is_null()))
+ if (!((*field)->is_null_in_record(record)))
{
ptr= (*field)->unpack(record + (*field)->offset(table->record[0]), ptr);
}
@@ -1670,9 +1673,9 @@ int ha_archive::end_bulk_insert()
This is done for security reasons. In a later version we will enable this by
allowing the user to select a different row format.
*/
-int ha_archive::delete_all_rows()
+int ha_archive::truncate()
{
- DBUG_ENTER("ha_archive::delete_all_rows");
+ DBUG_ENTER("ha_archive::truncate");
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -1702,11 +1705,12 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
azflush(&(share->archive_write), Z_SYNC_FLUSH);
mysql_mutex_unlock(&share->mutex);
+ if (init_archive_reader())
+ DBUG_RETURN(HA_ADMIN_CORRUPT);
/*
Now we will rewind the archive file so that we are positioned at the
start of the file.
*/
- init_archive_reader();
read_data_header(&archive);
while (!(rc= get_row(&archive, table->record[0])))
count--;
diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h
index 712c1e1358d..034b759e091 100644
--- a/storage/archive/ha_archive.h
+++ b/storage/archive/ha_archive.h
@@ -90,7 +90,7 @@ public:
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_STATS_RECORDS_IS_EXACT |
- HA_HAS_RECORDS |
+ HA_HAS_RECORDS | HA_CAN_REPAIR |
HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
}
ulong index_flags(uint idx, uint part, bool all_parts) const
@@ -115,7 +115,7 @@ public:
int close(void);
int write_row(uchar * buf);
int real_write_row(uchar *buf, azio_stream *writer);
- int delete_all_rows();
+ int truncate();
int rnd_init(bool scan=1);
int rnd_next(uchar *buf);
int rnd_pos(uchar * buf, uchar *pos);
diff --git a/storage/archive/plug.in b/storage/archive/plug.in
deleted file mode 100644
index 52131b12e6b..00000000000
--- a/storage/archive/plug.in
+++ /dev/null
@@ -1,4 +0,0 @@
-MYSQL_STORAGE_ENGINE(archive,, [Archive Storage Engine],
- [Archive Storage Engine], [max,max-no-ndb])
-MYSQL_PLUGIN_STATIC(archive, [libarchive.a])
-MYSQL_PLUGIN_DYNAMIC(archive, [ha_archive.la])
diff --git a/storage/blackhole/Makefile.am b/storage/blackhole/Makefile.am
deleted file mode 100644
index 7016f265365..00000000000
--- a/storage/blackhole/Makefile.am
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright (C) 2005-2006 MySQL AB, 2009 Sun Microsystems, Inc.
-# All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-#called from the top level Makefile
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-pkgplugindir = $(pkglibdir)/plugin
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir)
-WRAPLIBS=
-
-LDADD =
-
-DEFS = @DEFS@
-
-noinst_HEADERS = ha_blackhole.h
-
-EXTRA_LTLIBRARIES = ha_blackhole.la
-pkgplugin_LTLIBRARIES = @plugin_blackhole_shared_target@
-ha_blackhole_la_LDFLAGS=-module -rpath $(pkgplugindir)
-ha_blackhole_la_CXXFLAGS=-shared $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_blackhole_la_SOURCES=ha_blackhole.cc
-
-
-EXTRA_LIBRARIES = libblackhole.a
-noinst_LIBRARIES = @plugin_blackhole_static_target@
-libblackhole_a_CXXFLAGS=$(AM_CXXFLAGS)
-libblackhole_a_SOURCES= ha_blackhole.cc
-
-
-EXTRA_DIST = CMakeLists.txt plug.in
-
-if HAVE_DTRACE_DASH_G
-# The object for static and dynamic linking of blackhole differ
-# For static linkage of blackhole to mysqld
-
-libblackhole_a_LIBADD = probes_mysql.o
-libblackhole_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-# For blackhole as shared library
-ha_blackhole_la_LIBADD = probes_sh_mysql.o
-# Hack: We "depend" on ".libs/" but have no rule for it,
-# but it is created as a byproduct of the ".lo"
-DTRACESHAREDDEPS = ha_blackhole_la-ha_blackhole.lo
-DTRACESHAREDFILES = ha_blackhole_la-ha_blackhole.o
-DTRACEPROVIDER = probes_mysql.d
-ha_blackhole_la_DEPENDENCIES = probes_sh_mysql.o $(DTRACESHAREDDEPS) dtrace_providers
-
-CLEANFILES = $(DTRACEPROVIDERS) dtrace_files dtrace_providers $(DTRACESHAREDDEPS)
-DTRACEFILES = libblackhole_a-ha_blackhole.o
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_sh_mysql.o: $(DTRACEPROVIDER) $(DTRACESHAREDDEPS)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACESHAREDFILES) -o $@
- $(CP) $(DTRACESHAREDFILES) .libs
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-
-endif
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 993ba9c7cd4..14eb24eaaa3 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -87,6 +87,16 @@ int ha_blackhole::create(const char *name, TABLE *table_arg,
DBUG_RETURN(0);
}
+/*
+ Intended to support partitioning.
+ Allows a particular partition to be truncated.
+*/
+int ha_blackhole::truncate()
+{
+ DBUG_ENTER("ha_blackhole::truncate");
+ DBUG_RETURN(0);
+}
+
const char *ha_blackhole::index_type(uint key_number)
{
DBUG_ENTER("ha_blackhole::index_type");
diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h
index 9de3c22c614..17066b6edce 100644
--- a/storage/blackhole/ha_blackhole.h
+++ b/storage/blackhole/ha_blackhole.h
@@ -76,6 +76,7 @@ public:
uint max_supported_key_part_length() const { return BLACKHOLE_MAX_KEY_LENGTH; }
int open(const char *name, int mode, uint test_if_locked);
int close(void);
+ int truncate();
int rnd_init(bool scan);
int rnd_next(uchar *buf);
int rnd_pos(uchar * buf, uchar *pos);
diff --git a/storage/blackhole/plug.in b/storage/blackhole/plug.in
deleted file mode 100644
index 725db0facba..00000000000
--- a/storage/blackhole/plug.in
+++ /dev/null
@@ -1,6 +0,0 @@
-MYSQL_STORAGE_ENGINE(blackhole,,[Blackhole Storage Engine],
- [Basic Write-only Read-never tables], [max,max-no-ndb])
-MYSQL_PLUGIN_DIRECTORY(blackhole, [storage/blackhole])
-MYSQL_PLUGIN_STATIC(blackhole, [libblackhole.a])
-MYSQL_PLUGIN_DYNAMIC(blackhole, [ha_blackhole.la])
-
diff --git a/storage/csv/Makefile.am b/storage/csv/Makefile.am
deleted file mode 100644
index 76e683ec282..00000000000
--- a/storage/csv/Makefile.am
+++ /dev/null
@@ -1,64 +0,0 @@
-# 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 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
-
-#called from the top level Makefile
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-INCLUDES = -I$(top_builddir)/include \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir)
-LDADD =
-
-DEFS = @DEFS@
-noinst_HEADERS = ha_tina.h transparent_file.h
-
-EXTRA_LTLIBRARIES = ha_csv.la
-pkglib_LTLIBRARIES = @plugin_csv_shared_target@
-ha_csv_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
-ha_csv_la_CXXFLAGS = -shared $(AM_CXXFLAGS) -DMYSQL_PLUGIN
-ha_csv_la_SOURCES = transparent_file.cc ha_tina.cc
-
-EXTRA_LIBRARIES = libcsv.a
-noinst_LIBRARIES = @plugin_csv_static_target@
-libcsv_a_CXXFLAGS = $(AM_CXXFLAGS)
-libcsv_a_SOURCES = transparent_file.cc ha_tina.cc
-
-EXTRA_DIST = CMakeLists.txt plug.in
-
-if HAVE_DTRACE_DASH_G
-libcsv_a_LIBADD = probes_mysql.o
-libcsv_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-CLEANFILES = probes_mysql.o dtrace_files dtrace_providers
-DTRACEFILES = libcsv_a-ha_tina.o
-DTRACEPROVIDER = probes_mysql.d
-CLEANFILES += $(DTRACEPROVIDER) dtrace_sources
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-endif
diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
index dc2fc743117..a2f12443528 100644
--- a/storage/csv/ha_tina.h
+++ b/storage/csv/ha_tina.h
@@ -108,7 +108,8 @@ public:
ulonglong table_flags() const
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT |
- HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE);
+ HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
+ HA_CAN_REPAIR);
}
ulong index_flags(uint idx, uint part, bool all_parts) const
{
diff --git a/storage/csv/plug.in b/storage/csv/plug.in
deleted file mode 100644
index bbc69680fcd..00000000000
--- a/storage/csv/plug.in
+++ /dev/null
@@ -1,5 +0,0 @@
-MYSQL_STORAGE_ENGINE(csv,, [CSV Storage Engine],
- [Stores tables in text CSV format])
-MYSQL_PLUGIN_DIRECTORY(csv, [storage/csv])
-MYSQL_PLUGIN_STATIC(csv, [libcsv.a])
-MYSQL_PLUGIN_MANDATORY(csv) dnl Used for logging
diff --git a/storage/example/Makefile.am b/storage/example/Makefile.am
deleted file mode 100644
index a8b0506e8dd..00000000000
--- a/storage/example/Makefile.am
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright (C) 2005-2006 MySQL AB, 2009 Sun Microsystems, Inc.
-# All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-#called from the top level Makefile
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-pkgplugindir = $(pkglibdir)/plugin
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir)
-WRAPLIBS=
-
-LDADD =
-
-DEFS = @DEFS@
-
-noinst_HEADERS = ha_example.h
-
-EXTRA_LTLIBRARIES = ha_example.la
-pkgplugin_LTLIBRARIES = @plugin_example_shared_target@
-ha_example_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
-ha_example_la_CXXFLAGS= -shared $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_example_la_SOURCES = ha_example.cc
-
-EXTRA_LIBRARIES = libexample.a
-noinst_LIBRARIES = @plugin_example_static_target@
-libexample_a_CXXFLAGS = $(AM_CXXFLAGS)
-libexample_a_SOURCES= ha_example.cc
-
-
-EXTRA_DIST = CMakeLists.txt plug.in
-
-if HAVE_DTRACE_DASH_G
-# The object for static and dynamic linking of example differ
-# For static linkage of example to mysqld
-# That's actually not needed as example is only dynamic loadable, but for completion
-libexample_a_LIBADD = probes_mysql.o
-libexample_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-# For example as shared library
-ha_example_la_LIBADD = probes_sh_mysql.o
-# Hack: We "depend" on ".libs/" but have no rule for it,
-# but it is created as a byproduct of the ".lo"
-DTRACESHAREDDEPS = ha_example_la-ha_example.lo
-DTRACESHAREDFILES = ha_example_la-ha_example.o
-DTRACEPROVIDER = probes_mysql.d
-ha_example_la_DEPENDENCIES = probes_sh_mysql.o $(DTRACESHAREDDEPS) dtrace_providers
-
-CLEANFILES = $(DTRACEPROVIDER) dtrace_files dtrace_providers $(DTRACESHAREDFILES)
-DTRACEFILES = libexample_a-ha_example.o
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_sh_mysql.o: $(DTRACEPROVIDER) $(DTRACESHAREDDEPS)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACESHAREDFILES) -o $@
- $(CP) $(DTRACESHAREDFILES) .libs
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-
-endif
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index 2a076f0dc14..eeb9b12007b 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -439,14 +439,14 @@ int ha_example::close(void)
is happening. buf() is a byte array of data. You can use the field
information to extract the data from the native byte array type.
- @details
+ @details
Example of this would be:
- @code
+ @code
for (Field **field=table->field ; *field ; field++)
{
...
}
- @endcode
+ @endcode
See ha_tina.cc for an example of extracting all of the data as strings.
ha_berekly.cc has an example of how to store it intact by "packing" it
@@ -458,7 +458,7 @@ int ha_example::close(void)
Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
- @see
+ @see
item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc and sql_update.cc
*/
@@ -483,19 +483,19 @@ int ha_example::write_row(uchar *buf)
Keep in mind that the server can do updates based on ordering if an ORDER BY
clause was used. Consecutive ordering is not guaranteed.
- @details
+ @details
Currently new_data will not have an updated auto_increament record, or
and updated timestamp field. You can do these for example by doing:
- @code
+ @code
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
if (table->next_number_field && record == table->record[0])
update_auto_increment();
- @endcode
+ @endcode
Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
- @see
+ @see
sql_select.cc, sql_acl.cc, sql_update.cc and sql_insert.cc
*/
int ha_example::update_row(const uchar *old_data, uchar *new_data)
@@ -590,10 +590,10 @@ int ha_example::index_prev(uchar *buf)
@brief
index_first() asks for the first key in the index.
- @details
+ @details
Called from opt_range.cc, opt_sum.cc, sql_handler.cc, and sql_select.cc.
- @see
+ @see
opt_range.cc, opt_sum.cc, sql_handler.cc and sql_select.cc
*/
int ha_example::index_first(uchar *buf)
@@ -611,10 +611,10 @@ int ha_example::index_first(uchar *buf)
@brief
index_last() asks for the last key in the index.
- @details
+ @details
Called from opt_range.cc, opt_sum.cc, sql_handler.cc, and sql_select.cc.
- @see
+ @see
opt_range.cc, opt_sum.cc, sql_handler.cc and sql_select.cc
*/
int ha_example::index_last(uchar *buf)
@@ -634,11 +634,11 @@ int ha_example::index_last(uchar *buf)
scan. See the example in the introduction at the top of this file to see when
rnd_init() is called.
- @details
+ @details
Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc,
and sql_update.cc.
- @see
+ @see
filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc and sql_update.cc
*/
int ha_example::rnd_init(bool scan)
@@ -661,11 +661,11 @@ int ha_example::rnd_end()
The Field structure for the table is the key to getting data into buf
in a manner that will allow the server to understand it.
- @details
+ @details
Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc,
and sql_update.cc.
- @see
+ @see
filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc and sql_update.cc
*/
int ha_example::rnd_next(uchar *buf)
@@ -685,11 +685,11 @@ int ha_example::rnd_next(uchar *buf)
position() is called after each call to rnd_next() if the data needs
to be ordered. You can do something like the following to store
the position:
- @code
+ @code
my_store_ptr(ref, ref_length, current_position);
- @endcode
+ @endcode
- @details
+ @details
The server uses ref to store data. ref_length in the above case is
the size needed to store current_position. ref is just a byte array
that the server will maintain. If you are using offsets to mark rows, then
@@ -698,7 +698,7 @@ int ha_example::rnd_next(uchar *buf)
Called from filesort.cc, sql_select.cc, sql_delete.cc, and sql_update.cc.
- @see
+ @see
filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc
*/
void ha_example::position(const uchar *record)
@@ -715,10 +715,10 @@ void ha_example::position(const uchar *record)
ref. You can use ha_get_ptr(pos,ref_length) to retrieve whatever key
or position you saved when position() was called.
- @details
+ @details
Called from filesort.cc, records.cc, sql_insert.cc, sql_select.cc, and sql_update.cc.
- @see
+ @see
filesort.cc, records.cc, sql_insert.cc, sql_select.cc and sql_update.cc
*/
int ha_example::rnd_pos(uchar *buf, uchar *pos)
@@ -738,15 +738,15 @@ int ha_example::rnd_pos(uchar *buf, uchar *pos)
::info() is used to return information to the optimizer. See my_base.h for
the complete description.
- @details
+ @details
Currently this table handler doesn't implement most of the fields really needed.
SHOW also makes use of this data.
You will probably want to have the following in your code:
- @code
+ @code
if (records < 2)
records = 2;
- @endcode
+ @endcode
The reason is that the server will optimize for cases of only a single
record. If, in a table scan, you don't know the number of records, it
will probably be better to set records to two so you can return as many
@@ -765,7 +765,7 @@ int ha_example::rnd_pos(uchar *buf, uchar *pos)
sql_select.cc, sql_select.cc, sql_show.cc, sql_show.cc, sql_show.cc, sql_show.cc,
sql_table.cc, sql_union.cc, and sql_update.cc.
- @see
+ @see
filesort.cc, ha_heap.cc, item_sum.cc, opt_sum.cc, sql_delete.cc, sql_delete.cc,
sql_derived.cc, sql_select.cc, sql_select.cc, sql_select.cc, sql_select.cc,
sql_select.cc, sql_show.cc, sql_show.cc, sql_show.cc, sql_show.cc, sql_table.cc,
@@ -799,14 +799,14 @@ int ha_example::extra(enum ha_extra_function operation)
Used to delete all rows in a table, including cases of truncate and cases where
the optimizer realizes that all rows will be removed as a result of an SQL statement.
- @details
+ @details
Called from item_sum.cc by Item_func_group_concat::clear(),
Item_sum_count_distinct::clear(), and Item_func_group_concat::clear().
Called from sql_delete.cc by mysql_delete().
Called from sql_select.cc by JOIN::reinit().
Called from sql_union.cc by st_select_lex_unit::exec().
- @see
+ @see
Item_func_group_concat::clear(), Item_sum_count_distinct::clear() and
Item_func_group_concat::clear() in item_sum.cc;
mysql_delete() in sql_delete.cc;
@@ -822,17 +822,40 @@ int ha_example::delete_all_rows()
/**
@brief
+ Used for handler specific truncate table. The table is locked in
+ exclusive mode and handler is responsible for reseting the auto-
+ increment counter.
+
+ @details
+ Called from Truncate_statement::handler_truncate.
+ Not used if the handlerton supports HTON_CAN_RECREATE, unless this
+ engine can be used as a partition. In this case, it is invoked when
+ a particular partition is to be truncated.
+
+ @see
+ Truncate_statement in sql_truncate.cc
+ Remarks in handler::truncate.
+*/
+int ha_example::truncate()
+{
+ DBUG_ENTER("ha_example::truncate");
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+}
+
+
+/**
+ @brief
This create a lock on the table. If you are implementing a storage engine
that can handle transacations look at ha_berkely.cc to see how you will
want to go about doing this. Otherwise you should consider calling flock()
here. Hint: Read the section "locking functions for mysql" in lock.cc to understand
this.
- @details
+ @details
Called from lock.cc by lock_external() and unlock_external(). Also called
from sql_table.cc by copy_data_between_tables().
- @see
+ @see
lock.cc by lock_external() and unlock_external() in lock.cc;
the section "locking functions for mysql" in lock.cc;
copy_data_between_tables() in sql_table.cc.
@@ -850,7 +873,7 @@ int ha_example::external_lock(THD *thd, int lock_type)
should be needed for the table. For updates/deletes/inserts we get WRITE
locks, for SELECT... we get read locks.
- @details
+ @details
Before adding the lock into the table lock handler (see thr_lock.c),
mysqld calls store lock with the requested locks. Store lock can now
modify a write lock to a read lock (or some other lock), ignore the
@@ -873,12 +896,12 @@ int ha_example::external_lock(THD *thd, int lock_type)
Called from lock.cc by get_lock_data().
- @note
+ @note
In this method one should NEVER rely on table->in_use, it may, in fact,
refer to a different thread! (this happens if get_lock_data() is called
from mysql_lock_abort_for_thread() function)
- @see
+ @see
get_lock_data() in lock.cc
*/
THR_LOCK_DATA **ha_example::store_lock(THD *thd,
@@ -899,7 +922,7 @@ THR_LOCK_DATA **ha_example::store_lock(THD *thd,
shared references released). The variable name will just be the name of
the table. You will need to remove any files you have created at this point.
- @details
+ @details
If you do not implement this, the default delete_table() is called from
handler.cc and it will delete all files with the file extensions returned
by bas_ext().
@@ -908,7 +931,7 @@ THR_LOCK_DATA **ha_example::store_lock(THD *thd,
during create if the table_flag HA_DROP_BEFORE_CREATE was specified for
the storage engine.
- @see
+ @see
delete_table and ha_create_table() in handler.cc
*/
int ha_example::delete_table(const char *name)
@@ -1113,7 +1136,7 @@ static int show_func_example(MYSQL_THD thd, struct st_mysql_show_var *var,
var->type= SHOW_CHAR;
var->value= buf; // it's of SHOW_VAR_FUNC_BUFF_SIZE bytes
my_snprintf(buf, SHOW_VAR_FUNC_BUFF_SIZE,
- "enum_var is %u, ulong_var is %lu, %.6b", // %b is MySQL extension
+ "enum_var is %lu, ulong_var is %lu, %.6b", // %b is MySQL extension
srv_enum_var, srv_ulong_var, "really");
return 0;
}
diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h
index 27b97395544..98ef563b877 100644
--- a/storage/example/ha_example.h
+++ b/storage/example/ha_example.h
@@ -245,6 +245,7 @@ public:
int extra(enum ha_extra_function operation);
int external_lock(THD *thd, int lock_type); ///< required
int delete_all_rows(void);
+ int truncate();
ha_rows records_in_range(uint inx, key_range *min_key,
key_range *max_key);
int delete_table(const char *from);
diff --git a/storage/example/plug.in b/storage/example/plug.in
deleted file mode 100644
index ee6beaac64f..00000000000
--- a/storage/example/plug.in
+++ /dev/null
@@ -1,3 +0,0 @@
-MYSQL_STORAGE_ENGINE(example,, [Example Storage Engine],
- [Example for Storage Engines for developers], [max,max-no-ndb])
-MYSQL_PLUGIN_DYNAMIC(example, [ha_example.la])
diff --git a/storage/federated/Makefile.am b/storage/federated/Makefile.am
deleted file mode 100644
index 28b71900af2..00000000000
--- a/storage/federated/Makefile.am
+++ /dev/null
@@ -1,84 +0,0 @@
-# Copyright (C) 2005-2006 MySQL AB, 2009 Sun Microsystems, Inc.
-# All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-#called from the top level Makefile
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-pkgplugindir = $(pkglibdir)/plugin
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir)
-
-WRAPLIBS=
-
-DEFS = @DEFS@
-
-noinst_HEADERS = ha_federated.h
-
-EXTRA_LTLIBRARIES = ha_federated.la
-pkgplugin_LTLIBRARIES = @plugin_federated_shared_target@
-ha_federated_la_LDFLAGS = -module -rpath $(pkgplugindir) \
- -L$(top_builddir)/libservices -lmysqlservices
-ha_federated_la_CXXFLAGS= -shared $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_federated_la_CFLAGS = -shared $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_federated_la_SOURCES = ha_federated.cc $(top_srcdir)/mysys/string.c
-
-
-EXTRA_LIBRARIES = libfederated.a
-noinst_LIBRARIES = @plugin_federated_static_target@
-libfederated_a_CXXFLAGS = $(AM_CXXFLAGS)
-libfederated_a_SOURCES= ha_federated.cc
-
-
-EXTRA_DIST = CMakeLists.txt plug.in
-
-if HAVE_DTRACE_DASH_G
-# The object for static and dynamic linking of federated differ
-# For static linkage of federated to mysqld
-
-libfederated_a_LIBADD = probes_mysql.o
-libfederated_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-# For federated as shared library
-ha_federated_la_LIBADD = probes_sh_mysql.o
-# Hack: We "depend" on ".libs/" but have no rule for it,
-# but it is created as a byproduct of the ".lo"
-DTRACESHAREDDEPS = ha_federated_la-ha_federated.lo
-DTRACESHAREDFILES = ha_federated_la-ha_federated.o
-DTRACEPROVIDER = probes_mysql.d
-ha_federated_la_DEPENDENCIES = probes_sh_mysql.o $(DTRACESHAREDDEPS) dtrace_providers
-
-CLEANFILES = $(DTRACEPROVIDER) dtrace_files dtrace_providers $(DTRACESHAREDFILES)
-DTRACEFILES = libfederated_a-ha_federated.o
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_sh_mysql.o: $(DTRACEPROVIDER) $(DTRACESHAREDDEPS)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACESHAREDFILES) -o $@
- $(CP) $(DTRACESHAREDFILES) .libs
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-
-endif
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index f38f71b15ee..17412808d44 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -3044,6 +3044,16 @@ int ha_federated::delete_all_rows()
/*
+ Used to manually truncate the table via a delete of all rows in a table.
+*/
+
+int ha_federated::truncate()
+{
+ return delete_all_rows();
+}
+
+
+/*
The idea with handler::store_lock() is the following:
The statement decided which locks we should need for the table
diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h
index be52a54be50..ad74521042e 100644
--- a/storage/federated/ha_federated.h
+++ b/storage/federated/ha_federated.h
@@ -149,7 +149,8 @@ public:
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
HA_NO_TRANSACTIONS /* until fixed by WL#2952 */ |
- HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY);
+ HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY |
+ HA_CAN_REPAIR);
}
/*
This is a bitmap of flags that says how the storage engine
@@ -248,6 +249,7 @@ public:
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int delete_all_rows(void);
+ int truncate();
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); //required
ha_rows records_in_range(uint inx, key_range *start_key,
diff --git a/storage/federated/plug.in b/storage/federated/plug.in
deleted file mode 100644
index 714888b2ebf..00000000000
--- a/storage/federated/plug.in
+++ /dev/null
@@ -1,5 +0,0 @@
-MYSQL_STORAGE_ENGINE(federated,,[Federated Storage Engine],
- [Connects to tables on remote MySQL servers], [])
-MYSQL_PLUGIN_STATIC(federated, [libfederated.a])
-MYSQL_PLUGIN_DYNAMIC(federated, [ha_federated.la])
-MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(federated, [ha_federated.cc])
diff --git a/storage/federatedx/plug.in b/storage/federatedx/plug.in
deleted file mode 100644
index 95afe270f4c..00000000000
--- a/storage/federatedx/plug.in
+++ /dev/null
@@ -1,5 +0,0 @@
-MYSQL_STORAGE_ENGINE(federatedx,,[FederatedX Storage Engine],
- [FederatedX Storage Engine], [max,max-no-ndb])
-MYSQL_PLUGIN_DYNAMIC(federatedx, [ha_federatedx.la])
-MYSQL_PLUGIN_STATIC(federatedx, [libfederatedx.a])
-MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(federatedx, [ha_federatedx.cc])
diff --git a/storage/heap/Makefile.am b/storage/heap/Makefile.am
deleted file mode 100644
index 677b2d60269..00000000000
--- a/storage/heap/Makefile.am
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 2000-2002, 2005-2006 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
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir)
-WRAPLIBS=
-
-LDADD =
-
-DEFS = @DEFS@
-pkglib_LIBRARIES = libheap.a
-noinst_PROGRAMS = hp_test1 hp_test2
-noinst_LIBRARIES = libheap.a
-hp_test1_LDFLAGS = @NOINST_LDFLAGS@
-hp_test1_LDADD = libheap.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a
-hp_test2_LDFLAGS = @NOINST_LDFLAGS@
-hp_test2_LDADD = libheap.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a
-noinst_HEADERS = heapdef.h ha_heap.h
-libheap_a_SOURCES = hp_open.c hp_extra.c hp_close.c hp_panic.c hp_info.c \
- hp_rrnd.c hp_scan.c hp_update.c hp_write.c hp_delete.c \
- hp_rsame.c hp_create.c hp_rename.c hp_rfirst.c \
- hp_rnext.c hp_rlast.c hp_rprev.c hp_clear.c \
- hp_rkey.c hp_block.c \
- ha_heap.cc \
- hp_hash.c _check.c _rectest.c hp_static.c
-
-
-EXTRA_DIST = CMakeLists.txt plug.in
-
-if HAVE_DTRACE_DASH_G
-libheap_a_LIBADD = probes_mysql.o
-libheap_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-CLEANFILES = probes_mysql.o dtrace_files dtrace_providers
-DTRACEFILES = ha_heap.o
-DTRACEPROVIDER = probes_mysql.d
-CLEANFILES += $(DTRACEPROVIDER) dtrace_sources
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-endif
diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc
index 93bee5ad7f1..fc6e89e54e0 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -157,11 +157,11 @@ int ha_heap::close(void)
DESCRIPTION
Do same as default implementation but use file->s->name instead of
table->s->path. This is needed by Windows where the clone() call sees
- '/'-delimited path in table->s->path, while ha_peap::open() was called
+ '/'-delimited path in table->s->path, while ha_heap::open() was called
with '\'-delimited path.
*/
-handler *ha_heap::clone(MEM_ROOT *mem_root)
+handler *ha_heap::clone(const char *name, MEM_ROOT *mem_root)
{
handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
@@ -455,6 +455,13 @@ int ha_heap::delete_all_rows()
}
+int ha_heap::truncate()
+{
+ int error= delete_all_rows();
+ return error ? error : reset_auto_increment(0);
+}
+
+
int ha_heap::reset_auto_increment(ulonglong value)
{
file->s->auto_increment= value;
diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h
index 7185fbc7720..cc335870f06 100644
--- a/storage/heap/ha_heap.h
+++ b/storage/heap/ha_heap.h
@@ -35,7 +35,7 @@ class ha_heap: public handler
public:
ha_heap(handlerton *hton, TABLE_SHARE *table);
~ha_heap() {}
- handler *clone(MEM_ROOT *mem_root);
+ handler *clone(const char *name, MEM_ROOT *mem_root);
const char *table_type() const
{
return (table->in_use->variables.sql_mode & MODE_MYSQL323) ?
@@ -99,6 +99,7 @@ public:
int reset();
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
+ int truncate();
int reset_auto_increment(ulonglong value);
int disable_indexes(uint mode);
int enable_indexes(uint mode);
diff --git a/storage/heap/heapdef.h b/storage/heap/heapdef.h
index bc3c6bf7239..87866678c2f 100644
--- a/storage/heap/heapdef.h
+++ b/storage/heap/heapdef.h
@@ -17,9 +17,7 @@
#include <my_base.h> /* This includes global */
C_MODE_START
-#ifdef THREAD
#include <my_pthread.h>
-#endif
#include "heap.h" /* Structs & some defines */
#include "my_tree.h"
@@ -102,14 +100,11 @@ extern void hp_clear(HP_SHARE *info);
extern void hp_clear_keys(HP_SHARE *info);
extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
key_part_map keypart_map);
-#ifdef THREAD
+
extern mysql_mutex_t THR_LOCK_heap;
-#endif
#ifdef HAVE_PSI_INTERFACE
-#ifdef THREAD
extern PSI_mutex_key hp_key_mutex_HP_SHARE_intern_lock;
-#endif /* THREAD */
void init_heap_psi_keys();
#endif /* HAVE_PSI_INTERFACE */
diff --git a/storage/heap/hp_block.c b/storage/heap/hp_block.c
index 7f6cc1ef90a..41391fba060 100644
--- a/storage/heap/hp_block.c
+++ b/storage/heap/hp_block.c
@@ -86,7 +86,6 @@ int hp_get_new_block(HP_BLOCK *block, size_t *alloc_length)
}
else
{
- dont_break(); /* Dont allow SIGHUP or SIGINT */
if ((uint) i == block->levels)
{
/* Adding a new level on top of the existing ones. */
@@ -117,7 +116,6 @@ int hp_get_new_block(HP_BLOCK *block, size_t *alloc_length)
allocated bytes. Use it as a leaf block.
*/
block->level_info[0].last_blocks= root;
- allow_break(); /* Allow SIGHUP & SIGINT */
}
return 0;
}
diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c
index bbf649c5e46..67fe0b3136f 100644
--- a/storage/heap/hp_create.c
+++ b/storage/heap/hp_create.c
@@ -192,11 +192,9 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info,
my_free(share);
goto err;
}
-#ifdef THREAD
thr_lock_init(&share->lock);
mysql_mutex_init(hp_key_mutex_HP_SHARE_intern_lock,
&share->intern_lock, MY_MUTEX_INIT_FAST);
-#endif
if (!create_info->internal_table)
{
share->open_list.data= (void*) share;
@@ -301,10 +299,8 @@ void hp_free(HP_SHARE *share)
if (share->open_list.data) /* If not internal table */
heap_share_list= list_delete(heap_share_list, &share->open_list);
hp_clear(share); /* Remove blocks from memory */
-#ifdef THREAD
thr_lock_delete(&share->lock);
mysql_mutex_destroy(&share->intern_lock);
-#endif
my_free(share->name);
my_free(share);
return;
diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c
index 9e9e28da335..ceba0fcf12e 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/heap/hp_open.c b/storage/heap/hp_open.c
index 12d9bfe1ed3..5ac4da22e0a 100644
--- a/storage/heap/hp_open.c
+++ b/storage/heap/hp_open.c
@@ -37,9 +37,7 @@ HP_INFO *heap_open_from_share(HP_SHARE *share, int mode)
DBUG_RETURN(0);
}
share->open_count++;
-#ifdef THREAD
thr_lock_data_init(&share->lock,&info->lock,NULL);
-#endif
info->s= share;
info->lastkey= (uchar*) (info + 1);
info->recbuf= (uchar*) (info->lastkey + share->max_key_length);
diff --git a/storage/heap/hp_static.c b/storage/heap/hp_static.c
index e1ca7d1f445..a58ecb8b754 100644
--- a/storage/heap/hp_static.c
+++ b/storage/heap/hp_static.c
@@ -25,7 +25,6 @@
LIST *heap_open_list=0,*heap_share_list=0;
#ifdef HAVE_PSI_INTERFACE
-#ifdef THREAD
PSI_mutex_key hp_key_mutex_HP_SHARE_intern_lock;
static PSI_mutex_info all_heap_mutexes[]=
@@ -36,11 +35,9 @@ static PSI_mutex_info all_heap_mutexes[]=
THR_LOCK_heap is part of mysys, not storage/heap.
*/
};
-#endif /* THREAD */
void init_heap_psi_keys()
{
-#ifdef THREAD
const char* category= "memory";
int count;
@@ -49,7 +46,6 @@ void init_heap_psi_keys()
count= array_elements(all_heap_mutexes);
PSI_server->register_mutex(category, all_heap_mutexes, count);
-#endif /* THREAD */
}
#endif /* HAVE_PSI_INTERFACE */
diff --git a/storage/heap/hp_test2.c b/storage/heap/hp_test2.c
index 3ee903be7ed..af388867c3c 100644
--- a/storage/heap/hp_test2.c
+++ b/storage/heap/hp_test2.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2003, 2006 MySQL AB
+/* Copyright (C) 2000, 2011, Oracle and/or its affiliates. All rights
+ reserved
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -656,11 +657,6 @@ static int rnd(int max_value)
static sig_handler endprog(int sig_number __attribute__((unused)))
{
-#ifndef THREAD
- if (my_dont_interrupt)
- my_remember_signal(sig_number,endprog);
- else
-#endif
{
hp_panic(HA_PANIC_CLOSE);
my_end(1);
diff --git a/storage/heap/plug.in b/storage/heap/plug.in
deleted file mode 100644
index 50f31c60f2b..00000000000
--- a/storage/heap/plug.in
+++ /dev/null
@@ -1,7 +0,0 @@
-MYSQL_STORAGE_ENGINE(heap,no, [Memory Storage Engine],
- [Volatile memory based tables])
-MYSQL_PLUGIN_DIRECTORY(heap, [storage/heap])
-MYSQL_PLUGIN_STATIC(heap, [libheap.a])
-MYSQL_PLUGIN_MANDATORY(heap) dnl Memory tables
-MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(heap, [ha_heap.cc])
-
diff --git a/storage/ibmdb2i/CMakeLists.txt b/storage/ibmdb2i/CMakeLists.txt
deleted file mode 100644
index 54da2b00ef2..00000000000
--- a/storage/ibmdb2i/CMakeLists.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software 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
-
-CHECK_INCLUDE_FILES(qlgusr.h HAVE_PASE_ENVIRONMENT)
-IF(HAVE_PASE_ENVIRONMENT)
-
-INCLUDE_DIRECTORIES(
- ${CMAKE_SOURCE_DIR}/include
- ${CMAKE_BINARY_DIR}/include
- ${CMAKE_SOURCE_DIR}/regex
- ${CMAKE_SOURCE_DIR}/sql
- ${CMAKE_CURRENT_SOURCE_DIR}
- /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0f.xpf/cur/cmvc/base.pgm/my.xpf/apis
- /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0.xpf/bld/cmvc/base.pgm/lg.xpf
- /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0.xpf/bld/cmvc/base.pgm/tq.xpf
-)
-
-
-SET (IBMDB2I_SOURCES ha_ibmdb2i.cc db2i_ileBridge.cc db2i_conversion.cc
- db2i_blobCollection.cc db2i_file.cc db2i_charsetSupport.cc
- db2i_collationSupport.cc db2i_errors.cc db2i_constraints.cc
- db2i_rir.cc db2i_sqlStatementStream.cc db2i_ioBuffers.cc db2i_myconv.cc)
-
-
-MYSQL_ADD_PLUGIN(ibmdb2i ${IBMDB2I_SOURCES} STORAGE_ENGINE LINK_LIBRARIES iconv)
-
-ENDIF(HAVE_PASE_ENVIRONMENT)
diff --git a/storage/ibmdb2i/Makefile.am b/storage/ibmdb2i/Makefile.am
deleted file mode 100644
index a9977de895d..00000000000
--- a/storage/ibmdb2i/Makefile.am
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# Copyright (c) 2007, 2008, IBM Corporation.
-# All rights reserved.
-#
-#
-
-#called from the top level Makefile
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-pkgplugindir = $(pkglibdir)/plugin
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir) \
- -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0f.xpf/cur/cmvc/base.pgm/my.xpf/apis \
- -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0.xpf/bld/cmvc/base.pgm/lg.xpf \
- -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0.xpf/bld/cmvc/base.pgm/tq.xpf
-WRAPLIBS=
-
-LDADD =
-
-DEFS = @DEFS@
-
-noinst_HEADERS = ha_ibmdb2i.h db2i_collationSupport.h db2i_file.h \
- db2i_ioBuffers.h db2i_blobCollection.h \
- db2i_global.h db2i_misc.h db2i_charsetSupport.h db2i_errors.h \
- db2i_iconv.h db2i_myconv.h db2i_safeString.h db2i_sqlStatementStream.h \
- db2i_ileBridge.h db2i_validatedPointer.h
-
-EXTRA_LTLIBRARIES = ha_ibmdb2i.la
-pkgplugin_LTLIBRARIES = @plugin_ibmdb2i_shared_target@
-ha_ibmdb2i_la_LIBADD = -liconv
-ha_ibmdb2i_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
-ha_ibmdb2i_la_CXXFLAGS= $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_ibmdb2i_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_ibmdb2i_la_SOURCES = ha_ibmdb2i.cc db2i_ileBridge.cc db2i_conversion.cc \
- db2i_blobCollection.cc db2i_file.cc db2i_charsetSupport.cc \
- db2i_collationSupport.cc db2i_errors.cc db2i_constraints.cc \
- db2i_rir.cc db2i_sqlStatementStream.cc db2i_ioBuffers.cc \
- db2i_myconv.cc
-
-EXTRA_LIBRARIES = libibmdb2i.a
-noinst_LIBRARIES = @plugin_ibmdb2i_static_target@
-libibmdb2i_a_CXXFLAGS = $(AM_CXXFLAGS)
-libibmdb2i_a_CFLAGS = $(AM_CFLAGS)
-libibmdb2i_a_SOURCES= $(ha_ibmdb2i_la_SOURCES)
-
-
-EXTRA_DIST = CMakeLists.txt plug.in
diff --git a/storage/ibmdb2i/db2i_blobCollection.cc b/storage/ibmdb2i/db2i_blobCollection.cc
deleted file mode 100644
index 17101c9c0a4..00000000000
--- a/storage/ibmdb2i/db2i_blobCollection.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#include "db2i_blobCollection.h"
-
-/**
- Return the size to use when allocating space for blob reads.
-
- @param fieldIndex The field to allocate for
- @param[out] shouldProtect Indicates whether storage protection should be
- applied to the space, because the size returned is
- smaller than the maximum possible size.
-*/
-
-uint32
-BlobCollection::getSizeToAllocate(int fieldIndex, bool& shouldProtect)
-{
- Field* field = table->getMySQLTable()->field[fieldIndex];
- uint fieldLength = field->max_display_length();
-
- if (fieldLength <= MAX_FULL_ALLOCATE_BLOB_LENGTH)
- {
- shouldProtect = false;
- return fieldLength;
- }
-
- shouldProtect = true;
-
- uint curMaxSize = table->getBlobFieldActualSize(fieldIndex);
-
- uint defaultAllocSize = min(defaultAllocation, fieldLength);
-
- return max(defaultAllocSize, curMaxSize);
-
-}
-
-void
-BlobCollection::generateBuffer(int fieldIndex)
-{
- DBUG_ASSERT(table->db2Field(fieldIndex).isBlob());
-
- bool protect;
- buffers[table->getBlobIdFromField(fieldIndex)].Malloc(getSizeToAllocate(fieldIndex, protect), protect);
-
- return;
-}
-
-/**
- Realloc the read buffer associated with a blob field.
-
- This is used when the previous allocation for a blob field is found to be
- too small (this is discovered when QMY_READ trips over the protected boundary
- page).
-
- @param fieldIndex The field to be reallocated
- @param size The size of buffer to allocate for this field.
-*/
-
-ValidatedPointer<char>&
-BlobCollection::reallocBuffer(int fieldIndex, size_t size)
-{
- ProtectedBuffer& buf = buffers[table->getBlobIdFromField(fieldIndex)];
- if (size <= buf.allocLen())
- return buf.ptr();
-
- table->updateBlobFieldActualSize(fieldIndex, size);
-
- DBUG_PRINT("BlobCollection::reallocBuffer",("PERF: reallocing %d to %d: ", fieldIndex, size));
-
- bool protect;
- buf.Free();
- buf.Malloc(getSizeToAllocate(fieldIndex, protect), protect);
- return buf.ptr();
-}
diff --git a/storage/ibmdb2i/db2i_blobCollection.h b/storage/ibmdb2i/db2i_blobCollection.h
deleted file mode 100644
index 6a60394555f..00000000000
--- a/storage/ibmdb2i/db2i_blobCollection.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#ifndef DB2I_BLOBCOLLECTION_H
-#define DB2I_BLOBCOLLECTION_H
-
-#include "db2i_global.h"
-#include "db2i_file.h"
-
-/**
- @class ProtectedBuffer
- @brief Implements memory management for (optionally) protected buffers.
-
- Buffers created with the protection option will have a guard page set on the
- page following requested allocation size. The side effect is that the actual
- allocation is up to 2*4096-1 bytes larger than the size requested by the
- using code.
-*/
-
-class ProtectedBuffer
-{
-public:
- ProtectedBuffer() : protectBuf(false)
- {;}
-
- void Malloc(size_t size, bool protect = false)
- {
- protectBuf = protect;
- bufptr.alloc(size + (protectBuf ? 0x1fff : 0x0));
- if ((void*)bufptr != NULL)
- {
- len = size;
- if (protectBuf)
- mprotect(protectedPage(), 0x1000, PROT_NONE);
-#ifndef DBUG_OFF
- // Prevents a problem with DBUG_PRINT over-reading in recent versions of
- // MySQL
- *((char*)protectedPage()-1) = 0;
-#endif
- }
- }
-
- void Free()
- {
- if ((void*)bufptr != NULL)
- {
- if (protectBuf)
- mprotect(protectedPage(), 0x1000, PROT_READ | PROT_WRITE);
- bufptr.dealloc();
- }
- }
-
- ~ProtectedBuffer()
- {
- Free();
- }
-
- ValidatedPointer<char>& ptr() {return bufptr;}
- bool isProtected() const {return protectBuf;}
- size_t allocLen() const {return len;}
-private:
- void* protectedPage()
- {
- return (void*)(((address64_t)(void*)bufptr + len + 0x1000) & ~0xfff);
- }
-
- ValidatedPointer<char> bufptr;
- size_t len;
- bool protectBuf;
-
-};
-
-
-/**
- @class BlobCollection
- @brief Manages memory allocation for reading blobs associated with a table.
-
- Allocations are done on-demand and are protected with a guard page if less
- than the max possible size is allocated.
-*/
-class BlobCollection
-{
- public:
- BlobCollection(db2i_table* db2Table, uint32 defaultAllocSize) :
- defaultAllocation(defaultAllocSize), table(db2Table)
- {
- buffers = new ProtectedBuffer[table->getBlobCount()];
- }
-
- ~BlobCollection()
- {
- delete[] buffers;
- }
-
- ValidatedPointer<char>& getBufferPtr(int fieldIndex)
- {
- int blobIndex = table->getBlobIdFromField(fieldIndex);
- if ((char*)buffers[blobIndex].ptr() == NULL)
- generateBuffer(fieldIndex);
-
- return buffers[blobIndex].ptr();
- }
-
- ValidatedPointer<char>& reallocBuffer(int fieldIndex, size_t size);
-
-
- private:
-
- uint32 getSizeToAllocate(int fieldIndex, bool& shouldProtect);
- void generateBuffer(int fieldIndex);
-
- db2i_table* table; // The table being read
- ProtectedBuffer* buffers; // The buffers
- uint32 defaultAllocation;
- /* The default size to use when first allocating a buffer */
-};
-
-#endif
diff --git a/storage/ibmdb2i/db2i_charsetSupport.cc b/storage/ibmdb2i/db2i_charsetSupport.cc
deleted file mode 100644
index f5a3a74025e..00000000000
--- a/storage/ibmdb2i/db2i_charsetSupport.cc
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-
-#include "db2i_charsetSupport.h"
-#include "as400_types.h"
-#include "as400_protos.h"
-#include "db2i_ileBridge.h"
-#include "qlgusr.h"
-#include "db2i_errors.h"
-
-
-/*
- The following arrays define a mapping between IANA-style text descriptors and
- IBM i CCSID text descriptors. The mapping is a 1-to-1 correlation between
- corresponding array slots.
-*/
-#define MAX_IANASTRING 23
-static const char ianaStringType[MAX_IANASTRING][10] =
-{
- {"ascii"},
- {"Big5"}, //big5
- {"cp1250"},
- {"cp1251"},
- {"cp1256"},
- {"cp850"},
- {"cp852"},
- {"cp866"},
- {"IBM943"}, //cp932
- {"EUC-KR"}, //euckr
- {"IBM1381"}, //gb2312
- {"IBM1386"}, //gbk
- {"greek"},
- {"hebrew"},
- {"latin1"},
- {"latin2"},
- {"latin5"},
- {"macce"},
- {"tis620"},
- {"Shift_JIS"}, //sjis
- {"ucs2"},
- {"EUC-JP"}, //ujis
- {"utf8"}
-};
-static const char ccsidType[MAX_IANASTRING][6] =
-{
- {"367"}, //ascii
- {"950"}, //big5
- {"1250"}, //cp1250
- {"1251"}, //cp1251
- {"1256"}, //cp1256
- {"850"}, //cp850
- {"852"}, //cp852
- {"866"}, //cp866
- {"943"}, //cp932
- {"970"}, //euckr
- {"1381"}, //gb2312
- {"1386"}, //gbk
- {"813"}, //greek
- {"916"}, //hebrew
- {"923"}, //latin1
- {"912"}, //latin2
- {"920"}, //latin5
- {"1282"}, //macce
- {"874"}, //tis620
- {"943"}, //sjis
- {"13488"},//ucs2
- {"5050"}, //ujis
- {"1208"} //utf8
-};
-
-static _ILEpointer *QlgCvtTextDescToDesc_sym;
-
-/* We keep a cache of the mapping for text descriptions obtained via
- QlgTextDescToDesc. The following structures implement this cache. */
-static HASH textDescMapHash;
-static MEM_ROOT textDescMapMemroot;
-static pthread_mutex_t textDescMapHashMutex;
-struct TextDescMap
-{
- struct HashKey
- {
- int32 inType;
- int32 outType;
- char inDesc[Qlg_MaxDescSize];
- } hashKey;
- char outDesc[Qlg_MaxDescSize];
-};
-
-/* We keep a cache of the mapping for open iconv descriptors. The following
- structures implement this cache. */
-static HASH iconvMapHash;
-static MEM_ROOT iconvMapMemroot;
-static pthread_mutex_t iconvMapHashMutex;
-struct IconvMap
-{
- struct HashKey
- {
- uint32 direction; // These are uint32s to avoid garbage data in the key from compiler padding
- uint32 db2CCSID;
- const CHARSET_INFO* myCharset;
- } hashKey;
- iconv_t iconvDesc;
-};
-
-
-/**
- Initialize the static structures used by this module.
-
- This must only be called once per plugin instantiation.
-
- @return 0 if successful. Failure otherwise
-*/
-int32 initCharsetSupport()
-{
- DBUG_ENTER("initCharsetSupport");
-
- int actmark = _ILELOAD("QSYS/QLGUSR", ILELOAD_LIBOBJ);
- if ( actmark == -1 )
- {
- DBUG_PRINT("initCharsetSupport", ("conversion srvpgm activation failed"));
- DBUG_RETURN(1);
- }
-
- QlgCvtTextDescToDesc_sym = (ILEpointer*)malloc_aligned(sizeof(ILEpointer));
- if (_ILESYM(QlgCvtTextDescToDesc_sym, actmark, "QlgCvtTextDescToDesc") == -1)
- {
- DBUG_PRINT("initCharsetSupport",
- ("resolve of QlgCvtTextDescToDesc failed"));
- DBUG_RETURN(errno);
- }
-
- VOID(pthread_mutex_init(&textDescMapHashMutex,MY_MUTEX_INIT_FAST));
- my_hash_init(&textDescMapHash, &my_charset_bin, 10, offsetof(TextDescMap, hashKey), sizeof(TextDescMap::hashKey), 0, 0, HASH_UNIQUE);
-
- VOID(pthread_mutex_init(&iconvMapHashMutex,MY_MUTEX_INIT_FAST));
- my_hash_init(&iconvMapHash, &my_charset_bin, 10, offsetof(IconvMap, hashKey), sizeof(IconvMap::hashKey), 0, 0, HASH_UNIQUE);
-
- init_alloc_root(&textDescMapMemroot, 2048, 0);
- init_alloc_root(&iconvMapMemroot, 256, 0);
-
- initMyconv();
-
- DBUG_RETURN(0);
-}
-
-/**
- Cleanup the static structures used by this module.
-
- This must only be called once per plugin instantiation and only if
- initCharsetSupport() was successful.
-*/
-void doneCharsetSupport()
-{
- cleanupMyconv();
-
- free_root(&textDescMapMemroot, 0);
- free_root(&iconvMapMemroot, 0);
-
- pthread_mutex_destroy(&textDescMapHashMutex);
- my_hash_free(&textDescMapHash);
- pthread_mutex_destroy(&iconvMapHashMutex);
- my_hash_free(&iconvMapHash);
- free_aligned(QlgCvtTextDescToDesc_sym);
-}
-
-
-/**
- Convert a text description from one type to another.
-
- This function is just a wrapper for the IBM i QlgTextDescToDesc function plus
- some overrides for conversions that the API does not handle correctly and
- support for caching the computed conversion.
-
- @param inType The type of descriptor pointed to by "in".
- @param outType The type of descriptor requested for "out".
- @param in The descriptor to be convereted.
- @param[out] out The equivalent descriptor
- @param hashKey The hash key to be used for caching the conversion result.
-
- @return 0 if successful. Failure otherwise
-*/
-static int32 getNewTextDesc(const int32 inType,
- const int32 outType,
- const char* in,
- char* out,
- const TextDescMap::HashKey* hashKey)
-{
- DBUG_ENTER("db2i_charsetSupport::getNewTextDesc");
- const arg_type_t signature[] = { ARG_INT32, ARG_INT32, ARG_MEMPTR, ARG_INT32, ARG_MEMPTR, ARG_INT32, ARG_INT32, ARG_END };
- struct ArgList
- {
- ILEarglist_base base;
- int32 CRDIInType;
- int32 CRDIOutType;
- ILEpointer CRDIDesc;
- int32 CRDIDescSize;
- ILEpointer CRDODesc;
- int32 CRDODescSize;
- int32 CTDCCSID;
- } *arguments;
-
- if ((inType == Qlg_TypeIANA) && (outType == Qlg_TypeAix41))
- {
- // Override non-standard charsets
- if (unlikely(strcmp("IBM1381", in) == 0))
- {
- strcpy(out, "IBM-1381");
- DBUG_RETURN(0);
- }
- }
- else if ((inType == Qlg_TypeAS400CCSID) && (outType == Qlg_TypeAix41))
- {
- // Override non-standard charsets
- if (strcmp("1148", in) == 0)
- {
- strcpy(out, "IBM-1148");
- DBUG_RETURN(0);
- }
- else if (unlikely(strcmp("1153", in) == 0))
- {
- strcpy(out, "IBM-1153");
- DBUG_RETURN(0);
- }
- }
-
- char argBuf[sizeof(ArgList)+15];
- arguments = (ArgList*)roundToQuadWordBdy(argBuf);
-
- arguments->CRDIInType = inType;
- arguments->CRDIOutType = outType;
- arguments->CRDIDesc.s.addr = (address64_t) in;
- arguments->CRDIDescSize = Qlg_MaxDescSize;
- arguments->CRDODesc.s.addr = (address64_t) out;
- arguments->CRDODescSize = Qlg_MaxDescSize;
- arguments->CTDCCSID = 819;
- _ILECALL(QlgCvtTextDescToDesc_sym,
- &arguments->base,
- signature,
- RESULT_INT32);
- if (unlikely(arguments->base.result.s_int32.r_int32 < 0))
- {
- if (arguments->base.result.s_int32.r_int32 == Qlg_InDescriptorNotFound)
- {
- DBUG_RETURN(DB2I_ERR_UNSUPP_CHARSET);
- }
- else
- {
- getErrTxt(DB2I_ERR_ILECALL,"QlgCvtTextDescToDesc",arguments->base.result.s_int32.r_int32);
- DBUG_RETURN(DB2I_ERR_ILECALL);
- }
- }
-
- // Store the conversion information into a cache entry
- TextDescMap* mapping = (TextDescMap*)alloc_root(&textDescMapMemroot, sizeof(TextDescMap));
- if (unlikely(!mapping))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- memcpy(&(mapping->hashKey), hashKey, sizeof(hashKey));
- strcpy(mapping->outDesc, out);
- pthread_mutex_lock(&textDescMapHashMutex);
- my_hash_insert(&textDescMapHash, (const uchar*)mapping);
- pthread_mutex_unlock(&textDescMapHashMutex);
-
- DBUG_RETURN(0);
-}
-
-
-/**
- Convert a text description from one type to another.
-
- This function takes a text description in one representation and converts
- it into another representation. Although the OS provides some facilities for
- doing this, the support is not complete, nor does MySQL always use standard
- identifiers. Therefore, there are a lot of hardcoded overrides required.
- There is probably some room for optimization here, but this should not be
- called frequently under most circumstances.
-
- @param inType The type of descriptor pointed to by "in".
- @param outType The type of descriptor requested for "out".
- @param in The descriptor to be convereted.
- @param[out] out The equivalent descriptor
-
- @return 0 if successful. Failure otherwise
-*/
-static int32 convertTextDesc(const int32 inType, const int32 outType, const char* inDesc, char* outDesc)
-{
- DBUG_ENTER("db2i_charsetSupport::convertTextDesc");
- const char* inDescOverride;
-
- if (inType == Qlg_TypeIANA)
- {
- // Override non-standard charsets
- if (strcmp("big5", inDesc) == 0)
- inDescOverride = "Big5";
- else if (strcmp("cp932", inDesc) == 0)
- inDescOverride = "IBM943";
- else if (strcmp("euckr", inDesc) == 0)
- inDescOverride = "EUC-KR";
- else if (strcmp("gb2312", inDesc) == 0)
- inDescOverride = "IBM1381";
- else if (strcmp("gbk", inDesc) == 0)
- inDescOverride = "IBM1386";
- else if (strcmp("sjis", inDesc) == 0)
- inDescOverride = "Shift_JIS";
- else if (strcmp("ujis", inDesc) == 0)
- inDescOverride = "EUC-JP";
- else
- inDescOverride = inDesc;
-
- // Hardcode non-standard charsets
- if (outType == Qlg_TypeAix41)
- {
- if (strcmp("Big5", inDescOverride) == 0)
- {
- strcpy(outDesc,"big5");
- DBUG_RETURN(0);
- }
- else if (strcmp("IBM1386", inDescOverride) == 0)
- {
- strcpy(outDesc,"GBK");
- DBUG_RETURN(0);
- }
- else if (strcmp("Shift_JIS", inDescOverride) == 0 ||
- strcmp("IBM943", inDescOverride) == 0)
- {
- strcpy(outDesc,"IBM-943");
- DBUG_RETURN(0);
- }
- else if (strcmp("tis620", inDescOverride) == 0)
- {
- strcpy(outDesc,"TIS-620");
- DBUG_RETURN(0);
- }
- else if (strcmp("ucs2", inDescOverride) == 0)
- {
- strcpy(outDesc,"UCS-2");
- DBUG_RETURN(0);
- }
- else if (strcmp("cp1250", inDescOverride) == 0)
- {
- strcpy(outDesc,"IBM-1250");
- DBUG_RETURN(0);
- }
- else if (strcmp("cp1251", inDescOverride) == 0)
- {
- strcpy(outDesc,"IBM-1251");
- DBUG_RETURN(0);
- }
- else if (strcmp("cp1256", inDescOverride) == 0)
- {
- strcpy(outDesc,"IBM-1256");
- DBUG_RETURN(0);
- }
- else if (strcmp("macce", inDescOverride) == 0)
- {
- strcpy(outDesc,"IBM-1282");
- DBUG_RETURN(0);
- }
- }
- else if (outType == Qlg_TypeAS400CCSID)
- {
- // See if we can fast path the convert
- for (int loopCnt = 0; loopCnt < MAX_IANASTRING; ++loopCnt)
- {
- if (strcmp((char*)ianaStringType[loopCnt],inDescOverride) == 0)
- {
- strcpy(outDesc,ccsidType[loopCnt]);
- DBUG_RETURN(0);
- }
- }
- }
- }
- else
- inDescOverride = inDesc;
-
- // We call getNewTextDesc for all other conversions and cache the result.
- TextDescMap *mapping;
- TextDescMap::HashKey hashKey;
- hashKey.inType= inType;
- hashKey.outType= outType;
- uint32 len = strlen(inDescOverride);
- memcpy(hashKey.inDesc, inDescOverride, len);
- memset(hashKey.inDesc+len, 0, sizeof(hashKey.inDesc) - len);
-
- if (!(mapping=(TextDescMap *) my_hash_search(&textDescMapHash,
- (const uchar*)&hashKey,
- sizeof(hashKey))))
- {
- DBUG_RETURN(getNewTextDesc(inType, outType, inDescOverride, outDesc, &hashKey));
- }
- else
- {
- strcpy(outDesc, mapping->outDesc);
- }
- DBUG_RETURN(0);
-}
-
-
-/**
- Convert an IANA character set name into a DB2 for i CCSID value.
-
- @param parmIANADesc An IANA character set name
- @param[out] db2Ccsid The equivalent CCSID value
-
- @return 0 if successful. Failure otherwise
-*/
-int32 convertIANAToDb2Ccsid(const char* parmIANADesc, uint16* db2Ccsid)
-{
- int32 rc;
- uint16 aixCcsid;
- char aixCcsidString[Qlg_MaxDescSize];
- int aixEncodingScheme;
- int db2EncodingScheme;
- rc = convertTextDesc(Qlg_TypeIANA, Qlg_TypeAS400CCSID, parmIANADesc, aixCcsidString);
- if (unlikely(rc))
- {
- if (rc == DB2I_ERR_UNSUPP_CHARSET)
- getErrTxt(DB2I_ERR_UNSUPP_CHARSET, parmIANADesc);
-
- return rc;
- }
- aixCcsid = atoi(aixCcsidString);
- rc = getEncodingScheme(aixCcsid, aixEncodingScheme);
- if (rc != 0)
- return rc;
- switch(aixEncodingScheme) { // Select on encoding scheme
- case 0x1100: // EDCDIC SBCS
- case 0x2100: // ASCII SBCS
- case 0x4100: // AIX SBCS
- case 0x4105: // MS Windows
- case 0x5100: // ISO 7 bit ASCII
- db2EncodingScheme = 0x1100;
- break;
- case 0x1200: // EDCDIC DBCS
- case 0x2200: // ASCII DBCS
- db2EncodingScheme = 0x1200;
- break;
- case 0x1301: // EDCDIC Mixed
- case 0x2300: // ASCII Mixed
- case 0x4403: // EUC (ISO 2022)
- db2EncodingScheme = 0x1301;
- break;
- case 0x7200: // UCS2
- db2EncodingScheme = 0x7200;
- break;
- case 0x7807: // UTF-8
- db2EncodingScheme = 0x7807;
- break;
- case 0x7500: // UTF-32
- db2EncodingScheme = 0x7500;
- break;
- default: // Unknown
- {
- getErrTxt(DB2I_ERR_UNKNOWN_ENCODING,aixEncodingScheme);
- return DB2I_ERR_UNKNOWN_ENCODING;
- }
- break;
- }
- if (aixEncodingScheme == db2EncodingScheme)
- {
- *db2Ccsid = aixCcsid;
- }
- else
- {
- rc = getAssociatedCCSID(aixCcsid, db2EncodingScheme, db2Ccsid); // EDCDIC SBCS
- if (rc != 0)
- return rc;
- }
-
- return 0;
-}
-
-
-/**
- Obtain the encoding scheme of a CCSID.
-
- @param inCcsid An IBM i CCSID
- @param[out] outEncodingScheme The associated encoding scheme
-
- @return 0 if successful. Failure otherwise
-*/
-int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme)
-{
- DBUG_ENTER("db2i_charsetSupport::getEncodingScheme");
-
- static bool ptrInited = FALSE;
- static char ptrSpace[sizeof(ILEpointer) + 15];
- static ILEpointer* ptrToPtr = (ILEpointer*)roundToQuadWordBdy(ptrSpace);
- int rc;
-
- if (!ptrInited)
- {
- rc = _RSLOBJ2(ptrToPtr, RSLOBJ_TS_PGM, "QTQGESP", "QSYS");
-
- if (rc)
- {
- getErrTxt(DB2I_ERR_RESOLVE_OBJ,"QTQGESP","QSYS","*PGM",errno);
- DBUG_RETURN(DB2I_ERR_RESOLVE_OBJ);
- }
- ptrInited = TRUE;
- }
-
- DBUG_ASSERT(inCcsid != 0);
-
- int GESPCCSID = inCcsid;
- int GESPLen = 32;
- int GESPNbrVal = 0;
- int32 GESPES;
- int GESPCSCPL[32];
- int GESPFB[3];
- void* ILEArgv[7];
- ILEArgv[0] = &GESPCCSID;
- ILEArgv[1] = &GESPLen;
- ILEArgv[2] = &GESPNbrVal;
- ILEArgv[3] = &GESPES;
- ILEArgv[4] = &GESPCSCPL;
- ILEArgv[5] = &GESPFB;
- ILEArgv[6] = NULL;
-
- rc = _PGMCALL(ptrToPtr, (void**)&ILEArgv, 0);
-
- if (rc)
- {
- getErrTxt(DB2I_ERR_PGMCALL,"QTQGESP","QSYS",rc);
- DBUG_RETURN(DB2I_ERR_PGMCALL);
- }
- if (GESPFB[0] != 0 ||
- GESPFB[1] != 0 ||
- GESPFB[2] != 0)
- {
- getErrTxt(DB2I_ERR_QTQGESP,GESPFB[0],GESPFB[1],GESPFB[2]);
- DBUG_RETURN(DB2I_ERR_QTQGESP);
- }
- outEncodingScheme = GESPES;
-
- DBUG_RETURN(0);
-}
-
-
-/**
- Get the best fit equivalent CCSID. (Wrapper for QTQGRDC API)
-
- @param inCcsid An IBM i CCSID
- @param inEncodingScheme The encoding scheme
- @param[out] outCcsid The equivalent CCSID
-
- @return 0 if successful. Failure otherwise
-*/
-int32 getAssociatedCCSID(const uint16 inCcsid, const int inEncodingScheme, uint16* outCcsid)
-{
- DBUG_ENTER("db2i_charsetSupport::getAssociatedCCSID");
- static bool ptrInited = FALSE;
- static char ptrSpace[sizeof(ILEpointer) + 15];
- static ILEpointer* ptrToPtr = (ILEpointer*)roundToQuadWordBdy(ptrSpace);
- int rc;
-
- // Override non-standard charsets
- if ((inCcsid == 923) && (inEncodingScheme == 0x1100))
- {
- *outCcsid = 1148;
- DBUG_RETURN(0);
- }
- else if ((inCcsid == 1250) && (inEncodingScheme == 0x1100))
- {
- *outCcsid = 1153;
- DBUG_RETURN(0);
- }
-
- if (!ptrInited)
- {
- rc = _RSLOBJ2(ptrToPtr, RSLOBJ_TS_PGM, "QTQGRDC", "QSYS");
-
- if (rc)
- {
- getErrTxt(DB2I_ERR_RESOLVE_OBJ,"QTQGRDC","QSYS","*PGM",errno);
- DBUG_RETURN(DB2I_ERR_RESOLVE_OBJ);
- }
- ptrInited = TRUE;
- }
-
- int GRDCCCSID = inCcsid;
- int GRDCES = inEncodingScheme;
- int GRDCSel = 0;
- int GRDCAssCCSID;
- int GRDCFB[3];
- void* ILEArgv[7];
- ILEArgv[0] = &GRDCCCSID;
- ILEArgv[1] = &GRDCES;
- ILEArgv[2] = &GRDCSel;
- ILEArgv[3] = &GRDCAssCCSID;
- ILEArgv[4] = &GRDCFB;
- ILEArgv[5] = NULL;
-
- rc = _PGMCALL(ptrToPtr, (void**)&ILEArgv, 0);
-
- if (rc)
- {
- getErrTxt(DB2I_ERR_PGMCALL,"QTQGRDC","QSYS",rc);
- DBUG_RETURN(DB2I_ERR_PGMCALL);
- }
- if (GRDCFB[0] != 0 ||
- GRDCFB[1] != 0 ||
- GRDCFB[2] != 0)
- {
- getErrTxt(DB2I_ERR_QTQGRDC,GRDCFB[0],GRDCFB[1],GRDCFB[2]);
- DBUG_RETURN(DB2I_ERR_QTQGRDC);
- }
-
- *outCcsid = GRDCAssCCSID;
-
- DBUG_RETURN(0);
-}
-
-/**
- Open an iconv conversion between a MySQL charset and the respective IBM i CCSID
-
- @param direction The direction of the conversion
- @param mysqlCSName Name of the MySQL character set
- @param db2CCSID The IBM i CCSID
- @param hashKey The key to use for inserting the opened conversion into the cache
- @param[out] newConversion The iconv descriptor
-
- @return 0 if successful. Failure otherwise
-*/
-static int32 openNewConversion(enum_conversionDirection direction,
- const char* mysqlCSName,
- uint16 db2CCSID,
- IconvMap::HashKey* hashKey,
- iconv_t& newConversion)
-{
- DBUG_ENTER("db2i_charsetSupport::openNewConversion");
-
- char mysqlAix41Desc[Qlg_MaxDescSize];
- char db2Aix41Desc[Qlg_MaxDescSize];
- char db2CcsidString[6] = "";
- int32 rc;
-
- /*
- First we have to convert the MySQL IANA-like name and the DB2 CCSID into
- there equivalent iconv descriptions.
- */
- rc = convertTextDesc(Qlg_TypeIANA, Qlg_TypeAix41, mysqlCSName, mysqlAix41Desc);
- if (unlikely(rc))
- {
- if (rc == DB2I_ERR_UNSUPP_CHARSET)
- getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName);
-
- DBUG_RETURN(rc);
- }
- CHARSET_INFO *cs= &my_charset_bin;
- (uint)(cs->cset->long10_to_str)(cs,db2CcsidString,sizeof(db2CcsidString), 10, db2CCSID);
- rc = convertTextDesc(Qlg_TypeAS400CCSID, Qlg_TypeAix41, db2CcsidString, db2Aix41Desc);
- if (unlikely(rc))
- {
- if (rc == DB2I_ERR_UNSUPP_CHARSET)
- getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName);
-
- DBUG_RETURN(rc);
- }
-
- /* Call iconv to open the conversion. */
- if (direction == toDB2)
- {
- newConversion = iconv_open(db2Aix41Desc, mysqlAix41Desc);
- }
- else
- {
- newConversion = iconv_open(mysqlAix41Desc, db2Aix41Desc);
- }
-
- if (unlikely(newConversion == (iconv_t) -1))
- {
- getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName);
- DBUG_RETURN(DB2I_ERR_UNSUPP_CHARSET);
- }
-
- /* Insert the new conversion into the cache. */
- IconvMap* mapping = (IconvMap*)alloc_root(&iconvMapMemroot, sizeof(IconvMap));
- if (!mapping)
- {
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(IconvMap));
- DBUG_RETURN( HA_ERR_OUT_OF_MEM);
- }
- memcpy(&(mapping->hashKey), hashKey, sizeof(mapping->hashKey));
- mapping->iconvDesc = newConversion;
- pthread_mutex_lock(&iconvMapHashMutex);
- my_hash_insert(&iconvMapHash, (const uchar*)mapping);
- pthread_mutex_unlock(&iconvMapHashMutex);
-
- DBUG_RETURN(0);
-}
-
-
-/**
- Open an iconv conversion between a MySQL charset and the respective IBM i CCSID
-
- @param direction The direction of the conversion
- @param cs The MySQL character set
- @param db2CCSID The IBM i CCSID
- @param[out] newConversion The iconv descriptor
-
- @return 0 if successful. Failure otherwise
-*/
-int32 getConversion(enum_conversionDirection direction, const CHARSET_INFO* cs, uint16 db2CCSID, iconv_t& conversion)
-{
- DBUG_ENTER("db2i_charsetSupport::getConversion");
-
- int32 rc;
-
- /* Build the hash key */
- IconvMap::HashKey hashKey;
- hashKey.direction= direction;
- hashKey.myCharset= cs;
- hashKey.db2CCSID= db2CCSID;
-
- /* Look for the conversion in the cache and add it if it is not there. */
- IconvMap *mapping;
- if (!(mapping= (IconvMap *) my_hash_search(&iconvMapHash,
- (const uchar*)&hashKey,
- sizeof(hashKey))))
- {
- DBUG_PRINT("getConversion", ("Hash miss for direction=%d, cs=%s, ccsid=%d", direction, cs->name, db2CCSID));
- rc= openNewConversion(direction, cs->csname, db2CCSID, &hashKey, conversion);
- if (rc)
- DBUG_RETURN(rc);
- }
- else
- {
- conversion= mapping->iconvDesc;
- }
-
- DBUG_RETURN(0);
-}
-
-/**
- Fast-path conversion from ASCII to EBCDIC for use in converting
- identifiers to be sent to the QMY APIs.
-
- @param input ASCII data
- @param[out] ouput EBCDIC data
- @param ilen Size of input buffer and output buffer
-*/
-int convToEbcdic(const char* input, char* output, size_t ilen)
-{
- static bool inited = FALSE;
- static iconv_t ic;
-
- if (ilen == 0)
- return 0;
-
- if (!inited)
- {
- ic = iconv_open( "IBM-037", "ISO8859-1" );
- inited = TRUE;
- }
- size_t substitutedChars;
- size_t olen = ilen;
- if (iconv( ic, (char**)&input, &ilen, &output, &olen, &substitutedChars ) == -1)
- return errno;
-
- return 0;
-}
-
-
-/**
- Fast-path conversion from EBCDIC to ASCII for use in converting
- data received from the QMY APIs.
-
- @param input EBCDIC data
- @param[out] ouput ASCII data
- @param ilen Size of input buffer and output buffer
-*/
-int convFromEbcdic(const char* input, char* output, size_t ilen)
-{
- static bool inited = FALSE;
- static iconv_t ic;
-
- if (ilen == 0)
- return 0;
-
- if (!inited)
- {
- ic = iconv_open("ISO8859-1", "IBM-037");
- inited = TRUE;
- }
-
- size_t substitutedChars;
- size_t olen = ilen;
- if (iconv( ic, (char**)&input, &ilen, &output, &olen, &substitutedChars) == -1)
- return errno;
-
- return 0;
-}
diff --git a/storage/ibmdb2i/db2i_charsetSupport.h b/storage/ibmdb2i/db2i_charsetSupport.h
deleted file mode 100644
index 77051e1e0db..00000000000
--- a/storage/ibmdb2i/db2i_charsetSupport.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#ifndef DB2I_CHARSETSUPPORT_H
-#define DB2I_CHARSETSUPPORT_H
-
-#include "db2i_global.h"
-#include "mysql_priv.h"
-#include <mysql/plugin.h>
-#include "db2i_iconv.h"
-
-/**
- @enum enum_conversionDirection
-
- Conversion directions for getConversion()
-*/
-enum enum_conversionDirection
-{
- toMySQL,
- toDB2
-};
-
-int initCharsetSupport();
-void doneCharsetSupport();
-int32 convertIANAToDb2Ccsid(const char* parmIANADesc, uint16* db2Ccsid);
-int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme);
-int32 getAssociatedCCSID(const uint16 inCcsid, const int inEncodingScheme, uint16* outCcsid);
-int convToEbcdic(const char* input, char* output, size_t ilen);
-int convFromEbcdic(const char* input, char* output, size_t ilen);
-int32 getConversion(enum_conversionDirection direction, const CHARSET_INFO* cs, uint16 db2CCSID, iconv_t& conversion);
-
-#endif
diff --git a/storage/ibmdb2i/db2i_collationSupport.cc b/storage/ibmdb2i/db2i_collationSupport.cc
deleted file mode 100644
index 65a17fd2452..00000000000
--- a/storage/ibmdb2i/db2i_collationSupport.cc
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#include "db2i_collationSupport.h"
-#include "db2i_errors.h"
-
-
-/*
- The following arrays define a mapping between MySQL collation names and
- corresponding IBM i sort sequences. The mapping is a 1-to-1 correlation
- between corresponding array slots but is incomplete without case-sensitivity
- markers dynamically added to the mySqlSortSequence names.
-*/
-#define MAX_COLLATION 87
-static const char* mySQLCollation[MAX_COLLATION] =
-{
- {"ascii_general"},
- {"ascii"},
- {"big5_chinese"},
- {"big5"},
- {"cp1250_croatian"},
- {"cp1250_general"},
- {"cp1250_polish"},
- {"cp1250"},
- {"cp1251_bulgarian"},
- {"cp1251_general"},
- {"cp1251"},
- {"cp1256_general"},
- {"cp1256"},
- {"cp850_general"},
- {"cp850"},
- {"cp852_general"},
- {"cp852"},
- {"cp932_japanese"},
- {"cp932"},
- {"euckr_korean"},
- {"euckr"},
- {"gb2312_chinese"},
- {"gb2312"},
- {"gbk_chinese"},
- {"gbk"},
- {"greek_general"},
- {"greek"},
- {"hebrew_general"},
- {"hebrew"},
- {"latin1_danish"},
- {"latin1_general"},
- {"latin1_german1"},
- {"latin1_spanish"},
- {"latin1_swedish"},
- {"latin1"},
- {"latin2_croatian"},
- {"latin2_general"},
- {"latin2_hungarian"},
- {"latin2"},
- {"latin5_turkish"},
- {"latin5"},
- {"macce_general"},
- {"macce"},
- {"sjis_japanese"},
- {"sjis"},
- {"tis620_thai"},
- {"tis620"},
- {"ucs2_czech"},
- {"ucs2_danish"},
- {"ucs2_esperanto"},
- {"ucs2_estonian"},
- {"ucs2_general"},
- {"ucs2_hungarian"},
- {"ucs2_icelandic"},
- {"ucs2_latvian"},
- {"ucs2_lithuanian"},
- {"ucs2_persian"},
- {"ucs2_polish"},
- {"ucs2_romanian"},
- {"ucs2_slovak"},
- {"ucs2_slovenian"},
- {"ucs2_spanish"},
- {"ucs2_swedish"},
- {"ucs2_turkish"},
- {"ucs2_unicode"},
- {"ucs2"},
- {"ujis_japanese"},
- {"ujis"},
- {"utf8_czech"},
- {"utf8_danish"},
- {"utf8_esperanto"},
- {"utf8_estonian"},
- {"utf8_general"},
- {"utf8_hungarian"},
- {"utf8_icelandic"},
- {"utf8_latvian"},
- {"utf8_lithuanian"},
- {"utf8_persian"},
- {"utf8_polish"},
- {"utf8_romanian"},
- {"utf8_slovak"},
- {"utf8_slovenian"},
- {"utf8_spanish"},
- {"utf8_swedish"},
- {"utf8_turkish"},
- {"utf8_unicode"},
- {"utf8"}
-};
-
-
-static const char* mySqlSortSequence[MAX_COLLATION] =
-{
- {"QALA101F4"},
- {"QBLA101F4"},
- {"QACHT04B0"},
- {"QBCHT04B0"},
- {"QALA20481"},
- {"QCLA20481"},
- {"QDLA20481"},
- {"QELA20481"},
- {"QACYR0401"},
- {"QBCYR0401"},
- {"QCCYR0401"},
- {"QAARA01A4"},
- {"QBARA01A4"},
- {"QCLA101F4"},
- {"QDLA101F4"},
- {"QALA20366"},
- {"QBLA20366"},
- {"QAJPN04B0"},
- {"QBJPN04B0"},
- {"QAKOR04B0"},
- {"QBKOR04B0"},
- {"QACHS04B0"},
- {"QBCHS04B0"},
- {"QCCHS04B0"},
- {"QDCHS04B0"},
- {"QAELL036B"},
- {"QBELL036B"},
- {"QAHEB01A8"},
- {"QBHEB01A8"},
- {"QALA1047C"},
- {"QBLA1047C"},
- {"QCLA1047C"},
- {"QDLA1047C"},
- {"QELA1047C"},
- {"QFLA1047C"},
- {"QCLA20366"},
- {"QELA20366"},
- {"QFLA20366"},
- {"QGLA20366"},
- {"QATRK0402"},
- {"QBTRK0402"},
- {"QHLA20366"},
- {"QILA20366"},
- {"QCJPN04B0"},
- {"QDJPN04B0"},
- {"QATHA0346"},
- {"QBTHA0346"},
- {"ACS_CZ"},
- {"ADA_DK"},
- {"AEO"},
- {"AET"},
- {"QAUCS04B0"},
- {"AHU"},
- {"AIS"},
- {"ALV"},
- {"ALT"},
- {"AFA"},
- {"APL"},
- {"ARO"},
- {"ASK"},
- {"ASL"},
- {"AES"},
- {"ASW"},
- {"ATR"},
- {"AEN"},
- {"*HEX"},
- {"QEJPN04B0"},
- {"QFJPN04B0"},
- {"ACS_CZ"},
- {"ADA_DK"},
- {"AEO"},
- {"AET"},
- {"QAUCS04B0"},
- {"AHU"},
- {"AIS"},
- {"ALV"},
- {"ALT"},
- {"AFA"},
- {"APL"},
- {"ARO"},
- {"ASK"},
- {"ASL"},
- {"AES"},
- {"ASW"},
- {"ATR"},
- {"AEN"},
- {"*HEX"}
-};
-
-
-/**
- Get the IBM i sort sequence that corresponds to the given MySQL collation.
-
- @param fieldCharSet The collated character set
- @param[out] rtnSortSequence The corresponding sort sequence
-
- @return 0 if successful. Failure otherwise
-*/
-static int32 getAssociatedSortSequence(const CHARSET_INFO *fieldCharSet, const char** rtnSortSequence)
-{
- DBUG_ENTER("ha_ibmdb2i::getAssociatedSortSequence");
-
- if (strcmp(fieldCharSet->csname,"binary") != 0)
- {
- int collationSearchLen = strlen(fieldCharSet->name);
- if (fieldCharSet->state & MY_CS_BINSORT)
- collationSearchLen -= 4;
- else
- collationSearchLen -= 3;
-
- uint16 loopCnt = 0;
- for (loopCnt; loopCnt < MAX_COLLATION; ++loopCnt)
- {
- if ((strlen(mySQLCollation[loopCnt]) == collationSearchLen) &&
- (strncmp((char*)mySQLCollation[loopCnt], fieldCharSet->name, collationSearchLen) == 0))
- break;
- }
- if (loopCnt == MAX_COLLATION) // Did not find associated sort sequence
- {
- getErrTxt(DB2I_ERR_SRTSEQ);
- DBUG_RETURN(DB2I_ERR_SRTSEQ);
- }
- *rtnSortSequence = mySqlSortSequence[loopCnt];
- }
-
- DBUG_RETURN(0);
-}
-
-
-/**
- Update sort sequence information for a key.
-
- This function accumulates information about a key as it is called for each
- field composing the key. The caller should invoke the function for each field
- and (with the exception of the charset parm) preserve the values for the
- parms across invocations, until a particular key has been evaluated. Once
- the last field in the key has been evaluated, the fileSortSequence and
- fileSortSequenceLibrary parms will contain the correct information for
- creating the corresponding DB2 key.
-
- @param charset The character set under consideration
- @param[in, out] fileSortSequenceType The type of the current key's sort seq
- @param[in, out] fileSortSequence The IBM i identifier for the DB2 sort sequence
- that corresponds
-
- @return 0 if successful. Failure otherwise
-*/
-int32 updateAssociatedSortSequence(const CHARSET_INFO* charset,
- char* fileSortSequenceType,
- char* fileSortSequence,
- char* fileSortSequenceLibrary)
-{
- DBUG_ENTER("ha_ibmdb2i::updateAssociatedSortSequence");
- DBUG_ASSERT(charset);
- if (strcmp(charset->csname,"binary") != 0)
- {
- char newSortSequence[11] = "";
- char newSortSequenceType = ' ';
- const char* foundSortSequence;
- int rc = getAssociatedSortSequence(charset, &foundSortSequence);
- if (rc) DBUG_RETURN (rc);
- switch(foundSortSequence[0])
- {
- case '*': // Binary
- strcat(newSortSequence,foundSortSequence);
- newSortSequenceType = 'B';
- break;
- case 'Q': // Non-ICU sort sequence
- strcat(newSortSequence,foundSortSequence);
- if ((charset->state & MY_CS_BINSORT) != 0)
- {
- strcat(newSortSequence,"U");
- }
- else if ((charset->state & MY_CS_CSSORT) != 0)
- {
- strcat(newSortSequence,"U");
- }
- else
- {
- strcat(newSortSequence,"S");
- }
- newSortSequenceType = 'N';
- break;
- default: // ICU sort sequence
- {
- if ((charset->state & MY_CS_CSSORT) == 0)
- {
- if (osVersion.v >= 6)
- strcat(newSortSequence,"I34"); // ICU 3.4
- else
- strcat(newSortSequence,"I26"); // ICU 2.6.1
- }
- strcat(newSortSequence,foundSortSequence);
- newSortSequenceType = 'I';
- }
- break;
- }
- if (*fileSortSequenceType == ' ') // If no sort sequence has been set yet
- {
- // Set associated sort sequence
- strcpy(fileSortSequence,newSortSequence);
- strcpy(fileSortSequenceLibrary,"QSYS");
- *fileSortSequenceType = newSortSequenceType;
- }
- else if (strcmp(fileSortSequence,newSortSequence) != 0)
- {
- // Only one sort sequence/collation is supported for each DB2 index.
- getErrTxt(DB2I_ERR_MIXED_COLLATIONS);
- DBUG_RETURN(DB2I_ERR_MIXED_COLLATIONS);
- }
- }
-
- DBUG_RETURN(0);
-}
diff --git a/storage/ibmdb2i/db2i_collationSupport.h b/storage/ibmdb2i/db2i_collationSupport.h
deleted file mode 100644
index b2ce09de1ea..00000000000
--- a/storage/ibmdb2i/db2i_collationSupport.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#ifndef DB2I_COLLATIONSUPPORT_H
-#define DB2I_COLLATIONSUPPORT_H
-
-#include "db2i_global.h"
-#include "mysql_priv.h"
-
-int32 updateAssociatedSortSequence(const CHARSET_INFO* charset,
- char* fileSortSequenceType,
- char* fileSortSequence,
- char* fileSortSequenceLibrary);
-
-#endif
diff --git a/storage/ibmdb2i/db2i_constraints.cc b/storage/ibmdb2i/db2i_constraints.cc
deleted file mode 100644
index 3afa12032d0..00000000000
--- a/storage/ibmdb2i/db2i_constraints.cc
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-
-#include "ha_ibmdb2i.h"
-#include "db2i_safeString.h"
-
-// This function is called when building the CREATE TABLE information for
-// foreign key constraints. It converts a constraint, table, schema, or
-// field name from EBCDIC to ASCII. If the DB2 name is quoted, it removes
-// those quotes. It then adds the appropriate quotes for a MySQL identifier.
-
-static void convNameForCreateInfo(THD *thd, SafeString& info, char* fromName, int len)
-{
- int quote;
- char cquote; // Quote character
- char convName[MAX_DB2_FILENAME_LENGTH]; // Converted name
-
- memset(convName, 0, sizeof(convName));
- convFromEbcdic(fromName, convName, len);
- quote = get_quote_char_for_identifier(thd, convName, len);
- cquote = (char) quote;
- if (quote != EOF)
- info.strcat(cquote);
- if (convName[0] == '"') // If DB2 name was quoted, remove quotes
- {
- if (strstr(convName, "\"\""))
- stripExtraQuotes(convName+1, len-1);
- info.strncat((char*)(convName+1), len-2);
- }
- else // DB2 name was not quoted
- info.strncat(convName, len);
- if (quote != EOF)
- info.strcat(cquote);
-}
-
-/**
- Evaluate the parse tree to build foreign key constraint clauses
-
- @parm lex The parse tree
- @parm appendHere The DB2 string to receive the constraint clauses
- @parm path The path to the table under consideration
- @parm fields Pointer to the table's list of field pointers
- @parm[in, out] fileSortSequenceType The sort sequence type associated with the table
- @parm[in, out] fileSortSequence The sort sequence associated with the table
- @parm[in, out] fileSortSequenceLibrary The sort sequence library associated with the table
-
- @return 0 if successful; HA_ERR_CANNOT_ADD_FOREIGN otherwise
-*/
-int ha_ibmdb2i::buildDB2ConstraintString(LEX* lex,
- String& appendHere,
- const char* path,
- Field** fields,
- char* fileSortSequenceType,
- char* fileSortSequence,
- char* fileSortSequenceLibrary)
-{
- List_iterator<Key> keyIter(lex->alter_info.key_list);
- char colName[MAX_DB2_COLNAME_LENGTH+1];
-
- Key* curKey;
-
- while (curKey = keyIter++)
- {
- if (curKey->type == Key::FOREIGN_KEY)
- {
- appendHere.append(STRING_WITH_LEN(", "));
-
- Foreign_key* fk = (Foreign_key*)curKey;
-
- char db2LibName[MAX_DB2_SCHEMANAME_LENGTH+1];
- if (fk->name.str)
- {
- char db2FKName[MAX_DB2_FILENAME_LENGTH+1];
- appendHere.append(STRING_WITH_LEN("CONSTRAINT "));
- if (fk->ref_table->db.str)
- {
- convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName));
- }
- else
- {
- db2i_table::getDB2LibNameFromPath(path, db2LibName);
- }
- if (lower_case_table_names == 1)
- my_casedn_str(files_charset_info, db2LibName);
- appendHere.append(db2LibName);
-
- appendHere.append('.');
-
- convertMySQLNameToDB2Name(fk->name.str, db2FKName, sizeof(db2FKName));
- appendHere.append(db2FKName);
- }
-
- appendHere.append(STRING_WITH_LEN(" FOREIGN KEY ("));
-
- bool firstTime = true;
-
- List_iterator<Key_part_spec> column(fk->columns);
- Key_part_spec* curColumn;
-
- while (curColumn = column++)
- {
- if (!firstTime)
- {
- appendHere.append(',');
- }
- firstTime = false;
-
- convertMySQLNameToDB2Name(curColumn->field_name.str, colName, sizeof(colName));
- appendHere.append(colName);
-
- // DB2 requires that the sort sequence on the child table match the parent table's
- // sort sequence. We ensure that happens by updating the sort sequence according
- // to the constrained fields.
- Field** field = fields;
- do
- {
- if (strcmp((*field)->field_name, curColumn->field_name.str) == 0)
- {
- int rc = updateAssociatedSortSequence((*field)->charset(),
- fileSortSequenceType,
- fileSortSequence,
- fileSortSequenceLibrary);
-
- if (unlikely(rc)) return rc;
- }
- } while (*(++field));
- }
-
- firstTime = true;
-
- appendHere.append(STRING_WITH_LEN(") REFERENCES "));
-
- if (fk->ref_table->db.str)
- {
- convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName));
- }
- else
- {
- db2i_table::getDB2LibNameFromPath(path, db2LibName);
- }
- if (lower_case_table_names == 1)
- my_casedn_str(files_charset_info, db2LibName);
- appendHere.append(db2LibName);
- appendHere.append('.');
-
- char db2FileName[MAX_DB2_FILENAME_LENGTH+1];
- convertMySQLNameToDB2Name(fk->ref_table->table.str, db2FileName, sizeof(db2FileName));
- if (lower_case_table_names)
- my_casedn_str(files_charset_info, db2FileName);
- appendHere.append(db2FileName);
-
-
- if (!fk->ref_columns.is_empty())
- {
- List_iterator<Key_part_spec> ref(fk->ref_columns);
- Key_part_spec* curRef;
- appendHere.append(STRING_WITH_LEN(" ("));
-
-
- while (curRef = ref++)
- {
- if (!firstTime)
- {
- appendHere.append(',');
- }
- firstTime = false;
-
- convertMySQLNameToDB2Name(curRef->field_name.str, colName, sizeof(colName));
- appendHere.append(colName);
- }
-
- appendHere.append(STRING_WITH_LEN(") "));
- }
-
- if (fk->delete_opt != Foreign_key::FK_OPTION_UNDEF)
- {
- appendHere.append(STRING_WITH_LEN("ON DELETE "));
- switch (fk->delete_opt)
- {
- case Foreign_key::FK_OPTION_RESTRICT:
- appendHere.append(STRING_WITH_LEN("RESTRICT ")); break;
- case Foreign_key::FK_OPTION_CASCADE:
- appendHere.append(STRING_WITH_LEN("CASCADE ")); break;
- case Foreign_key::FK_OPTION_SET_NULL:
- appendHere.append(STRING_WITH_LEN("SET NULL ")); break;
- case Foreign_key::FK_OPTION_NO_ACTION:
- appendHere.append(STRING_WITH_LEN("NO ACTION ")); break;
- case Foreign_key::FK_OPTION_DEFAULT:
- appendHere.append(STRING_WITH_LEN("SET DEFAULT ")); break;
- default:
- return HA_ERR_CANNOT_ADD_FOREIGN; break;
- }
- }
-
- if (fk->update_opt != Foreign_key::FK_OPTION_UNDEF)
- {
- appendHere.append(STRING_WITH_LEN("ON UPDATE "));
- switch (fk->update_opt)
- {
- case Foreign_key::FK_OPTION_RESTRICT:
- appendHere.append(STRING_WITH_LEN("RESTRICT ")); break;
- case Foreign_key::FK_OPTION_NO_ACTION:
- appendHere.append(STRING_WITH_LEN("NO ACTION ")); break;
- default:
- return HA_ERR_CANNOT_ADD_FOREIGN; break;
- }
- }
-
- }
-
- }
-
- return 0;
-}
-
-
-/***********************************************************************
-Get the foreign key information in the form of a character string so
-that it can be inserted into a CREATE TABLE statement. This is used by
-the SHOW CREATE TABLE statement. The string will later be freed by the
-free_foreign_key_create_info() method.
-************************************************************************/
-
-char* ha_ibmdb2i::get_foreign_key_create_info(void)
-{
- DBUG_ENTER("ha_ibmdb2i::get_foreign_key_create_info");
- int rc = 0;
- char* infoBuffer = NULL; // Pointer to string returned to MySQL
- uint32 constraintSpaceLength;// Length of space passed to DB2
- ValidatedPointer<char> constraintSpace; // Space pointer passed to DB2
- uint32 neededLen; // Length returned from DB2
- uint32 cstCnt; // Number of foreign key constraints from DB2
- uint32 fld; //
- constraint_hdr* cstHdr; // Pointer to constraint header structure
- FK_constraint* FKCstDef; // Pointer to constraint definition structure
- cst_name* fieldName; // Pointer to field name structure
- char* tempPtr; // Temp pointer for traversing constraint space
- char convName[128];
-
- /* Allocate space to retrieve the DB2 constraint information. */
-
- if (!(share = get_share(table_share->path.str, table)))
- DBUG_RETURN(NULL);
-
- constraintSpaceLength = 5000; // Try allocating 5000 bytes and see if enough.
-
- initBridge();
-
- constraintSpace.alloc(constraintSpaceLength);
- rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
- ->constraints(db2Table->dataFile()->getMasterDefnHandle(),
- constraintSpace,
- constraintSpaceLength,
- &neededLen,
- &cstCnt);
-
- if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE))
- {
- constraintSpaceLength = neededLen; // Get length of space that's needed
- constraintSpace.realloc(constraintSpaceLength);
- rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
- ->constraints(db2Table->dataFile()->getMasterDefnHandle(),
- constraintSpace,
- constraintSpaceLength,
- &neededLen,
- &cstCnt);
- }
-
- /* If constraint information was returned by DB2, build a text string */
- /* to return to MySQL. */
-
- if ((rc == 0) && (cstCnt > 0))
- {
- THD* thd = ha_thd();
- infoBuffer = (char*) my_malloc(MAX_FOREIGN_LEN + 1, MYF(MY_WME));
- if (infoBuffer == NULL)
- {
- free_share(share);
- DBUG_RETURN(NULL);
- }
-
- SafeString info(infoBuffer, MAX_FOREIGN_LEN + 1);
-
- /* Loop through the DB2 constraints and build a text string for each foreign */
- /* key constraint that is found. */
-
- tempPtr = constraintSpace;
- cstHdr = (constraint_hdr_t*)(void*)constraintSpace; // Address first constraint definition
- for (int i = 0; i < cstCnt && !info.overflowed(); ++i)
- {
- if (cstHdr->CstType[0] == QMY_CST_FK) // If this is a foreign key constraint
- {
- tempPtr = (char*)(tempPtr + cstHdr->CstDefOff);
- FKCstDef = (FK_constraint_t*)tempPtr;
-
- /* Process the constraint name. */
-
- info.strncat(STRING_WITH_LEN(",\n CONSTRAINT "));
- convNameForCreateInfo(thd, info,
- FKCstDef->CstName.Name, FKCstDef->CstName.Len);
-
- /* Process the names of the foreign keys. */
-
- info.strncat(STRING_WITH_LEN(" FOREIGN KEY ("));
- tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff);
- fieldName= (cst_name_t*)tempPtr;
- for (fld = 0; fld < FKCstDef->KeyCnt; ++fld)
- {
- convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len);
- if ((fld + 1) < FKCstDef->KeyCnt)
- {
- info.strncat(STRING_WITH_LEN(", "));
- fieldName = fieldName + 1;
- }
- }
-
- /* Process the schema-name and name of the referenced table. */
-
- info.strncat(STRING_WITH_LEN(") REFERENCES "));
- convNameForCreateInfo(thd, info,
- FKCstDef->RefSchema.Name, FKCstDef->RefSchema.Len);
- info.strcat('.');
- convNameForCreateInfo(thd, info,
- FKCstDef->RefTable.Name, FKCstDef->RefTable.Len);
- info.strncat(STRING_WITH_LEN(" ("));
-
- /* Process the names of the referenced keys. */
-
- tempPtr = (char*)FKCstDef;
- tempPtr = (char*)(tempPtr + FKCstDef->RefColOff);
- fieldName= (cst_name_t*)tempPtr;
- for (fld = 0; fld < FKCstDef->RefCnt; ++fld)
- {
- convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len);
- if ((fld + 1) < FKCstDef->RefCnt)
- {
- info.strncat(STRING_WITH_LEN(", "));
- fieldName = fieldName + 1;
- }
- }
-
- /* Process the ON UPDATE and ON DELETE rules. */
-
- info.strncat(STRING_WITH_LEN(") ON UPDATE "));
- switch(FKCstDef->UpdMethod)
- {
- case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break;
- case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break;
- default: break;
- }
- info.strncat(STRING_WITH_LEN(" ON DELETE "));
- switch(FKCstDef->DltMethod)
- {
- case QMY_CASCADE: info.strncat(STRING_WITH_LEN("CASCADE")); break;
- case QMY_SETDFT: info.strncat(STRING_WITH_LEN("SET DEFAULT")); break;
- case QMY_SETNULL: info.strncat(STRING_WITH_LEN("SET NULL")); break;
- case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break;
- case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break;
- default: break;
- }
- }
-
- /* Address the next constraint, if any. */
-
- if ((i+1) < cstCnt)
- {
- tempPtr = (char*)cstHdr + cstHdr->CstLen;
- cstHdr = (constraint_hdr_t*)(tempPtr);
- }
- }
- }
-
- /* Cleanup and return */
- free_share(share);
-
- DBUG_RETURN(infoBuffer);
-}
-
-/***********************************************************************
-Free the foreign key create info (for a table) that was acquired by the
-get_foreign_key_create_info() method.
-***********************************************************************/
-
-void ha_ibmdb2i::free_foreign_key_create_info(char* info)
-{
- DBUG_ENTER("ha_ibmdb2i::free_foreign_key_create_info");
-
- if (info)
- {
- my_free(info);
- }
- DBUG_VOID_RETURN;
-}
-
-/***********************************************************************
-This method returns to MySQL a list, with one entry in the list describing
-each foreign key constraint.
-***********************************************************************/
-
-int ha_ibmdb2i::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
-{
- DBUG_ENTER("ha_ibmdb2i::get_foreign_key_list");
- int rc = 0;
- uint32 constraintSpaceLength; // Length of space passed to DB2
- ValidatedPointer<char> constraintSpace; // Space pointer passed to DB2
- uint16 rtnCode; // Return code from DB2
- uint32 neededLen; // Bytes needed to contain DB2 constraint info
- uint32 cstCnt; // Number of constraints returned by DB2
- uint32 fld;
- constraint_hdr* cstHdr; // Pointer to a cst header structure
- FK_constraint* FKCstDef; // Pointer to definition of foreign key constraint
- cst_name* fieldName; // Pointer to field name structure
- const char *method;
- ulong methodLen;
- char* tempPtr; // Temp pointer for traversing constraint space
- char convName[128];
-
- if (!(share = get_share(table_share->path.str, table)))
- DBUG_RETURN(0);
-
- // Allocate space to retrieve the DB2 constraint information.
- constraintSpaceLength = 5000; // Try allocating 5000 bytes and see if enough.
-
- constraintSpace.alloc(constraintSpaceLength);
- rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
- ->constraints(db2Table->dataFile()->getMasterDefnHandle(),
- constraintSpace,
- constraintSpaceLength,
- &neededLen,
- &cstCnt);
-
- if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE))
- {
- constraintSpaceLength = neededLen; // Get length of space that's needed
- constraintSpace.realloc(constraintSpaceLength);
- rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
- ->constraints(db2Table->dataFile()->getMasterDefnHandle(),
- constraintSpace,
- constraintSpaceLength,
- &neededLen,
- &cstCnt);
- }
-
- /* If constraint information was returned by DB2, build a text string */
- /* to return to MySQL. */
- if ((rc == 0) && (cstCnt > 0))
- {
- tempPtr = constraintSpace;
- cstHdr = (constraint_hdr_t*)(void*)constraintSpace; // Address first constraint definition
- for (int i = 0; i < cstCnt; ++i)
- {
- if (cstHdr->CstType[0] == QMY_CST_FK) // If this is a foreign key constraint
- {
- FOREIGN_KEY_INFO f_key_info;
- LEX_STRING *name= 0;
- tempPtr = (char*)(tempPtr + cstHdr->CstDefOff);
- FKCstDef = (FK_constraint_t*)tempPtr;
-
- /* Process the constraint name. */
-
- convFromEbcdic(FKCstDef->CstName.Name, convName,FKCstDef->CstName.Len);
- if (convName[0] == '"') // If quoted, exclude quotes.
- f_key_info.forein_id = thd_make_lex_string(thd, 0,
- convName + 1, (uint) (FKCstDef->CstName.Len - 2), 1);
- else // Not quoted
- f_key_info.forein_id = thd_make_lex_string(thd, 0,
- convName, (uint) FKCstDef->CstName.Len, 1);
-
- /* Process the names of the foreign keys. */
-
-
- tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff);
- fieldName = (cst_name_t*)tempPtr;
- for (fld = 0; fld < FKCstDef->KeyCnt; ++fld)
- {
- convFromEbcdic(fieldName->Name, convName, fieldName->Len);
- if (convName[0] == '"') // If quoted, exclude quotes.
- name = thd_make_lex_string(thd, name,
- convName + 1, (uint) (fieldName->Len - 2), 1);
- else
- name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1);
- f_key_info.foreign_fields.push_back(name);
- if ((fld + 1) < FKCstDef->KeyCnt)
- fieldName = fieldName + 1;
- }
-
- /* Process the schema and name of the referenced table. */
-
- convFromEbcdic(FKCstDef->RefSchema.Name, convName, FKCstDef->RefSchema.Len);
- if (convName[0] == '"') // If quoted, exclude quotes.
- f_key_info.referenced_db = thd_make_lex_string(thd, 0,
- convName + 1, (uint) (FKCstDef->RefSchema.Len -2), 1);
- else
- f_key_info.referenced_db = thd_make_lex_string(thd, 0,
- convName, (uint) FKCstDef->RefSchema.Len, 1);
- convFromEbcdic(FKCstDef->RefTable.Name, convName, FKCstDef->RefTable.Len);
- if (convName[0] == '"') // If quoted, exclude quotes.
- f_key_info.referenced_table = thd_make_lex_string(thd, 0,
- convName +1, (uint) (FKCstDef->RefTable.Len -2), 1);
- else
- f_key_info.referenced_table = thd_make_lex_string(thd, 0,
- convName, (uint) FKCstDef->RefTable.Len, 1);
-
- /* Process the names of the referenced keys. */
-
- tempPtr = (char*)FKCstDef;
- tempPtr = (char*)(tempPtr + FKCstDef->RefColOff);
- fieldName= (cst_name_t*)tempPtr;
- for (fld = 0; fld < FKCstDef->RefCnt; ++fld)
- {
- convFromEbcdic(fieldName->Name, convName, fieldName->Len);
- if (convName[0] == '"') // If quoted, exclude quotes.
- name = thd_make_lex_string(thd, name,
- convName + 1, (uint) (fieldName->Len -2), 1);
- else
- name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1);
- f_key_info.referenced_fields.push_back(name);
- if ((fld + 1) < FKCstDef->RefCnt)
- fieldName = fieldName + 1;
- }
-
- /* Process the ON UPDATE and ON DELETE rules. */
-
- switch(FKCstDef->UpdMethod)
- {
- case QMY_NOACTION:
- {
- method = "NO ACTION";
- methodLen=9;
- }
- break;
- case QMY_RESTRICT:
- {
- method = "RESTRICT";
- methodLen = 8;
- }
- break;
- default: break;
- }
- f_key_info.update_method = thd_make_lex_string(
- thd, f_key_info.update_method, method, methodLen, 1);
- switch(FKCstDef->DltMethod)
- {
- case QMY_CASCADE:
- {
- method = "CASCADE";
- methodLen = 7;
- }
- break;
- case QMY_SETDFT:
- {
- method = "SET DEFAULT";
- methodLen = 11;
- }
- break;
- case QMY_SETNULL:
- {
- method = "SET NULL";
- methodLen = 8;
- }
- break;
- case QMY_NOACTION:
- {
- method = "NO ACTION";
- methodLen = 9;
- }
- break;
- case QMY_RESTRICT:
- {
- method = "RESTRICT";
- methodLen = 8;
- }
- break;
- default: break;
- }
- f_key_info.delete_method = thd_make_lex_string(
- thd, f_key_info.delete_method, method, methodLen, 1);
- f_key_info.referenced_key_name= thd_make_lex_string(thd, 0, (char *)"", 1, 1);
- FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
- thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO));
- f_key_list->push_back(pf_key_info);
- }
-
- /* Address the next constraint, if any. */
-
- if ((i+1) < cstCnt)
- {
- tempPtr = (char*)cstHdr + cstHdr->CstLen;
- cstHdr = (constraint_hdr_t*)(tempPtr);
- }
- }
- }
-
- /* Cleanup and return. */
-
- free_share(share);
- DBUG_RETURN(0);
-}
-
-/***********************************************************************
-Checks if the table is referenced by a foreign key.
-Returns: 0 if not referenced (or error occurs),
- > 0 if is referenced
-***********************************************************************/
-
-uint ha_ibmdb2i::referenced_by_foreign_key(void)
-{
- DBUG_ENTER("ha_ibmdb2i::referenced_by_foreign_key");
-
- int rc = 0;
- FILE_HANDLE queryFile = 0;
- uint32 resultRowLen;
- uint32 count = 0;
-
- const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL);
- const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL);
-
- String query(128);
- query.append(STRING_WITH_LEN(" SELECT COUNT(*) FROM SYSIBM.SQLFOREIGNKEYS WHERE PKTABLE_SCHEM = '"));
- query.append(libName+1, strlen(libName)-2); // parent library name
- query.append(STRING_WITH_LEN("' AND PKTABLE_NAME = '"));
- query.append(fileName+1, strlen(fileName)-2); // parent file name
- query.append(STRING_WITH_LEN("'"));
-
- SqlStatementStream sqlStream(query);
-
- rc = bridge()->prepOpen(sqlStream.getPtrToData(),
- &queryFile,
- &resultRowLen);
- if (rc == 0)
- {
- IOReadBuffer rowBuffer(1, resultRowLen);
- rc = bridge()->read(queryFile, rowBuffer.ptr(), QMY_READ_ONLY, QMY_NONE, QMY_FIRST);
- if (!rc) count = *((uint32*)rowBuffer.getRowN(0));
- bridge()->deallocateFile(queryFile);
- }
- DBUG_RETURN(count);
-}
diff --git a/storage/ibmdb2i/db2i_conversion.cc b/storage/ibmdb2i/db2i_conversion.cc
deleted file mode 100644
index 71a30802bf9..00000000000
--- a/storage/ibmdb2i/db2i_conversion.cc
+++ /dev/null
@@ -1,1459 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-
-#include "db2i_ileBridge.h"
-#include "mysql_priv.h"
-#include "db2i_charsetSupport.h"
-#include "ctype.h"
-#include "ha_ibmdb2i.h"
-#include "db2i_errors.h"
-#include "wchar.h"
-
-const char ZERO_DATETIME_VALUE[] = "0000-00-00 00:00:00";
-const char ZERO_DATETIME_VALUE_SUBST[] = "0001-01-01 00:00:00";
-const char ZERO_DATE_VALUE[] = "0000-00-00";
-const char ZERO_DATE_VALUE_SUBST[] = "0001-01-01";
-
-
-/**
- Put a BCD digit into a BCD string.
-
- @param[out] bcdString The BCD string to be modified
- @param pos The position within the string to be updated.
- @param val The value to be assigned into the string at pos.
-*/
-static inline void bcdAssign(char* bcdString, uint pos, uint val)
-{
- bcdString[pos/2] |= val << ((pos % 2) ? 0 : 4);
-}
-
-/**
- Read a BCD digit from a BCD string.
-
- @param[out] bcdString The BCD string to be read
- @param pos The position within the string to be read.
-
- @return bcdGet The value of the BCD digit at pos.
-*/
-static inline uint bcdGet(const char* bcdString, uint pos)
-{
- return (bcdString[pos/2] >> ((pos % 2) ? 0 : 4)) & 0xf;
-}
-
-/**
- In-place convert a number in ASCII represenation to EBCDIC representation.
-
- @param string The string of ASCII characters
- @param len The length of string
-*/
-static inline void convertNumericToEbcdicFast(char* string, int len)
-{
- for (int i = 0; i < len; ++i, ++string)
- {
- switch(*string)
- {
- case '-':
- *string = 0x60; break;
- case ':':
- *string = 0x7A; break;
- case '.':
- *string = 0x4B; break;
- default:
- DBUG_ASSERT(isdigit(*string));
- *string += 0xF0 - '0';
- break;
- }
- }
-}
-
-
-/**
- atoi()-like function for a 4-character EBCDIC string.
-
- @param string The EBCDIC string
- @return a4toi_ebcdic The decimal value of the EBCDIC string
-*/
-static inline uint16 a4toi_ebcdic(const uchar* string)
-{
- return ((string[0]-0xF0) * 1000 +
- (string[1]-0xF0) * 100 +
- (string[2]-0xF0) * 10 +
- (string[3]-0xF0));
-};
-
-
-/**
- atoi()-like function for a 4-character EBCDIC string.
-
- @param string The EBCDIC string
- @return a4toi_ebcdic The decimal value of the EBCDIC string
-*/
-static inline uint8 a2toi_ebcdic(const uchar* string)
-{
- return ((string[0]-0xF0) * 10 +
- (string[1]-0xF0));
-};
-
-/**
- Perform character conversion for textual field data.
-*/
-int ha_ibmdb2i::convertFieldChars(enum_conversionDirection direction,
- uint16 fieldID,
- const char* input,
- char* output,
- size_t ilen,
- size_t olen,
- size_t* outDataLen,
- bool tacitErrors,
- size_t* substChars)
-{
- DBUG_PRINT("ha_ibmdb2i::convertFieldChars",("Direction: %d; length = %d", direction, ilen));
-
- if (unlikely(ilen == 0))
- {
- if (outDataLen) *outDataLen = 0;
- return (0);
- }
-
- iconv_t& conversion = db2Table->getConversionDefinition(direction, fieldID);
-
- if (unlikely(conversion == (iconv_t)(-1)))
- {
- return (DB2I_ERR_UNSUPP_CHARSET);
- }
-
- size_t initOLen= olen;
- size_t substitutedChars = 0;
- int rc = iconv(conversion, (char**)&input, &ilen, &output, &olen, &substitutedChars );
- if (outDataLen) *outDataLen = initOLen - olen;
- if (substChars) *substChars = substitutedChars;
- if (unlikely(rc < 0))
- {
- int er = errno;
- if (er == EILSEQ)
- {
- if (!tacitErrors) getErrTxt(DB2I_ERR_ILL_CHAR, table->field[fieldID]->field_name);
- return (DB2I_ERR_ILL_CHAR);
- }
- else
- {
- if (!tacitErrors) getErrTxt(DB2I_ERR_ICONV,er);
- return (DB2I_ERR_ICONV);
- }
- }
- if (unlikely(substitutedChars) && (!tacitErrors))
- {
- warning(ha_thd(), DB2I_ERR_SUB_CHARS, table->field[fieldID]->field_name);
- }
-
- return (0);
-}
-
-/**
- Append the appropriate default value clause onto a CREATE TABLE definition
-
- This was inspired by get_field_default_value in sql/sql_show.cc.
-
- @param field The field whose value is to be obtained
- @param statement The string to receive the DEFAULT clause
- @param quoteIt Does the data type require single quotes around the value?
- @param ccsid The ccsid of the field value (if a string type); 0 if no conversion needed
-*/
-static void get_field_default_value(Field *field,
- String &statement,
- bool quoteIt,
- uint32 ccsid,
- bool substituteZeroDates)
-{
- if ((field->type() != FIELD_TYPE_BLOB &&
- !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
- field->unireg_check != Field::NEXT_NUMBER))
- {
- my_ptrdiff_t old_ptr= (my_ptrdiff_t) (field->table->s->default_values - field->table->record[0]);
- field->move_field_offset(old_ptr);
-
- String defaultClause(64);
- defaultClause.length(0);
- defaultClause.append(" DEFAULT ");
- if (!field->is_null())
- {
- my_bitmap_map *old_map = tmp_use_all_columns(field->table, field->table->read_set);
- char tmp[MAX_FIELD_WIDTH];
-
- if (field->real_type() == MYSQL_TYPE_ENUM ||
- field->real_type() == MYSQL_TYPE_SET)
- {
- CHARSET_INFO *cs= &my_charset_bin;
- uint len = (uint)(cs->cset->longlong10_to_str)(cs,tmp,sizeof(tmp), 10, field->val_int());
- tmp[len]=0;
- defaultClause.append(tmp);
- }
- else
- {
- String type(tmp, sizeof(tmp), field->charset());
- field->val_str(&type);
- if (type.length())
- {
- if (field->type() == MYSQL_TYPE_DATE &&
- memcmp(type.ptr(), STRING_WITH_LEN(ZERO_DATE_VALUE)) == 0)
- {
- if (substituteZeroDates)
- type.set(STRING_WITH_LEN(ZERO_DATE_VALUE_SUBST), field->charset());
- else
- {
- warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name);
- return;
- }
- }
- else if ((field->type() == MYSQL_TYPE_DATETIME ||
- field->type() == MYSQL_TYPE_TIMESTAMP) &&
- memcmp(type.ptr(), STRING_WITH_LEN(ZERO_DATETIME_VALUE)) == 0)
- {
- if (substituteZeroDates)
- type.set(STRING_WITH_LEN(ZERO_DATETIME_VALUE_SUBST), field->charset());
- else
- {
- warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name);
- return;
- }
- }
-
-
- if (field->type() != MYSQL_TYPE_STRING &&
- field->type() != MYSQL_TYPE_VARCHAR &&
- field->type() != MYSQL_TYPE_BLOB &&
- field->type() != MYSQL_TYPE_BIT)
- {
- if (quoteIt)
- defaultClause.append('\'');
- defaultClause.append(type);
- if (quoteIt)
- defaultClause.append('\'');
- }
- else
- {
- int length;
- char* out;
-
- // If a ccsid is specified, we need to make sure that the DEFAULT
- // string is converted to that encoding.
- if (ccsid != 0)
- {
- iconv_t iconvD;
- if (getConversion(toDB2, field->charset(), ccsid, iconvD))
- {
- warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name);
- return;
- }
-
- size_t ilen = type.length();
- size_t olen = 6 * ilen;
- size_t origOlen = olen;
- const char* in = type.ptr();
- const char* tempIn = in;
- out = (char*)my_malloc(olen, MYF(MY_WME));
- char* tempOut = out;
- size_t substitutedChars;
-
- if (iconv(iconvD, (char**)&tempIn, &ilen, &tempOut, &olen, &substitutedChars) < 0)
- {
- warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name);
- my_free(out);
- return;
- }
- // Now we process the converted string to represent it as
- // hexadecimal values.
-
- length = origOlen - olen;
- }
- else
- {
- length = type.length();
- out = (char*)my_malloc(length*2, MYF(MY_WME));
- memcpy(out, (char*)type.ptr(), length);
- }
-
- if (length > 16370)
- {
- warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name);
- my_free(out);
- return;
- }
-
- if (ccsid == 1200)
- defaultClause.append("ux'");
- else if (ccsid == 13488)
- defaultClause.append("gx'");
- else if (field->charset() == &my_charset_bin)
- defaultClause.append("binary(x'");
- else
- defaultClause.append("x'");
-
- const char hexMap[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- for (int c = length-1; c >= 0; --c)
- {
- out[c*2+1] = hexMap[out[c] & 0xF];
- out[c*2] = hexMap[out[c] >> 4];
- }
-
- defaultClause.append(out, length*2);
- defaultClause.append('\'');
- if (field->charset() == &my_charset_bin)
- defaultClause.append(")");
-
- my_free(out);
- }
- }
- else
- defaultClause.length(0);
- }
- tmp_restore_column_map(field->table->read_set, old_map);
- }
- else if (field->maybe_null())
- defaultClause.append(STRING_WITH_LEN("NULL"));
-
- if (old_ptr)
- field->move_field_offset(-old_ptr);
-
- statement.append(defaultClause);
- }
-}
-
-
-
-
-/**
- Convert a MySQL field definition into its corresponding DB2 type.
-
- The result will be appended to mapping as a DB2 SQL phrase.
-
- @param field The MySQL field to be evaluated
- @param[out] mapping The receiver for the DB2 SQL syntax
- @param timeFormat The format to be used for mapping the TIME type
-*/
-int ha_ibmdb2i::getFieldTypeMapping(Field* field,
- String& mapping,
- enum_TimeFormat timeFormat,
- enum_BlobMapping blobMapping,
- enum_ZeroDate zeroDateHandling,
- bool propagateDefaults,
- enum_YearFormat yearFormat)
-{
- char stringBuildBuffer[257];
- uint32 fieldLength;
- bool defaultNeedsQuotes = false;
- uint16 db2Ccsid = 0;
-
- CHARSET_INFO* fieldCharSet = field->charset();
- switch (field->type())
- {
- case MYSQL_TYPE_NEWDECIMAL:
- {
- uint precision= ((Field_new_decimal*)field)->precision;
- uint scale= field->decimals();
-
- if (precision <= MAX_DEC_PRECISION)
- {
- sprintf(stringBuildBuffer,"DECIMAL(%d, %d)",precision,scale);
- }
- else
- {
- if (scale > precision - MAX_DEC_PRECISION)
- {
- scale = scale - (precision - MAX_DEC_PRECISION);
- precision = MAX_DEC_PRECISION;
- sprintf(stringBuildBuffer,"DECIMAL(%d, %d)",precision,scale);
- }
- else
- {
- return HA_ERR_UNSUPPORTED;
- }
- warning(ha_thd(), DB2I_ERR_PRECISION);
- }
-
- mapping.append(stringBuildBuffer);
- }
- break;
- case MYSQL_TYPE_TINY:
- mapping.append(STRING_WITH_LEN("SMALLINT"));
- break;
- case MYSQL_TYPE_SHORT:
- if (((Field_num*)field)->unsigned_flag)
- mapping.append(STRING_WITH_LEN("INT"));
- else
- mapping.append(STRING_WITH_LEN("SMALLINT"));
- break;
- case MYSQL_TYPE_LONG:
- if (((Field_num*)field)->unsigned_flag)
- mapping.append(STRING_WITH_LEN("BIGINT"));
- else
- mapping.append(STRING_WITH_LEN("INT"));
- break;
- case MYSQL_TYPE_FLOAT:
- mapping.append(STRING_WITH_LEN("REAL"));
- break;
- case MYSQL_TYPE_DOUBLE:
- mapping.append(STRING_WITH_LEN("DOUBLE"));
- break;
- case MYSQL_TYPE_LONGLONG:
- if (((Field_num*)field)->unsigned_flag)
- mapping.append(STRING_WITH_LEN("DECIMAL(20,0)"));
- else
- mapping.append(STRING_WITH_LEN("BIGINT"));
- break;
- case MYSQL_TYPE_INT24:
- mapping.append(STRING_WITH_LEN("INTEGER"));
- break;
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_NEWDATE:
- mapping.append(STRING_WITH_LEN("DATE"));
- defaultNeedsQuotes = true;
- break;
- case MYSQL_TYPE_TIME:
- if (timeFormat == TIME_OF_DAY)
- {
- mapping.append(STRING_WITH_LEN("TIME"));
- defaultNeedsQuotes = true;
- }
- else
- mapping.append(STRING_WITH_LEN("INTEGER"));
- break;
- case MYSQL_TYPE_DATETIME:
- mapping.append(STRING_WITH_LEN("TIMESTAMP"));
- defaultNeedsQuotes = true;
- break;
- case MYSQL_TYPE_TIMESTAMP:
- mapping.append(STRING_WITH_LEN("TIMESTAMP"));
-
- if (table_share->timestamp_field == field && propagateDefaults)
- {
- switch (((Field_timestamp*)field)->get_auto_set_type())
- {
- case TIMESTAMP_NO_AUTO_SET:
- break;
- case TIMESTAMP_AUTO_SET_ON_INSERT:
- mapping.append(STRING_WITH_LEN(" DEFAULT CURRENT_TIMESTAMP"));
- break;
- case TIMESTAMP_AUTO_SET_ON_UPDATE:
- if (osVersion.v >= 6 &&
- !field->is_null())
- {
- mapping.append(STRING_WITH_LEN(" GENERATED BY DEFAULT FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP"));
- warning(ha_thd(), DB2I_ERR_WARN_COL_ATTRS, field->field_name);
- }
- else
- warning(ha_thd(), DB2I_ERR_WARN_COL_ATTRS, field->field_name);
- break;
- case TIMESTAMP_AUTO_SET_ON_BOTH:
- if (osVersion.v >= 6 &&
- !field->is_null())
- mapping.append(STRING_WITH_LEN(" GENERATED BY DEFAULT FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP"));
- else
- {
- mapping.append(STRING_WITH_LEN(" DEFAULT CURRENT_TIMESTAMP"));
- warning(ha_thd(), DB2I_ERR_WARN_COL_ATTRS, field->field_name);
- }
- break;
- }
- }
- else
- defaultNeedsQuotes = true;
- break;
- case MYSQL_TYPE_YEAR:
- if (yearFormat == CHAR4)
- {
- mapping.append(STRING_WITH_LEN("CHAR(4) CCSID 1208"));
- defaultNeedsQuotes = true;
- }
- else
- {
- mapping.append(STRING_WITH_LEN("SMALLINT"));
- defaultNeedsQuotes = false;
- }
- break;
- case MYSQL_TYPE_BIT:
- sprintf(stringBuildBuffer, "BINARY(%d)", (field->max_display_length() / 8) + 1);
- mapping.append(stringBuildBuffer);
- break;
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_VARCHAR:
- case MYSQL_TYPE_STRING:
- {
- if (field->real_type() == MYSQL_TYPE_ENUM ||
- field->real_type() == MYSQL_TYPE_SET)
- {
- mapping.append(STRING_WITH_LEN("BIGINT"));
- }
- else
- {
- defaultNeedsQuotes = true;
-
- fieldLength = field->max_display_length(); // Get field byte length
-
- if (fieldCharSet == &my_charset_bin)
- {
- if (field->type() == MYSQL_TYPE_STRING)
- {
- sprintf(stringBuildBuffer, "BINARY(%d)", max(fieldLength, 1));
- }
- else
- {
- if (fieldLength <= MAX_VARCHAR_LENGTH)
- {
- sprintf(stringBuildBuffer, "VARBINARY(%d)", max(fieldLength, 1));
- }
- else if (blobMapping == AS_VARCHAR &&
- (field->flags & PART_KEY_FLAG))
- {
- sprintf(stringBuildBuffer, "LONG VARBINARY ");
- }
- else
- {
- fieldLength = min(MAX_BLOB_LENGTH, fieldLength);
- sprintf(stringBuildBuffer, "BLOB(%d)", max(fieldLength, 1));
- }
- }
- mapping.append(stringBuildBuffer);
- }
- else
- {
- if (field->type() == MYSQL_TYPE_STRING)
- {
- if (fieldLength > MAX_CHAR_LENGTH)
- return 1;
- if (fieldCharSet->mbmaxlen > 1)
- {
- if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2
- {
- sprintf(stringBuildBuffer, "GRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
- db2Ccsid = 13488;
- }
- else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 &&
- strcmp(fieldCharSet->name, "utf8_general_ci") != 0)
- {
- sprintf(stringBuildBuffer, "CHAR(%d)", max(fieldLength, 1)); // Number of bytes
- db2Ccsid = 1208;
- }
- else
- {
- sprintf(stringBuildBuffer, "GRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
- db2Ccsid = 1200;
- }
- }
- else
- {
- sprintf(stringBuildBuffer, "CHAR(%d)", max(fieldLength, 1));
- }
- mapping.append(stringBuildBuffer);
- }
- else
- {
- if (fieldLength <= MAX_VARCHAR_LENGTH)
- {
- if (fieldCharSet->mbmaxlen > 1)
- {
- if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2
- {
- sprintf(stringBuildBuffer, "VARGRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
- db2Ccsid = 13488;
- }
- else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 &&
- strcmp(fieldCharSet->name, "utf8_general_ci") != 0)
- {
- sprintf(stringBuildBuffer, "VARCHAR(%d)", max(fieldLength, 1)); // Number of bytes
- db2Ccsid = 1208;
- }
- else
- {
- sprintf(stringBuildBuffer, "VARGRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
- db2Ccsid = 1200;
- }
- }
- else
- {
- sprintf(stringBuildBuffer, "VARCHAR(%d)", max(fieldLength, 1));
- }
- }
- else if (blobMapping == AS_VARCHAR &&
- (field->flags & PART_KEY_FLAG))
- {
- if (fieldCharSet->mbmaxlen > 1)
- {
- if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2
- {
- sprintf(stringBuildBuffer, "LONG VARGRAPHIC ");
- db2Ccsid = 13488;
- }
- else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 &&
- strcmp(fieldCharSet->name, "utf8_general_ci") != 0)
- {
- sprintf(stringBuildBuffer, "LONG VARCHAR ");
- db2Ccsid = 1208;
- }
- else
- {
- sprintf(stringBuildBuffer, "LONG VARGRAPHIC ");
- db2Ccsid = 1200;
- }
- }
- else
- {
- sprintf(stringBuildBuffer, "LONG VARCHAR ");
- }
- }
- else
- {
- fieldLength = min(MAX_BLOB_LENGTH, fieldLength);
-
- if (fieldCharSet->mbmaxlen > 1)
- {
- if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2
- {
- sprintf(stringBuildBuffer, "DBCLOB(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
- db2Ccsid = 13488;
- }
- else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 &&
- strcmp(fieldCharSet->name, "utf8_general_ci") != 0)
- {
- sprintf(stringBuildBuffer, "CLOB(%d)", max(fieldLength, 1)); // Number of bytes
- db2Ccsid = 1208;
- }
- else
- {
- sprintf(stringBuildBuffer, "DBCLOB(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
- db2Ccsid = 1200;
- }
- }
- else
- {
- sprintf(stringBuildBuffer, "CLOB(%d)", max(fieldLength, 1)); // Number of characters
- }
- }
-
- mapping.append(stringBuildBuffer);
- }
- if (db2Ccsid == 0) // If not overriding CCSID
- {
- int32 rtnCode = convertIANAToDb2Ccsid(fieldCharSet->csname, &db2Ccsid);
- if (rtnCode)
- return rtnCode;
- }
-
- if (db2Ccsid != 1208 &&
- db2Ccsid != 13488)
- {
- // Check whether there is a character conversion available.
- iconv_t temp;
- int32 rc = getConversion(toDB2, fieldCharSet, db2Ccsid, temp);
- if (unlikely(rc))
- return rc;
- }
-
- sprintf(stringBuildBuffer, " CCSID %d ", db2Ccsid);
- mapping.append(stringBuildBuffer);
- }
- }
- }
- break;
-
- }
-
- if (propagateDefaults)
- get_field_default_value(field,
- mapping,
- defaultNeedsQuotes,
- db2Ccsid,
- (zeroDateHandling==SUBSTITUTE_0001_01_01));
-
- return 0;
-}
-
-
-/**
- Convert MySQL field data into the equivalent DB2 format
-
- @param field The MySQL field to be converted
- @param db2Field The corresponding DB2 field definition
- @param db2Buf The buffer to receive the converted data
- @param data NULL if field points to the correct data; otherwise,
- the data to be converted (for use with keys)
-*/
-int32 ha_ibmdb2i::convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char* db2Buf, const uchar* data)
-{
- enum_field_types fieldType = field->type();
- switch (fieldType)
- {
- case MYSQL_TYPE_NEWDECIMAL:
- {
- uint precision= ((Field_new_decimal*)field)->precision;
- uint scale= field->decimals();
- uint db2Precision = min(precision, MAX_DEC_PRECISION);
- uint truncationAmount = precision - db2Precision;
-
- if (scale >= truncationAmount)
- {
- String tempString(precision+2);
-
- if (data == NULL)
- {
- field->val_str((String*)&tempString, (String*)(NULL));
- }
- else
- {
- field->val_str(&tempString, data);
- }
- const char* temp = tempString.ptr();
- char packed[32];
- memset(&packed, 0, sizeof(packed));
-
- int bcdPos = db2Precision - (db2Precision % 2 ? 1 : 0);
- bcdAssign(packed, bcdPos+1, (temp[0] == '-' ? 0xD : 0xF));
-
- int strPos=tempString.length() - 1 - truncationAmount;
-
- for (;strPos >= 0 && bcdPos >= 0; strPos--)
- {
- if (my_isdigit(&my_charset_latin1, temp[strPos]))
- {
- bcdAssign(packed, bcdPos, temp[strPos]-'0');
- --bcdPos;
- }
- }
- memcpy(db2Buf, &packed, (db2Precision/2)+1);
- }
-
- }
- break;
- case MYSQL_TYPE_TINY:
- {
- int16 temp = (data == NULL ? field->val_int() : field->val_int(data));
- memcpy(db2Buf , &temp, sizeof(temp));
- }
- break;
- case MYSQL_TYPE_SHORT:
- {
- if (((Field_num*)field)->unsigned_flag)
- {
- memset(db2Buf, 0, 2);
- memcpy(db2Buf+2, (data == NULL ? field->ptr : data), 2);
- }
- else
- {
- memcpy(db2Buf, (data == NULL ? field->ptr : data), 2);
- }
- }
- break;
- case MYSQL_TYPE_LONG:
- {
- if (((Field_num*)field)->unsigned_flag)
- {
- memset(db2Buf, 0, 4);
- memcpy(db2Buf+4, (data == NULL ? field->ptr : data), 4);
- }
- else
- {
- memcpy(db2Buf, (data == NULL ? field->ptr : data), 4);
- }
- }
- break;
- case MYSQL_TYPE_FLOAT:
- {
- memcpy(db2Buf, (data == NULL ? field->ptr : data), 4);
- }
- break;
- case MYSQL_TYPE_DOUBLE:
- {
- memcpy(db2Buf, (data == NULL ? field->ptr : data), 8);
- }
- break;
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATETIME:
- {
- String tempString(27);
- if (data == NULL)
- {
- field->val_str(&tempString, &tempString);
- }
- else
- {
- field->val_str(&tempString, data);
- }
- memset(db2Buf, '0', 26);
- memcpy(db2Buf, tempString.ptr(), tempString.length());
- if (strncmp(db2Buf,ZERO_DATETIME_VALUE,strlen(ZERO_DATETIME_VALUE)) == 0)
- {
- if (cachedZeroDateOption == SUBSTITUTE_0001_01_01)
- memcpy(db2Buf, ZERO_DATETIME_VALUE_SUBST, sizeof(ZERO_DATETIME_VALUE_SUBST));
- else
- {
- getErrTxt(DB2I_ERR_INVALID_COL_VALUE, field->field_name);
- return(DB2I_ERR_INVALID_COL_VALUE);
- }
- }
- (db2Buf)[10] = '-';
- (db2Buf)[13] = (db2Buf)[16] = (db2Buf)[19] = '.';
-
- convertNumericToEbcdicFast(db2Buf, 26);
- }
- break;
- case MYSQL_TYPE_LONGLONG:
- {
- if (((Field_num*)field)->unsigned_flag)
- {
- char temp[23];
- String tempString(temp, sizeof(temp), &my_charset_latin1);
-
- if (data == NULL)
- {
- field->val_str((String*)&tempString, (String*)(NULL));
- }
- else
- {
- field->val_str(&tempString, data);
- }
- char packed[11];
- memset(packed, 0, sizeof(packed));
- bcdAssign(packed, 21, (temp[0] == '-' ? 0xD : 0xF));
- int strPos=tempString.length()-1;
- int bcdPos=20;
-
- for (;strPos >= 0; strPos--)
- {
- if (my_isdigit(&my_charset_latin1, temp[strPos]))
- {
- bcdAssign(packed, bcdPos, temp[strPos]-'0');
- --bcdPos;
- }
- }
- memcpy(db2Buf, &packed, 11);
- }
- else
- {
- *(uint64*)db2Buf = *(uint64*)(data == NULL ? field->ptr : data);
- }
- }
- break;
- case MYSQL_TYPE_INT24:
- {
- int32 temp= (data == NULL ? field->val_int() : field->val_int(data));
- memcpy(db2Buf , &temp, sizeof(temp));
- }
- break;
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_NEWDATE:
- {
- String tempString(11);
- if (data == NULL)
- {
- field->val_str(&tempString, (String*)NULL);
- }
- else
- {
- field->val_str(&tempString, data);
- }
- memcpy(db2Buf, tempString.ptr(), 10);
- if (strncmp(db2Buf,ZERO_DATE_VALUE,strlen(ZERO_DATE_VALUE)) == 0)
- {
- if (cachedZeroDateOption == SUBSTITUTE_0001_01_01)
- memcpy(db2Buf, ZERO_DATE_VALUE_SUBST, sizeof(ZERO_DATE_VALUE_SUBST));
- else
- {
- getErrTxt(DB2I_ERR_INVALID_COL_VALUE,field->field_name);
- return(DB2I_ERR_INVALID_COL_VALUE);
- }
- }
-
- convertNumericToEbcdicFast(db2Buf,10);
- }
- break;
- case MYSQL_TYPE_TIME:
- {
- if (db2Field.getType() == QMY_TIME)
- {
- String tempString(10);
- if (data == NULL)
- {
- field->val_str(&tempString, (String*)NULL);
- }
- else
- {
- field->val_str(&tempString, data);
- }
- memcpy(db2Buf, tempString.ptr(), 8);
- (db2Buf)[2]=(db2Buf)[5] = '.';
-
- convertNumericToEbcdicFast(db2Buf, 8);
- }
- else
- {
- int32 temp = sint3korr(data == NULL ? field->ptr : data);
- memcpy(db2Buf, &temp, sizeof(temp));
- }
- }
- break;
- case MYSQL_TYPE_YEAR:
- {
- String tempString(5);
- if (db2Field.getType() == QMY_CHAR)
- {
- if (data == NULL)
- {
- field->val_str(&tempString, (String*)NULL);
- }
- else
- {
- field->val_str(&tempString, data);
- }
- memcpy(db2Buf, tempString.ptr(), 4);
- }
- else
- {
- uint8 temp = *(uint8*)(data == NULL ? field->ptr : data);
- *(uint16*)(db2Buf) = (temp ? temp + 1900 : 0);
- }
- }
- break;
- case MYSQL_TYPE_BIT:
- {
- int bytesToCopy = db2Field.getByteLengthInRecord();
-
- if (data == NULL)
- {
- uint64 temp = field->val_int();
- memcpy(db2Buf,
- ((char*)&temp) + (sizeof(temp) - bytesToCopy),
- bytesToCopy);
- }
- else
- {
- memcpy(db2Buf,
- data,
- bytesToCopy);
- }
- }
- break;
- case MYSQL_TYPE_VARCHAR:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_BLOB:
- {
- if (field->real_type() == MYSQL_TYPE_ENUM ||
- field->real_type() == MYSQL_TYPE_SET)
- {
- int64 temp= (data == NULL ? field->val_int() : field->val_int(data));
- *(int64*)db2Buf = temp;
- }
- else
- {
- const uchar* dataToStore;
- uint32 bytesToStore;
- uint32 bytesToPad = 0;
- CHARSET_INFO* fieldCharSet = field->charset();
- uint32 maxDisplayLength = field->max_display_length();
- switch (fieldType)
- {
- case MYSQL_TYPE_STRING:
- {
- bytesToStore = maxDisplayLength;
- if (data == NULL)
- dataToStore = field->ptr;
- else
- dataToStore = data;
- }
- break;
- case MYSQL_TYPE_VARCHAR:
- {
-
- if (data == NULL)
- {
- bytesToStore = field->data_length();
- dataToStore = field->ptr + ((Field_varstring*)field)->length_bytes;
- }
- else
- {
- // Key lens are stored little-endian
- bytesToStore = *(uint8*)data + ((*(uint8*)(data+1)) << 8);
- dataToStore = data + 2;
- }
- bytesToPad = maxDisplayLength - bytesToStore;
- }
- break;
- case MYSQL_TYPE_BLOB:
- {
- if (data == NULL)
- {
- bytesToStore = ((Field_blob*)field)->get_length();
- bytesToPad = maxDisplayLength - bytesToStore;
- ((Field_blob*)field)->get_ptr((uchar**)&dataToStore);
- }
- else
- {
- // Key lens are stored little-endian
- bytesToStore = *(uint8*)data + ((*(uint8*)(data+1)) << 8);
- dataToStore = data + 2;
- }
- }
- break;
- }
-
- int32 rc;
- uint16 db2FieldType = db2Field.getType();
- switch(db2FieldType)
- {
- case QMY_CHAR:
- if (maxDisplayLength == 0)
- bytesToPad = 1;
- case QMY_VARCHAR:
- if (db2FieldType == QMY_VARCHAR)
- {
- db2Buf += sizeof(uint16);
- bytesToPad = 0;
- }
-
- if (bytesToStore > db2Field.getDataLengthInRecord())
- {
- bytesToStore = db2Field.getDataLengthInRecord();
- field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
- }
-
- if (fieldCharSet == &my_charset_bin) // If binary
- {
- if (bytesToStore)
- memcpy(db2Buf, dataToStore, bytesToStore);
- if (bytesToPad)
- memset(db2Buf + bytesToStore, 0x00, bytesToPad);
- }
- else if (db2Field.getCCSID() == 1208) // utf8
- {
- if (bytesToStore)
- memcpy(db2Buf, dataToStore, bytesToStore);
- if (bytesToPad)
- memset(db2Buf + bytesToStore, ' ', bytesToPad);
- }
- else // single-byte ASCII to EBCDIC
- {
- DBUG_ASSERT(fieldCharSet->mbmaxlen == 1);
- if (bytesToStore)
- {
- rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore, db2Buf, bytesToStore, bytesToStore, NULL);
- if (rc)
- return rc;
- }
- if (bytesToPad)
- memset(db2Buf + bytesToStore, 0x40, bytesToPad);
- }
-
- if (db2FieldType == QMY_VARCHAR)
- *(uint16*)(db2Buf - sizeof(uint16)) = bytesToStore;
- break;
- case QMY_VARGRAPHIC:
- db2Buf += sizeof(uint16);
- bytesToPad = 0;
- case QMY_GRAPHIC:
- if (maxDisplayLength == 0 && db2FieldType == QMY_GRAPHIC)
- bytesToPad = 2;
-
- if (db2Field.getCCSID() == 13488)
- {
- if (bytesToStore)
- memcpy(db2Buf, dataToStore, bytesToStore);
- if (bytesToPad)
- memset16((db2Buf + bytesToStore), 0x0020, bytesToPad/2);
- }
- else
- {
- size_t db2BytesToStore;
- size_t maxDb2BytesToStore;
-
- if (maxDisplayLength == 0 && db2FieldType == QMY_GRAPHIC)
- maxDb2BytesToStore = 2;
- else
- maxDb2BytesToStore = min(((bytesToStore * 2) / fieldCharSet->mbminlen),
- ((maxDisplayLength * 2) / fieldCharSet->mbmaxlen));
-
- if (bytesToStore == 0)
- db2BytesToStore = 0;
- else
- {
- rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore, db2Buf, bytesToStore, maxDb2BytesToStore, &db2BytesToStore);
- if (rc)
- return rc;
- bytesToStore = db2BytesToStore;
- }
- if (db2BytesToStore < maxDb2BytesToStore) // If need to pad
- memset16((db2Buf + db2BytesToStore), 0x0020, (maxDb2BytesToStore - db2BytesToStore)/2);
- }
-
- if (db2FieldType == QMY_VARGRAPHIC)
- *(uint16*)(db2Buf-sizeof(uint16)) = bytesToStore/2;
- break;
- case QMY_BLOBCLOB:
- case QMY_DBCLOB:
- {
- DBUG_ASSERT(data == NULL);
- DB2LobField* lobField = (DB2LobField*)(db2Buf + db2Field.calcBlobPad());
-
- if ((fieldCharSet == &my_charset_bin) || // binary or
- (db2Field.getCCSID()==13488) ||
- (db2Field.getCCSID()==1208)) // binary UTF8
- {
- }
- else
- {
- char* temp;
- int32 rc;
- size_t db2BytesToStore;
- if (fieldCharSet->mbmaxlen == 1) // single-byte ASCII to EBCDIC
- {
- temp = getCharacterConversionBuffer(field->field_index, bytesToStore);
- rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore,temp,bytesToStore, bytesToStore, NULL);
- if (rc)
- return (rc);
- }
- else // Else Far East, special UTF8 or non-special UTF8/UCS2
- {
- size_t maxDb2BytesToStore;
- maxDb2BytesToStore = min(((bytesToStore * 2) / fieldCharSet->mbminlen),
- ((maxDisplayLength * 2) / fieldCharSet->mbmaxlen));
- temp = getCharacterConversionBuffer(field->field_index, maxDb2BytesToStore);
- rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore,temp,bytesToStore, maxDb2BytesToStore, &db2BytesToStore);
- if (rc)
- return (rc);
- bytesToStore = db2BytesToStore;
- }
- dataToStore = (uchar*)temp;
- }
-
- uint16 blobID = db2Table->getBlobIdFromField(field->field_index);
- if (blobWriteBuffers[blobID] != (char*)dataToStore)
- blobWriteBuffers[blobID].reassign((char*)dataToStore);
- if ((void*)blobWriteBuffers[blobID])
- lobField->dataHandle = (ILEMemHandle)blobWriteBuffers[blobID];
- else
- lobField->dataHandle = 0;
- lobField->length = bytesToStore / (db2FieldType == QMY_DBCLOB ? 2 : 1);
- }
- break;
- }
- }
- }
- break;
- default:
- DBUG_ASSERT(0);
- break;
- }
-
- return (ha_thd()->is_error());
-}
-
-
-/**
- Convert DB2 field data into the equivalent MySQL format
-
- @param db2Field The DB2 field definition
- @param field The MySQL field to receive the converted data
- @param buf The DB2 data to be converted
-*/
-int32 ha_ibmdb2i::convertDB2toMySQL(const DB2Field& db2Field, Field* field, const char* buf)
-{
- int32 storeRC = 0; // Result of the field->store() operation
-
- const char* bufPtr = buf + db2Field.getBufferOffset();
-
- switch (field->type())
- {
- case MYSQL_TYPE_NEWDECIMAL:
- {
- uint precision= ((Field_new_decimal*)field)->precision;
- uint scale= field->decimals();
- uint db2Precision = min(precision, MAX_DEC_PRECISION);
- uint decimalPlace = precision-scale+1;
- char temp[80];
-
- if (precision <= MAX_DEC_PRECISION ||
- scale > precision - MAX_DEC_PRECISION)
- {
- uint numNibbles = db2Precision + (db2Precision % 2 ? 0 : 1);
-
- temp[0] = (bcdGet(bufPtr, numNibbles) == 0xD ? '-' : ' ');
- int strPos=1;
- int bcdPos=(db2Precision % 2 ? 0 : 1);
-
- for (;bcdPos < numNibbles; bcdPos++, strPos++)
- {
- if (strPos == decimalPlace)
- {
- temp[strPos] = '.';
- strPos++;
- }
-
- temp[strPos] = bcdGet(bufPtr, bcdPos) + '0';
- }
-
- temp[strPos] = 0;
-
- storeRC = field->store(temp, strPos, &my_charset_latin1);
- }
- }
- break;
- case MYSQL_TYPE_TINY:
- {
- storeRC = field->store(*(int16*)bufPtr, ((Field_num*)field)->unsigned_flag);
- }
- break;
- case MYSQL_TYPE_SHORT:
- {
- if (((Field_num*)field)->unsigned_flag)
- {
- storeRC = field->store(*(int32*)bufPtr, TRUE);
- }
- else
- {
- storeRC = field->store(*(int16*)bufPtr, FALSE);
- }
- }
- break;
- case MYSQL_TYPE_LONG:
- {
- if (((Field_num*)field)->unsigned_flag)
- {
- storeRC = field->store(*(int64*)bufPtr, TRUE);
- }
- else
- {
- storeRC = field->store(*(int32*)bufPtr, FALSE);
- }
- }
- break;
- case MYSQL_TYPE_FLOAT:
- {
- storeRC = field->store(*(float*)bufPtr);
- }
- break;
- case MYSQL_TYPE_DOUBLE:
- {
- storeRC = field->store(*(double*)bufPtr);
- }
- break;
- case MYSQL_TYPE_LONGLONG:
- {
- char temp[23];
- if (((Field_num*)field)->unsigned_flag)
- {
- temp[0] = (bcdGet(bufPtr, 21) == 0xD ? '-' : ' ');
- int strPos=1;
- int bcdPos=0;
-
- for (;bcdPos <= 20; bcdPos++, strPos++)
- {
- temp[strPos] = bcdGet(bufPtr, bcdPos) + '0';
- }
-
- temp[strPos] = 0;
-
- storeRC = field->store(temp, strPos, &my_charset_latin1);
- }
- else
- {
- storeRC = field->store(*(int64*)bufPtr, FALSE);
- }
- }
- break;
- case MYSQL_TYPE_INT24:
- {
- storeRC = field->store(*(int32*)bufPtr, ((Field_num*)field)->unsigned_flag);
- }
- break;
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_NEWDATE:
- {
- longlong value= a4toi_ebcdic((uchar*)bufPtr) * 10000 +
- a2toi_ebcdic((uchar*)bufPtr+5) * 100 +
- a2toi_ebcdic((uchar*)bufPtr+8);
-
- if (cachedZeroDateOption == SUBSTITUTE_0001_01_01 &&
- value == (10000 + 100 + 1))
- value = 0;
-
- storeRC = field->store(value);
- }
- break;
- case MYSQL_TYPE_TIME:
- {
- if (db2Field.getType() == QMY_TIME)
- {
- longlong value= a2toi_ebcdic((uchar*)bufPtr) * 10000 +
- a2toi_ebcdic((uchar*)bufPtr+3) * 100 +
- a2toi_ebcdic((uchar*)bufPtr+6);
-
- storeRC = field->store(value);
- }
- else
- storeRC = field->store(*((int32*)bufPtr));
- }
- break;
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATETIME:
- {
- longlong value= (a4toi_ebcdic((uchar*)bufPtr) * 10000 +
- a2toi_ebcdic((uchar*)bufPtr+5) * 100 +
- a2toi_ebcdic((uchar*)bufPtr+8)) * 1000000LL +
- (a2toi_ebcdic((uchar*)bufPtr+11) * 10000 +
- a2toi_ebcdic((uchar*)bufPtr+14) * 100 +
- a2toi_ebcdic((uchar*)bufPtr+17));
-
- if (cachedZeroDateOption == SUBSTITUTE_0001_01_01 &&
- value == (10000 + 100 + 1) * 1000000LL)
- value = 0;
-
- storeRC = field->store(value);
- }
- break;
- case MYSQL_TYPE_YEAR:
- {
- if (db2Field.getType() == QMY_CHAR)
- {
- storeRC = field->store(bufPtr, 4, &my_charset_bin);
- }
- else
- {
- storeRC = field->store(*((uint16*)bufPtr));
- }
- }
- break;
- case MYSQL_TYPE_BIT:
- {
- uint64 temp= 0;
- int bytesToCopy= db2Field.getByteLengthInRecord();
- memcpy(((char*)&temp) + (sizeof(temp) - bytesToCopy), bufPtr, bytesToCopy);
- storeRC = field->store(temp, TRUE);
- }
- break;
- case MYSQL_TYPE_VARCHAR:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_BLOB:
- {
- if (field->real_type() == MYSQL_TYPE_ENUM ||
- field->real_type() == MYSQL_TYPE_SET)
- {
- storeRC = field->store(*(int64*)bufPtr);
- }
- else
- {
-
- const char* dataToStore = NULL;
- uint32 bytesToStore = 0;
- CHARSET_INFO* fieldCharSet = field->charset();
- switch(db2Field.getType())
- {
- case QMY_CHAR:
- case QMY_GRAPHIC:
- {
- bytesToStore = db2Field.getByteLengthInRecord();
- if (bytesToStore == 0)
- bytesToStore = 1;
- dataToStore = bufPtr;
- }
- break;
- case QMY_VARCHAR:
- {
- bytesToStore = *(uint16*)bufPtr;
- dataToStore = bufPtr+sizeof(uint16);
- }
- break;
- case QMY_VARGRAPHIC:
- {
- /* For VARGRAPHIC, convert the number of double-byte characters
- to the number of bytes. */
- bytesToStore = (*(uint16*)bufPtr)*2;
- dataToStore = bufPtr+sizeof(uint16);
- }
- break;
- case QMY_DBCLOB:
- case QMY_BLOBCLOB:
- {
- DB2LobField* lobField = (DB2LobField* )(bufPtr + db2Field.calcBlobPad());
- bytesToStore = lobField->length * (db2Field.getType() == QMY_DBCLOB ? 2 : 1);
- dataToStore = (char*)blobReadBuffers->getBufferPtr(field->field_index);
- }
- break;
-
- }
-
- if ((fieldCharSet != &my_charset_bin) && // not binary &
- (db2Field.getCCSID() != 13488) && // not UCS2 &
- (db2Field.getCCSID() != 1208))
- {
- char* temp;
- size_t db2BytesToStore;
- int rc;
- if (fieldCharSet->mbmaxlen > 1)
- {
- size_t maxDb2BytesToStore = ((bytesToStore / 2) * fieldCharSet->mbmaxlen); // Worst case for number of bytes
- temp = getCharacterConversionBuffer(field->field_index, maxDb2BytesToStore);
- rc = convertFieldChars(toMySQL, field->field_index, dataToStore, temp, bytesToStore, maxDb2BytesToStore, &db2BytesToStore);
- bytesToStore = db2BytesToStore;
- }
- else // single-byte ASCII to EBCDIC
- {
- temp = getCharacterConversionBuffer(field->field_index, bytesToStore);
- rc = convertFieldChars(toMySQL, field->field_index, dataToStore, temp, bytesToStore, bytesToStore, NULL);
- }
- if (rc)
- return (rc);
- dataToStore = temp;
- }
-
- if ((field)->flags & BLOB_FLAG)
- ((Field_blob*)(field))->set_ptr(bytesToStore, (uchar*)dataToStore);
- else
- storeRC = field->store(dataToStore, bytesToStore, &my_charset_bin);
- }
- }
- break;
- default:
- DBUG_ASSERT(0);
- break;
-
- }
-
- if (storeRC)
- {
- invalidDataFound = true;
- }
-
- return 0;
-}
diff --git a/storage/ibmdb2i/db2i_errors.cc b/storage/ibmdb2i/db2i_errors.cc
deleted file mode 100644
index dd50e40e61b..00000000000
--- a/storage/ibmdb2i/db2i_errors.cc
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#include "db2i_errors.h"
-#include "db2i_ileBridge.h"
-#include "db2i_charsetSupport.h"
-#include "mysql_priv.h"
-#include "stdarg.h"
-
-#define MAX_MSGSTRING 109
-
-/*
- The following strings are associated with errors that can be produced
- within the storage engine proper.
-*/
-static const char* engineErrors[MAX_MSGSTRING] =
-{
- {""},
- {"Error opening codeset conversion from %.64s to %.64s (errno = %d)"},
- {"Invalid %-.10s name '%-.128s'"},
- {"Unsupported move from '%-.128s' to '%-.128s' on RENAME TABLE statement"},
- {"The %-.64s character set is not supported."},
- {"Auto_increment is not allowed for a partitioned table"},
- {"Character set conversion error due to unknown encoding scheme %d"},
- {""},
- {"Table '%-.128s' was not found by the storage engine"},
- {"Could not resolve to %-.128s in library %-.10s type %-.10s (errno = %d)"},
- {"Error on _PGMCALL for program %-.10s in library %-.10s (error = %d)"},
- {"Error on _ILECALL for API '%.128s' (error = %d)"},
- {"Error in iconv() function during character set conversion (errno = %d)"},
- {"Error from Get Encoding Scheme (QTQGESP) API: %d, %d, %d"},
- {"Error from Get Related Default CCSID (QTQGRDC) API: %d, %d, %d"},
- {"Data out of range for column '%.192s'"},
- {"Schema name '%.128s' exceeds maximum length of %d characters"},
- {"Multiple collations not supported in a single index or constraint"},
- {"Sort sequence was not found"},
- {"One or more characters in column %.128s were substituted during conversion"},
- {"A decimal column exceeded the maximum precision. Data may be truncated."},
- {"Some data returned by DB2 for table %s could not be converted for MySQL"},
- {""},
- {"Column %.128s contains characters that cannot be converted"},
- {"An invalid name was specified for ibmdb2i_rdb_name."},
- {"A duplicate key was encountered for index '%.128s'"},
- {"A table with the same name exists but has incompatible column definitions."},
- {"The created table was discovered as an existing DB2 object."},
- {"Some attribute(s) defined for column '%.128s' may not be honored by accesses from DB2."},
-};
-
-/*
- The following strings are associated with errors that can be returned
- by the operating system via the QMY_* APIs. Most are very uncommon and
- indicate a bug somewhere.
-*/
-static const char* systemErrors[MAX_MSGSTRING] =
-{
- {"Thread ID is too long"},
- {"Error creating a SPACE memory object"},
- {"Error creating a FILE memory object"},
- {"Error creating a SPACE synchronization token"},
- {"Error creating a FILE synchronization token"},
- {"See message %-.7s in joblog for job %-.6s/%-.10s/%-.10s."},
- {"Error unlocking a synchronization token when closing a connection"},
- {"Invalid action specified for an 'object lock' request"},
- {"Invalid action specified for a savepoint request"},
- {"Partial keys are not supported with an ICU sort sequence"},
- {"Error retrieving an ICU sort key"},
- {"Error converting single-byte sort sequence to UCS-2"},
- {"An unsupported collation was specified"},
- {"Validation failed for referenced table of foreign key constraint"},
- {"Error extracting table for constraint information"},
- {"Error extracting referenced table for constraint information"},
- {"Invalid action specified for a 'commitment control' request"},
- {"Invalid commitment control isolation level specified on 'open' request"},
- {"Invalid file handle"},
- {" "},
- {"Invalid option specified for returning data on 'read' request"},
- {"Invalid orientation specified for 'read' request"},
- {"Invalid option type specified for 'read' request"},
- {"Invalid isolation level for starting commitment control"},
- {"Error unlocking a synchronization token in module QMYALC"},
- {"Length of space for returned format is not long enough"},
- {"SQL XA transactions are currently unsupported by this interface"},
- {"The associated QSQSRVR job was killed or ended unexpectedly."},
- {"Error unlocking a synchronization token in module QMYSEI"},
- {"Error unlocking a synchronization token in module QMYSPO"},
- {"Error converting input CCSID from short form to long form"},
- {" "},
- {"Error getting associated CCSID for CCSID conversion"},
- {"Error converting a string from one CCSID to another"},
- {"Error unlocking a synchronization token"},
- {"Error destroying a synchronization token"},
- {"Error locking a synchronization token"},
- {"Error recreating a synchronization token"},
- {"A space handle was not specified for a constraint request"},
- {"An SQL cursor was specified for a delete request"},
- {" "},
- {"Error on delete request because current UFCB for connection is not open"},
- {"An SQL cursor was specified for an object initialization request"},
- {"An SQL cursor was specified for an object override request"},
- {"A space handle was not specified for an object override request"},
- {"An SQL cursor was specified for an information request"},
- {"An SQL cursor was specified for an object lock request"},
- {"An SQL cursor was specified for an optimize request"},
- {"A data handle was not specified for a read request"},
- {"A row number handle was not specified for a read request"},
- {"A key handle was not specified for a read request"},
- {"An SQL cursor was specified for an row estimation request"},
- {"A space handle was not specified for a row estimation request"},
- {"An SQL cursor was specified for a release record request"},
- {"A statement handle was not specified for an 'execute immediate' request"},
- {"A statement handle was not specified for a 'prepare open' request"},
- {"An SQL cursor was specified for an update request"},
- {"The UFCB was not open for read"},
- {"Error on update request because current UFCB for connection is not open"},
- {"A data handle was not specified for an update request"},
- {"An SQL cursor was specified for a write request"},
- {"A data handle was not specified for a write request"},
- {"An unknown function was specified on a process request"},
- {"A share definition was not specified for an 'allocate share' request"},
- {"A share handle was not specified for an 'allocate share' request"},
- {"A use count handle was not specified for an 'allocate share' request"},
- {"A 'records per key' handle was not specified for an information request"},
- {"Error resolving LOB addresss"},
- {"Length of a LOB space is too small"},
- {"An unknown function was specified for a server request"},
- {"Object authorization failed. See message %-.7s in joblog for job %-.6s/%-.10s/%-.10s. for more information."},
- {" "},
- {"Error locking mutex on server"},
- {"Error unlocking mutex on server"},
- {"Error checking for RDB name in RDB Directory"},
- {"Error creating mutex on server"},
- {"A table with that name already exists"},
- {" "},
- {"Error unlocking mutex"},
- {"Error connecting to server job"},
- {"Error connecting to server job"},
- {" "},
- {"Function check occurred while registering parameter spaces. See joblog."},
- {" "},
- {" "},
- {"End of block"},
- {"The file has changed and might not be compatible with the MySQL table definition"},
- {"Error giving pipe to server job"},
- {"There are open object locks when attempting to deallocate"},
- {"There is no open lock"},
- {" "},
- {" "},
- {"The maximum value for the auto_increment data type was exceeded"},
- {"Error occurred closing the pipe "},
- {"Error occurred taking a descriptor for the pipe"},
- {"Error writing to pipe "},
- {"Server was interrupted "},
- {"No pipe descriptor exists for reuse "},
- {"Error occurred during an SQL prepare statement "},
- {"Error occurred during an SQL open "},
- {" "},
- {" "},
- {" "},
- {" "},
- {" "},
- {" "},
- {"An unspecified error was returned from the system."},
- {" "}
-};
-
-/**
- This function builds the text string for an error code, and substitutes
- a variable number of replacement variables into the string.
-*/
-void getErrTxt(int errCode, ...)
-{
- va_list args;
- va_start(args,errCode);
- char* buffer = db2i_ileBridge::getBridgeForThread()->getErrorStorage();
- const char* msg;
-
- if (errCode >= QMY_ERR_MIN && errCode <= QMY_ERR_SQ_OPEN)
- msg = systemErrors[errCode - QMY_ERR_MIN];
- else
- {
- DBUG_ASSERT(errCode >= DB2I_FIRST_ERR && errCode <= DB2I_LAST_ERR);
- msg = engineErrors[errCode - DB2I_FIRST_ERR];
- }
-
- (void) my_vsnprintf (buffer, MYSQL_ERRMSG_SIZE, msg, args);
- va_end(args);
- fprintf(stderr,"ibmdb2i error %d: %s\n",errCode,buffer);
- DBUG_PRINT("error", ("ibmdb2i error %d: %s",errCode,buffer));
-}
-
-static inline void trimSpace(char* str)
-{
- char* end = strchr(str, ' ');
- if (end) *end = 0;
-}
-
-
-/**
- Generate the error text specific to an API error returned by a QMY_* API.
-
- @parm errCode The error value
- @parm errInfo The structure containing the message and job identifiers.
-*/
-void reportSystemAPIError(int errCode, const Qmy_Error_output *errInfo)
-{
- if (errCode >= QMY_ERR_MIN && errCode <= QMY_ERR_SQ_OPEN)
- {
- switch(errCode)
- {
- case QMY_ERR_MSGID:
- case QMY_ERR_NOT_AUTH:
- {
- DBUG_ASSERT(errInfo);
- char jMsg[8]; // Error message ID
- char jName[11]; // Job name
- char jUser[11]; // Job user
- char jNbr[7]; // Job number
- memset(jMsg, 0, sizeof(jMsg));
- memset(jName, 0, sizeof(jMsg));
- memset(jUser, 0, sizeof(jMsg));
- memset(jMsg, 0, sizeof(jMsg));
-
- convFromEbcdic(errInfo->MsgId,jMsg,sizeof(jMsg)-1);
- convFromEbcdic(errInfo->JobName,jName,sizeof(jName)-1);
- trimSpace(jName);
- convFromEbcdic(errInfo->JobUser,jUser,sizeof(jUser)-1);
- trimSpace(jUser);
- convFromEbcdic(errInfo->JobNbr,jNbr,sizeof(jNbr)-1);
- getErrTxt(errCode,jMsg,jNbr,jUser,jName);
- }
- break;
- case QMY_ERR_RTNFMT:
- {
- getErrTxt(QMY_ERR_LVLID_MISMATCH);
- }
- break;
- default:
- getErrTxt(errCode);
- break;
- }
- }
-}
-
-
-/**
- Generate a warning for the specified error.
-*/
-void warning(THD *thd, int errCode, ...)
-{
- va_list args;
- va_start(args,errCode);
- char buffer[MYSQL_ERRMSG_SIZE];
- const char* msg;
-
- DBUG_ASSERT(errCode >= DB2I_FIRST_ERR && errCode <= DB2I_LAST_ERR);
- msg = engineErrors[errCode - DB2I_FIRST_ERR];
-
- (void) my_vsnprintf (buffer, MYSQL_ERRMSG_SIZE, msg, args);
- va_end(args);
- DBUG_PRINT("warning", ("ibmdb2i warning %d: %s",errCode,buffer));
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, errCode, buffer);
-}
-
-
diff --git a/storage/ibmdb2i/db2i_errors.h b/storage/ibmdb2i/db2i_errors.h
deleted file mode 100644
index b6dd314ef50..00000000000
--- a/storage/ibmdb2i/db2i_errors.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#ifndef DB2I_ERRORS_H
-#define DB2I_ERRORS_H
-
-#include "qmyse.h"
-class THD;
-
-/**
- @enum DB2I_errors
-
- @brief These are the errors that can be returned by the storage engine proper
- and that are specific to the engine. Refer to db2i_errors.cc for text
- descriptions of the errors.
-*/
-
-enum DB2I_errors
-{
- DB2I_FIRST_ERR = 2500,
- DB2I_ERR_ICONV_OPEN,
- DB2I_ERR_INVALID_NAME,
- DB2I_ERR_RENAME_MOVE,
- DB2I_ERR_UNSUPP_CHARSET,
- DB2I_ERR_PART_AUTOINC,
- DB2I_ERR_UNKNOWN_ENCODING,
- DB2I_ERR_RESERVED,
- DB2I_ERR_TABLE_NOT_FOUND,
- DB2I_ERR_RESOLVE_OBJ,
- DB2I_ERR_PGMCALL,
- DB2I_ERR_ILECALL,
- DB2I_ERR_ICONV,
- DB2I_ERR_QTQGESP,
- DB2I_ERR_QTQGRDC,
- DB2I_ERR_INVALID_COL_VALUE,
- DB2I_ERR_TOO_LONG_SCHEMA,
- DB2I_ERR_MIXED_COLLATIONS,
- DB2I_ERR_SRTSEQ,
- DB2I_ERR_SUB_CHARS,
- DB2I_ERR_PRECISION,
- DB2I_ERR_INVALID_DATA,
- DB2I_ERR_RESERVED2,
- DB2I_ERR_ILL_CHAR,
- DB2I_ERR_BAD_RDB_NAME,
- DB2I_ERR_UNKNOWN_IDX,
- DB2I_ERR_DISCOVERY_MISMATCH,
- DB2I_ERR_WARN_CREATE_DISCOVER,
- DB2I_ERR_WARN_COL_ATTRS,
- DB2I_LAST_ERR = DB2I_ERR_WARN_COL_ATTRS
-};
-
-void getErrTxt(int errcode, ...);
-void reportSystemAPIError(int errCode, const Qmy_Error_output *errInfo);
-void warning(THD *thd, int errCode, ...);
-
-const char* DB2I_SQL0350 = "\xE2\xD8\xD3\xF0\xF3\xF5\xF0"; // SQL0350 in EBCDIC
-const char* DB2I_CPF503A = "\xC3\xD7\xC6\xF5\xF0\xF3\xC1"; // CPF503A in EBCDIC
-const char* DB2I_SQL0538 = "\xE2\xD8\xD3\xF0\xF5\xF3\xF8"; // SQL0538 in EBCDIC
-
-#endif
diff --git a/storage/ibmdb2i/db2i_file.cc b/storage/ibmdb2i/db2i_file.cc
deleted file mode 100644
index 2d83248eea7..00000000000
--- a/storage/ibmdb2i/db2i_file.cc
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-
-#include "db2i_file.h"
-#include "db2i_charsetSupport.h"
-#include "db2i_collationSupport.h"
-#include "db2i_misc.h"
-#include "db2i_errors.h"
-#include "my_dir.h"
-
-db2i_table::db2i_table(const TABLE_SHARE* myTable, const char* path) :
- mysqlTable(myTable),
- db2StartId(0),
- blobFieldCount(0),
- blobFields(NULL),
- blobFieldActualSizes(NULL),
- logicalFiles(NULL),
- physicalFile(NULL),
- db2TableNameSQLAscii(NULL),
- db2LibNameSQLAscii(NULL)
-{
- char asciiLibName[MAX_DB2_SCHEMANAME_LENGTH + 1];
- getDB2LibNameFromPath(path, asciiLibName, ASCII_NATIVE);
-
- char asciiFileName[MAX_DB2_FILENAME_LENGTH + 1];
- getDB2FileNameFromPath(path, asciiFileName, ASCII_NATIVE);
-
- size_t libNameLen = strlen(asciiLibName);
- size_t fileNameLen = strlen(asciiFileName);
-
- db2LibNameEbcdic=(char *)
- my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &db2LibNameEbcdic, libNameLen+1,
- &db2LibNameAscii, libNameLen+1,
- &db2LibNameSQLAscii, libNameLen*2 + 1,
- &db2TableNameEbcdic, fileNameLen+1,
- &db2TableNameAscii, fileNameLen+1,
- &db2TableNameSQLAscii, fileNameLen*2 + 1,
- NullS);
-
- if (likely(db2LibNameEbcdic))
- {
- memcpy(db2LibNameAscii, asciiLibName, libNameLen);
- convertNativeToSQLName(db2LibNameAscii, db2LibNameSQLAscii);
- convToEbcdic(db2LibNameAscii, db2LibNameEbcdic, libNameLen);
- memcpy(db2TableNameAscii, asciiFileName, fileNameLen);
- convertNativeToSQLName(db2TableNameAscii, db2TableNameSQLAscii);
- convToEbcdic(db2TableNameAscii, db2TableNameEbcdic, fileNameLen);
- }
-
- conversionDefinitions[toMySQL] = NULL;
- conversionDefinitions[toDB2] = NULL;
-
- isTemporaryTable = (strstr(mysqlTable->path.str, mysql_tmpdir) == mysqlTable->path.str);
-}
-
-
-int32 db2i_table::initDB2Objects(const char* path)
-{
- uint fileObjects = 1 + mysqlTable->keys;
- ValidatedPointer<ShrDef> fileDefnSpace(sizeof(ShrDef) * fileObjects);
-
- physicalFile = new db2i_file(this);
- physicalFile->fillILEDefn(&fileDefnSpace[0], true);
-
- logicalFileCount = mysqlTable->keys;
- if (logicalFileCount > 0)
- {
- logicalFiles = new db2i_file*[logicalFileCount];
- for (int k = 0; k < logicalFileCount; k++)
- {
- logicalFiles[k] = new db2i_file(this, k);
- logicalFiles[k]->fillILEDefn(&fileDefnSpace[k+1], false);
- }
- }
-
- ValidatedPointer<FILE_HANDLE> fileDefnHandles(sizeof(FILE_HANDLE) * fileObjects);
- size_t formatSpaceLen = sizeof(format_hdr_t) + mysqlTable->fields * sizeof(DB2Field);
- formatSpace.alloc(formatSpaceLen);
-
- int rc = db2i_ileBridge::getBridgeForThread()->
- expectErrors(QMY_ERR_RTNFMT)->
- allocateFileDefn(fileDefnSpace,
- fileDefnHandles,
- fileObjects,
- db2LibNameEbcdic,
- strlen(db2LibNameEbcdic),
- formatSpace,
- formatSpaceLen);
-
- if (rc)
- {
- // We have to handle a format space error as a special case of a FID
- // mismatch. We should only get the space error if columns have been added
- // to the DB2 table without MySQL's knowledge, which is effectively a
- // FID problem.
- if (rc == QMY_ERR_RTNFMT)
- {
- rc = QMY_ERR_LVLID_MISMATCH;
- getErrTxt(rc);
- }
- return rc;
- }
-
- convFromEbcdic(((format_hdr_t*)formatSpace)->FilLvlId, fileLevelID, sizeof(fileLevelID));
-
- if (!doFileIDsMatch(path))
- {
- getErrTxt(QMY_ERR_LVLID_MISMATCH);
- return QMY_ERR_LVLID_MISMATCH;
- }
-
- physicalFile->setMasterDefnHandle(fileDefnHandles[0]);
- for (int k = 0; k < mysqlTable->keys; k++)
- {
- logicalFiles[k]->setMasterDefnHandle(fileDefnHandles[k+1]);
- }
-
- db2StartId = (uint64)(((format_hdr_t*)formatSpace)->StartIdVal);
- db2Fields = (DB2Field*)((char*)(void*)formatSpace + ((format_hdr_t*)formatSpace)->ColDefOff);
-
- uint fields = mysqlTable->fields;
- for (int i = 0; i < fields; ++i)
- {
- if (db2Field(i).isBlob())
- {
- blobFieldCount++;
- }
- }
-
- if (blobFieldCount)
- {
- blobFieldActualSizes = (uint*)my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &blobFieldActualSizes, blobFieldCount * sizeof(uint),
- &blobFields, blobFieldCount * sizeof(uint16),
- NullS);
-
- int b = 0;
- for (int i = 0; i < fields; ++i)
- {
- if (db2Field(i).isBlob())
- {
- blobFields[b++] = i;
- }
- }
- }
-
- my_multi_malloc(MYF(MY_WME),
- &conversionDefinitions[toMySQL], fields * sizeof(iconv_t),
- &conversionDefinitions[toDB2], fields * sizeof(iconv_t),
- NullS);
- for (int i = 0; i < fields; ++i)
- {
- conversionDefinitions[toMySQL][i] = (iconv_t)(-1);
- conversionDefinitions[toDB2][i] = (iconv_t)(-1);
- }
-
- return 0;
-}
-
-int db2i_table::fastInitForCreate(const char* path)
-{
- ValidatedPointer<ShrDef> fileDefnSpace(sizeof(ShrDef));
-
- physicalFile = new db2i_file(this);
- physicalFile->fillILEDefn(fileDefnSpace, true);
-
- ValidatedPointer<FILE_HANDLE> fileDefnHandles(sizeof(FILE_HANDLE));
-
- size_t formatSpaceLen = sizeof(format_hdr_t) +
- mysqlTable->fields * sizeof(DB2Field);
- formatSpace.alloc(formatSpaceLen);
-
- int rc = db2i_ileBridge::getBridgeForThread()->allocateFileDefn(fileDefnSpace,
- fileDefnHandles,
- 1,
- db2LibNameEbcdic,
- strlen(db2LibNameEbcdic),
- formatSpace,
- formatSpaceLen);
-
- if (rc)
- return rc;
-
- convFromEbcdic(((format_hdr_t*)formatSpace)->FilLvlId, fileLevelID, sizeof(fileLevelID));
- doFileIDsMatch(path);
-
- return 0;
-}
-
-bool db2i_table::doFileIDsMatch(const char* path)
-{
- char name_buff[FN_REFLEN];
-
- fn_format(name_buff, path, "", FID_EXT, (MY_REPLACE_EXT | MY_UNPACK_FILENAME));
-
- File fd = my_open(name_buff, O_RDONLY, MYF(0));
-
- if (fd == -1)
- {
- if (errno == ENOENT)
- {
- fd = my_create(name_buff, 0, O_WRONLY, MYF(MY_WME));
-
- if (fd == -1)
- {
- // TODO: Report errno here
- return false;
- }
- my_write(fd, (uchar*)fileLevelID, sizeof(fileLevelID), MYF(MY_WME));
- my_close(fd, MYF(0));
- return true;
- }
- else
- {
- // TODO: Report errno here
- return false;
- }
- }
-
- char diskFID[sizeof(fileLevelID)];
-
- bool match = false;
-
- if (my_read(fd, (uchar*)diskFID, sizeof(diskFID), MYF(MY_WME)) == sizeof(diskFID) &&
- (memcmp(diskFID, fileLevelID, sizeof(diskFID)) == 0))
- match = true;
-
- my_close(fd, MYF(0));
-
- return match;
-}
-
-void db2i_table::deleteAssocFiles(const char* name)
-{
- char name_buff[FN_REFLEN];
- fn_format(name_buff, name, "", FID_EXT, (MY_REPLACE_EXT | MY_UNPACK_FILENAME));
- my_delete(name_buff, MYF(0));
-}
-
-void db2i_table::renameAssocFiles(const char* from, const char* to)
-{
- rename_file_ext(from, to, FID_EXT);
-}
-
-
-db2i_table::~db2i_table()
-{
- my_free(blobFieldActualSizes);
- my_free(conversionDefinitions[toMySQL]);
-
- if (logicalFiles)
- {
- for (int k = 0; k < logicalFileCount; ++k)
- {
- delete logicalFiles[k];
- }
-
- delete[] logicalFiles;
- }
- delete physicalFile;
-
- my_free(db2LibNameEbcdic);
-}
-
-void db2i_table::getDB2QualifiedName(char* to)
-{
- strcat(to, getDB2LibName(ASCII_SQL));
- strcat(to, ".");
- strcat(to, getDB2TableName(ASCII_SQL));
-}
-
-
-void db2i_table::getDB2QualifiedNameFromPath(const char* path, char* to)
-{
- getDB2LibNameFromPath(path, to);
- strcat(to, ".");
- getDB2FileNameFromPath(path, strend(to));
-}
-
-
-size_t db2i_table::smartFilenameToTableName(const char *in, char* out, size_t outlen)
-{
- if (strchr(in, '@') == NULL)
- {
- return filename_to_tablename(in, out, outlen);
- }
-
- char* test = (char*) my_malloc(outlen, MYF(MY_WME));
-
- filename_to_tablename(in, test, outlen);
-
- char* cur = test;
-
- while (*cur)
- {
- if ((*cur <= 0x20) || (*cur >= 0x80))
- {
- strncpy(out, in, outlen);
- my_free(test);
- return min(outlen, strlen(out));
- }
- ++cur;
- }
-
- strncpy(out, test, outlen);
- my_free(test);
- return min(outlen, strlen(out));
-}
-
-void db2i_table::filenameToTablename(const char* in, char* out, size_t outlen)
-{
- if (strchr(in, '#') == NULL)
- {
- smartFilenameToTableName(in, out, outlen);
- return;
- }
-
- char* temp = (char*)sql_alloc(outlen);
-
- const char* part1, *part2, *part3, *part4;
- part1 = in;
- part2 = strstr(part1, "#P#");
- if (part2);
- {
- part3 = part2 + 3;
- part4 = strchr(part3, '#');
- if (!part4)
- part4 = strend(in);
- }
-
- memcpy(temp, part1, min(outlen, part2 - part1));
- temp[min(outlen-1, part2-part1)] = 0;
-
- int32 accumLen = smartFilenameToTableName(temp, out, outlen);
-
- if (part2 && (accumLen + 4 < outlen))
- {
- strcat(out, "#P#");
- accumLen += 4;
-
- memset(temp, 0, min(outlen, part2-part1));
- memcpy(temp, part3, min(outlen, part4-part3));
- temp[min(outlen-1, part4-part3)] = 0;
-
- accumLen += smartFilenameToTableName(temp, strend(out), outlen-accumLen);
-
- if (part4 && (accumLen + (strend(in) - part4 + 1) < outlen))
- {
- strcat(out, part4);
- }
- }
-}
-
-void db2i_table::getDB2LibNameFromPath(const char* path, char* lib, NameFormatFlags format)
-{
- if (strstr(path, mysql_tmpdir) == path)
- {
- strcpy(lib, DB2I_TEMP_TABLE_SCHEMA);
- }
- else
- {
- const char* c = strend(path) - 1;
- while (c > path && *c != '\\' && *c != '/')
- --c;
-
- if (c != path)
- {
- const char* dbEnd = c;
- do {
- --c;
- } while (c >= path && *c != '\\' && *c != '/');
-
- if (c >= path)
- {
- const char* dbStart = c+1;
- char fileName[FN_REFLEN];
- memcpy(fileName, dbStart, dbEnd - dbStart);
- fileName[dbEnd-dbStart] = 0;
-
- char dbName[MAX_DB2_SCHEMANAME_LENGTH+1];
- filenameToTablename(fileName, dbName , sizeof(dbName));
-
- convertMySQLNameToDB2Name(dbName, lib, sizeof(dbName), true, (format==ASCII_SQL) );
- }
- else
- DBUG_ASSERT(0); // This should never happen!
- }
- }
-}
-
-void db2i_table::getDB2FileNameFromPath(const char* path, char* file, NameFormatFlags format)
-{
- const char* fileEnd = strend(path);
- const char* c = fileEnd;
- while (c > path && *c != '\\' && *c != '/')
- --c;
-
- if (c != path)
- {
- const char* fileStart = c+1;
- char fileName[FN_REFLEN];
- memcpy(fileName, fileStart, fileEnd - fileStart);
- fileName[fileEnd - fileStart] = 0;
- char db2Name[MAX_DB2_FILENAME_LENGTH+1];
- filenameToTablename(fileName, db2Name, sizeof(db2Name));
- convertMySQLNameToDB2Name(db2Name, file, sizeof(db2Name), true, (format==ASCII_SQL) );
- }
-}
-
-// Generates the DB2 index name when given the MySQL index and table names.
-int32 db2i_table::appendQualifiedIndexFileName(const char* indexName,
- const char* tableName,
- String& to,
- NameFormatFlags format,
- enum_DB2I_INDEX_TYPE type)
-{
- char generatedName[MAX_DB2_FILENAME_LENGTH+1];
- strncpy(generatedName, indexName, DB2I_INDEX_NAME_LENGTH_TO_PRESERVE);
- generatedName[DB2I_INDEX_NAME_LENGTH_TO_PRESERVE] = 0;
- char* endOfGeneratedName;
-
- if (type == typeDefault)
- {
- strcat(generatedName, DB2I_DEFAULT_INDEX_NAME_DELIMITER);
- endOfGeneratedName = strend(generatedName);
- }
- else if (type != typeNone)
- {
- strcat(generatedName, DB2I_ADDL_INDEX_NAME_DELIMITER);
- endOfGeneratedName = strend(generatedName);
- *(endOfGeneratedName-2) = char(type);
- }
-
- uint lenWithoutFile = endOfGeneratedName - generatedName;
-
- char strippedTableName[MAX_DB2_FILENAME_LENGTH+1];
- if (format == ASCII_SQL)
- {
- strcpy(strippedTableName, tableName);
- stripExtraQuotes(strippedTableName+1, sizeof(strippedTableName));
- tableName = strippedTableName;
- }
-
- if (strlen(tableName) > (MAX_DB2_FILENAME_LENGTH-lenWithoutFile))
- return -1;
-
- strncat(generatedName,
- tableName+1,
- min(strlen(tableName), (MAX_DB2_FILENAME_LENGTH-lenWithoutFile))-2 );
-
- char finalName[MAX_DB2_FILENAME_LENGTH+1];
- convertMySQLNameToDB2Name(generatedName, finalName, sizeof(finalName), true, (format==ASCII_SQL));
- to.append(finalName);
-
- return 0;
-}
-
-
-void db2i_table::findConversionDefinition(enum_conversionDirection direction, uint16 fieldID)
-{
- getConversion(direction,
- mysqlTable->field[fieldID]->charset(),
- db2Field(fieldID).getCCSID(),
- conversionDefinitions[direction][fieldID]);
-}
-
-
-db2i_file::db2i_file(db2i_table* table) : db2Table(table)
-{
- commonCtorInit();
-
- DBUG_ASSERT(table->getMySQLTable()->table_name.length <= MAX_DB2_FILENAME_LENGTH-2);
-
- db2FileName = (char*)table->getDB2TableName(db2i_table::EBCDIC_NATIVE);
-}
-
-db2i_file::db2i_file(db2i_table* table, int index) : db2Table(table)
-{
- commonCtorInit();
-
- if ((index == table->getMySQLTable()->primary_key) && !table->isTemporary())
- {
- db2FileName = (char*)table->getDB2TableName(db2i_table::EBCDIC_NATIVE);
- }
- else
- {
- // Generate the index name (in index___table form); quote and EBCDICize it.
- String qualifiedPath;
- qualifiedPath.length(0);
-
- const char* asciiFileName = table->getDB2TableName(db2i_table::ASCII_NATIVE);
-
- db2i_table::appendQualifiedIndexFileName(table->getMySQLTable()->key_info[index].name,
- asciiFileName,
- qualifiedPath,
- db2i_table::ASCII_NATIVE,
- typeDefault);
-
- db2FileName = (char*)my_malloc(qualifiedPath.length()+1, MYF(MY_WME | MY_ZEROFILL));
- convToEbcdic(qualifiedPath.ptr(), db2FileName, qualifiedPath.length());
- }
-}
-
-void db2i_file::commonCtorInit()
-{
- masterDefn = 0;
- memset(&formats, 0, maxRowFormats*sizeof(RowFormat));
-}
-
-
-void db2i_file::fillILEDefn(ShrDef* defn, bool readInArrivalSeq)
-{
- defn->ObjNamLen = strlen(db2FileName);
- DBUG_ASSERT(defn->ObjNamLen <= sizeof(defn->ObjNam));
- memcpy(defn->ObjNam, db2FileName, defn->ObjNamLen);
- defn->ArrSeq[0] = (readInArrivalSeq ? QMY_YES : QMY_NO);
-}
-
diff --git a/storage/ibmdb2i/db2i_file.h b/storage/ibmdb2i/db2i_file.h
deleted file mode 100644
index 6cc6ae8947b..00000000000
--- a/storage/ibmdb2i/db2i_file.h
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#ifndef DB2I_FILE_H
-#define DB2I_FILE_H
-
-#include "db2i_global.h"
-#include "db2i_ileBridge.h"
-#include "db2i_validatedPointer.h"
-#include "my_atomic.h"
-#include "db2i_iconv.h"
-#include "db2i_charsetSupport.h"
-
-const char FID_EXT[] = ".FID";
-
-class db2i_file;
-
-#pragma pack(1)
-struct DB2LobField
-{
- char reserved1;
- uint32 length;
- char reserved2[4];
- uint32 ordinal;
- ILEMemHandle dataHandle;
- char reserved3[8];
-};
-#pragma pack(pop)
-
-class DB2Field
-{
- public:
- uint16 getType() const { return *(uint16*)(&definition.ColType); }
- uint16 getByteLengthInRecord() const { return definition.ColLen; }
- uint16 getDataLengthInRecord() const
- {
- return (getType() == QMY_VARCHAR || getType() == QMY_VARGRAPHIC ? definition.ColLen - 2 : definition.ColLen);
- }
- uint16 getCCSID() const { return *(uint16*)(&definition.ColCCSID); }
- bool isBlob() const
- {
- uint16 type = getType();
- return (type == QMY_BLOBCLOB || type == QMY_DBCLOB);
- }
- uint16 getBufferOffset() const { return definition.ColBufOff; }
- uint16 calcBlobPad() const
- {
- DBUG_ASSERT(isBlob());
- return getByteLengthInRecord() - sizeof (DB2LobField);
- }
- DB2LobField* asBlobField(char* buf) const
- {
- DBUG_ASSERT(isBlob());
- return (DB2LobField*)(buf + getBufferOffset() + calcBlobPad());
- }
- private:
- col_def_t definition;
-};
-
-
-/**
- @class db2i_table
-
- @details
- This class describes the logical SQL table provided by DB2.
- It stores "table-scoped" information such as the name of the
- DB2 schema, BLOB descriptions, and the corresponding MySQL table definition.
- Only one instance exists per SQL table.
-*/
-class db2i_table
-{
- public:
- enum NameFormatFlags
- {
- ASCII_SQL,
- ASCII_NATIVE,
- EBCDIC_NATIVE
- };
-
- db2i_table(const TABLE_SHARE* myTable, const char* path = NULL);
-
- ~db2i_table();
-
- int32 initDB2Objects(const char* path);
-
- const TABLE_SHARE* getMySQLTable() const
- {
- return mysqlTable;
- }
-
- uint64 getStartId() const
- {
- return db2StartId;
- }
-
- void updateStartId(uint64 newStartId)
- {
- db2StartId = newStartId;
- }
-
- bool hasBlobs() const
- {
- return (blobFieldCount > 0);
- }
-
- uint16 getBlobCount() const
- {
- return blobFieldCount;
- }
-
- uint getBlobFieldActualSize(uint fieldIndex) const
- {
- return blobFieldActualSizes[getBlobIdFromField(fieldIndex)];
- }
-
- void updateBlobFieldActualSize(uint fieldIndex, uint32 newSize)
- {
- // It's OK that this isn't threadsafe, since this is just an advisory
- // value. If a race condition causes the lesser of two values to be stored,
- // that's OK.
- uint16 blobID = getBlobIdFromField(fieldIndex);
- DBUG_ASSERT(blobID < blobFieldCount);
-
- if (blobFieldActualSizes[blobID] < newSize)
- {
- blobFieldActualSizes[blobID] = newSize;
- }
- }
-
-
-
- const char* getDB2LibName(NameFormatFlags format = EBCDIC_NATIVE)
- {
- switch (format)
- {
- case EBCDIC_NATIVE:
- return db2LibNameEbcdic; break;
- case ASCII_NATIVE:
- return db2LibNameAscii; break;
- case ASCII_SQL:
- return db2LibNameSQLAscii; break;
- default:
- DBUG_ASSERT(0);
- }
- return NULL;
- }
-
- const char* getDB2TableName(NameFormatFlags format = EBCDIC_NATIVE) const
- {
- switch (format)
- {
- case EBCDIC_NATIVE:
- return db2TableNameEbcdic; break;
- case ASCII_NATIVE:
- return db2TableNameAscii; break;
- case ASCII_SQL:
- return db2TableNameAscii; break;
- break;
- default:
- DBUG_ASSERT(0);
- }
- return NULL;
- }
-
- DB2Field& db2Field(int fieldID) const { return db2Fields[fieldID]; }
- DB2Field& db2Field(const Field* field) const { return db2Field(field->field_index); }
-
- void processFormatSpace();
-
- void* getFormatSpace(size_t& spaceNeeded)
- {
- DBUG_ASSERT(formatSpace == NULL);
- spaceNeeded = sizeof(format_hdr_t) + mysqlTable->fields * sizeof(DB2Field);
- formatSpace.alloc(spaceNeeded);
- return (void*)formatSpace;
- }
-
- bool isTemporary() const
- {
- return isTemporaryTable;
- }
-
- void getDB2QualifiedName(char* to);
- static void getDB2LibNameFromPath(const char* path, char* lib, NameFormatFlags format=ASCII_SQL);
- static void getDB2FileNameFromPath(const char* path, char* file, NameFormatFlags format=ASCII_SQL);
- static void getDB2QualifiedNameFromPath(const char* path, char* to);
- static int32 appendQualifiedIndexFileName(const char* indexName,
- const char* tableName,
- String& to,
- NameFormatFlags format=ASCII_SQL,
- enum_DB2I_INDEX_TYPE type=typeDefault);
-
- uint16 getBlobIdFromField(uint16 fieldID) const
- {
- for (int i = 0; i < blobFieldCount; ++i)
- {
- if (blobFields[i] == fieldID)
- return i;
- }
- DBUG_ASSERT(0);
- return 0;
- }
-
- iconv_t& getConversionDefinition(enum_conversionDirection direction,
- uint16 fieldID)
- {
- if (conversionDefinitions[direction][fieldID] == (iconv_t)(-1))
- findConversionDefinition(direction, fieldID);
-
- return conversionDefinitions[direction][fieldID];
- }
-
- const db2i_file* dataFile() const
- {
- return physicalFile;
- }
-
- const db2i_file* indexFile(uint idx) const
- {
- return logicalFiles[idx];
- }
-
- const char* getFileLevelID() const
- {
- return fileLevelID;
- }
-
- static void deleteAssocFiles(const char* name);
- static void renameAssocFiles(const char* from, const char* to);
-
- int fastInitForCreate(const char* path);
- int initDiscoveredTable(const char* path);
-
- uint16* blobFields;
-
-private:
-
- void findConversionDefinition(enum_conversionDirection direction, uint16 fieldID);
- static void filenameToTablename(const char* in, char* out, size_t outlen);
- static size_t smartFilenameToTableName(const char *in, char* out, size_t outlen);
- void convertNativeToSQLName(const char* input,
- char* output)
- {
-
- output[0] = input[0];
-
- uint o = 1;
- uint i = 1;
- do
- {
- output[o++] = input[i];
- if (input[i] == '"' && input[i+1])
- output[o++] = '"';
- } while (input[++i]);
-
- output[o] = 0; // This isn't the most user-friendly way to handle overflows,
- // but at least its safe.
- }
-
- bool doFileIDsMatch(const char* path);
-
- ValidatedPointer<format_hdr_t> formatSpace;
- DB2Field* db2Fields;
- uint64 db2StartId; // Starting value for identity column
- uint16 blobFieldCount; // Count of LOB fields in the DB2 table
- uint* blobFieldActualSizes; // Array of LOB field lengths (actual vs. allocated).
- // This is updated as LOBs are read and will contain
- // the length of the longest known LOB in that field.
- iconv_t* conversionDefinitions[2];
-
- const TABLE_SHARE* mysqlTable;
- uint16 logicalFileCount;
- char* db2LibNameEbcdic; // Quoted and in EBCDIC
- char* db2LibNameAscii;
- char* db2TableNameEbcdic;
- char* db2TableNameAscii;
- char* db2TableNameSQLAscii;
- char* db2LibNameSQLAscii;
-
- db2i_file* physicalFile;
- db2i_file** logicalFiles;
-
- bool isTemporaryTable;
- char fileLevelID[13];
-};
-
-/**
- @class db2i_file
-
- @details This class describes a file object underlaying a particular SQL
- table. Both "physical files" (data) and "logical files" (indices) are
- described by this class. Only one instance of the class exists per DB2 file
- object. The single instance is responsible for de/allocating the multiple
- handles used by the handlers.
-*/
-class db2i_file
-{
-
-public:
- struct RowFormat
- {
- uint16 readRowLen;
- uint16 readRowNullOffset;
- uint16 writeRowLen;
- uint16 writeRowNullOffset;
- char inited;
- };
-
-public:
-
- // Construct an instance for a physical file.
- db2i_file(db2i_table* table);
-
- // Construct an instance for a logical file.
- db2i_file(db2i_table* table, int index);
-
- ~db2i_file()
- {
- if (masterDefn)
- db2i_ileBridge::getBridgeForThread()->deallocateFile(masterDefn);
-
- if (db2FileName != (char*)db2Table->getDB2TableName(db2i_table::EBCDIC_NATIVE))
- my_free(db2FileName);
- }
-
- // This is roughly equivalent to an "open". It tells ILE to allocate a descriptor
- // for the file. The associated handle is returned to the caller.
- int allocateNewInstance(FILE_HANDLE* newHandle, ILEMemHandle inuseSpace) const
- {
- int rc;
-
- rc = db2i_ileBridge::getBridgeForThread()->allocateFileInstance(masterDefn,
- inuseSpace,
- newHandle);
-
- if (rc) *newHandle = 0;
-
- return rc;
- }
-
- // This obtains the row layout associated with a particular access intent for
- // an open instance of the file.
- int obtainRowFormat(FILE_HANDLE instanceHandle,
- char intent,
- char commitLevel,
- const RowFormat** activeFormat) const
- {
- DBUG_ENTER("db2i_file::obtainRowFormat");
- RowFormat* rowFormat;
-
- if (intent == QMY_UPDATABLE)
- rowFormat = &(formats[readWrite]);
- else if (intent == QMY_READ_ONLY)
- rowFormat = &(formats[readOnly]);
-
- if (unlikely(!rowFormat->inited))
- {
- int rc = db2i_ileBridge::getBridgeForThread()->
- initFileForIO(instanceHandle,
- intent,
- commitLevel,
- &(rowFormat->writeRowLen),
- &(rowFormat->writeRowNullOffset),
- &(rowFormat->readRowLen),
- &(rowFormat->readRowNullOffset));
- if (rc) DBUG_RETURN(rc);
- rowFormat->inited = 1;
- }
-
- *activeFormat = rowFormat;
- DBUG_RETURN(0);
- }
-
- const char* getDB2FileName() const
- {
- return db2FileName;
- }
-
- void fillILEDefn(ShrDef* defn, bool readInArrivalSeq);
-
- void setMasterDefnHandle(FILE_HANDLE handle)
- {
- masterDefn = handle;
- }
-
- FILE_HANDLE getMasterDefnHandle() const
- {
- return masterDefn;
- }
-
-private:
- enum RowFormats
- {
- readOnly = 0,
- readWrite,
- maxRowFormats
- };
-
- mutable RowFormat formats[maxRowFormats];
-
- void commonCtorInit();
-
- char* db2FileName; // Quoted and in EBCDIC
-
- db2i_table* db2Table; // The logical SQL table contained by this file.
-
- bool db2CanSort;
-
- FILE_HANDLE masterDefn;
-};
-
-
-#endif
diff --git a/storage/ibmdb2i/db2i_global.h b/storage/ibmdb2i/db2i_global.h
deleted file mode 100644
index 1cf8a9a7c61..00000000000
--- a/storage/ibmdb2i/db2i_global.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#ifndef DB2I_GLOBAL_H
-#define DB2I_GLOBAL_H
-
-#define MYSQL_SERVER 1
-
-#include "my_global.h"
-#include "my_sys.h"
-
-const uint MAX_DB2_KEY_PARTS=120;
-const int MAX_DB2_V5R4_LIBNAME_LENGTH = 10;
-const int MAX_DB2_V6R1_LIBNAME_LENGTH = 30;
-const int MAX_DB2_SCHEMANAME_LENGTH=258;
-const int MAX_DB2_FILENAME_LENGTH=258;
-const int MAX_DB2_COLNAME_LENGTH=128;
-const int MAX_DB2_SAVEPOINTNAME_LENGTH=128;
-const int MAX_DB2_QUALIFIEDNAME_LENGTH=MAX_DB2_V6R1_LIBNAME_LENGTH + 1 + MAX_DB2_FILENAME_LENGTH;
-const uint32 MAX_CHAR_LENGTH = 32765;
-const uint32 MAX_VARCHAR_LENGTH = 32739;
-const uint32 MAX_DEC_PRECISION = 63;
-const uint32 MAX_BLOB_LENGTH = 2147483646;
-const uint32 MAX_BINARY_LENGTH = MAX_CHAR_LENGTH;
-const uint32 MAX_VARBINARY_LENGTH = MAX_VARCHAR_LENGTH;
-const uint32 MAX_FULL_ALLOCATE_BLOB_LENGTH = 65536;
-const uint32 MAX_FOREIGN_LEN = 64000;
-const char* DB2I_TEMP_TABLE_SCHEMA = "QTEMP";
-const char DB2I_ADDL_INDEX_NAME_DELIMITER[5] = {'_','_','_','_','_'};
-const char DB2I_DEFAULT_INDEX_NAME_DELIMITER[3] = {'_','_','_'};
-const int DB2I_INDEX_NAME_LENGTH_TO_PRESERVE = 110;
-
-enum enum_DB2I_INDEX_TYPE
-{
- typeNone = 0,
- typeDefault = 'D',
- typeHex = 'H',
- typeAscii = 'A'
-};
-
-void* roundToQuadWordBdy(void* ptr)
-{
- return (void*)(((uint64)(ptr)+0xf) & ~0xf);
-}
-
-typedef uint64_t ILEMemHandle;
-
-struct OSVersion
-{
- uint8 v;
- uint8 r;
-};
-extern OSVersion osVersion;
-
-
-/**
- Allocate 16-byte aligned space using the MySQL heap allocator
-
- @details Many of the spaces used by the QMY_* APIS are required to be
- aligned on 16 byte boundaries. The standard system malloc will do this
- alignment by default. However, in order to use the heap debug and tracking
- features of the mysql allocator, we chose to implement an aligning wrapper
- around my_malloc. Essentially, we overallocate the storage space, find the
- first aligned address in the space, store a pointer to the true malloc
- allocation in the bytes immediately preceding the aligned address, and return
- the aligned address to the caller.
-
- @parm size The size of heap storage needed
-
- @return A 16-byte aligned pointer to the storage requested.
-*/
-void* malloc_aligned(size_t size)
-{
- char* p;
- char* base;
- base = (char*)my_malloc(size + sizeof(void*) + 15, MYF(MY_WME));
- if (likely(base))
- {
- p = (char*)roundToQuadWordBdy(base + sizeof(void*));
- char** p2 = (char**)(p - sizeof(void*));
- *p2 = base;
- }
- else
- p = NULL;
-
- return p;
-}
-
-/**
- Free a 16-byte aligned space alloced by malloc_aligned
-
- @details We know that a pointer to the true malloced storage immediately
- precedes the aligned address, so we pull that out and call my_free().
-
- @parm p A 16-byte aligned pointer generated by malloc_aligned
-*/
-void free_aligned(void* p)
-{
- if (likely(p))
- {
- my_free(*(char**)((char*)p-sizeof(void*)));
- }
-}
-
-#endif
diff --git a/storage/ibmdb2i/db2i_iconv.h b/storage/ibmdb2i/db2i_iconv.h
deleted file mode 100644
index 9fc6e4ed636..00000000000
--- a/storage/ibmdb2i/db2i_iconv.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-/**
- @file
-
- @brief Used to redefine iconv symbols to the optimized "myconv" ones
-*/
-
-#ifndef DB2I_ICONV_H
-#define DB2I_ICONV_H
-
-#include "db2i_myconv.h"
-#define iconv_open(A, B) myconv_open(A, B, CONVERTER_DMAP)
-#define iconv_close myconv_close
-#define iconv myconv_dmap
-#define iconv_t myconv_t
-
-#endif
diff --git a/storage/ibmdb2i/db2i_ileBridge.cc b/storage/ibmdb2i/db2i_ileBridge.cc
deleted file mode 100644
index fac98dd7107..00000000000
--- a/storage/ibmdb2i/db2i_ileBridge.cc
+++ /dev/null
@@ -1,1342 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-
-#include "db2i_ileBridge.h"
-#include "my_dbug.h"
-#include "db2i_global.h"
-#include "db2i_charsetSupport.h"
-#include "db2i_errors.h"
-
-
-// static class member data
-ILEpointer* db2i_ileBridge::functionSymbols;
-db2i_ileBridge* db2i_ileBridge::globalBridge;
-#ifndef DBUG_OFF
-uint32 db2i_ileBridge::registeredPtrs;
-#endif
-
-pthread_key(IleParms*, THR_ILEPARMS);
-
-static void ileParmsDtor(void* parmsToFree)
-{
- if (parmsToFree)
- {
- free_aligned(parmsToFree);
- DBUG_PRINT("db2i_ileBridge", ("Freeing space for parms"));
- }
-}
-
-
-/**
- Convert a timestamp in ILE time format into a unix time_t
-*/
-static inline time_t convertILEtime(const ILE_time_t& input)
-{
- tm temp;
-
- temp.tm_sec = input.Second;
- temp.tm_min = input.Minute;
- temp.tm_hour = input.Hour;
- temp.tm_mday = input.Day;
- temp.tm_mon = input.Month-1;
- temp.tm_year = input.Year - 1900;
- temp.tm_isdst = -1;
-
- return mktime(&temp);
-}
-
-/**
- Allocate and intialize a new bridge structure
-*/
-db2i_ileBridge* db2i_ileBridge::createNewBridge(CONNECTION_HANDLE connID)
-{
- DBUG_PRINT("db2i_ileBridge::createNewBridge",("Building new bridge..."));
- db2i_ileBridge* newBridge = (db2i_ileBridge*)my_malloc(sizeof(db2i_ileBridge), MYF(MY_WME));
-
- if (unlikely(newBridge == NULL))
- return NULL;
-
- newBridge->stmtTxActive = false;
- newBridge->connErrText = NULL;
- newBridge->pendingLockedHandles.head = NULL;
- newBridge->cachedConnectionID = connID;
-
- return newBridge;
-}
-
-
-void db2i_ileBridge::destroyBridge(db2i_ileBridge* bridge)
-{
- bridge->freeErrorStorage();
- my_free(bridge);
-}
-
-
-void db2i_ileBridge::destroyBridgeForThread(const THD* thd)
-{
- void* thdData = *thd_ha_data(thd, ibmdb2i_hton);
- if (thdData != NULL)
- {
- destroyBridge((db2i_ileBridge*)thdData);
- }
-}
-
-
-void db2i_ileBridge::registerPtr(const void* ptr, ILEMemHandle* receiver)
-{
- static const arg_type_t ileSignature[] = { ARG_MEMPTR, ARG_END };
-
- if (unlikely(ptr == NULL))
- {
- *receiver = 0;
- return;
- }
-
- struct ArgList
- {
- ILEarglist_base base;
- ILEpointer ptr;
- } *arguments;
-
- char argBuf[sizeof(ArgList)+15];
- arguments = (ArgList*)roundToQuadWordBdy(argBuf);
-
- arguments->ptr.s.addr = (address64_t)(ptr);
-
- _ILECALL(&functionSymbols[funcRegisterSpace],
- &arguments->base,
- ileSignature,
- RESULT_INT64);
-
-#ifndef DBUG_OFF
- uint32 truncHandle = arguments->base.result.r_uint64;
- DBUG_PRINT("db2i_ileBridge::registerPtr",("Register 0x%p with handle %d", ptr, truncHandle));
- getBridgeForThread()->registeredPtrs++;
-#endif
-
- *receiver = arguments->base.result.r_uint64;
- return;
-}
-
-void db2i_ileBridge::unregisterPtr(ILEMemHandle handle)
-{
- static const arg_type_t ileSignature[] = { ARG_UINT64, ARG_END };
-
- if (unlikely(handle == NULL))
- return;
-
- struct ArgList
- {
- ILEarglist_base base;
- uint64 handle;
- } *arguments;
-
- char argBuf[sizeof(ArgList)+15];
- arguments = (ArgList*)roundToQuadWordBdy(argBuf);
-
- arguments->handle = (uint64)(handle);
-
- _ILECALL(&functionSymbols[funcUnregisterSpace],
- &arguments->base,
- ileSignature,
- RESULT_VOID);
-
-#ifndef DBUG_OFF
- DBUG_PRINT("db2i_ileBridge::unregisterPtr",("Unregister handle %d", (uint32)handle));
- getBridgeForThread()->registeredPtrs--;
-#endif
-}
-
-
-
-/**
- Initialize the bridge component
-
- @details Resolves srvpgm and function names of the APIs. If this fails,
- the approrpiate operating system support (PTFs) is probably not installed.
-
- WARNING:
- Must be called before any other functions in this class are used!!!!
- Can only be called by a single thread!
-*/
-int db2i_ileBridge::setup()
-{
- static const char funcNames[db2i_ileBridge::funcListEnd][32] =
- {
- {"QmyRegisterParameterSpaces"},
- {"QmyRegisterSpace"},
- {"QmyUnregisterSpace"},
- {"QmyProcessRequest"}
- };
-
- DBUG_ENTER("db2i_ileBridge::setup");
-
- int actmark = _ILELOAD("QSYS/QMYSE", ILELOAD_LIBOBJ);
- if ( actmark == -1 )
- {
- DBUG_PRINT("db2i_ileBridge::setup", ("srvpgm activation failed"));
- DBUG_RETURN(1);
- }
-
- functionSymbols = (ILEpointer*)malloc_aligned(sizeof(ILEpointer) * db2i_ileBridge::funcListEnd);
-
- for (int i = 0; i < db2i_ileBridge::funcListEnd; i++)
- {
- if (_ILESYM(&functionSymbols[i], actmark, funcNames[i]) == -1)
- {
- DBUG_PRINT("db2i_ileBridge::setup",
- ("resolve of %s failed", funcNames[i]));
- DBUG_RETURN(errno);
- }
- }
-
- pthread_key_create(&THR_ILEPARMS, &ileParmsDtor);
-
-#ifndef DBUG_OFF
- registeredPtrs = 0;
-#endif
-
- globalBridge = createNewBridge(0);
-
- DBUG_RETURN(0);
-}
-
-/**
- Cleanup any resources before shutting down plug-in
-*/
-void db2i_ileBridge::takedown()
-{
- if (globalBridge)
- destroyBridge(globalBridge);
- free_aligned(functionSymbols);
-}
-
-/**
- Call off to QmyProcessRequest to perform the API that the caller prepared
-*/
-inline int32 db2i_ileBridge::doIt()
-{
- static const arg_type_t ileSignature[] = {ARG_END};
-
- struct ArgList
- {
- ILEarglist_base base;
- } *arguments;
-
- char argBuf[sizeof(ArgList)+15];
- arguments = (ArgList*)roundToQuadWordBdy(argBuf);
-
- _ILECALL(&functionSymbols[funcProcessRequest],
- &arguments->base,
- ileSignature,
- RESULT_INT32);
-
- return translateErrorCode(arguments->base.result.s_int32.r_int32);
-}
-
-/**
- Call off to QmyProcessRequest to perform the API that the caller prepared and
- log any errors that may occur.
-*/
-inline int32 db2i_ileBridge::doItWithLog()
-{
- int32 rc = doIt();
-
- if (unlikely(rc))
- {
- // Only report errors that we weren't expecting
- if (rc != tacitErrors[0] &&
- rc != tacitErrors[1] &&
- rc != QMY_ERR_END_OF_BLOCK)
- reportSystemAPIError(rc, (Qmy_Error_output_t*)parms()->outParms);
- }
- memset(tacitErrors, 0, sizeof(tacitErrors));
-
- return rc;
-}
-
-
-/**
- Interface to QMY_ALLOCATE_SHARE API
-
- See QMY_ALLOCATE_SHARE documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::allocateFileDefn(ILEMemHandle definitionSpace,
- ILEMemHandle handleSpace,
- uint16 fileCount,
- const char* schemaName,
- uint16 schemaNameLength,
- ILEMemHandle formatSpace,
- uint32 formatSpaceLen)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
-
- IleParms* parmBlock = parms();
- Qmy_MAOS0100 *input = (Qmy_MAOS0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_ALLOCATE_SHARE;
- input->ShrDefSpcHnd = definitionSpace;
- input->ShrHndSpcHnd = handleSpace;
- input->ShrDefCnt = fileCount;
- input->FmtSpcHnd = formatSpace;
- input->FmtSpcLen = formatSpaceLen;
-
- if (schemaNameLength > sizeof(input->SchNam))
- {
- // This should never happen!
- DBUG_ASSERT(0);
- return HA_ERR_GENERIC;
- }
-
- memcpy(input->SchNam, schemaName, schemaNameLength);
- input->SchNamLen = schemaNameLength;
-
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-
-/**
- Interface to QMY_ALLOCATE_INSTANCE API
-
- See QMY_ALLOCATE_INSTANCE documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::allocateFileInstance(FILE_HANDLE defnHandle,
- ILEMemHandle inuseSpace,
- FILE_HANDLE* instance)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
-
- IleParms* parmBlock = parms();
- Qmy_MAOI0100 *input = (Qmy_MAOI0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_ALLOCATE_INSTANCE;
- input->ShrHnd = defnHandle;
- input->CnnHnd = cachedConnectionID;
- input->UseSpcHnd = inuseSpace;
-
- int32 rc = doItWithLog();
-
- if (likely(rc == 0))
- {
- Qmy_MAOI0100_output* output = (Qmy_MAOI0100_output*)parmBlock->outParms;
- DBUG_ASSERT(instance);
- *instance = output->ObjHnd;
- }
-
- return rc;
-}
-
-
-/**
- Interface to QMY_DEALLOCATE_OBJECT API
-
- See QMY_DEALLOCATE_OBJECT documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::deallocateFile(FILE_HANDLE rfileHandle,
- bool postDropTable)
-{
- IleParms* parmBlock = parms();
- Qmy_MDLC0100 *input = (Qmy_MDLC0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_DEALLOCATE_OBJECT;
- input->ObjHnd = rfileHandle;
- input->ObjDrp[0] = (postDropTable ? QMY_YES : QMY_NO);
-
- DBUG_PRINT("db2i_ileBridge::deallocateFile", ("Deallocating %d", (uint32)rfileHandle));
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-
-/**
- Interface to QMY_OBJECT_INITIALIZATION API
-
- See QMY_OBJECT_INITIALIZATION documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::initFileForIO(FILE_HANDLE rfileHandle,
- char accessIntent,
- char commitLevel,
- uint16* inRecSize,
- uint16* inRecNullOffset,
- uint16* outRecSize,
- uint16* outRecNullOffset)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MOIX0100 *input = (Qmy_MOIX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_OBJECT_INITIALIZATION;
- input->CmtLvl[0] = commitLevel;
- input->Intent[0] = accessIntent;
- input->ObjHnd = rfileHandle;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- if (likely(rc == 0))
- {
- Qmy_MOIX0100_output* output = (Qmy_MOIX0100_output*)parmBlock->outParms;
- *inRecSize = output->InNxtRowOff;
- *inRecNullOffset = output->InNullMapOff;
- *outRecSize = output->OutNxtRowOff;
- *outRecNullOffset = output->OutNullMapOff;
- }
-
- return rc;
-}
-
-
-/**
- Interface to QMY_READ_ROWS API for reading a row with a specific RRN.
-
- See QMY_READ_ROWS documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::readByRRN(FILE_HANDLE rfileHandle,
- ILEMemHandle buf,
- uint32 inRRN,
- char accessIntent,
- char commitLevel)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MRDX0100 *input = (Qmy_MRDX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_READ_ROWS;
- input->CmtLvl[0] = commitLevel;
- input->ObjHnd = rfileHandle;
- input->Intent[0] = accessIntent;
- input->OutSpcHnd = (uint64)buf;
- input->RelRowNbr = inRRN;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- if (rc == QMY_ERR_END_OF_BLOCK)
- {
- rc = 0;
- DBUG_PRINT("db2i_ileBridge::readByRRN", ("End of block signalled"));
- }
-
- return rc;
-}
-
-
-/**
- Interface to QMY_WRITE_ROWS API.
-
- See QMY_WRITE_ROWS documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::writeRows(FILE_HANDLE rfileHandle,
- ILEMemHandle buf,
- char commitLevel,
- int64* outIdVal,
- bool* outIdGen,
- uint32* dupKeyRRN,
- char** dupKeyName,
- uint32* dupKeyNameLen,
- uint32* outIdIncrement)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MWRT0100 *input = (Qmy_MWRT0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_WRITE_ROWS;
- input->CmtLvl[0] = commitLevel;
-
- input->ObjHnd = rfileHandle;
- input->InSpcHnd = (uint64_t) buf;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- Qmy_MWRT0100_output_t* output = (Qmy_MWRT0100_output_t*)parmBlock->outParms;
- if (likely(rc == 0 || rc == HA_ERR_FOUND_DUPP_KEY))
- {
- DBUG_ASSERT(dupKeyRRN && dupKeyName && dupKeyNameLen && outIdGen && outIdIncrement && outIdVal);
- *dupKeyRRN = output->DupRRN;
- *dupKeyName = (char*)parmBlock->outParms + output->DupObjNamOff;
- *dupKeyNameLen = output->DupObjNamLen;
- *outIdGen = (output->NewIdGen[0] == QMY_YES ? TRUE : FALSE);
- if (*outIdGen == TRUE)
- {
- *outIdIncrement = output->IdIncrement;
- *outIdVal = output->NewIdVal;
- }
- }
-
- return rc;
-
-}
-
-/**
- Interface to QMY_EXECUTE_IMMEDIATE API.
-
- See QMY_EXECUTE_IMMEDIATE documentation for more information about
- parameters and return codes.
-*/
-uint32 db2i_ileBridge::execSQL(const char* statement,
- uint32 statementCount,
- uint8 commitLevel,
- bool autoCreateSchema,
- bool dropSchema,
- bool noCommit,
- FILE_HANDLE fileHandle)
-
-{
- IleParms* parmBlock = parms();
- Qmy_MSEI0100 *input = (Qmy_MSEI0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_EXECUTE_IMMEDIATE;
-
- registerPtr(statement, &input->StmtsSpcHnd);
-
- input->NbrStmts = statementCount;
- *(uint16*)(&input->StmtCCSID) = 850;
- input->AutoCrtSchema[0] = (autoCreateSchema == TRUE ? QMY_YES : QMY_NO);
- input->DropSchema[0] = (dropSchema == TRUE ? QMY_YES : QMY_NO);
- input->CmtLvl[0] = commitLevel;
- if ((commitLevel == QMY_NONE && statementCount == 1) || noCommit)
- {
- input->CmtBefore[0] = QMY_NO;
- input->CmtAfter[0] = QMY_NO;
- }
- else
- {
- input->CmtBefore[0] = QMY_YES;
- input->CmtAfter[0] = QMY_YES;
- }
- input->CnnHnd = current_thd->thread_id;
- input->ObjHnd = fileHandle;
-
- int32 rc = doItWithLog();
-
- unregisterPtr(input->StmtsSpcHnd);
-
- return rc;
-}
-
-/**
- Interface to QMY_PREPARE_OPEN_CURSOR API.
-
- See QMY_PREPARE_OPEN_CURSOR documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::prepOpen(const char* statement,
- FILE_HANDLE* rfileHandle,
- uint32* recLength)
-{
- IleParms* parmBlock = parms();
- Qmy_MSPO0100 *input = (Qmy_MSPO0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_PREPARE_OPEN_CURSOR;
-
- registerPtr(statement, &input->StmtsSpcHnd );
- *(uint16*)(&input->StmtCCSID) = 850;
- input->CnnHnd = current_thd->thread_id;
-
- int32 rc = doItWithLog();
-
- if (likely(rc == 0))
- {
- Qmy_MSPO0100_output* output = (Qmy_MSPO0100_output*)parmBlock->outParms;
- *rfileHandle = output->ObjHnd;
- *recLength = max(output->InNxtRowOff, output->OutNxtRowOff);
- }
-
-
- unregisterPtr(input->StmtsSpcHnd);
-
- return rc;
-}
-
-
-/**
- Interface to QMY_DELETE_ROW API.
-
- See QMY_DELETE_ROW documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::deleteRow(FILE_HANDLE rfileHandle,
- uint32 rrn)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MDLT0100 *input = (Qmy_MDLT0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_DELETE_ROW;
- input->ObjHnd = rfileHandle;
- input->RelRowNbr = rrn;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-
-/**
- Interface to QMY_UPDATE_ROW API.
-
- See QMY_UPDATE_ROW documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::updateRow(FILE_HANDLE rfileHandle,
- uint32 rrn,
- ILEMemHandle buf,
- uint32* dupKeyRRN,
- char** dupKeyName,
- uint32* dupKeyNameLen)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MUPD0100 *input = (Qmy_MUPD0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_UPDATE_ROW;
- input->ObjHnd = rfileHandle;
- input->InSpcHnd = (uint64)buf;
- input->RelRowNbr = rrn;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- if (rc == HA_ERR_FOUND_DUPP_KEY)
- {
- Qmy_MUPD0100_output* output = (Qmy_MUPD0100_output*)parmBlock->outParms;
- DBUG_ASSERT(dupKeyRRN && dupKeyName && dupKeyNameLen);
- *dupKeyRRN = output->DupRRN;
- *dupKeyName = (char*)parmBlock->outParms + output->DupObjNamOff;
- *dupKeyNameLen = output->DupObjNamLen;
- }
-
- return rc;
-}
-
-/**
- Interface to QMY_DESCRIBE_RANGE API.
-
- See QMY_DESCRIBE_RANGE documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::recordsInRange(FILE_HANDLE defnHandle,
- ILEMemHandle inSpc,
- uint32 inKeyCnt,
- uint32 inLiteralCnt,
- uint32 inBoundsOff,
- uint32 inLitDefOff,
- uint32 inLiteralsOff,
- uint32 inCutoff,
- uint32 inSpcLen,
- uint16 inEndByte,
- uint64* outRecCnt,
- uint16* outRtnCode)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
-
- IleParms* parmBlock = parms();
- Qmy_MDRG0100 *input = (Qmy_MDRG0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_DESCRIBE_RANGE;
- input->ShrHnd = defnHandle;
- input->SpcHnd = (uint64)inSpc;
- input->KeyCnt = inKeyCnt;
- input->LiteralCnt = inLiteralCnt;
- input->BoundsOff = inBoundsOff;
- input->LitDefOff = inLitDefOff;
- input->LiteralsOff = inLiteralsOff;
- input->Cutoff = inCutoff;
- input->SpcLen = inSpcLen;
- input->EndByte = inEndByte;
- input->CnnHnd = cachedConnectionID;
-
- int rc = doItWithLog();
-
- if (likely(rc == 0))
- {
- Qmy_MDRG0100_output* output = (Qmy_MDRG0100_output*)parmBlock->outParms;
- DBUG_ASSERT(outRecCnt && outRtnCode);
- *outRecCnt = output->RecCnt;
- *outRtnCode = output->RtnCode;
- }
-
- return rc;
-}
-
-
-/**
- Interface to QMY_RELEASE_ROW API.
-
- See QMY_RELEASE_ROW documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::rrlslck(FILE_HANDLE rfileHandle, char accessIntent)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
-
- IleParms* parmBlock = parms();
- Qmy_MRRX0100 *input = (Qmy_MRRX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_RELEASE_ROW;
-
- input->ObjHnd = rfileHandle;
- input->CnnHnd = cachedConnectionID;
- input->Intent[0] = accessIntent;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-/**
- Interface to QMY_LOCK_OBJECT API.
-
- See QMY_LOCK_OBJECT documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::lockObj(FILE_HANDLE defnHandle,
- uint64 lockVal,
- char lockAction,
- char lockType,
- char lockTimeout)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MOLX0100 *input = (Qmy_MOLX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_LOCK_OBJECT;
- input->ShrHnd = defnHandle;
- input->LckTimeoutVal = lockVal;
- input->Action[0] = lockAction;
- input->LckTyp[0] = lockType;
- input->LckTimeout[0] = lockTimeout;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-/**
- Interface to QMY_DESCRIBE_CONSTRAINTS API.
-
- See QMY_DESCRIBE_CONSTRAINTS documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::constraints(FILE_HANDLE defnHandle,
- ILEMemHandle inSpc,
- uint32 inSpcLen,
- uint32* outLen,
- uint32* outCnt)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MDCT0100 *input = (Qmy_MDCT0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_DESCRIBE_CONSTRAINTS;
- input->ShrHnd = defnHandle;
- input->CstSpcHnd = (uint64)inSpc;
- input->CstSpcLen = inSpcLen;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- if (likely(rc == 0))
- {
- Qmy_MDCT0100_output* output = (Qmy_MDCT0100_output*)parmBlock->outParms;
- DBUG_ASSERT(outLen && outCnt);
- *outLen = output->NeededLen;
- *outCnt = output->CstCnt;
- }
-
- return rc;
-}
-
-
-/**
- Interface to QMY_REORGANIZE_TABLE API.
-
- See QMY_REORGANIZE_TABLE documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::optimizeTable(FILE_HANDLE defnHandle)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MRGX0100 *input = (Qmy_MRGX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_REORGANIZE_TABLE;
- input->ShrHnd = defnHandle;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-
-/**
- Interface to QMY_PROCESS_COMMITMENT_CONTROL API.
-
- See QMY_PROCESS_COMMITMENT_CONTROL documentation for more information about
- parameters and return codes.
-*/
-int32 db2i_ileBridge::commitmentControl(uint8 function)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MCCX0100 *input = (Qmy_MCCX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_PROCESS_COMMITMENT_CONTROL;
- input->Function[0] = function;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-
-/**
- Interface to QMY_PROCESS_SAVEPOINT API.
-
- See QMY_PROCESS_SAVEPOINT documentation for more information about parameters and
- return codes.
-*/
-int32 db2i_ileBridge::savepoint(uint8 function,
- const char* savepointName)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- DBUG_PRINT("db2i_ileBridge::savepoint",("%d %s", (uint32)function, savepointName));
-
- IleParms* parmBlock = parms();
- Qmy_MSPX0100 *input = (Qmy_MSPX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- char* savPtNam = (char*)(input+1);
-
- input->Format = QMY_PROCESS_SAVEPOINT;
-
- if (strlen(savepointName) > MAX_DB2_SAVEPOINTNAME_LENGTH)
- {
- DBUG_ASSERT(0);
- return HA_ERR_GENERIC;
- }
- strcpy(savPtNam, savepointName);
-
- input->Function[0] = function;
- input->SavPtNamOff = savPtNam - (char*)(input);
- input->SavPtNamLen = strlen(savepointName);
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-static ILEMemHandle traceSpcHandle;
-/**
- Do initialization for the QMY_* APIs.
-
- @parm aspName The name of the relational database to use for all
- connections.
-
- @return 0 if successful; error otherwise
-*/
-int32 db2i_ileBridge::initILE(const char* aspName,
- uint16* traceCtlPtr)
-{
- // We forego the typical thread-based parms space because MySQL doesn't
- // allow us to clean it up before checking for memory leaks. As a result
- // we get a complaint about leaked memory on server shutdown.
- int32 rc;
- char inParms[db2i_ileBridge_MAX_INPARM_SIZE];
- char outParms[db2i_ileBridge_MAX_OUTPARM_SIZE];
- if (rc = registerParmSpace(inParms, outParms))
- {
- reportSystemAPIError(rc, NULL);
- return rc;
- }
-
- registerPtr(traceCtlPtr, &traceSpcHandle);
-
- struct ParmBlock
- {
- Qmy_MINI0100 parms;
- } *parmBlock = (ParmBlock*)inParms;
-
- memset(inParms, 0, sizeof(ParmBlock));
-
- parmBlock->parms.Format = QMY_INITIALIZATION;
-
- char paddedName[18];
- if (strlen(aspName) > sizeof(paddedName))
- {
- getErrTxt(DB2I_ERR_BAD_RDB_NAME);
- return DB2I_ERR_BAD_RDB_NAME;
- }
-
- memset(paddedName, ' ', sizeof(paddedName));
- memcpy(paddedName, aspName, strlen(aspName));
- convToEbcdic(paddedName, parmBlock->parms.RDBName, strlen(paddedName));
-
- parmBlock->parms.RDBNamLen = strlen(paddedName);
- parmBlock->parms.TrcSpcHnd = traceSpcHandle;
-
- rc = doIt();
-
- if (rc)
- {
- reportSystemAPIError(rc, (Qmy_Error_output_t*)outParms);
- }
-
- return rc;
-}
-
-/**
- Signal to the QMY_ APIs to perform any cleanup they need to do.
-*/
-int32 db2i_ileBridge::exitILE()
-{
- IleParms* parmBlock = parms();
- Qmy_MCLN0100 *input = (Qmy_MCLN0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_CLEANUP;
-
- int32 rc = doIt();
-
- if (rc)
- {
- reportSystemAPIError(rc, (Qmy_Error_output_t*)parmBlock->outParms);
- }
-
- unregisterPtr(traceSpcHandle);
-
- DBUG_PRINT("db2i_ileBridge::exitILE", ("Registered ptrs remaining: %d", registeredPtrs));
-#ifndef DBUG_OFF
- if (registeredPtrs != 0)
- printf("Oh no! IBMDB2I left some pointers registered. Count was %d.\n", registeredPtrs);
-#endif
-
- // This is needed to prevent SAFE_MALLOC from complaining at process termination.
- my_pthread_setspecific_ptr(THR_ILEPARMS, NULL);
- free_aligned(parmBlock);
-
- return rc;
-
-}
-
-
-/**
- Designate the specified addresses as parameter passing buffers.
-
- @parm in Input to the API will go here; format is defined by the individual API
- @parm out Output from the API will be; format is defined by the individual API
-
- @return 0 if success; error otherwise
-*/
-int db2i_ileBridge::registerParmSpace(char* in, char* out)
-{
- static const arg_type_t ileSignature[] = { ARG_MEMPTR, ARG_MEMPTR, ARG_END };
-
- struct ArgList
- {
- ILEarglist_base base;
- ILEpointer input;
- ILEpointer output;
- } *arguments;
-
- char argBuf[sizeof(ArgList)+15];
- arguments = (ArgList*)roundToQuadWordBdy(argBuf);
-
- arguments->input.s.addr = (address64_t)(in);
- arguments->output.s.addr = (address64_t)(out);
-
- _ILECALL(&functionSymbols[funcRegisterParameterSpaces],
- &arguments->base,
- ileSignature,
- RESULT_INT32);
-
- return arguments->base.result.s_int32.r_int32;
-}
-
-
-/**
- Interface to QMY_OBJECT_OVERRIDE API.
-
- See QMY_OBJECT_OVERRIDE documentation for more information about parameters and
- return codes.
-*/
-int32 db2i_ileBridge::objectOverride(FILE_HANDLE rfileHandle,
- ILEMemHandle buf,
- uint32 recordWidth)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MOOX0100 *input = (Qmy_MOOX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_OBJECT_OVERRIDE;
- input->ObjHnd = rfileHandle;
- input->OutSpcHnd = (uint64)buf;
- input->NxtRowOff = recordWidth;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-/**
- Interface to QMY_DESCRIBE_OBJECT API for obtaining table stats.
-
- See QMY_DESCRIBE_OBJECT documentation for more information about parameters and
- return codes.
-*/
-int32 db2i_ileBridge::retrieveTableInfo(FILE_HANDLE defnHandle,
- uint16 dataRequested,
- ha_statistics& stats,
- ILEMemHandle inSpc)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MDSO0100 *input = (Qmy_MDSO0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_DESCRIBE_OBJECT;
- input->ShrHnd = defnHandle;
- input->CnnHnd = cachedConnectionID;
-
- if (dataRequested & objLength)
- input->RtnObjLen[0] = QMY_YES;
- if (dataRequested & rowCount)
- input->RtnRowCnt[0] = QMY_YES;
- if (dataRequested & deletedRowCount)
- input->RtnDltRowCnt[0] = QMY_YES;
- if (dataRequested & rowsPerKey)
- {
- input->RowKeyHnd = (uint64)inSpc;
- input->RtnRowKey[0] = QMY_YES;
- }
- if (dataRequested & meanRowLen)
- input->RtnMeanRowLen[0] = QMY_YES;
- if (dataRequested & lastModTime)
- input->RtnModTim[0] = QMY_YES;
- if (dataRequested & createTime)
- input->RtnCrtTim[0] = QMY_YES;
- if (dataRequested & ioCount)
- input->RtnEstIoCnt[0] = QMY_YES;
-
- int32 rc = doItWithLog();
-
- if (likely(rc == 0))
- {
- Qmy_MDSO0100_output* output = (Qmy_MDSO0100_output*)parmBlock->outParms;
- if (dataRequested & objLength)
- stats.data_file_length = output->ObjLen;
- if (dataRequested & rowCount)
- stats.records= output->RowCnt;
- if (dataRequested & deletedRowCount)
- stats.deleted = output->DltRowCnt;
- if (dataRequested & meanRowLen)
- stats.mean_rec_length = output->MeanRowLen;
- if (dataRequested & lastModTime)
- stats.update_time = convertILEtime(output->ModTim);
- if (dataRequested & createTime)
- stats.create_time = convertILEtime(output->CrtTim);
- if (dataRequested & ioCount)
- stats.data_file_length = output->EstIoCnt;
- }
-
- return rc;
-}
-
-/**
- Interface to QMY_DESCRIBE_OBJECT API for finding index size.
-
- See QMY_DESCRIBE_OBJECT documentation for more information about parameters and
- return codes.
-*/
-int32 db2i_ileBridge::retrieveIndexInfo(FILE_HANDLE defnHandle,
- uint64* outPageCnt)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MDSO0100 *input = (Qmy_MDSO0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_DESCRIBE_OBJECT;
- input->ShrHnd = defnHandle;
- input->CnnHnd = cachedConnectionID;
- input->RtnPageCnt[0] = QMY_YES;
-
- int32 rc = doItWithLog();
-
- if (likely(rc == 0))
- {
- Qmy_MDSO0100_output* output = (Qmy_MDSO0100_output*)parmBlock->outParms;
- *outPageCnt = output->PageCnt;
- }
-
- return rc;
-}
-
-
-/**
- Interface to QMY_CLOSE_CONNECTION API
-
- See QMY_CLOSE_CONNECTION documentation for more information about parameters and
- return codes.
-*/
-int32 db2i_ileBridge::closeConnection(CONNECTION_HANDLE conn)
-{
- IleParms* parmBlock = parms();
- Qmy_MCCN0100 *input = (Qmy_MCCN0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_CLOSE_CONNECTION;
- input->CnnHnd = conn;
-
- int32 rc = doItWithLog();
-
- return rc;
-}
-
-
-/**
- Interface to QMY_INTERRUPT API
-
- See QMY_INTERRUPT documentation for more information about parameters and
- return codes.
-*/
-int32 db2i_ileBridge::readInterrupt(FILE_HANDLE fileHandle)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MINT0100 *input = (Qmy_MINT0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_INTERRUPT;
- input->CnnHnd = cachedConnectionID;
- input->ObjHnd = fileHandle;
-
- int32 rc = doItWithLog();
-
- if (rc == QMY_ERR_END_OF_BLOCK)
- {
- rc = 0;
- DBUG_PRINT("db2i_ileBridge::readInterrupt", ("End of block signalled"));
- }
-
- return rc;
-}
-
-/**
- Interface to QMY_READ_ROWS API
-
- See QMY_READ_ROWS documentation for more information about parameters and
- return codes.
-*/
-int32 db2i_ileBridge::read(FILE_HANDLE rfileHandle,
- ILEMemHandle buf,
- char accessIntent,
- char commitLevel,
- char orientation,
- bool asyncRead,
- ILEMemHandle rrn,
- ILEMemHandle key,
- uint32 keylen,
- uint16 keyParts,
- int pipeFD)
-{
- DBUG_ASSERT(cachedStateIsCoherent());
- IleParms* parmBlock = parms();
- Qmy_MRDX0100 *input = (Qmy_MRDX0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_READ_ROWS;
- input->CmtLvl[0] = commitLevel;
-
- input->ObjHnd = rfileHandle;
- input->Intent[0] = accessIntent;
- input->OutSpcHnd = (uint64)buf;
- input->OutRRNSpcHnd = (uint64)rrn;
- input->RtnData[0] = QMY_RETURN_DATA;
-
- if (key)
- {
- input->KeySpcHnd = (uint64)key;
- input->KeyColsLen = keylen;
- input->KeyColsNbr = keyParts;
- }
-
- input->Async[0] = (asyncRead ? QMY_YES : QMY_NO);
- input->PipeDesc = pipeFD;
- input->Orientation[0] = orientation;
- input->CnnHnd = cachedConnectionID;
-
- int32 rc = doItWithLog();
-
- // QMY_ERR_END_OF_BLOCK is informational only, so we ignore it.
- if (rc == QMY_ERR_END_OF_BLOCK)
- {
- rc = 0;
- DBUG_PRINT("db2i_ileBridge::read", ("End of block signalled"));
- }
-
- return rc;
-}
-
-
-/**
- Interface to QMY_QUIESCE_OBJECT API
-
- See QMY_QUIESCE_OBJECT documentation for more information about parameters and
- return codes.
-*/
-int32 db2i_ileBridge::quiesceFileInstance(FILE_HANDLE rfileHandle)
-{
- IleParms* parmBlock = parms();
- Qmy_MQSC0100 *input = (Qmy_MQSC0100*)&(parmBlock->inParms);
- memset(input, 0, sizeof(*input));
-
- input->Format = QMY_QUIESCE_OBJECT;
- input->ObjHnd = rfileHandle;
-
- int32 rc = doItWithLog();
-
-#ifndef DBUG_OFF
- if (unlikely(rc))
- {
- DBUG_ASSERT(0);
- }
-#endif
-
- return rc;
-}
-
-void db2i_ileBridge::PreservedHandleList::add(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share)
-{
- NameHandlePair *newPair = (NameHandlePair*)my_malloc(sizeof(NameHandlePair), MYF(MY_WME));
-
- newPair->next = head;
- head = newPair;
-
- strcpy(newPair->name, newname);
- newPair->handle = newhandle;
- newPair->share = share;
- DBUG_PRINT("db2i_ileBridge", ("Added handle %d for %s", uint32(newhandle), newname));
-}
-
-
-FILE_HANDLE db2i_ileBridge::PreservedHandleList::findAndRemove(const char* fileName, IBMDB2I_SHARE** share)
-{
- NameHandlePair* current = head;
- NameHandlePair* prev = NULL;
-
- while (current)
- {
- NameHandlePair* next = current->next;
- if (strcmp(fileName, current->name) == 0)
- {
- FILE_HANDLE tmp = current->handle;
- *share = current->share;
- if (prev)
- prev->next = next;
- if (current == head)
- head = next;
- my_free(current);
- DBUG_PRINT("db2i_ileBridge", ("Found handle %d for %s", uint32(tmp), fileName));
- return tmp;
- }
- prev = current;
- current = next;
- }
-
- return 0;
-}
-
-
-IleParms* db2i_ileBridge::initParmsForThread()
-{
-
- IleParms* p = (IleParms*)malloc_aligned(sizeof(IleParms));
- DBUG_ASSERT((uint64)(&(p->outParms))% 16 == 0); // Guarantee that outParms are aligned correctly
-
- if (likely(p))
- {
- int32 rc = registerParmSpace((p->inParms), (p->outParms));
- if (likely(rc == 0))
- {
- my_pthread_setspecific_ptr(THR_ILEPARMS, p);
- DBUG_PRINT("db2i_ileBridge", ("Inited space for parms"));
- return p;
- }
- else
- reportSystemAPIError(rc, NULL);
- }
-
- return NULL;
-}
-
diff --git a/storage/ibmdb2i/db2i_ileBridge.h b/storage/ibmdb2i/db2i_ileBridge.h
deleted file mode 100644
index 3a3ca141f69..00000000000
--- a/storage/ibmdb2i/db2i_ileBridge.h
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#ifndef DB2I_ILEBRIDGE_H
-#define DB2I_ILEBRIDGE_H
-
-#include "db2i_global.h"
-#include "mysql_priv.h"
-#include "as400_types.h"
-#include "as400_protos.h"
-#include "qmyse.h"
-#include "db2i_errors.h"
-
-typedef uint64_t FILE_HANDLE;
-typedef my_thread_id CONNECTION_HANDLE;
-const char SAVEPOINT_NAME[] = {0xD4,0xE2,0xD7,0xC9,0xD5,0xE3,0xC5,0xD9,0xD5,0x0};
-const uint32 TACIT_ERRORS_SIZE=2;
-
-enum db2i_InfoRequestSpec
-{
- objLength = 1,
- rowCount = 2,
- deletedRowCount = 4,
- rowsPerKey = 8,
- meanRowLen = 16,
- lastModTime = 32,
- createTime = 64,
- ioCount = 128
-};
-
-extern handlerton *ibmdb2i_hton;
-struct IBMDB2I_SHARE;
-
-const uint32 db2i_ileBridge_MAX_INPARM_SIZE = 512;
-const uint32 db2i_ileBridge_MAX_OUTPARM_SIZE = 512;
-
-extern pthread_key(IleParms*, THR_ILEPARMS);
-struct IleParms
-{
- char inParms[db2i_ileBridge_MAX_INPARM_SIZE];
- char outParms[db2i_ileBridge_MAX_OUTPARM_SIZE];
-};
-
-/**
- @class db2i_ileBridge
-
- Implements a connection-based interface to the QMY_* APIs
-
- @details Each client connection that touches an IBMDB2I table has a "bridge"
- associated with it. This bridge is constructed on first use and provides a
- more C-like interface to the APIs. As well, it is reponsible for tracking
- connection scoped information such as statement transaction state and error
- message text. The bridge is destroyed when the connection ends.
-*/
-class db2i_ileBridge
-{
- enum ileFuncs
- {
- funcRegisterParameterSpaces,
- funcRegisterSpace,
- funcUnregisterSpace,
- funcProcessRequest,
- funcListEnd
- };
-
- static db2i_ileBridge* globalBridge;
-public:
-
-
- static int setup();
- static void takedown();
-
- /**
- Obtain a pointer to the bridge for the current connection.
-
- If a MySQL client connection is on the stack, we get the associated brideg.
- Otherwise, we use the globalBridge.
- */
- static db2i_ileBridge* getBridgeForThread()
- {
- THD* thd = current_thd;
- if (likely(thd))
- return getBridgeForThread(thd);
-
- return globalBridge;
- }
-
- /**
- Obtain a pointer to the bridge for the specified connection.
-
- If a bridge exists already, we return it immediately. Otherwise, prepare
- a new bridge for the connection.
- */
- static db2i_ileBridge* getBridgeForThread(const THD* thd)
- {
- void* thdData = *thd_ha_data(thd, ibmdb2i_hton);
- if (likely(thdData != NULL))
- return (db2i_ileBridge*)(thdData);
-
- db2i_ileBridge* newBridge = createNewBridge(thd->thread_id);
- *thd_ha_data(thd, ibmdb2i_hton) = (void*)newBridge;
- return newBridge;
- }
-
- static void destroyBridgeForThread(const THD* thd);
- static void registerPtr(const void* ptr, ILEMemHandle* receiver);
- static void unregisterPtr(ILEMemHandle handle);
- int32 allocateFileDefn(ILEMemHandle definitionSpace,
- ILEMemHandle handleSpace,
- uint16 fileCount,
- const char* schemaName,
- uint16 schemaNameLength,
- ILEMemHandle formatSpace,
- uint32 formatSpaceLen);
- int32 allocateFileInstance(FILE_HANDLE defnHandle,
- ILEMemHandle inuseSpace,
- FILE_HANDLE* instance);
- int32 deallocateFile(FILE_HANDLE fileHandle,
- bool postDropTable=FALSE);
- int32 read(FILE_HANDLE rfileHandle,
- ILEMemHandle buf,
- char accessIntent,
- char commitLevel,
- char orientation,
- bool asyncRead = FALSE,
- ILEMemHandle rrn = 0,
- ILEMemHandle key = 0,
- uint32 keylen = 0,
- uint16 keyParts = 0,
- int pipeFD = -1);
- int32 readByRRN(FILE_HANDLE rfileHandle,
- ILEMemHandle buf,
- uint32 inRRN,
- char accessIntent,
- char commitLevel);
- int32 writeRows(FILE_HANDLE rfileHandle,
- ILEMemHandle buf,
- char commitLevel,
- int64* outIdVal,
- bool* outIdGen,
- uint32* dupKeyRRN,
- char** dupKeyName,
- uint32* dupKeyNameLen,
- uint32* outIdIncrement);
- uint32 execSQL(const char* statement,
- uint32 statementCount,
- uint8 commitLevel,
- bool autoCreateSchema = FALSE,
- bool dropSchema = FALSE,
- bool noCommit = FALSE,
- FILE_HANDLE fileHandle = 0);
- int32 prepOpen(const char* statement,
- FILE_HANDLE* rfileHandle,
- uint32* recLength);
- int32 deleteRow(FILE_HANDLE rfileHandle,
- uint32 rrn);
- int32 updateRow(FILE_HANDLE rfileHandle,
- uint32 rrn,
- ILEMemHandle buf,
- uint32* dupKeyRRN,
- char** dupKeyName,
- uint32* dupKeyNameLen);
- int32 commitmentControl(uint8 function);
- int32 savepoint(uint8 function,
- const char* savepointName);
- int32 recordsInRange(FILE_HANDLE rfileHandle,
- ILEMemHandle inSpc,
- uint32 inKeyCnt,
- uint32 inLiteralCnt,
- uint32 inBoundsOff,
- uint32 inLitDefOff,
- uint32 inLiteralsOff,
- uint32 inCutoff,
- uint32 inSpcLen,
- uint16 inEndByte,
- uint64* outRecCnt,
- uint16* outRtnCode);
- int32 rrlslck(FILE_HANDLE rfileHandle,
- char accessIntent);
- int32 lockObj(FILE_HANDLE rfileHandle,
- uint64 inTimeoutVal,
- char inAction,
- char inLockType,
- char inTimeout);
- int32 constraints(FILE_HANDLE rfileHandle,
- ILEMemHandle inSpc,
- uint32 inSpcLen,
- uint32* outLen,
- uint32* outCnt);
- int32 optimizeTable(FILE_HANDLE rfileHandle);
- static int32 initILE(const char* aspName,
- uint16* traceCtlPtr);
- int32 initFileForIO(FILE_HANDLE rfileHandle,
- char accessIntent,
- char commitLevel,
- uint16* inRecSize,
- uint16* inRecNullOffset,
- uint16* outRecSize,
- uint16* outRecNullOffset);
- int32 readInterrupt(FILE_HANDLE fileHandle);
- static int32 exitILE();
-
- int32 objectOverride(FILE_HANDLE rfileHandle,
- ILEMemHandle buf,
- uint32 recordWidth = 0);
-
- int32 retrieveTableInfo(FILE_HANDLE rfileHandle,
- uint16 dataRequested,
- ha_statistics& stats,
- ILEMemHandle inSpc = NULL);
-
- int32 retrieveIndexInfo(FILE_HANDLE rfileHandle,
- uint64* outPageCnt);
-
- int32 closeConnection(CONNECTION_HANDLE conn);
- int32 quiesceFileInstance(FILE_HANDLE rfileHandle);
-
- /**
- Mark the beginning of a "statement transaction"
-
- @detail MySQL "statement transactions" (see sql/handler.cc) are implemented
- as DB2 savepoints having a predefined name.
-
- @return 0 if successful; error otherwise
- */
- uint32 beginStmtTx()
- {
- DBUG_ENTER("db2i_ileBridge::beginStmtTx");
- if (stmtTxActive)
- DBUG_RETURN(0);
-
- stmtTxActive = true;
-
- DBUG_RETURN(savepoint(QMY_SET_SAVEPOINT, SAVEPOINT_NAME));
- }
-
- /**
- Commit a "statement transaction"
-
- @return 0 if successful; error otherwise
- */
- uint32 commitStmtTx()
- {
- DBUG_ENTER("db2i_ileBridge::commitStmtTx");
- DBUG_ASSERT(stmtTxActive);
- stmtTxActive = false;
- DBUG_RETURN(savepoint(QMY_RELEASE_SAVEPOINT, SAVEPOINT_NAME));
- }
-
- /**
- Roll back a "statement transaction"
-
- @return 0 if successful; error otherwise
- */
- uint32 rollbackStmtTx()
- {
- DBUG_ENTER("db2i_ileBridge::rollbackStmtTx");
- DBUG_ASSERT(stmtTxActive);
- stmtTxActive = false;
- DBUG_RETURN(savepoint(QMY_ROLLBACK_SAVEPOINT, SAVEPOINT_NAME));
- }
-
-
- /**
- Provide storage for generating error messages.
-
- This storage must persist until the error message is retrieved from the
- handler instance. It is for this reason that we associate it with the bridge.
-
- @return Pointer to heap storage of MYSQL_ERRMSG_SIZE bytes
- */
- char* getErrorStorage()
- {
- if (!connErrText)
- {
- connErrText = (char*)my_malloc(MYSQL_ERRMSG_SIZE, MYF(MY_WME));
- if (connErrText) connErrText[0] = 0;
- }
-
- return connErrText;
- }
-
- /**
- Free storage for generating error messages.
- */
- void freeErrorStorage()
- {
- if (likely(connErrText))
- {
- my_free(connErrText);
- connErrText = NULL;
- }
- }
-
-
- /**
- Store a file handle for later retrieval.
-
- If deallocateFile encounters a lock when trying to perform its operation,
- the file remains allocated but must be deallocated later. This function
- provides a way for the connection to "remember" that this deallocation is
- still needed.
-
- @param newname The name of the file to be added
- @param newhandle The handle associated with newname
-
- */
- void preserveHandle(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share)
- {
- pendingLockedHandles.add(newname, newhandle, share);
- }
-
- /**
- Retrieve a file handle stored by preserveHandle().
-
- @param name The name of the file to be retrieved.
-
- @return The handle associated with name
- */
- FILE_HANDLE findAndRemovePreservedHandle(const char* name, IBMDB2I_SHARE** share)
- {
- FILE_HANDLE hdl = pendingLockedHandles.findAndRemove(name, share);
- return hdl;
- }
-
- /**
- Indicate which error messages should be suppressed on the next API call
-
- These functions are useful for ensuring that the provided error numbers
- are returned if a failure occurs but do not cause a spurious error message
- to be returned.
-
- @return A pointer to this instance
- */
- db2i_ileBridge* expectErrors(int32 er1)
- {
- tacitErrors[0]=er1;
- return this;
- }
-
- db2i_ileBridge* expectErrors(int32 er1, int32 er2)
- {
- tacitErrors[0]=er1;
- tacitErrors[1]=er2;
- return this;
- }
-
- /**
- Obtain the IBM i system message that accompanied the last API failure.
-
- @return A pointer to the 7 character message ID.
- */
- static const char* getErrorMsgID()
- {
- return ((Qmy_Error_output_t*)parms()->outParms)->MsgId;
- }
-
- /**
- Convert an API error code into the equivalent MySQL error code (if any)
-
- @param rc The QMYSE API error code
-
- @return If an equivalent exists, the MySQL error code; else rc
- */
- static int32 translateErrorCode(int32 rc)
- {
- if (likely(rc == 0))
- return 0;
-
- switch (rc)
- {
- case QMY_ERR_KEY_NOT_FOUND:
- return HA_ERR_KEY_NOT_FOUND;
- case QMY_ERR_DUP_KEY:
- return HA_ERR_FOUND_DUPP_KEY;
- case QMY_ERR_END_OF_FILE:
- return HA_ERR_END_OF_FILE;
- case QMY_ERR_LOCK_TIMEOUT:
- return HA_ERR_LOCK_WAIT_TIMEOUT;
- case QMY_ERR_CST_VIOLATION:
- return HA_ERR_NO_REFERENCED_ROW;
- case QMY_ERR_TABLE_NOT_FOUND:
- return HA_ERR_NO_SUCH_TABLE;
- case QMY_ERR_NON_UNIQUE_KEY:
- return ER_DUP_ENTRY;
- case QMY_ERR_MSGID:
- {
- if (memcmp(getErrorMsgID(), DB2I_CPF503A, 7) == 0)
- return HA_ERR_ROW_IS_REFERENCED;
- if (memcmp(getErrorMsgID(), DB2I_SQL0538, 7) == 0)
- return HA_ERR_CANNOT_ADD_FOREIGN;
- }
- }
- return rc;
- }
-
-private:
-
- static db2i_ileBridge* createNewBridge(CONNECTION_HANDLE connID);
- static void destroyBridge(db2i_ileBridge* bridge);
- static int registerParmSpace(char* in, char* out);
- static int32 doIt();
- int32 doItWithLog();
-
- static _ILEpointer *functionSymbols; ///< Array of ILE function pointers
- CONNECTION_HANDLE cachedConnectionID; ///< The associated connection
- bool stmtTxActive; ///< Inside statement transaction
- char *connErrText; ///< Storage for error message
- int32 tacitErrors[TACIT_ERRORS_SIZE]; ///< List of errors to be suppressed
-
- static IleParms* initParmsForThread();
-
- /**
- Get space for passing parameters to the QMY_* APIs
-
- @details A fixed-length parameter passing space is associated with each
- pthread. This space is allocated and registered by initParmsForThread()
- the first time a pthread works with a bridge. The space is cached away
- and remains available until the pthread ends. It became necessary to
- disassociate the parameter space from the bridge in order to support
- future enhancements to MySQL that sever the one-to-one relationship between
- pthreads and user connections. The QMY_* APIs scope a registered parameter
- space to the thread that executes the register operation.
- */
- static IleParms* parms()
- {
- IleParms* p = my_pthread_getspecific_ptr(IleParms*, THR_ILEPARMS);
- if (likely(p))
- return p;
-
- return initParmsForThread();
- }
-
- class PreservedHandleList
- {
- friend db2i_ileBridge* db2i_ileBridge::createNewBridge(CONNECTION_HANDLE);
- public:
- void add(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share);
- FILE_HANDLE findAndRemove(const char* fileName, IBMDB2I_SHARE** share);
-
- private:
- struct NameHandlePair
- {
- char name[FN_REFLEN];
- FILE_HANDLE handle;
- IBMDB2I_SHARE* share;
- NameHandlePair* next;
- }* head;
- } pendingLockedHandles;
-
-
-#ifndef DBUG_OFF
- bool cachedStateIsCoherent()
- {
- return (current_thd->thread_id == cachedConnectionID);
- }
-
- friend void db2i_ileBridge::unregisterPtr(ILEMemHandle);
- friend void db2i_ileBridge::registerPtr(const void*, ILEMemHandle*);
- static uint32 registeredPtrs;
-#endif
-};
-
-
-
-#endif
diff --git a/storage/ibmdb2i/db2i_ioBuffers.cc b/storage/ibmdb2i/db2i_ioBuffers.cc
deleted file mode 100644
index 9525a6e34b5..00000000000
--- a/storage/ibmdb2i/db2i_ioBuffers.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#include "db2i_ioBuffers.h"
-
-/**
- Request another block of rows
-
- Request the next set of rows from DB2. This must only be called after
- newReadRequest().
-
- @param orientation The direction to use when reading through the table.
-*/
-void IOAsyncReadBuffer::loadNewRows(char orientation)
-{
- rewind();
- maxRows() = rowsToBlock;
-
- DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("Requesting %d rows, async = %d", rowsToBlock, readIsAsync));
-
- rc = getBridge()->expectErrors(QMY_ERR_END_OF_BLOCK, QMY_ERR_LOB_SPACE_TOO_SMALL)
- ->read(file,
- ptr(),
- accessIntent,
- commitLevel,
- orientation,
- readIsAsync,
- rrnList,
- 0,
- 0,
- 0);
-
- DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("recordsRead: %d, rc: %d", (uint32)rowCount(), rc));
-
-
- *releaseRowNeeded = true;
-
- if (rc == QMY_ERR_END_OF_BLOCK)
- {
- // This is really just an informational error, so we ignore it.
- rc = 0;
- DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("End of block signalled"));
- }
- else if (rc == QMY_ERR_END_OF_FILE)
- {
- // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked.
- rc = HA_ERR_END_OF_FILE;
- *releaseRowNeeded = false;
- }
- else if (rc == QMY_ERR_KEY_NOT_FOUND)
- {
- rc = HA_ERR_KEY_NOT_FOUND;
- *releaseRowNeeded = false;
- }
-
- if (rc) closePipe();
-}
-
-
-/**
- Empty the message pipe to prepare for another read.
-*/
-void IOAsyncReadBuffer::drainPipe()
-{
- DBUG_ASSERT(pipeState == PendingFullBufferMsg);
- PipeRpy_t msg[32];
- int bytes;
- PipeRpy_t* lastMsg;
- while ((bytes = read(msgPipe, msg, sizeof(msg))) > 0)
- {
- DBUG_PRINT("db2i_ioBuffers::drainPipe",("Pipe returned %d bytes", bytes));
- lastMsg = &msg[bytes / (sizeof(msg[0]))-1];
- if (lastMsg->CumRowCnt == maxRows() ||
- lastMsg->RtnCod != 0)
- {
- pipeState = ConsumedFullBufferMsg;
- break;
- }
-
- }
- DBUG_PRINT("db2i_ioBuffers::drainPipe",("rc = %d, rows = %d, max = %d", lastMsg->RtnCod, lastMsg->CumRowCnt, (uint32)maxRows()));
-}
-
-
-/**
- Poll the message pipe for async read messages
-
- Only valid in async
-
- @param orientation The direction to use when reading through the table.
-*/
-void IOAsyncReadBuffer::pollNextRow(char orientation)
-{
- DBUG_ASSERT(readIsAsync);
-
- // Handle the case in which the buffer is full.
- if (rowCount() == maxRows())
- {
- // If we haven't read to the end, exit here.
- if (readCursor < rowCount())
- return;
-
- if (pipeState == PendingFullBufferMsg)
- drainPipe();
- if (pipeState == ConsumedFullBufferMsg)
- loadNewRows(orientation);
- }
-
- if (!rc)
- {
- PipeRpy_t* lastMsg = NULL;
- while (true)
- {
- PipeRpy_t msg[32];
- int bytes = read(msgPipe, msg, sizeof(msg));
- DBUG_PRINT("db2i_ioBuffers::pollNextRow",("Pipe returned %d bytes", bytes));
-
- if (unlikely(bytes < 0))
- {
- DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("Error"));
- rc = errno;
- break;
- }
- else if (bytes == 0)
- break;
-
- DBUG_ASSERT(bytes % sizeof(msg[0]) == 0);
- lastMsg = &msg[bytes / (sizeof(msg[0]))-1];
-
- if (lastMsg->RtnCod || (lastMsg->CumRowCnt == usedRows()))
- {
- rc = lastMsg->RtnCod;
- break;
- }
- }
-
- *releaseRowNeeded = true;
-
- if (rc == QMY_ERR_END_OF_BLOCK)
- rc = 0;
- else if (rc == QMY_ERR_END_OF_FILE)
- {
- // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked.
- rc = HA_ERR_END_OF_FILE;
- *releaseRowNeeded = false;
- }
- else if (rc == QMY_ERR_KEY_NOT_FOUND)
- {
- rc = HA_ERR_KEY_NOT_FOUND;
- *releaseRowNeeded = false;
- }
-
- if (lastMsg)
- DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("Good data: rc=%d; rows=%d; usedRows=%d", lastMsg->RtnCod, lastMsg->CumRowCnt, (uint32)usedRows()));
- if (lastMsg && likely(!rc))
- {
- if (lastMsg->CumRowCnt < maxRows())
- pipeState = PendingFullBufferMsg;
- else
- pipeState = ConsumedFullBufferMsg;
-
- DBUG_ASSERT(lastMsg->CumRowCnt <= usedRows());
-
- }
- DBUG_ASSERT(rowCount() <= getRowCapacity());
- }
- DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("filledRows: %d, rc: %d", rowCount(), rc));
- if (rc) closePipe();
-}
-
-
-/**
- Prepare for the destruction of the row buffer storage.
-*/
-void IOAsyncReadBuffer::prepForFree()
-{
- interruptRead();
- rewind();
- IORowBuffer::prepForFree();
-}
-
-
-/**
- Initialize the newly allocated storage.
-
- @param sizeChanged Indicates whether the storage capacity is being changed.
-*/
-void IOAsyncReadBuffer::initAfterAllocate(bool sizeChanged)
-{
- rewind();
-
- if (sizeChanged || ((void*)rrnList == NULL))
- rrnList.realloc(getRowCapacity() * sizeof(uint32));
-}
-
-
-/**
- Send an initial read request
-
- @param infile The file (table/index) being read from
- @param orientation The orientation to use for this read request
- @param rowsToBuffer The number of rows to request each time
- @param useAsync Whether reads should be performed asynchronously.
- @param key The key to use (if any)
- @param keyLength The length of key (if any)
- @param keyParts The number of columns in the key (if any)
-
-*/
-void IOAsyncReadBuffer::newReadRequest(FILE_HANDLE infile,
- char orientation,
- uint32 rowsToBuffer,
- bool useAsync,
- ILEMemHandle key,
- int keyLength,
- int keyParts)
-{
- DBUG_ENTER("db2i_ioBuffers::newReadRequest");
- DBUG_ASSERT(rowsToBuffer <= getRowCapacity());
-#ifndef DBUG_OFF
- if (readCursor < rowCount())
- DBUG_PRINT("PERF:",("Wasting %d buffered rows!\n", rowCount() - readCursor));
-#endif
-
- int fildes[2];
- int ileDescriptor = QMY_REUSE;
-
- interruptRead();
-
- if (likely(useAsync))
- {
- if (rowsToBuffer == 1)
- {
- // Async provides little or no benefit for single row reads, so we turn it off
- DBUG_PRINT("db2i_ioBuffers::newReadRequest", ("Disabling async"));
- useAsync = false;
- }
- else
- {
- rc = pipe(fildes);
- if (rc) DBUG_VOID_RETURN;
-
- // Translate the pipe write descriptor into the equivalent ILE descriptor
- rc = fstatx(fildes[1], (struct stat*)&ileDescriptor, sizeof(ileDescriptor), STX_XPFFD_PASE);
- if (rc)
- {
- close(fildes[0]);
- close(fildes[1]);
- DBUG_VOID_RETURN;
- }
- pipeState = Untouched;
- msgPipe = fildes[0];
-
- DBUG_PRINT("db2i_ioBuffers::newReadRequest", ("Opened pipe %d", fildes[0]));
- }
- }
-
- file = infile;
- readIsAsync = useAsync;
- rowsToBlock = rowsToBuffer;
-
- rewind();
- maxRows() = 1;
- rc = getBridge()->expectErrors(QMY_ERR_END_OF_BLOCK, QMY_ERR_LOB_SPACE_TOO_SMALL)
- ->read(file,
- ptr(),
- accessIntent,
- commitLevel,
- orientation,
- useAsync,
- rrnList,
- key,
- keyLength,
- keyParts,
- ileDescriptor);
-
- // Having shared the pipe with ILE, we relinquish our claim on the write end
- // of the pipe.
- if (useAsync)
- close(fildes[1]);
-
- // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked.
- if (rc == QMY_ERR_END_OF_FILE)
- {
- rc = HA_ERR_END_OF_FILE;
- *releaseRowNeeded = false;
- }
- else if (rc == QMY_ERR_KEY_NOT_FOUND)
- {
- if (rowCount())
- rc = HA_ERR_END_OF_FILE;
- else
- rc = HA_ERR_KEY_NOT_FOUND;
- *releaseRowNeeded = false;
- }
- else
- *releaseRowNeeded = true;
-
- DBUG_VOID_RETURN;
-}
diff --git a/storage/ibmdb2i/db2i_ioBuffers.h b/storage/ibmdb2i/db2i_ioBuffers.h
deleted file mode 100644
index 350d854f055..00000000000
--- a/storage/ibmdb2i/db2i_ioBuffers.h
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-/**
- @file db2i_ioBuffers.h
-
- @brief Buffer classes used for interacting with QMYSE read/write buffers.
-
-*/
-
-
-#include "db2i_validatedPointer.h"
-#include "mysql_priv.h"
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <as400_types.h>
-
-// Needed for compilers which do not include fstatx in standard headers.
-extern "C" int fstatx(int, struct stat *, int, int);
-
-/**
- Basic row buffer
-
- Provides the basic structure and methods needed for communicating
- with QMYSE I/O APIs.
-
- @details All QMYSE I/O apis use a buffer that is structured as two integer
- row counts (max and used) and storage for some number of rows. The row counts
- are both input and output for the API, and their usage depends on the
- particular API invoked. This class encapsulates that buffer definition.
-*/
-class IORowBuffer
-{
- public:
- IORowBuffer() : allocSize(0), rowLength(0) {;}
- ~IORowBuffer() { freeBuf(); }
- ValidatedPointer<char>& ptr() { return data; }
-
- /**
- Sets up the buffer to hold the size indicated.
-
- @param rowLen length of the rows that will be stored in this buffer
- @param nullMapOffset position of null map within each row
- @param size buffer size requested
- */
- void allocBuf(uint32 rowLen, uint16 nullMapOffset, uint32 size)
- {
- nullOffset = nullMapOffset;
- uint32 newSize = size + sizeof(BufferHdr_t);
- // If the internal structure of the row is changing, we need to
- // remember this and notify the subclasses via initAfterAllocate();
- bool formatChanged = ((size/rowLen) != rowCapacity);
-
- if (newSize > allocSize)
- {
- this->freeBuf();
- data.alloc(newSize);
- if (likely((void*)data))
- allocSize = newSize;
- }
-
- if (likely((void*)data))
- {
- DBUG_ASSERT((uint64)(void*)data % 16 == 0);
- rowLength = rowLen;
- rowCapacity = size / rowLength;
- initAfterAllocate(formatChanged);
- }
- else
- {
- allocSize = 0;
- rowCapacity = 0;
- }
-
- DBUG_PRINT("db2i_ioBuffers::allocBuf",("rowCapacity = %d", rowCapacity));
- }
-
- void zeroBuf()
- {
- memset(data, 0, allocSize);
- }
-
- void freeBuf()
- {
- if (likely(allocSize))
- {
- prepForFree();
- DBUG_PRINT("IORowBuffer::freeBuf",("Freeing 0x%p", (char*)data));
- data.dealloc();
- }
- }
-
- char* getRowN(uint32 n)
- {
- if (unlikely(n >= getRowCapacity()))
- return NULL;
- return (char*)data + sizeof(BufferHdr_t) + (rowLength * n);
- };
-
- uint32 getRowCapacity() const {return rowCapacity;}
- uint32 getRowNullOffset() const {return nullOffset;}
- uint32 getRowLength() const {return rowLength;}
-
- protected:
- /**
- Called prior to freeing buffer storage so that subclasses can do
- any required cleanup
- */
- virtual void prepForFree()
- {
- allocSize = 0;
- rowCapacity = 0;
- }
-
- /**
- Called after buffer storage so that subclasses can do any required setup.
- */
- virtual void initAfterAllocate(bool sizeChanged) { return;}
-
- ValidatedPointer<char> data;
- uint32 allocSize;
- uint32 rowCapacity;
- uint32 rowLength;
- uint16 nullOffset;
- uint32& usedRows() const { return ((BufferHdr_t*)(char*)data)->UsedRowCnt; }
- uint32& maxRows() const {return ((BufferHdr_t*)(char*)data)->MaxRowCnt; }
-};
-
-
-/**
- Write buffer
-
- Implements methods for inserting data into a row buffer for use with the
- QMY_WRITE and QMY_UPDATE APIs.
-
- @details The max row count defines how many rows are in the buffer. The used
- row count is updated by QMYSE to indicate how many rows have been
- successfully written.
-*/
-class IOWriteBuffer : public IORowBuffer
-{
- public:
- bool endOfBuffer() const {return (maxRows() == getRowCapacity());}
-
- char* addRow()
- {
- return getRowN(maxRows()++);
- }
-
- void resetAfterWrite()
- {
- maxRows() = 0;
- }
-
- void deleteRow()
- {
- --maxRows();
- }
-
- uint32 rowCount() const {return maxRows();}
-
- uint32 rowsWritten() const {return usedRows()-1;}
-
- private:
- void initAfterAllocate(bool sizeChanged) {maxRows() = 0; usedRows() = 0;}
-};
-
-
-/**
- Read buffer
-
- Implements methods for reading data from and managing a row buffer for use
- with the QMY_READ APIs. This is primarily for use with metainformation queries.
-*/
-class IOReadBuffer : public IORowBuffer
-{
- public:
-
- IOReadBuffer() {;}
- IOReadBuffer(uint32 rows, uint32 rowLength)
- {
- allocBuf(rows, 0, rows * rowLength);
- maxRows() = rows;
- }
-
- uint32 rowCount() {return usedRows();}
- void setRowsToProcess(uint32 rows) { maxRows() = rows; }
-};
-
-
-/**
- Read buffer
-
- Implements methods for reading data from and managing a row buffer for use
- with the QMY_READ APIs.
-
- @details This class supports both sync and async read modes. The max row
- count defines the number of rows that are requested to be read. The used row
- count defines how many rows have been read. Sync mode is reasonably
- straightforward, but async mode has a complex system of communicating with
- QMYSE that is optimized for low latency. In async mode, the used row count is
- updated continuously by QMYSE as rows are read. At the same time, messages are
- sent to the associated pipe indicating that a row has been read. As long as
- the internal read cursor lags behind the used row count, the pipe is never
- consulted. But if the internal read cursor "catches up to" the used row count,
- then we block on the pipe until we find a message indicating that a new row
- has been read or that an error has occurred.
-*/
-class IOAsyncReadBuffer : public IOReadBuffer
-{
- public:
- IOAsyncReadBuffer() :
- file(0), readIsAsync(false), msgPipe(QMY_REUSE), bridge(NULL)
- {
- }
-
- ~IOAsyncReadBuffer()
- {
- interruptRead();
- rrnList.dealloc();
- }
-
-
- /**
- Signal read operation complete
-
- Indicates that the storage engine requires no more data from the table.
- Must be called between calls to newReadRequest().
- */
- void endRead()
- {
-#ifndef DBUG_OFF
- if (readCursor < rowCount())
- DBUG_PRINT("PERF:",("Wasting %d buffered rows!\n", rowCount() - readCursor));
-#endif
- interruptRead();
-
- file = 0;
- bridge = NULL;
- }
-
- /**
- Update data that may change on each read operation
- */
- void update(char newAccessIntent,
- bool* newReleaseRowNeeded,
- char commitLvl)
- {
- accessIntent = newAccessIntent;
- releaseRowNeeded = newReleaseRowNeeded;
- commitLevel = commitLvl;
- }
-
- /**
- Read the next row in the table.
-
- Return a pointer to the next row in the table, where "next" is defined
- by the orientation.
-
- @param orientaton
- @param[out] rrn The relative record number of the row returned. Not reliable
- if NULL is returned by this function.
-
- @return Pointer to the row. Null if no more rows are available or an error
- occurred.
- */
- char* readNextRow(char orientation, uint32& rrn)
- {
- DBUG_PRINT("db2i_ioBuffers::readNextRow", ("readCursor: %d, filledRows: %d, rc: %d", readCursor, rowCount(), rc));
-
- while (readCursor >= rowCount() && !rc)
- {
- if (!readIsAsync)
- loadNewRows(orientation);
- else
- pollNextRow(orientation);
- }
-
- if (readCursor >= rowCount())
- return NULL;
-
- rrn = rrnList[readCursor];
- return getRowN(readCursor++);
- }
-
- /**
- Retrieve the return code generated by the last operation.
-
- @return The return code, translated to the appropriate HA_ERR_*
- value if possible.
- */
- int32 lastrc()
- {
- return db2i_ileBridge::translateErrorCode(rc);
- }
-
- void rewind()
- {
- readCursor = 0;
- rc = 0;
- usedRows() = 0;
- }
-
- bool reachedEOD() { return EOD; }
-
- void newReadRequest(FILE_HANDLE infile,
- char orientation,
- uint32 rowsToBuffer,
- bool useAsync,
- ILEMemHandle key,
- int keyLength,
- int keyParts);
-
- private:
-
- /**
- End any running async read operation.
- */
- void interruptRead()
- {
- closePipe();
- if (file && readIsAsync && (rc == 0) && (rowCount() < getRowCapacity()))
- {
- DBUG_PRINT("IOReadBuffer::interruptRead", ("PERF: Interrupting %d", (uint32)file));
- getBridge()->readInterrupt(file);
- }
- }
-
- void closePipe()
- {
- if (msgPipe != QMY_REUSE)
- {
- DBUG_PRINT("db2i_ioBuffers::closePipe", ("Closing pipe %d", msgPipe));
- close(msgPipe);
- msgPipe = QMY_REUSE;
- }
- }
-
- /**
- Get a pointer to the active ILE bridge.
-
- Getting the bridge pointer is (relatively) expensive, so we cache
- it off for each operation.
- */
- db2i_ileBridge* getBridge()
- {
- if (unlikely(bridge == NULL))
- {
- bridge = db2i_ileBridge::getBridgeForThread();
- }
- return bridge;
- }
-
- void drainPipe();
- void pollNextRow(char orientation);
- void prepForFree();
- void initAfterAllocate(bool sizeChanged);
- void loadNewRows(char orientation);
-
-
- uint32 readCursor; // Read position within buffer
- int32 rc; // Last return code received
- ValidatedPointer<uint32> rrnList; // Receiver for list of rrns
- char accessIntent; // The access intent for this read
- char commitLevel; // What isolation level should be used
- char EOD; // Whether end-of-data was hit
- char readIsAsync; // Are reads to be done asynchronously?
- bool* releaseRowNeeded;
- /* Does the caller need to release the current row when finished reading */
- FILE_HANDLE file; // The file to be read
- int msgPipe;
- /* The read descriptor of the pipe used to pass messages during async reads */
- db2i_ileBridge* bridge; // Cached pointer to bridge
- uint32 rowsToBlock; // Number of rows to request
- enum
- {
- ConsumedFullBufferMsg,
- PendingFullBufferMsg,
- Untouched
- } pipeState;
- /* The state of the async read message pipe */
-};
-
diff --git a/storage/ibmdb2i/db2i_misc.h b/storage/ibmdb2i/db2i_misc.h
deleted file mode 100644
index f0b527aaad0..00000000000
--- a/storage/ibmdb2i/db2i_misc.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-#ifndef DB2I_MISC_H
-#define DB2I_MISC_H
-
-/**
- Undelimit quote-delimited DB2 names in-place
-*/
-void stripExtraQuotes(char* name, uint maxLen)
-{
- char* oldName = (char*)sql_strdup(name);
- uint i = 0;
- uint j = 0;
- do
- {
- name[j] = oldName[i];
- if (oldName[i] == '"' && oldName[i+1] == '"')
- ++i;
- } while (++j < maxLen && oldName[++i]);
-
- if (j == maxLen)
- --j;
- name[j] = 0;
-}
-
-/**
- Convert a MySQL identifier name into a DB2 compatible format
-
- @parm input The MySQL name
- @parm output The DB2 name
- @parm outlen The amount of space allocated for output
- @parm delimit Should delimiting quotes be placed around the converted name?
- @parm delimitQuotes Should quotes in the MySQL be delimited with additional quotes?
-
- @return FALSE if output was too small and name was truncated; TRUE otherwise
-*/
-bool convertMySQLNameToDB2Name(const char* input,
- char* output,
- size_t outlen,
- bool delimit = true,
- bool delimitQuotes = true)
-{
- uint o = 0;
- if (delimit)
- output[o++] = '"';
-
- uint i = 0;
- do
- {
- output[o] = input[i];
- if (delimitQuotes && input[i] == '"')
- output[++o] = '"';
- } while (++o < outlen-2 && input[++i]);
-
- if (delimit)
- output[o++] = '"';
- output[min(o, outlen-1)] = 0; // This isn't the most user-friendly way to handle overflows,
- // but at least its safe.
- return (o <= outlen-1);
-}
-
-bool isOrdinaryIdentifier(const char* s)
-{
- while (*s)
- {
- if (my_isupper(system_charset_info, *s) ||
- my_isdigit(system_charset_info, *s) ||
- (*s == '_') ||
- (*s == '@') ||
- (*s == '$') ||
- (*s == '#') ||
- (*s == '"'))
- ++s;
- else
- return false;
- }
- return true;
-}
-
-/**
- Fill memory with a 16-bit word.
-
- @param p Pointer to space to fill.
- @param v Value to fill
- @param l Length of space (in 16-bit words)
-*/
-void memset16(void* p, uint16 v, size_t l)
-{
- uint16* p2=(uint16*)p;
- while (l--)
- {
- *(p2++) = v;
- }
-}
-
-#endif
diff --git a/storage/ibmdb2i/db2i_myconv.cc b/storage/ibmdb2i/db2i_myconv.cc
deleted file mode 100644
index 7be6e1236cd..00000000000
--- a/storage/ibmdb2i/db2i_myconv.cc
+++ /dev/null
@@ -1,1498 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-/**
- @file
-
- @brief A direct map optimization of iconv and related functions
- This was show to significantly reduce character conversion cost
- for short strings when compared to calling iconv system code.
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <wchar.h>
-#include <errno.h>
-#include <iconv.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <string.h>
-#include <as400_protos.h>
-
-#include "db2i_myconv.h"
-#include "db2i_global.h"
-
-int32_t myconvDebug=0;
-
-static char szGetTimeString[20];
-static char * GetTimeString(time_t now)
-{
- struct tm * tm;
-
- now = time(&now);
- tm = (struct tm *) localtime(&now);
- sprintf(szGetTimeString, "%04d/%02d/%02d %02d:%02d:%02d",
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
-
- return szGetTimeString;
-}
-
-static MEM_ROOT dmapMemRoot;
-
-void initMyconv()
-{
- init_alloc_root(&dmapMemRoot, 0x200, 0);
-}
-
-void cleanupMyconv()
-{
- free_root(&dmapMemRoot,0);
-}
-
-
-#ifdef DEBUG
-/* type: */
-#define STDOUT_WITH_TIME -1 /* to stdout with time */
-#define STDERR_WITH_TIME -2 /* to stderr with time */
-#define STDOUT_WO_TIME 1 /* : to stdout */
-#define STDERR_WO_TIME 2 /* : to stderr */
-
-
-static void MyPrintf(long type,
- char * fmt, ...)
-{
- char StdoutFN[256];
- va_list ap;
- char * p;
- time_t now;
- FILE * fd=stderr;
-
- if (type < 0)
- {
- now = time(&now);
- fprintf(fd, "%s ", GetTimeString(now));
- }
- va_start(ap, fmt);
- vfprintf(fd, fmt, ap);
- va_end(ap);
-}
-#endif
-
-
-
-
-#define MAX_CONVERTER 128
-
-mycstoccsid(const char* pname)
-{
- if (strcmp(pname, "UTF-16")==0)
- return 1200;
- else if (strcmp(pname, "big5")==0)
- return 950;
- else
- return cstoccsid(pname);
-}
-#define cstoccsid mycstoccsid
-
-static struct __myconv_rec myconv_rec [MAX_CONVERTER];
-static struct __dmap_rec dmap_rec [MAX_CONVERTER];
-
-static int dmap_open(const char * to,
- const char * from,
- const int32_t idx)
-{
- if (myconvIsSBCS(from) && myconvIsSBCS(to)) {
- dmap_rec[idx].codingSchema = DMAP_S2S;
- if ((dmap_rec[idx].dmapS2S = (uchar *) alloc_root(&dmapMemRoot, 0x100)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_S2S, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapS2S, 0x00, 0x100);
- myconv_rec[idx].allocatedSize=0x100;
-
- {
- char dmapSrc[0x100];
- iconv_t cd;
- int32_t i;
- size_t inBytesLeft=0x100;
- size_t outBytesLeft=0x100;
- size_t len;
- char * inBuf=dmapSrc;
- char * outBuf=(char *) dmap_rec[idx].dmapS2S;
-
- if ((cd = iconv_open(to, from)) == (iconv_t) -1) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
-
- inBytesLeft = 0x100;
- for (i = 0; i < inBytesLeft; ++i)
- dmapSrc[i]=i;
-
- do {
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d: iconv() returns %d, errno = %d in %s at %d\n",
- to, from, idx, DMAP_S2S, len, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WITH_TIME,
- "inBytesLeft = %d, inBuf - dmapSrc = %d\n", inBytesLeft, inBuf-dmapSrc);
- MyPrintf(STDERR_WITH_TIME,
- "outBytesLeft = %d, outBuf - dmapS2S = %d\n", outBytesLeft, outBuf-(char *) dmap_rec[idx].dmapS2S);
- }
- if ((inBytesLeft == 86 || inBytesLeft == 64 || inBytesLeft == 1) &&
- memcmp(from, "IBM-1256", 9) == 0 &&
- memcmp(to, "IBM-420", 8) == 0) {
- /* Known problem for IBM-1256_IBM-420 */
- --inBytesLeft;
- ++inBuf;
- *outBuf=0x00;
- ++outBuf;
- --outBytesLeft;
- continue;
- } else if ((inBytesLeft == 173 || inBytesLeft == 172 ||
- inBytesLeft == 74 || inBytesLeft == 73 ||
- inBytesLeft == 52 || inBytesLeft == 50 ||
- inBytesLeft == 31 || inBytesLeft == 20 ||
- inBytesLeft == 6) &&
- memcmp(to, "IBM-1256", 9) == 0 &&
- memcmp(from, "IBM-420", 8) == 0) {
- /* Known problem for IBM-420_IBM-1256 */
- --inBytesLeft;
- ++inBuf;
- *outBuf=0x00;
- ++outBuf;
- --outBytesLeft;
- continue;
- } else if ((128 >= inBytesLeft) &&
- memcmp(to, "IBM-037", 8) == 0 &&
- memcmp(from, "IBM-367", 8) == 0) {
- /* Known problem for IBM-367_IBM-037 */
- --inBytesLeft;
- ++inBuf;
- *outBuf=0x00;
- ++outBuf;
- --outBytesLeft;
- continue;
- } else if (((1 <= inBytesLeft && inBytesLeft <= 4) || (97 <= inBytesLeft && inBytesLeft <= 128)) &&
- memcmp(to, "IBM-838", 8) == 0 &&
- memcmp(from, "TIS-620", 8) == 0) {
- /* Known problem for TIS-620_IBM-838 */
- --inBytesLeft;
- ++inBuf;
- *outBuf=0x00;
- ++outBuf;
- --outBytesLeft;
- continue;
- }
- iconv_close(cd);
- return -1;
-#else
- /* Tolerant to undefined conversions for any converter */
- --inBytesLeft;
- ++inBuf;
- *outBuf=0x00;
- ++outBuf;
- --outBytesLeft;
- continue;
-#endif
- }
- } while (inBytesLeft > 0);
-
- if (myconvIsISO(to))
- myconv_rec[idx].subS=0x1A;
- else if (myconvIsASCII(to))
- myconv_rec[idx].subS=0x7F;
- else if (myconvIsEBCDIC(to))
- myconv_rec[idx].subS=0x3F;
-
- if (myconvIsISO(from))
- myconv_rec[idx].srcSubS=0x1A;
- else if (myconvIsASCII(from))
- myconv_rec[idx].srcSubS=0x7F;
- else if (myconvIsEBCDIC(from))
- myconv_rec[idx].srcSubS=0x3F;
-
- iconv_close(cd);
- }
- } else if (((myconvIsSBCS(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_S2U)) ||
- ((myconvIsSBCS(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_S28))) {
- int i;
-
- /* single byte mapping */
- if ((dmap_rec[idx].dmapD12U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_S2U, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapD12U, 0x00, 0x100 * 2);
- myconv_rec[idx].allocatedSize=0x100 * 2;
-
-
- {
- char dmapSrc[2];
- iconv_t cd;
- int32_t i;
- size_t inBytesLeft;
- size_t outBytesLeft;
- size_t len;
- char * inBuf;
- char * outBuf;
- char SS=0x1A;
-#ifdef support_surrogate
- if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) {
-#else
- if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) {
-#endif
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
-
- for (i = 0; i < 0x100; ++i) {
- dmapSrc[0]=i;
- inBuf=dmapSrc;
- inBytesLeft=1;
- outBuf=(char *) &(dmap_rec[idx].dmapD12U[i]);
- outBytesLeft=2;
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
- if ((errno == EILSEQ || errno == EINVAL) &&
- inBytesLeft == 1 &&
- outBytesLeft == 2) {
- continue;
- } else {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%02x,%d,%02x%02x,%d), errno = %d in %s at %d\n",
- to, from, idx, dmapSrc[0], 1,
- (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1], 2,
- errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WITH_TIME,
- "inBytesLeft=%d, outBytesLeft=%d, %02x%02x\n",
- inBytesLeft, outBytesLeft,
- (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1]);
- }
-#endif
- iconv_close(cd);
- return -1;
- }
- dmap_rec[idx].dmapD12U[i]=0x0000;
- }
- if (dmap_rec[idx].dmapE02U[i] == 0x001A && /* pick the first one */
- myconv_rec[idx].srcSubS == 0x00) {
- myconv_rec[idx].srcSubS=i;
- }
- }
- iconv_close(cd);
- }
- myconv_rec[idx].subS=0x1A;
- myconv_rec[idx].subD=0xFFFD;
-
-
- } else if (((myconvIsUCS2(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_U2S)) ||
- ((myconvIsUTF16(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_T2S)) ||
- ((myconvIsUTF8(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_82S))) {
- /* UTF-16 -> SBCS, the direct map a bit of waste of space,
- * binary search may be reasonable alternative
- */
- if ((dmap_rec[idx].dmapU2S = (uchar *) alloc_root(&dmapMemRoot, 0x10000 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_U2S, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapU2S, 0x00, 0x10000);
- myconv_rec[idx].allocatedSize=(0x10000 * 2);
-
- {
- iconv_t cd;
- int32_t i;
-
-#ifdef support_surrogate
- if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) {
-#else
- if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) {
-#endif
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
-
- for (i = 0; i < 0x100; ++i) {
- UniChar dmapSrc[0x100];
- int32_t j;
- for (j = 0; j < 0x100; ++j) {
- dmapSrc[j]=i * 0x100 + j;
- }
- char * inBuf=(char *) dmapSrc;
- char * outBuf=(char *) &(dmap_rec[idx].dmapU2S[i*0x100]);
- size_t inBytesLeft=sizeof(dmapSrc);
- size_t outBytesLeft=0x100;
- size_t len;
-
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
- if (inBytesLeft == 0 && outBytesLeft == 0) { /* a number of substitution returns */
- continue;
- }
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- from, to, idx, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WITH_TIME,
- "iconv() retuns %d, errno=%d, InBytesLeft=%d, OutBytesLeft=%d\n",
- len, errno, inBytesLeft, outBytesLeft, __FILE__,__LINE__);
- }
-#endif
- iconv_close(cd);
- return -1;
- }
- }
- iconv_close(cd);
-
- myconv_rec[idx].subS = dmap_rec[idx].dmapU2S[0x1A];
- myconv_rec[idx].subD = dmap_rec[idx].dmapU2S[0xFFFD];
- myconv_rec[idx].srcSubS = 0x1A;
- myconv_rec[idx].srcSubD = 0xFFFD;
- }
-
-
-
- } else if (((myconvIsDBCS(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_D2U)) ||
- ((myconvIsDBCS(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_D28))) {
- int i;
- /* single byte mapping */
- if ((dmap_rec[idx].dmapD12U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_D2U, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapD12U, 0x00, 0x100 * 2);
-
- /* double byte mapping, assume 7 bit ASCII is not use as the first byte of DBCS. */
- if ((dmap_rec[idx].dmapD22U = (UniChar *) alloc_root(&dmapMemRoot, 0x8000 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_D2U, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapD22U, 0x00, 0x8000 * 2);
-
- myconv_rec[idx].allocatedSize=(0x100 + 0x8000) * 2;
-
-
- {
- char dmapSrc[2];
- iconv_t cd;
- int32_t i;
- size_t inBytesLeft;
- size_t outBytesLeft;
- size_t len;
- char * inBuf;
- char * outBuf;
- char SS=0x1A;
-
-#ifdef support_surrogate
- if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) {
-#else
- if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) {
-#endif
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
-
- for (i = 0; i < 0x100; ++i) {
- dmapSrc[0]=i;
- inBuf=dmapSrc;
- inBytesLeft=1;
- outBuf=(char *) (&dmap_rec[idx].dmapD12U[i]);
- outBytesLeft=2;
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
- if ((errno == EILSEQ || errno == EINVAL) &&
- inBytesLeft == 1 &&
- outBytesLeft == 2) {
- continue;
- } else {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%02x,%d,%02x%02x,%d), errno = %d in %s at %d\n",
- to, from, idx, dmapSrc[0], 1,
- (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1], 2,
- errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WITH_TIME,
- "inBytesLeft=%d, outBytesLeft=%d, %02x%02x\n",
- inBytesLeft, outBytesLeft,
- (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1]);
- }
-#endif
- iconv_close(cd);
- return -1;
- }
- dmap_rec[idx].dmapD12U[i]=0x0000;
- }
- if (dmap_rec[idx].dmapD12U[i] == 0x001A && /* pick the first one */
- myconv_rec[idx].srcSubS == 0x00) {
- myconv_rec[idx].srcSubS=i;
- }
- }
-
-
- for (i = 0x80; i < 0x100; ++i) {
- int j;
- if (dmap_rec[idx].dmapD12U[i] != 0x0000)
- continue;
- for (j = 0x01; j < 0x100; ++j) {
- dmapSrc[0]=i;
- dmapSrc[1]=j;
- int offset = i-0x80;
- offset<<=8;
- offset+=j;
-
- inBuf=dmapSrc;
- inBytesLeft=2;
- outBuf=(char *) &(dmap_rec[idx].dmapD22U[offset]);
- outBytesLeft=2;
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
- if (inBytesLeft == 2 && outBytesLeft == 2 && (errno == EILSEQ || errno == EINVAL)) {
- ; /* invalid DBCS character, dmapDD2U[offset] remains 0x0000 */
- } else {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%p,2,%p,2), errno = %d in %s at %d\n",
- to, from, idx,
- dmapSrc, &(dmap_rec[idx].dmapD22U[offset]),
- errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WO_TIME,
- "iconv(cd,0x%02x%02x,2,0x%04x,2) returns %d, inBytesLeft=%d, outBytesLeft=%d\n",
- dmapSrc[0], dmapSrc[1],
- dmap_rec[idx].dmapD22U[offset],
- len, inBytesLeft, outBytesLeft);
- }
-#endif
- iconv_close(cd);
- return -1;
- }
- } else {
-#ifdef TRACE_DMAP
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n",
- to, from, idx, len, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WITH_TIME,
- "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf=%02X%02X%02X, outBytesLeft=%d\n",
- i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1],
- inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft);
- MyPrintf(STDERR_WITH_TIME,
- "&dmapSrc=%p, inBuf=%p, %p, outBuf=%p\n",
- dmapSrc, inBuf, dmap_rec[idx].dmapU2M3 + (i - 0x80) * 2, outBuf);
- }
-#endif
- }
- }
- if (dmap_rec[idx].dmapD12U[i] == 0xFFFD) { /* pick the last one */
- myconv_rec[idx].srcSubD=i* 0x100 + j;
- }
- }
- iconv_close(cd);
- }
-
- myconv_rec[idx].subS=0x1A;
- myconv_rec[idx].subD=0xFFFD;
- myconv_rec[idx].srcSubD=0xFCFC;
-
-
- } else if (((myconvIsUCS2(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_U2D)) ||
- ((myconvIsUTF16(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_T2D)) ||
- ((myconvIsUTF8(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_82D))) {
- /* UTF-16 -> DBCS single/double byte */
- /* A single table will cover all characters, assuming no second byte is 0x00. */
- if ((dmap_rec[idx].dmapU2D = (uchar *) alloc_root(&dmapMemRoot, 0x10000 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_U2D, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
-
- memset(dmap_rec[idx].dmapU2D, 0x00, 0x10000 * 2);
- myconv_rec[idx].allocatedSize=(0x10000 * 2);
-
- {
- UniChar dmapSrc[1];
- iconv_t cd;
- int32_t i;
- size_t inBytesLeft;
- size_t outBytesLeft;
- size_t len;
- char * inBuf;
- char * outBuf;
-
-#ifdef support_surrogate
- if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) {
-#else
- if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) {
-#endif
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
-
- /* easy implementation, convert 1 Unicode character at one time. */
- /* If the open performance is an issue, convert a chunk such as 128 chracters. */
- /* if the converted length is not the same as the original, convert one by one. */
- (dmap_rec[idx].dmapU2D)[0x0000]=0x00;
- for (i = 1; i < 0x10000; ++i) {
- dmapSrc[0]=i;
- inBuf=(char *) dmapSrc;
- inBytesLeft=2;
- outBuf=(char *) &((dmap_rec[idx].dmapU2D)[2*i]);
- outBytesLeft=2;
- do {
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
- if (len == 1 && inBytesLeft == 0 && outBytesLeft == 1 && (dmap_rec[idx].dmapU2D)[2*i] == 0x1A) {
- /* UCS-2_TIS-620:0x0080 => 0x1A, converted to SBCS replacement character */
- (dmap_rec[idx].dmapU2D)[2*i+1]=0x00;
- break;
- } else if (len == 1 && inBytesLeft == 0 && outBytesLeft == 0) {
- break;
- }
- if (errno == EILSEQ || errno == EINVAL) {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WO_TIME,
- "iconv(cd,%04x,2,%02x%02x,2) returns inBytesLeft=%d, outBytesLeft=%d\n",
- dmapSrc[0],
- (dmap_rec[idx].dmapU2D)[2*i], (dmap_rec[idx].dmapU2D)[2*i+1],
- inBytesLeft, outBytesLeft);
- if (outBuf - (char *) dmap_rec[idx].dmapU2M2 > 1)
- MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]);
- else
- MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]);
- }
-#endif
- inBuf+=2;
- inBytesLeft-=2;
- memcpy(outBuf, (char *) &(myconv_rec[idx].subD), 2);
- outBuf+=2;
- outBytesLeft-=2;
- } else {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "[%d] dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- i, to, from, idx, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WO_TIME,
- "iconv(cd,%04x,2,%02x%02x,2) returns %d inBytesLeft=%d, outBytesLeft=%d\n",
- dmapSrc[0],
- (dmap_rec[idx].dmapU2D)[2*i],
- (dmap_rec[idx].dmapU2D)[2*i+1],
- len, inBytesLeft,outBytesLeft);
- if (i == 1) {
- MyPrintf(STDERR_WO_TIME,
- " inBuf [-1..2]=%02x%02x%02x%02x\n",
- inBuf[-1],inBuf[0],inBuf[1],inBuf[2]);
- MyPrintf(STDERR_WO_TIME,
- " outBuf [-1..2]=%02x%02x%02x%02x\n",
- outBuf[-1],outBuf[0],outBuf[1],outBuf[2]);
- } else {
- MyPrintf(STDERR_WO_TIME,
- " inBuf [-2..2]=%02x%02x%02x%02x%02x\n",
- inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]);
- MyPrintf(STDERR_WO_TIME,
- " outBuf [-2..2]=%02x%02x%02x%02x%02x\n",
- outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]);
- }
-#endif
- iconv_close(cd);
- return -1;
- }
- if (len == 0 && inBytesLeft == 0 && outBytesLeft == 1) { /* converted to SBCS */
- (dmap_rec[idx].dmapU2D)[2*i+1]=0x00;
- break;
- }
- }
- } while (inBytesLeft > 0);
- }
- iconv_close(cd);
- myconv_rec[idx].subS = dmap_rec[idx].dmapU2D[2*0x1A];
- myconv_rec[idx].subD = dmap_rec[idx].dmapU2D[2*0xFFFD] * 0x100
- + dmap_rec[idx].dmapU2D[2*0xFFFD+1];
- myconv_rec[idx].srcSubS = 0x1A;
- myconv_rec[idx].srcSubD = 0xFFFD;
- }
-
-
- } else if (((myconvIsEUC(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_E2U)) ||
- ((myconvIsEUC(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_E28))) {
- int i;
- /* S0: 0x00 - 0x7F */
- if ((dmap_rec[idx].dmapE02U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapE02U, 0x00, 0x100 * 2);
-
- /* S1: 0xA0 - 0xFF, 0xA0 - 0xFF */
- if ((dmap_rec[idx].dmapE12U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x60 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapE12U, 0x00, 0x60 * 0x60 * 2);
-
- /* SS2: 0x8E + 0xA0 - 0xFF, 0xA0 - 0xFF */
- if ((dmap_rec[idx].dmapE22U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x61 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapE22U, 0x00, 0x60 * 0x61 * 2);
-
- /* SS3: 0x8F + 0xA0 - 0xFF, 0xA0 - 0xFF */
- if ((dmap_rec[idx].dmapE32U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x61 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapE32U, 0x00, 0x60 * 0x61 * 2);
-
- myconv_rec[idx].allocatedSize=(0x100 + 0x60 * 0x60 + 0x60 * 0x61* 2) * 2;
-
-
- {
- char dmapSrc[0x60 * 0x60 * 3];
- iconv_t cd;
- int32_t i;
- size_t inBytesLeft;
- size_t outBytesLeft;
- size_t len;
- char * inBuf;
- char * outBuf;
- char SS=0x8E;
-
-#ifdef support_surrogate
- if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) {
-#else
- if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) {
-#endif
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
-
- for (i = 0; i < 0x100; ++i) {
- dmapSrc[0]=i;
- inBuf=dmapSrc;
- inBytesLeft=1;
- outBuf=(char *) (&dmap_rec[idx].dmapE02U[i]);
- outBytesLeft=2;
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
- }
-#endif
- dmap_rec[idx].dmapE02U[i]=0x0000;
- }
- if (dmap_rec[idx].dmapE02U[i] == 0x001A && /* pick the first one */
- myconv_rec[idx].srcSubS == 0x00) {
- myconv_rec[idx].srcSubS=i;
- }
- }
-
-
- inBuf=dmapSrc;
- for (i = 0; i < 0x60; ++i) {
- int j;
- for (j = 0; j < 0x60; ++j) {
- *inBuf=i+0xA0;
- ++inBuf;
- *inBuf=j+0xA0;
- ++inBuf;
- }
- }
- inBuf=dmapSrc;
- inBytesLeft=0x60 * 0x60 * 2;
- outBuf=(char *) dmap_rec[idx].dmapE12U;
- outBytesLeft=0x60 * 0x60 * 2;
- do {
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
- if (errno == EILSEQ) {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft);
- if (inBuf - dmapSrc > 1 && inBuf - dmapSrc <= sizeof(dmapSrc) - 2)
- MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]);
- else
- MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]);
- if (outBuf - (char *) dmap_rec[idx].dmapE12U > 1)
- MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]);
- else
- MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]);
- }
-#endif
- inBuf+=2;
- inBytesLeft-=2;
- outBuf[0]=0x00;
- outBuf[1]=0x00;
- outBuf+=2;
- outBytesLeft-=2;
- } else {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- iconv_close(cd);
- return -1;
- }
- }
- } while (inBytesLeft > 0);
-
- /* SS2: 0x8E + 1 or 2 bytes */
- /* SS3: 0x8E + 1 or 2 bytes */
- while (SS != 0x00) {
- int32_t numSuccess=0;
- for (i = 0; i < 0x60; ++i) {
- inBuf=dmapSrc;
- inBuf[0]=SS;
- inBuf[1]=i+0xA0;
- inBytesLeft=2;
- if (SS == 0x8E)
- outBuf=(char *) &(dmap_rec[idx].dmapE22U[i]);
- else
- outBuf=(char *) &(dmap_rec[idx].dmapE32U[i]);
- outBytesLeft=2;
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
- if (SS == 0x8E)
- dmap_rec[idx].dmapE22U[i]=0x0000;
- else
- dmap_rec[idx].dmapE32U[i]=0x0000;
- } else {
- ++numSuccess;
- }
- }
- if (numSuccess == 0) { /* SS2 is 2 bytes */
- inBuf=dmapSrc;
- for (i = 0; i < 0x60; ++i) {
- int j;
- for (j = 0; j < 0x60; ++j) {
- *inBuf=SS;
- ++inBuf;
- *inBuf=i+0xA0;
- ++inBuf;
- *inBuf=j+0xA0;
- ++inBuf;
- }
- }
- inBuf=dmapSrc;
- inBytesLeft=0x60 * 0x60 * 3;
- if (SS == 0x8E)
- outBuf=(char *) &(dmap_rec[idx].dmapE22U[0x60]);
- else
- outBuf=(char *) &(dmap_rec[idx].dmapE32U[0x60]);
- outBytesLeft=0x60 * 0x60 * 2;
- do {
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "%02X:dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- SS, to, from, idx, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft);
- if (inBuf - dmapSrc > 1 && inBuf - dmapSrc <= sizeof(dmapSrc) - 2)
- MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]);
- else
- MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]);
- }
-#endif
- if (errno == EILSEQ || errno == EINVAL) {
- inBuf+=3;
- inBytesLeft-=3;
- outBuf[0]=0x00;
- outBuf[1]=0x00;
- outBuf+=2;
- outBytesLeft-=2;
- } else {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "%02X:dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- SS, to, from, idx, errno, __FILE__,__LINE__);
-#endif
- iconv_close(cd);
- return -1;
- }
- }
- } while (inBytesLeft > 0);
- }
- if (SS == 0x8E)
- SS=0x8F;
- else
- SS = 0x00;
- }
- iconv_close(cd);
-
- myconv_rec[idx].subS=0x1A;
- myconv_rec[idx].subD=0xFFFD;
- for (i = 0; i < 0x80; ++i) {
- if (dmap_rec[idx].dmapE02U[i] == 0x001A) {
- myconv_rec[idx].srcSubS=i; /* pick the first one */
- break;
- }
- }
-
- for (i = 0; i < 0x60 * 0x60; ++i) {
- if (dmap_rec[idx].dmapE12U[i] == 0xFFFD) {
- uchar byte1=i / 0x60;
- uchar byte2=i % 0x60;
- myconv_rec[idx].srcSubD=(byte1 + 0xA0) * 0x100 + (byte2 + 0xA0); /* pick the last one */
- }
- }
-
- }
-
- } else if (((myconvIsUCS2(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_U2E)) ||
- ((myconvIsUTF16(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_T2E)) ||
- ((myconvIsUTF8(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_82E))) {
- /* S0: 0x00 - 0xFF */
- if ((dmap_rec[idx].dmapU2S = (uchar *) alloc_root(&dmapMemRoot, 0x100)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapU2S, 0x00, 0x100);
-
- /* U0080 - UFFFF -> S1: 0xA0 - 0xFF, 0xA0 - 0xFF */
- if ((dmap_rec[idx].dmapU2M2 = (uchar *) alloc_root(&dmapMemRoot, 0xFF80 * 2)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapU2M2, 0x00, 0xFF80 * 2);
-
- /* U0080 - UFFFF -> SS2: 0x8E + 0xA0 - 0xFF, 0xA0 - 0xFF
- * SS3: 0x8F + 0xA0 - 0xFF, 0xA0 - 0xFF */
- if ((dmap_rec[idx].dmapU2M3 = (uchar *) alloc_root(&dmapMemRoot, 0xFF80 * 3)) == NULL) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n",
- to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
- memset(dmap_rec[idx].dmapU2M3, 0x00, 0xFF80 * 3);
- myconv_rec[idx].allocatedSize=(0x100 + 0xFF80 * 2 + 0xFF80 * 3);
-
- {
- UniChar dmapSrc[0x80];
- iconv_t cd;
- int32_t i;
- size_t inBytesLeft;
- size_t outBytesLeft;
- size_t len;
- char * inBuf;
- char * outBuf;
-
-#ifdef support_surrogate
- if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) {
-#else
- if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) {
-#endif
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- return -1;
- }
-
- for (i = 0; i < 0x80; ++i)
- dmapSrc[i]=i;
- inBuf=(char *) dmapSrc;
- inBytesLeft=0x80 * 2;
- outBuf=(char *) dmap_rec[idx].dmapU2S;
- outBytesLeft=0x80;
- do {
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
-#ifdef DEBUG
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
-#endif
- iconv_close(cd);
- return -1;
- }
- } while (inBytesLeft > 0);
-
- myconv_rec[idx].srcSubS = 0x1A;
- myconv_rec[idx].srcSubD = 0xFFFD;
- myconv_rec[idx].subS = dmap_rec[idx].dmapU2S[0x1A];
-
- outBuf=(char *) &(myconv_rec[idx].subD);
- dmapSrc[0]=0xFFFD;
- inBuf=(char *) dmapSrc;
- inBytesLeft=2;
- outBytesLeft=2;
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n",
- to, from, idx, len, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WO_TIME, "iconv(0x1A,1,%p,1) returns outBuf=%p, outBytesLeft=%d\n",
- dmapSrc, outBuf, outBytesLeft);
- }
-#endif
- if (outBytesLeft == 0) {
- /* UCS-2_IBM-eucKR returns error.
- myconv(iconv) rc=1, error=0, InBytesLeft=0, OutBytesLeft=18
- myconv(iconvRev) rc=-1, error=116, InBytesLeft=2, OutBytesLeft=20
- iconv: 0xFFFD => 0xAFFE => 0x rc=1,-1 sub=0,0
- */
- ;
- } else {
- iconv_close(cd);
- return -1;
- }
- }
-
- for (i = 0x80; i < 0xFFFF; ++i) {
- uchar eucBuf[3];
- dmapSrc[0]=i;
- inBuf=(char *) dmapSrc;
- inBytesLeft=2;
- outBuf=(char *) eucBuf;
- outBytesLeft=sizeof(eucBuf);
- errno=0;
- if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) {
- if (len == 1 && errno == 0 && inBytesLeft == 0 && outBytesLeft == 1) { /* substitution occurred. */ continue;
- }
-
- if (errno == EILSEQ) {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n",
- to, from, idx, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft);
- if (inBuf - (char *) dmapSrc > 1 && inBuf - (char *) dmapSrc <= sizeof(dmapSrc) - 2)
- MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]);
- else
- MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]);
- if (outBuf - (char *) dmap_rec[idx].dmapU2M2 > 1)
- MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]);
- else
- MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]);
- }
-#endif
- inBuf+=2;
- inBytesLeft-=2;
- memcpy(outBuf, (char *) &(myconv_rec[idx].subD), 2);
- outBuf+=2;
- outBytesLeft-=2;
- } else {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc = %d, errno = %d in %s at %d\n",
- to, from, idx, len, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WITH_TIME,
- "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf[-2..0]=%02X%02X%02X, outBytesLeft=%d\n",
- i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1],
- inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft);
- MyPrintf(STDERR_WITH_TIME,
- "&dmapSrc=%p, inBuf=%p, dmapU2M2 + %d = %p, outBuf=%p\n",
- dmapSrc, inBuf, (i - 0x80) * 2, dmap_rec[idx].dmapU2M2 + (i - 0x80) * 2, outBuf);
- }
-#endif
- iconv_close(cd);
- return -1;
- }
- }
- if (sizeof(eucBuf) - outBytesLeft == 1) {
- if (i < 0x100) {
- (dmap_rec[idx].dmapU2S)[i]=eucBuf[0];
- } else {
- dmap_rec[idx].dmapU2M2[(i - 0x80) * 2] = eucBuf[0];
- dmap_rec[idx].dmapU2M2[(i - 0x80) * 2 + 1] = 0x00;
- }
- } else if (sizeof(eucBuf) - outBytesLeft == 2) { /* 2 bytes */
- dmap_rec[idx].dmapU2M2[(i - 0x80) * 2] = eucBuf[0];
- dmap_rec[idx].dmapU2M2[(i - 0x80) * 2 + 1] = eucBuf[1];
- } else if (sizeof(eucBuf) - outBytesLeft == 3) { /* 3 byte SS2/SS3 */
- dmap_rec[idx].dmapU2M3[(i - 0x80) * 3] = eucBuf[0];
- dmap_rec[idx].dmapU2M3[(i - 0x80) * 3 + 1] = eucBuf[1];
- dmap_rec[idx].dmapU2M3[(i - 0x80) * 3 + 2] = eucBuf[2];
- } else {
-#ifdef DEBUG
- if (myconvDebug) {
- MyPrintf(STDERR_WITH_TIME,
- "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n",
- to, from, idx, len, errno, __FILE__,__LINE__);
- MyPrintf(STDERR_WITH_TIME,
- "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf=%02X%02X%02X, outBytesLeft=%d\n",
- i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1],
- inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft);
- MyPrintf(STDERR_WITH_TIME,
- "&dmapSrc=%p, inBuf=%p, %p, outBuf=%p\n",
- dmapSrc, inBuf, dmap_rec[idx].dmapU2M3 + (i - 0x80) * 2, outBuf);
- }
-#endif
- return -1;
- }
-
- }
- iconv_close(cd);
- }
-
- } else if (myconvIsUTF16(from) && myconvIsUTF8(to)) {
- dmap_rec[idx].codingSchema = DMAP_T28;
-
- } else if (myconvIsUCS2(from) && myconvIsUTF8(to)) {
- dmap_rec[idx].codingSchema = DMAP_U28;
-
- } else if (myconvIsUTF8(from) && myconvIsUnicode2(to)) {
- dmap_rec[idx].codingSchema = DMAP_82U;
-
- } else if (myconvIsUnicode2(from) && myconvIsUnicode2(to)) {
- dmap_rec[idx].codingSchema = DMAP_U2U;
-
- } else {
-
- return -1;
- }
- myconv_rec[idx].cnv_dmap=&(dmap_rec[idx]);
- return 0;
-}
-
-
-
-static int bins_open(const char * to,
- const char * from,
- const int32_t idx)
-{
- return -1;
-}
-
-
-
-static int32_t dmap_close(const int32_t idx)
-{
- if (dmap_rec[idx].codingSchema == DMAP_S2S) {
- if (dmap_rec[idx].dmapS2S != NULL) {
- dmap_rec[idx].dmapS2S=NULL;
- }
- } else if (dmap_rec[idx].codingSchema = DMAP_E2U) {
- if (dmap_rec[idx].dmapE02U != NULL) {
- dmap_rec[idx].dmapE02U=NULL;
- }
- if (dmap_rec[idx].dmapE12U != NULL) {
- dmap_rec[idx].dmapE12U=NULL;
- }
- if (dmap_rec[idx].dmapE22U != NULL) {
- dmap_rec[idx].dmapE22U=NULL;
- }
- if (dmap_rec[idx].dmapE32U != NULL) {
- dmap_rec[idx].dmapE32U=NULL;
- }
- }
-
- return 0;
-}
-
-
-static int32_t bins_close(const int32_t idx)
-{
- return 0;
-}
-
-
-myconv_t myconv_open(const char * toCode,
- const char * fromCode,
- int32_t converter)
-{
- int32 i;
- for (i = 0; i < MAX_CONVERTER; ++i) {
- if (myconv_rec[i].converterType == 0)
- break;
- }
- if (i >= MAX_CONVERTER)
- return ((myconv_t) -1);
-
- myconv_rec[i].converterType = converter;
- myconv_rec[i].index=i;
- myconv_rec[i].fromCcsid=cstoccsid(fromCode);
- if (myconv_rec[i].fromCcsid == 0 && memcmp(fromCode, "big5",5) == 0)
- myconv_rec[i].fromCcsid=950;
- myconv_rec[i].toCcsid=cstoccsid(toCode);
- if (myconv_rec[i].toCcsid == 0 && memcmp(toCode, "big5",5) == 0)
- myconv_rec[i].toCcsid=950;
- strncpy(myconv_rec[i].from, fromCode, sizeof(myconv_rec[i].from)-1);
- strncpy(myconv_rec[i].to, toCode, sizeof(myconv_rec[i].to)-1);
-
- if (converter == CONVERTER_ICONV) {
- if ((myconv_rec[i].cnv_iconv=iconv_open(toCode, fromCode)) == (iconv_t) -1) {
- return ((myconv_t) -1);
- }
- myconv_rec[i].allocatedSize = -1;
- myconv_rec[i].srcSubS=myconvGetSubS(fromCode);
- myconv_rec[i].srcSubD=myconvGetSubD(fromCode);
- myconv_rec[i].subS=myconvGetSubS(toCode);
- myconv_rec[i].subD=myconvGetSubD(toCode);
- return &(myconv_rec[i]);
- } else if (converter == CONVERTER_DMAP &&
- dmap_open(toCode, fromCode, i) != -1) {
- return &(myconv_rec[i]);
- }
- return ((myconv_t) -1);
-}
-
-
-
-int32_t myconv_close(myconv_t cd)
-{
- int32_t ret=0;
-
- if (cd->converterType == CONVERTER_ICONV) {
- ret=iconv_close(cd->cnv_iconv);
- } else if (cd->converterType == CONVERTER_DMAP) {
- ret=dmap_close(cd->index);
- }
- memset(&(myconv_rec[cd->index]), 0x00, sizeof(myconv_rec[cd->index]));
- return ret;
-}
-
-
-
-
-/* reference: http://www-306.ibm.com/software/globalization/other/es.jsp */
-/* systemCL would be expensive, and myconvIsXXXXX is called frequently.
- need to cache entries */
-#define MAX_CCSID 256
-static int ccsidList [MAX_CCSID];
-static int esList [MAX_CCSID];
-int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme);
-EXTERN int myconvGetES(CCSID ccsid)
-{
- /* call QtqValidateCCSID in ILE to get encoding schema */
- /* return QtqValidateCCSID(ccsid); */
- int i;
- for (i = 0; i < MAX_CCSID; ++i) {
- if (ccsidList[i] == ccsid)
- return esList[i];
- if (ccsidList[i] == 0x00)
- break;
- }
-
- if (i >= MAX_CCSID) {
- i=MAX_CCSID-1;
- }
-
- {
- ccsidList[i]=ccsid;
- getEncodingScheme(ccsid, esList[i]);
-#ifdef DEBUG_PASE
- if (myconvDebug) {
- fprintf(stderr, "CCSID=%d, ES=0x%04X\n", ccsid, esList[i]);
- }
-#endif
- return esList[i];
- }
- return 0;
-}
-
-
-EXTERN int myconvIsEBCDIC(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x1100 ||
- es == 0x1200 ||
- es == 0x6100 ||
- es == 0x6200 ||
- es == 0x1301 ) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsISO(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x4100 ||
- es == 0x4105 ||
- es == 0x4155 ||
- es == 0x5100 ||
- es == 0x5150 ||
- es == 0x5200 ||
- es == 0x5404 ||
- es == 0x5409 ||
- es == 0x540A ||
- es == 0x5700) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsASCII(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x2100 ||
- es == 0x3100 ||
- es == 0x8100 ||
- es == 0x2200 ||
- es == 0x3200 ||
- es == 0x9200 ||
- es == 0x2300 ||
- es == 0x2305 ||
- es == 0x3300 ||
- es == 0x2900 ||
- es == 0x2A00) {
- return TRUE;
- } else if (memcmp(pName, "big5", 5) == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-
-EXTERN int myconvIsUCS2(const char * pName)
-{
- if (cstoccsid(pName) == 13488) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsUTF16(const char * pName)
-{
- if (cstoccsid(pName) == 1200) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsUnicode2(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x7200 ||
- es == 0x720B ||
- es == 0x720F) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsUTF8(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x7807) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsUnicode(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x7200 ||
- es == 0x720B ||
- es == 0x720F ||
- es == 0x7807) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsEUC(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x4403) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsDBCS(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x1200 ||
- es == 0x2200 ||
- es == 0x2300 ||
- es == 0x2305 ||
- es == 0x2A00 ||
- es == 0x3200 ||
- es == 0x3300 ||
- es == 0x5200 ||
- es == 0x6200 ||
- es == 0x9200) {
- return TRUE;
- } else if (memcmp(pName, "big5", 5) == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-EXTERN int myconvIsSBCS(const char * pName)
-{
- int es = myconvGetES(cstoccsid(pName));
- if (es == 0x1100 ||
- es == 0x2100 ||
- es == 0x3100 ||
- es == 0x4100 ||
- es == 0x4105 ||
- es == 0x5100 ||
- es == 0x5150 ||
- es == 0x6100 ||
- es == 0x8100) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-
-EXTERN char myconvGetSubS(const char * code)
-{
- if (myconvIsEBCDIC(code)) {
- return 0x3F;
- } else if (myconvIsASCII(code)) {
- return 0x1A;
- } else if (myconvIsISO(code)) {
- return 0x1A;
- } else if (myconvIsEUC(code)) {
- return 0x1A;
- } else if (myconvIsUCS2(code)) {
- return 0x00;
- } else if (myconvIsUTF8(code)) {
- return 0x1A;
- }
- return 0x00;
-}
-
-
-EXTERN UniChar myconvGetSubD(const char * code)
-{
- if (myconvIsEBCDIC(code)) {
- return 0xFDFD;
- } else if (myconvIsASCII(code)) {
- return 0xFCFC;
- } else if (myconvIsISO(code)) {
- return 0x00;
- } else if (myconvIsEUC(code)) {
- return 0x00;
- } else if (myconvIsUCS2(code)) {
- return 0xFFFD;
- } else if (myconvIsUTF8(code)) {
- return 0x00;
- }
- return 0x00;
-}
-
diff --git a/storage/ibmdb2i/db2i_myconv.h b/storage/ibmdb2i/db2i_myconv.h
deleted file mode 100644
index 98032748148..00000000000
--- a/storage/ibmdb2i/db2i_myconv.h
+++ /dev/null
@@ -1,3201 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-/**
- @file
-
- @brief A direct map optimization of iconv and related functions
- This was show to significantly reduce character conversion cost
- for short strings when compared to calling iconv system code.
-*/
-
-#ifndef DB2I_MYCONV_H
-#define DB2I_MYCONV_H
-
-
-#include <sys/time.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <wchar.h>
-#include <errno.h>
-#include <iconv.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdarg.h>
-#include <string.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifdef __cplusplus
-#define INTERN inline
-#define EXTERN extern "C"
-#else
-#define INTERN static
-#define EXTERN extern
-#endif
-
-
-/* ANSI integer data types */
-#if defined(__OS400_TGTVRM__)
-/* for DTAMDL(*P128), datamodel(P128): int/long/pointer=4/4/16 */
-/* LLP64:4/4/8 is used for teraspace ?? */
-typedef short int16_t;
-typedef unsigned short uint16_t;
-typedef int int32_t;
-typedef unsigned int uint32_t;
-typedef long long int64_t;
-typedef unsigned long long uint64_t;
-#elif defined(PASE)
-/* PASE uses IPL32: int/long/pointer=4/4/4 + long long */
-#elif defined(__64BIT__)
-/* AIX 64 bit uses LP64: int/long/pointer=4/8/8 */
-#endif
-
-#define CONVERTER_ICONV 1
-#define CONVERTER_DMAP 2
-
-#define DMAP_S2S 10
-#define DMAP_S2U 20
-#define DMAP_D2U 30
-#define DMAP_E2U 40
-#define DMAP_U2S 120
-#define DMAP_T2S 125
-#define DMAP_U2D 130
-#define DMAP_T2D 135
-#define DMAP_U2E 140
-#define DMAP_T2E 145
-#define DMAP_S28 220
-#define DMAP_D28 230
-#define DMAP_E28 240
-#define DMAP_82S 310
-#define DMAP_82D 320
-#define DMAP_82E 330
-#define DMAP_U28 410
-#define DMAP_82U 420
-#define DMAP_T28 425
-#define DMAP_U2U 510
-
-
-typedef struct __dmap_rec *dmap_t;
-
-struct __dmap_rec
-{
- uint32_t codingSchema;
- unsigned char * dmapS2S; /* SBCS -> SBCS */
- /* The following conversion needs be followed by conversion from UCS-2/UTF-16 to UTF-8 */
- UniChar * dmapD12U; /* DBCS(non-EUC) -> UCS-2/UTF-16 */
- UniChar * dmapD22U; /* DBCS(non-EUC) -> UCS-2/UTF-16 */
- UniChar * dmapE02U; /* EUC/SS0 -> UCS-2/UTF-16 */
- UniChar * dmapE12U; /* EUC/SS1 -> UCS-2/UTF-16 */
- UniChar * dmapE22U; /* EUC/0x8E + SS2 -> UCS-2/UTF-16 */
- UniChar * dmapE32U; /* EUC/0x8F + SS3 -> UCS-2/UTF-16 */
- uchar * dmapU2D; /* UCS-2 -> DBCS */
- uchar * dmapU2S; /* UCS-2 -> EUC SS0 */
- uchar * dmapU2M2; /* UCS-2 -> EUC SS1 */
- uchar * dmapU2M3; /* UCS-2 -> EUC SS2/SS3 */
- /* All of these pointers/tables are not used at the same time.
- * You may be able save some space if you consolidate them.
- */
- uchar * dmapS28; /* SBCS -> UTF-8 */
- uchar * dmapD28; /* DBCS -> UTF-8 */
-};
-
-typedef struct __myconv_rec *myconv_t;
-struct __myconv_rec
-{
- uint32_t converterType;
- uint32_t index; /* for close */
- union {
- iconv_t cnv_iconv;
- dmap_t cnv_dmap;
- };
- int32_t allocatedSize;
- int32_t fromCcsid;
- int32_t toCcsid;
- UniChar subD; /* DBCS substitution char */
- char subS; /* SBCS substitution char */
- UniChar srcSubD; /* DBCS substitution char of src codepage */
- char srcSubS; /* SBCS substitution char of src codepage */
- char from [41+1]; /* codepage name is up to 41 bytes */
- char to [41+1]; /* codepage name is up to 41 bytes */
-#ifdef __64BIT__
- char reserved[10]; /* align 128 */
-#else
- char reserved[14]; /* align 128 */
-#endif
-};
-
-
-EXTERN int32_t myconvDebug;
-
-
-
-EXTERN int myconvGetES(CCSID);
-EXTERN int myconvIsEBCDIC(const char *);
-EXTERN int myconvIsASCII(const char *);
-EXTERN int myconvIsUnicode(const char *); /* UTF-8, UTF-16, or UCS-2 */
-EXTERN int myconvIsUnicode2(const char *); /* 2 byte Unicode */
-EXTERN int myconvIsUCS2(const char *);
-EXTERN int myconvIsUTF16(const char *);
-EXTERN int myconvIsUTF8(const char *);
-EXTERN int myconvIsEUC(const char *);
-EXTERN int myconvIsISO(const char *);
-EXTERN int myconvIsSBCS(const char *);
-EXTERN int myconvIsDBCS(const char *);
-EXTERN char myconvGetSubS(const char *);
-EXTERN UniChar myconvGetSubD(const char *);
-
-
-EXTERN myconv_t myconv_open(const char*, const char*, int32_t);
-EXTERN int myconv_close(myconv_t);
-
-INTERN size_t myconv_iconv(myconv_t cd ,
- char** inBuf,
- size_t* inBytesLeft,
- char** outBuf,
- size_t* outBytesLeft,
- size_t* numSub)
-{
- return iconv(cd->cnv_iconv, inBuf, inBytesLeft, outBuf, outBytesLeft);
-}
-
-INTERN size_t myconv_dmap(myconv_t cd,
- char** inBuf,
- size_t* inBytesLeft,
- char** outBuf,
- size_t* outBytesLeft,
- size_t* numSub)
-{
- if (cd->cnv_dmap->codingSchema == DMAP_S2S) {
- register unsigned char * dmapS2S=cd->cnv_dmap->dmapS2S;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register size_t numS=0;
- while (0 < inLen) {
- if (pLastOutBuf < pOut)
- break;
- if (*pIn == 0x00) {
- *pOut=0x00;
- } else {
- *pOut=dmapS2S[*pIn];
- if (*pOut == 0x00) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(*inBytesLeft-inLen);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- if (*pOut == subS) {
- if ((*pOut=dmapS2S[*pIn]) == subS) {
- if (*pIn != cd->srcSubS)
- ++numS;
- }
- }
- }
- ++pIn;
- --inLen;
- ++pOut;
- }
- *outBytesLeft-=(*inBytesLeft-inLen);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_E2U) {
- /* use uchar * instead of UniChar to avoid memcpy */
- register uchar * dmapE02U=(uchar *) (cd->cnv_dmap->dmapE02U);
- register uchar * dmapE12U=(uchar *) (cd->cnv_dmap->dmapE12U);
- register uchar * dmapE22U=(uchar *) (cd->cnv_dmap->dmapE22U);
- register uchar * dmapE32U=(uchar *) (cd->cnv_dmap->dmapE32U);
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register int offset;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register size_t numS=0;
- while (0 < inLen) {
- if (pLastOutBuf < pOut)
- break;
- if (*pIn == 0x00) {
- *pOut=0x00;
- ++pOut;
- *pOut=0x00;
- ++pOut;
- ++pIn;
- --inLen;
- } else {
- if (*pIn == 0x8E) { /* SS2 */
- if (inLen < 2) {
- if (cd->fromCcsid == 33722 || /* IBM-eucJP */
- cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- ++pIn;
- if (*pIn < 0xA0) {
- if (cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE22U[offset] == 0x00 &&
- dmapE22U[offset+1] == 0x00) { /* 2 bytes */
- if (inLen < 3) {
- if (cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset=(*pIn - 0xA0) * 0x60 + 0x60;
- ++pIn;
- if (*pIn < 0xA0) {
- if (cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- return -1;
- }
- offset+=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE22U[offset] == 0x00 &&
- dmapE22U[offset+1] == 0x00) {
- if (cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- return -1;
- }
- *pOut=dmapE22U[offset];
- ++pOut;
- *pOut=dmapE22U[offset+1];
- ++pOut;
- if (dmapE22U[offset] == 0xFF &&
- dmapE22U[offset+1] == 0xFD) {
- if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD)
- ++numS;
- }
- ++pIn;
- inLen-=3;
- } else { /* 1 bytes */
- *pOut=dmapE22U[offset];
- ++pOut;
- *pOut=dmapE22U[offset+1];
- ++pOut;
- ++pIn;
- inLen-=2;
- }
- } else if (*pIn == 0x8F) { /* SS3 */
- if (inLen < 2) {
- if (cd->fromCcsid == 33722) /* IBM-eucJP */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- ++pIn;
- if (*pIn < 0xA0) {
- if (cd->fromCcsid == 970 || /* IBM-eucKR */
- cd->fromCcsid == 964 || /* IBM-eucTW */
- cd->fromCcsid == 1383 || /* IBM-eucCN */
- (cd->fromCcsid == 33722 && 3 <= inLen)) /* IBM-eucJP */
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE32U[offset] == 0x00 &&
- dmapE32U[offset+1] == 0x00) { /* 0x8F + 2 bytes */
- if (inLen < 3) {
- if (cd->fromCcsid == 33722)
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset=(*pIn - 0xA0) * 0x60 + 0x60;
- ++pIn;
- if (*pIn < 0xA0) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- return -1;
- }
- offset+=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE32U[offset] == 0x00 &&
- dmapE32U[offset+1] == 0x00) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- return -1;
- }
- *pOut=dmapE32U[offset];
- ++pOut;
- *pOut=dmapE32U[offset+1];
- ++pOut;
- if (dmapE32U[offset] == 0xFF &&
- dmapE32U[offset+1] == 0xFD) {
- if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD)
- ++numS;
- }
- ++pIn;
- inLen-=3;
- } else { /* 0x8F + 1 bytes */
- *pOut=dmapE32U[offset];
- ++pOut;
- *pOut=dmapE32U[offset+1];
- ++pOut;
- ++pIn;
- inLen-=2;
- }
-
- } else {
- offset=*pIn;
- offset<<=1;
- if (dmapE02U[offset] == 0x00 &&
- dmapE02U[offset+1] == 0x00) { /* SS1 */
- if (inLen < 2) {
- if ((cd->fromCcsid == 33722 && (*pIn == 0xA0 || (0xA9 <= *pIn && *pIn <= 0xAF) || *pIn == 0xFF)) ||
- (cd->fromCcsid == 970 && (*pIn == 0xA0 || *pIn == 0xAD || *pIn == 0xAE || *pIn == 0xAF || *pIn == 0xFF)) ||
- (cd->fromCcsid == 964 && (*pIn == 0xA0 || (0xAA <= *pIn && *pIn <= 0xC1) || *pIn == 0xC3 || *pIn == 0xFE || *pIn == 0xFF)) ||
- (cd->fromCcsid == 1383 && (*pIn == 0xA0 || *pIn == 0xFF)))
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- if (*pIn < 0xA0) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- offset=(*pIn - 0xA0) * 0x60;
- ++pIn;
- if (*pIn < 0xA0) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset+=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE12U[offset] == 0x00 &&
- dmapE12U[offset+1] == 0x00) { /* undefined mapping */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- *pOut=dmapE12U[offset];
- ++pOut;
- *pOut=dmapE12U[offset+1];
- ++pOut;
- if (dmapE12U[offset] == 0xFF &&
- dmapE12U[offset+1] == 0xFD) {
- if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD)
- ++numS;
- }
- ++pIn;
- inLen-=2;
- } else {
- *pOut=dmapE02U[offset];
- ++pOut;
- *pOut=dmapE02U[offset+1];
- ++pOut;
- if (dmapE02U[offset] == 0x00 &&
- dmapE02U[offset+1] == 0x1A) {
- if (*pIn != cd->srcSubS)
- ++numS;
- }
- ++pIn;
- --inLen;
- }
- }
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_E28) {
- /* use uchar * instead of UniChar to avoid memcpy */
- register uchar * dmapE02U=(uchar *) (cd->cnv_dmap->dmapE02U);
- register uchar * dmapE12U=(uchar *) (cd->cnv_dmap->dmapE12U);
- register uchar * dmapE22U=(uchar *) (cd->cnv_dmap->dmapE22U);
- register uchar * dmapE32U=(uchar *) (cd->cnv_dmap->dmapE32U);
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register int offset;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register size_t numS=0;
- register UniChar in; /* copy part of U28 */
- register UniChar ucs2;
- while (0 < inLen) {
- if (pLastOutBuf < pOut)
- break;
- if (*pIn == 0x00) {
- *pOut=0x00;
- ++pOut;
- ++pIn;
- --inLen;
- } else {
- if (*pIn == 0x8E) { /* SS2 */
- if (inLen < 2) {
- if (cd->fromCcsid == 33722 || /* IBM-eucJP */
- cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- ++pIn;
- if (*pIn < 0xA0) {
- if (cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE22U[offset] == 0x00 &&
- dmapE22U[offset+1] == 0x00) { /* 2 bytes */
- if (inLen < 3) {
- if (cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset=(*pIn - 0xA0) * 0x60 + 0x60;
- ++pIn;
- if (*pIn < 0xA0) {
- if (cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- return -1;
- }
- offset+=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE22U[offset] == 0x00 &&
- dmapE22U[offset+1] == 0x00) {
- if (cd->fromCcsid == 964) /* IBM-eucTW */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- return -1;
- }
- in=dmapE22U[offset];
- in<<=8;
- in+=dmapE22U[offset+1];
- if (dmapE22U[offset] == 0xFF &&
- dmapE22U[offset+1] == 0xFD) {
- if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD)
- ++numS;
- }
- ++pIn;
- inLen-=3;
- } else { /* 1 bytes */
- in=dmapE22U[offset];
- in<<=8;
- in+=dmapE22U[offset+1];
- ++pIn;
- inLen-=2;
- }
- } else if (*pIn == 0x8F) { /* SS3 */
- if (inLen < 2) {
- if (cd->fromCcsid == 33722) /* IBM-eucJP */
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- ++pIn;
- if (*pIn < 0xA0) {
- if (cd->fromCcsid == 970 || /* IBM-eucKR */
- cd->fromCcsid == 964 || /* IBM-eucTW */
- cd->fromCcsid == 1383 || /* IBM-eucCN */
- (cd->fromCcsid == 33722 && 3 <= inLen)) /* IBM-eucJP */
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE32U[offset] == 0x00 &&
- dmapE32U[offset+1] == 0x00) { /* 0x8F + 2 bytes */
- if (inLen < 3) {
- if (cd->fromCcsid == 33722)
- errno=EINVAL; /* 22 */
- else
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset=(*pIn - 0xA0) * 0x60 + 0x60;
- ++pIn;
- if (*pIn < 0xA0) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- return -1;
- }
- offset+=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE32U[offset] == 0x00 &&
- dmapE32U[offset+1] == 0x00) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- return -1;
- }
- in=dmapE32U[offset];
- in<<=8;
- in+=dmapE32U[offset+1];
- if (dmapE32U[offset] == 0xFF &&
- dmapE32U[offset+1] == 0xFD) {
- if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD)
- ++numS;
- }
- ++pIn;
- inLen-=3;
- } else { /* 0x8F + 1 bytes */
- in=dmapE32U[offset];
- in<<=8;
- in+=dmapE32U[offset+1];
- ++pIn;
- inLen-=2;
- }
-
- } else {
- offset=*pIn;
- offset<<=1;
- if (dmapE02U[offset] == 0x00 &&
- dmapE02U[offset+1] == 0x00) { /* SS1 */
- if (inLen < 2) {
- if ((cd->fromCcsid == 33722 && (*pIn == 0xA0 || (0xA9 <= *pIn && *pIn <= 0xAF) || *pIn == 0xFF)) ||
- (cd->fromCcsid == 970 && (*pIn == 0xA0 || *pIn == 0xAD || *pIn == 0xAE || *pIn == 0xAF || *pIn == 0xFF)) ||
- (cd->fromCcsid == 964 && (*pIn == 0xA0 || (0xAA <= *pIn && *pIn <= 0xC1) || *pIn == 0xC3 || *pIn == 0xFE || *pIn == 0xFF)) ||
- (cd->fromCcsid == 1383 && (*pIn == 0xA0 || *pIn == 0xFF)))
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- if (*pIn < 0xA0) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- offset=(*pIn - 0xA0) * 0x60;
- ++pIn;
- if (*pIn < 0xA0) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- offset+=(*pIn - 0xA0);
- offset<<=1;
- if (dmapE12U[offset] == 0x00 &&
- dmapE12U[offset+1] == 0x00) { /* undefined mapping */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- in=dmapE12U[offset];
- in<<=8;
- in+=dmapE12U[offset+1];
- if (dmapE12U[offset] == 0xFF &&
- dmapE12U[offset+1] == 0xFD) {
- if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD)
- ++numS;
- }
- ++pIn;
- inLen-=2;
- } else {
- in=dmapE02U[offset];
- in<<=8;
- in+=dmapE02U[offset+1];
- if (dmapE02U[offset] == 0x00 &&
- dmapE02U[offset+1] == 0x1A) {
- if (*pIn != cd->srcSubS)
- ++numS;
- }
- ++pIn;
- --inLen;
- }
- }
- ucs2=in;
- if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */
- *pOut=in;
- ++pOut;
- } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */
- register uchar byte;
- in>>=6;
- in&=0x001F; /* 0b0000000000011111 */
- in|=0x00C0; /* 0b0000000011000000 */
- *pOut=in;
- ++pOut;
- byte=ucs2; /* dmapD12U[offset+1]; */
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- } else if ((in & 0xFC00) == 0xD800) {
- *pOut=0xEF;
- ++pOut;
- *pOut=0xBF;
- ++pOut;
- *pOut=0xBD;
- ++pOut;
- } else {
- register uchar byte;
- register uchar work;
- byte=(ucs2>>8); /* dmapD12U[offset]; */
- byte>>=4;
- byte|=0xE0; /* 0b11100000; */
- *pOut=byte;
- ++pOut;
-
- byte=(ucs2>>8); /* dmapD12U[offset]; */
- byte<<=2;
- work=ucs2; /* dmapD12U[offset+1]; */
- work>>=6;
- byte|=work;
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
-
- byte=ucs2; /* dmapD12U[offset+1]; */
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- }
- /* end of U28 */
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_U2E) {
- register uchar * dmapU2S=cd->cnv_dmap->dmapU2S;
- register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2;
- register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register char * pSubD=(char *) &(cd->subD);
- register size_t numS=0;
- register size_t rc=0;
- while (0 < inLen) {
- register uint32_t in;
- if (inLen == 1) {
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- if (pLastOutBuf < pOut)
- break;
- in=pIn[0];
- in<<=8;
- in+=pIn[1];
- if (in == 0x0000) {
- *pOut=0x00;
- ++pOut;
- } else if (in < 0x100 && dmapU2S[in] != 0x0000) {
- if ((*pOut=dmapU2S[in]) == subS) {
- if (in != cd->srcSubS)
- ++numS;
- }
- ++pOut;
- } else {
- in<<=1;
- if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */
- in*=1.5;
- if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/
- *pOut=pSubD[0];
- ++pOut;
- *pOut=pSubD[1];
- ++pOut;
- ++numS;
- ++rc;
- } else {
- *pOut=dmapU2M3[in];
- ++pOut;
- *pOut=dmapU2M3[1+in];
- ++pOut;
- *pOut=dmapU2M3[2+in];
- ++pOut;
- }
- } else {
- *pOut=dmapU2M2[in];
- ++pOut;
- if (dmapU2M2[1+in] == 0x00) {
- if (*pOut == subS) {
- in>>=1;
- if (in != cd->srcSubS)
- ++numS;
- }
- } else {
- *pOut=dmapU2M2[1+in];
- ++pOut;
- if (memcmp(pOut-2, pSubD, 2) == 0) {
- in>>=1;
- if (in != cd->srcSubD) {
- ++numS;
- ++rc;
- }
- }
- }
- }
- }
- pIn+=2;
- inLen-=2;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return rc; /* compatibility to iconv() */
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_T2E) {
- register uchar * dmapU2S=cd->cnv_dmap->dmapU2S;
- register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2;
- register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register char * pSubD=(char *) &(cd->subD);
- register size_t numS=0;
- register size_t rc=0;
- while (0 < inLen) {
- register uint32_t in;
- if (inLen == 1) {
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen-1;
- *outBuf=pOut;
- *inBuf=pIn;
- ++numS;
- *numSub+=numS;
- return 0;
- }
- if (pLastOutBuf < pOut)
- break;
- in=pIn[0];
- in<<=8;
- in+=pIn[1];
- if (in == 0x0000) {
- *pOut=0x00;
- ++pOut;
- } else if (0xD800 <= in && in <= 0xDBFF) { /* first byte of surrogate */
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-2;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn+2;
- ++numS;
- *numSub+=numS;
- return -1;
-
- } else if (0xDC00 <= in && in <= 0xDFFF) { /* second byte of surrogate */
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-1;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- ++numS;
- *numSub+=numS;
- return -1;
-
- } else if (in < 0x100 && dmapU2S[in] != 0x0000) {
- if ((*pOut=dmapU2S[in]) == subS) {
- if (in != cd->srcSubS)
- ++numS;
- }
- ++pOut;
- } else {
- in<<=1;
- if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */
- in*=1.5;
- if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/
- *pOut=pSubD[0];
- ++pOut;
- *pOut=pSubD[1];
- ++pOut;
- ++numS;
- ++rc;
- } else {
- *pOut=dmapU2M3[in];
- ++pOut;
- *pOut=dmapU2M3[1+in];
- ++pOut;
- *pOut=dmapU2M3[2+in];
- ++pOut;
- }
- } else {
- *pOut=dmapU2M2[in];
- ++pOut;
- if (dmapU2M2[1+in] == 0x00) {
- if (*pOut == subS) {
- in>>=1;
- if (in != cd->srcSubS)
- ++numS;
- }
- } else {
- *pOut=dmapU2M2[1+in];
- ++pOut;
- if (memcmp(pOut-2, pSubD, 2) == 0) {
- in>>=1;
- if (in != cd->srcSubD) {
- ++numS;
- ++rc;
- }
- }
- }
- }
- }
- pIn+=2;
- inLen-=2;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_82E) {
- register uchar * dmapU2S=cd->cnv_dmap->dmapU2S;
- register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2;
- register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register char * pSubD=(char *) &(cd->subD);
- register size_t numS=0;
- register size_t rc=0;
- while (0 < inLen) {
- register uint32_t in;
- uint32_t in2;
- if (pLastOutBuf < pOut)
- break;
- /* convert from UTF-8 to UCS-2 */
- if (*pIn == 0x00) {
- in=0x0000;
- ++pIn;
- --inLen;
- } else { /* 82U: */
- register uchar byte1=*pIn;
- if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */
- /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/
- in=byte1;
- ++pIn;
- --inLen;
- } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */
- if (inLen < 2) {
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- /* 2 bytes sequence:
- 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */
- register uchar byte2;
- ++pIn;
- byte2=*pIn;
- if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */
- register uchar work=byte1;
- work<<=6;
- byte2&=0x3F; /* 0b00111111; */
- byte2|=work;
-
- byte1&=0x1F; /* 0b00011111; */
- byte1>>=2;
- in=byte1;
- in<<=8;
- in+=byte2;
- inLen-=2;
- ++pIn;
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- *numSub+=numS;
- return -1;
- }
- } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */
- /* 3 bytes sequence:
- 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */
- register uchar byte2;
- register uchar byte3;
- if (inLen < 3) {
- if (inLen == 2 && (pIn[1] & 0xC0) != 0x80)
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- ++pIn;
- byte2=*pIn;
- ++pIn;
- byte3=*pIn;
- if ((byte2 & 0xC0) != 0x80 ||
- (byte3 & 0xC0) != 0x80 ||
- (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- *numSub+=numS;
- return -1;
- }
- {
- register uchar work=byte2;
- work<<=6;
- byte3&=0x3F; /* 0b00111111; */
- byte3|=work;
-
- byte2&=0x3F; /* 0b00111111; */
- byte2>>=2;
-
- byte1<<=4;
- in=byte1 | byte2;;
- in<<=8;
- in+=byte3;
- inLen-=3;
- ++pIn;
- }
- } else if ((0xF0 <= byte1 && byte1 <= 0xF4)) { /* (bytes1 & 11111000) == 0x1110000 */
- /* 4 bytes sequence
- 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx
- where uuuuu = wwww + 1 */
- register uchar byte2;
- register uchar byte3;
- register uchar byte4;
- if (inLen < 4) {
- if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) ||
- (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) ||
- (cd->toCcsid == 13488) )
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- ++pIn;
- byte2=*pIn;
- ++pIn;
- byte3=*pIn;
- ++pIn;
- byte4=*pIn;
- if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */
- (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */
- (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */
- register uchar work=byte2;
- if (byte1 == 0xF0 && byte2 < 0x90) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- /* iconv() returns 0 for 0xF4908080 and convert to 0x00
- } else if (byte1 == 0xF4 && byte2 > 0x8F) {
- errno=EINVAL;
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- */
- }
-
- work&=0x30; /* 0b00110000; */
- work>>=4;
- byte1&=0x07; /* 0b00000111; */
- byte1<<=2;
- byte1+=work; /* uuuuu */
- --byte1; /* wwww */
-
- work=byte1 & 0x0F;
- work>>=2;
- work+=0xD8; /* 0b11011011; */
- in=work;
- in<<=8;
-
- byte1<<=6;
- byte2<<=2;
- byte2&=0x3C; /* 0b00111100; */
- work=byte3;
- work>>=4;
- work&=0x03; /* 0b00000011; */
- work|=byte1;
- work|=byte2;
- in+=work;
-
- work=byte3;
- work>>=2;
- work&=0x03; /* 0b00000011; */
- work|=0xDC; /* 0b110111xx; */
- in2=work;
- in2<<=8;
-
- byte3<<=6;
- byte4&=0x3F; /* 0b00111111; */
- byte4|=byte3;
- in2+=byte4;
- inLen-=4;
- ++pIn;
-#ifdef match_with_GBK
- if ((0xD800 == in && in2 < 0xDC80) ||
- (0xD840 == in && in2 < 0xDC80) ||
- (0xD880 == in && in2 < 0xDC80) ||
- (0xD8C0 == in && in2 < 0xDC80) ||
- (0xD900 == in && in2 < 0xDC80) ||
- (0xD940 == in && in2 < 0xDC80) ||
- (0xD980 == in && in2 < 0xDC80) ||
- (0xD9C0 == in && in2 < 0xDC80) ||
- (0xDA00 == in && in2 < 0xDC80) ||
- (0xDA40 == in && in2 < 0xDC80) ||
- (0xDA80 == in && in2 < 0xDC80) ||
- (0xDAC0 == in && in2 < 0xDC80) ||
- (0xDB00 == in && in2 < 0xDC80) ||
- (0xDB40 == in && in2 < 0xDC80) ||
- (0xDB80 == in && in2 < 0xDC80) ||
- (0xDBC0 == in && in2 < 0xDC80)) {
-#else
- if ((0xD800 <= in && in <= 0xDBFF) &&
- (0xDC00 <= in2 && in2 <= 0xDFFF)) {
-#endif
- *pOut=subS;
- ++pOut;
- ++numS;
- continue;
- }
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- }
- } else if (0xF5 <= byte1 && byte1 <= 0xFF) { /* minic iconv() behavior */
- if (inLen < 4 ||
- (inLen >= 4 && byte1 == 0xF8 && pIn[1] < 0x90) ||
- pIn[1] < 0x80 || 0xBF < pIn[1] ||
- pIn[2] < 0x80 || 0xBF < pIn[2] ||
- pIn[3] < 0x80 || 0xBF < pIn[3] ) {
- if (inLen == 1)
- errno=EINVAL; /* 22 */
- else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80)
- errno=EILSEQ; /* 116 */
- else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80))
- errno=EILSEQ; /* 116 */
- else if (inLen >= 4 && (byte1 == 0xF8 || (pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80))
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
-
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- } else if ((pIn[1] == 0x80 || pIn[1] == 0x90 || pIn[1] == 0xA0 || pIn[1] == 0xB0) &&
- pIn[2] < 0x82) {
- *pOut=subS; /* Though returns replacement character, which iconv() does not return. */
- ++pOut;
- ++numS;
- pIn+=4;
- inLen-=4;
- continue;
- } else {
- *pOut=pSubD[0]; /* Though returns replacement character, which iconv() does not return. */
- ++pOut;
- *pOut=pSubD[1];
- ++pOut;
- ++numS;
- pIn+=4;
- inLen-=4;
- continue;
- /* iconv() returns 0 with strange 1 byte converted values */
- }
-
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- }
- /* end of UTF-8 to UCS-2 */
- if (in == 0x0000) {
- *pOut=0x00;
- ++pOut;
- } else if (in < 0x100 && dmapU2S[in] != 0x0000) {
- if ((*pOut=dmapU2S[in]) == subS) {
- if (in != cd->srcSubS)
- ++numS;
- }
- ++pOut;
- } else {
- in<<=1;
- if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */
- in*=1.5;
- if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/
- *pOut=pSubD[0];
- ++pOut;
- *pOut=pSubD[1];
- ++pOut;
- ++numS;
- ++rc;
- } else {
- *pOut=dmapU2M3[in];
- ++pOut;
- *pOut=dmapU2M3[1+in];
- ++pOut;
- *pOut=dmapU2M3[2+in];
- ++pOut;
- }
- } else {
- *pOut=dmapU2M2[in];
- ++pOut;
- if (dmapU2M2[1+in] == 0x00) {
- if (*pOut == subS) {
- in>>=1;
- if (in != cd->srcSubS)
- ++numS;
- }
- } else {
- *pOut=dmapU2M2[1+in];
- ++pOut;
- if (memcmp(pOut-2, pSubD, 2) == 0) {
- in>>=1;
- if (in != cd->srcSubD) {
- ++numS;
- ++rc;
- }
- }
- }
- }
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_S2U) {
- /* use uchar * instead of UniChar to avoid memcpy */
- register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U);
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register int offset;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register size_t numS=0;
- while (0 < inLen) {
- if (pLastOutBuf < pOut)
- break;
- if (*pIn == 0x00) {
- *pOut=0x00;
- ++pOut;
- *pOut=0x00;
- ++pOut;
- ++pIn;
- --inLen;
- } else {
- offset=*pIn;
- offset<<=1;
- *pOut=dmapD12U[offset];
- ++pOut;
- *pOut=dmapD12U[offset+1];
- ++pOut;
- if (dmapD12U[offset] == 0x00) {
- if (dmapD12U[offset+1] == 0x1A) {
- if (*pIn != cd->srcSubS)
- ++numS;
- } else if (dmapD12U[offset+1] == 0x00) {
- pOut-=2;
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- }
- ++pIn;
- --inLen;
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_S28) {
- /* use uchar * instead of UniChar to avoid memcpy */
- register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U);
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register int offset;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register size_t numS=0;
- register UniChar in; /* copy part of U28 */
- while (0 < inLen) {
- if (pLastOutBuf < pOut)
- break;
- if (*pIn == 0x00) {
- *pOut=0x00;
- ++pOut;
- ++pIn;
- --inLen;
- } else {
- offset=*pIn;
- offset<<=1;
- in=dmapD12U[offset];
- in<<=8;
- in+=dmapD12U[offset+1];
- if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */
- if (in == 0x000) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- *pOut=in;
- ++pOut;
- } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */
- register uchar byte;
- in>>=6;
- in&=0x001F; /* 0b0000000000011111 */
- in|=0x00C0; /* 0b0000000011000000 */
- *pOut=in;
- ++pOut;
- byte=dmapD12U[offset+1];
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- } else if ((in & 0xFC00) == 0xD800) { /* There should not be no surrogate character in SBCS. */
- *pOut=0xEF;
- ++pOut;
- *pOut=0xBF;
- ++pOut;
- *pOut=0xBD;
- ++pOut;
- } else {
- register uchar byte;
- register uchar work;
- byte=dmapD12U[offset];
- byte>>=4;
- byte|=0xE0; /* 0b11100000; */
- *pOut=byte;
- ++pOut;
-
- byte=dmapD12U[offset];
- byte<<=2;
- work=dmapD12U[offset+1];
- work>>=6;
- byte|=work;
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
-
- byte=dmapD12U[offset+1];
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- }
- /* end of U28 */
- if (dmapD12U[offset] == 0x00) {
- if (dmapD12U[offset+1] == 0x1A) {
- if (*pIn != cd->srcSubS)
- ++numS;
- }
- }
- ++pIn;
- --inLen;
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_U2S) {
- register uchar * dmapU2S=cd->cnv_dmap->dmapU2S;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register size_t numS=0;
- while (0 < inLen) {
- register uint32_t in;
- if (inLen == 1) {
- errno=EINVAL; /* 22 */
-
- *inBytesLeft=inLen;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- if (pLastOutBuf < pOut)
- break;
- in=pIn[0];
- in<<=8;
- in+=pIn[1];
- if (in == 0x0000) {
- *pOut=0x00;
- } else {
- if ((*pOut=dmapU2S[in]) == 0x00) {
- *pOut=subS;
- ++numS;
- errno=EINVAL; /* 22 */
- } else if (*pOut == subS) {
- if (in != cd->srcSubS)
- ++numS;
- }
- }
- ++pOut;
- pIn+=2;
- inLen-=2;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return numS;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_T2S) {
- register uchar * dmapU2S=cd->cnv_dmap->dmapU2S;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register size_t numS=0;
- while (0 < inLen) {
- register uint32_t in;
- if (inLen == 1) {
- errno=EINVAL; /* 22 */
-
- *inBytesLeft=inLen-1;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- ++numS;
- *numSub+=numS;
- return 0;
- }
- if (pLastOutBuf < pOut)
- break;
- in=pIn[0];
- in<<=8;
- in+=pIn[1];
- if (in == 0x0000) {
- *pOut=0x00;
-
- } else if (0xD800 <= in && in <= 0xDFFF) { /* 0xD800-0xDFFF, surrogate first and second values */
- if (0xDC00 <= in ) {
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-1;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
-
- } else if (inLen < 4) {
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-2;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn+2;
- return -1;
-
- } else {
- register uint32_t in2;
- in2=pIn[2];
- in2<<=8;
- in2+=pIn[3];
- if (0xDC00 <= in2 && in2 <= 0xDFFF) { /* second surrogate character =0xDC00 - 0xDFFF*/
- *pOut=subS;
- ++numS;
- pIn+=4;
- } else {
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-1;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- }
- } else {
- if ((*pOut=dmapU2S[in]) == 0x00) {
- *pOut=subS;
- ++numS;
- errno=EINVAL; /* 22 */
- } else if (*pOut == subS) {
- if (in != cd->srcSubS)
- ++numS;
- }
- }
- ++pOut;
- pIn+=2;
- inLen-=2;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_82S) {
- register uchar * dmapU2S=cd->cnv_dmap->dmapU2S;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register size_t numS=0;
- while (0 < inLen) {
- register uint32_t in;
- uint32_t in2; /* The second surrogate value */
- if (pLastOutBuf < pOut)
- break;
- /* convert from UTF-8 to UCS-2 */
- if (*pIn == 0x00) {
- in=0x0000;
- ++pIn;
- --inLen;
- } else { /* 82U: */
- register uchar byte1=*pIn;
- if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */
- /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/
- in=byte1;
- ++pIn;
- --inLen;
- } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */
- if (inLen < 2) {
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- /* 2 bytes sequence:
- 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */
- register uchar byte2;
- ++pIn;
- byte2=*pIn;
- if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */
- register uchar work=byte1;
- work<<=6;
- byte2&=0x3F; /* 0b00111111; */
- byte2|=work;
-
- byte1&=0x1F; /* 0b00011111; */
- byte1>>=2;
- in=byte1;
- in<<=8;
- in+=byte2;
- inLen-=2;
- ++pIn;
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- *numSub+=numS;
- return -1;
- }
- } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */
- /* 3 bytes sequence:
- 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */
- register uchar byte2;
- register uchar byte3;
- if (inLen < 3) {
- if (inLen == 2 && (pIn[1] & 0xC0) != 0x80)
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- ++pIn;
- byte2=*pIn;
- ++pIn;
- byte3=*pIn;
- if ((byte2 & 0xC0) != 0x80 ||
- (byte3 & 0xC0) != 0x80 ||
- (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- *numSub+=numS;
- return -1;
- }
- {
- register uchar work=byte2;
- work<<=6;
- byte3&=0x3F; /* 0b00111111; */
- byte3|=work;
-
- byte2&=0x3F; /* 0b00111111; */
- byte2>>=2;
-
- byte1<<=4;
- in=byte1 | byte2;;
- in<<=8;
- in+=byte3;
- inLen-=3;
- ++pIn;
- }
- } else if ((0xF0 <= byte1 && byte1 <= 0xF4) || /* (bytes1 & 11111000) == 0x1110000 */
- ((byte1&=0xF7) && 0xF0 <= byte1 && byte1 <= 0xF4)) { /* minic iconv() behavior */
- /* 4 bytes sequence
- 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx
- where uuuuu = wwww + 1 */
- register uchar byte2;
- register uchar byte3;
- register uchar byte4;
- if (inLen < 4) {
- if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) ||
- (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) ||
- (cd->toCcsid == 13488) )
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- ++pIn;
- byte2=*pIn;
- ++pIn;
- byte3=*pIn;
- ++pIn;
- byte4=*pIn;
- if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */
- (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */
- (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */
- register uchar work=byte2;
- if (byte1 == 0xF0 && byte2 < 0x90) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- /* iconv() returns 0 for 0xF4908080 and convert to 0x00
- } else if (byte1 == 0xF4 && byte2 > 0x8F) {
- errno=EINVAL;
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- */
- }
-
- work&=0x30; /* 0b00110000; */
- work>>=4;
- byte1&=0x07; /* 0b00000111; */
- byte1<<=2;
- byte1+=work; /* uuuuu */
- --byte1; /* wwww */
-
- work=byte1 & 0x0F;
- work>>=2;
- work+=0xD8; /* 0b11011011; */
- in=work;
- in<<=8;
-
- byte1<<=6;
- byte2<<=2;
- byte2&=0x3C; /* 0b00111100; */
- work=byte3;
- work>>=4;
- work&=0x03; /* 0b00000011; */
- work|=byte1;
- work|=byte2;
- in+=work;
-
- work=byte3;
- work>>=2;
- work&=0x03; /* 0b00000011; */
- work|=0xDC; /* 0b110111xx; */
- in2=work;
- in2<<=8;
-
- byte3<<=6;
- byte4&=0x3F; /* 0b00111111; */
- byte4|=byte3;
- in2+=byte4;
- inLen-=4;
- ++pIn;
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- }
- } else if ((byte1 & 0xF0) == 0xF0) { /* minic iconv() behavior */
- if (inLen < 4 ||
- pIn[1] < 0x80 || 0xBF < pIn[1] ||
- pIn[2] < 0x80 || 0xBF < pIn[2] ||
- pIn[3] < 0x80 || 0xBF < pIn[3] ) {
- if (inLen == 1)
- errno=EINVAL; /* 22 */
- else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80)
- errno=EILSEQ; /* 116 */
- else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80))
- errno=EILSEQ; /* 116 */
- else if (inLen >= 4 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80))
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
-
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- } else {
- *pOut=subS; /* Though returns replacement character, which iconv() does not return. */
- ++pOut;
- ++numS;
- pIn+=4;
- inLen-=4;
- /* UTF-8_IBM-850 0xF0908080 : converted value does not match, iconv=0x00, dmap=0x7F
- UTF-8_IBM-850 0xF0908081 : converted value does not match, iconv=0x01, dmap=0x7F
- UTF-8_IBM-850 0xF0908082 : converted value does not match, iconv=0x02, dmap=0x7F
- UTF-8_IBM-850 0xF0908083 : converted value does not match, iconv=0x03, dmap=0x7F
- ....
- UTF-8_IBM-850 0xF09081BE : converted value does not match, iconv=0x7E, dmap=0x7F
- UTF-8_IBM-850 0xF09081BF : converted value does not match, iconv=0x1C, dmap=0x7F
- UTF-8_IBM-850 0xF09082A0 : converted value does not match, iconv=0xFF, dmap=0x7F
- UTF-8_IBM-850 0xF09082A1 : converted value does not match, iconv=0xAD, dmap=0x7F
- ....
- */
- continue;
- /* iconv() returns 0 with strange 1 byte converted values */
- }
-
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- }
- /* end of UTF-8 to UCS-2 */
- if (in == 0x0000) {
- *pOut=0x00;
- } else {
- if ((*pOut=dmapU2S[in]) == 0x00) {
- *pOut=subS;
- ++numS;
- errno=EINVAL; /* 22 */
- } else if (*pOut == subS) {
- if (in != cd->srcSubS) {
- ++numS;
- }
- }
- }
- ++pOut;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_D2U) {
- /* use uchar * instead of UniChar to avoid memcpy */
- register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U);
- register uchar * dmapD22U=(uchar *) (cd->cnv_dmap->dmapD22U);
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register int offset;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register size_t numS=0;
- while (0 < inLen) {
- if (pLastOutBuf < pOut)
- break;
- if (*pIn == 0x00) {
- *pOut=0x00;
- ++pOut;
- *pOut=0x00;
- ++pOut;
- ++pIn;
- --inLen;
- } else {
- offset=*pIn;
- offset<<=1;
- if (dmapD12U[offset] == 0x00 &&
- dmapD12U[offset+1] == 0x00) { /* DBCS */
- if (inLen < 2) {
- if (*pIn == 0x80 || *pIn == 0xFF ||
- (cd->fromCcsid == 943 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0xA0 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xEF || *pIn == 0xFD || *pIn == 0xFE)) ||
- (cd->fromCcsid == 932 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0x87 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xED || *pIn == 0xEE || *pIn == 0xEF)) ||
- (cd->fromCcsid == 1381 && ((0x85 <= *pIn && *pIn <= 0x8B) || (0xAA <= *pIn && *pIn <= 0xAF) || (0xF8 <= *pIn && *pIn <= 0xFE))))
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- offset-=0x100;
- ++pIn;
- offset<<=8;
- offset+=(*pIn * 2);
- if (dmapD22U[offset] == 0x00 &&
- dmapD22U[offset+1] == 0x00) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- *pOut=dmapD22U[offset];
- ++pOut;
- *pOut=dmapD22U[offset+1];
- ++pOut;
- if (dmapD22U[offset] == 0xFF &&
- dmapD22U[offset+1] == 0xFD) {
- if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD)
- ++numS;
- }
- ++pIn;
- inLen-=2;
- } else { /* SBCS */
- *pOut=dmapD12U[offset];
- ++pOut;
- *pOut=dmapD12U[offset+1];
- ++pOut;
- if (dmapD12U[offset] == 0x00 &&
- dmapD12U[offset+1] == 0x1A) {
- if (*pIn != cd->srcSubS)
- ++numS;
- }
- ++pIn;
- --inLen;
- }
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_D28) {
- /* use uchar * instead of UniChar to avoid memcpy */
- register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U);
- register uchar * dmapD22U=(uchar *) (cd->cnv_dmap->dmapD22U);
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register int offset;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register size_t numS=0;
- register UniChar in; /* copy part of U28 */
- register UniChar ucs2;
- while (0 < inLen) {
- if (pLastOutBuf < pOut)
- break;
- if (*pIn == 0x00) {
- *pOut=0x00;
- ++pOut;
- ++pIn;
- --inLen;
- } else {
- offset=*pIn;
- offset<<=1;
- if (dmapD12U[offset] == 0x00 &&
- dmapD12U[offset+1] == 0x00) { /* DBCS */
- if (inLen < 2) {
- if (*pIn == 0x80 || *pIn == 0xFF ||
- (cd->fromCcsid == 943 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0xA0 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xEF || *pIn == 0xFD || *pIn == 0xFE)) ||
- (cd->fromCcsid == 932 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0x87 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xED || *pIn == 0xEE || *pIn == 0xEF)) ||
- (cd->fromCcsid == 1381 && ((0x85 <= *pIn && *pIn <= 0x8B) || (0xAA <= *pIn && *pIn <= 0xAF) || (0xF8 <= *pIn && *pIn <= 0xFE))))
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- offset-=0x100;
- ++pIn;
- offset<<=8;
- offset+=(*pIn * 2);
- if (dmapD22U[offset] == 0x00 &&
- dmapD22U[offset+1] == 0x00) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- return -1;
- }
- in=dmapD22U[offset];
- in<<=8;
- in+=dmapD22U[offset+1];
- ucs2=in;
- if (dmapD22U[offset] == 0xFF &&
- dmapD22U[offset+1] == 0xFD) {
- if (in != cd->srcSubD)
- ++numS;
- }
- ++pIn;
- inLen-=2;
- } else { /* SBCS */
- in=dmapD12U[offset];
- in<<=8;
- in+=dmapD12U[offset+1];
- ucs2=in;
- if (dmapD12U[offset] == 0x00 &&
- dmapD12U[offset+1] == 0x1A) {
- if (in != cd->srcSubS)
- ++numS;
- }
- ++pIn;
- --inLen;
- }
- if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */
- *pOut=in;
- ++pOut;
- } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */
- register uchar byte;
- in>>=6;
- in&=0x001F; /* 0b0000000000011111 */
- in|=0x00C0; /* 0b0000000011000000 */
- *pOut=in;
- ++pOut;
- byte=ucs2; /* dmapD12U[offset+1]; */
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- } else if ((in & 0xFC00) == 0xD800) { /* There should not be no surrogate character in SBCS. */
- *pOut=0xEF;
- ++pOut;
- *pOut=0xBF;
- ++pOut;
- *pOut=0xBD;
- ++pOut;
- } else {
- register uchar byte;
- register uchar work;
- byte=(ucs2>>8); /* dmapD12U[offset]; */
- byte>>=4;
- byte|=0xE0; /* 0b11100000; */
- *pOut=byte;
- ++pOut;
-
- byte=(ucs2>>8); /* dmapD12U[offset]; */
- byte<<=2;
- work=ucs2; /* dmapD12U[offset+1]; */
- work>>=6;
- byte|=work;
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
-
- byte=ucs2; /* dmapD12U[offset+1]; */
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- }
- /* end of U28 */
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_U2D) {
- register uchar * dmapU2D=cd->cnv_dmap->dmapU2D;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register char * pSubD=(char *) &(cd->subD);
- register size_t numS=0;
- while (0 < inLen) {
- register uint32_t in;
- if (inLen == 1) {
- errno=EINVAL; /* 22 */
-
- *inBytesLeft=inLen;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- if (pLastOutBuf < pOut)
- break;
- in=pIn[0];
- in<<=8;
- in+=pIn[1];
- if (in == 0x0000) {
- *pOut=0x00;
- ++pOut;
- } else {
- in<<=1;
- *pOut=dmapU2D[in];
- ++pOut;
- if (dmapU2D[in+1] == 0x00) { /* SBCS */
- if (*pOut == subS) {
- if (in != cd->srcSubS)
- ++numS;
- }
- } else {
- *pOut=dmapU2D[in+1];
- ++pOut;
- if (dmapU2D[in] == pSubD[0] &&
- dmapU2D[in+1] == pSubD[1]) {
- in>>=1;
- if (in != cd->srcSubD)
- ++numS;
- }
- }
- }
- pIn+=2;
- inLen-=2;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return numS; /* to minic iconv() behavior */
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_T2D) {
- register uchar * dmapU2D=cd->cnv_dmap->dmapU2D;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register char * pSubD=(char *) &(cd->subD);
- register size_t numS=0;
- while (0 < inLen) {
- register uint32_t in;
- if (inLen == 1) {
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-1;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- ++numS;
- *numSub+=numS;
- return 0;
- }
- if (pLastOutBuf < pOut)
- break;
- in=pIn[0];
- in<<=8;
- in+=pIn[1];
- if (in == 0x0000) {
- *pOut=0x00;
- ++pOut;
- } else if (0xD800 <= in && in <= 0xDBFF) { /* first byte of surrogate */
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-2;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn+2;
- ++numS;
- *numSub+=numS;
- return -1;
-
- } else if (0xDC00 <= in && in <= 0xDFFF) { /* second byte of surrogate */
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-1;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- ++numS;
- *numSub+=numS;
- return -1;
-
- } else {
- in<<=1;
- *pOut=dmapU2D[in];
- ++pOut;
- if (dmapU2D[in+1] == 0x00) { /* SBCS */
- if (*pOut == subS) {
- if (in != cd->srcSubS)
- ++numS;
- }
- } else {
- *pOut=dmapU2D[in+1];
- ++pOut;
- if (dmapU2D[in] == pSubD[0] &&
- dmapU2D[in+1] == pSubD[1]) {
- in>>=1;
- if (in != cd->srcSubD)
- ++numS;
- }
- }
- }
- pIn+=2;
- inLen-=2;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0; /* to minic iconv() behavior */
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_82D) {
- register uchar * dmapU2D=cd->cnv_dmap->dmapU2D;
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register char subS=cd->subS;
- register char * pSubD=(char *) &(cd->subD);
- register size_t numS=0;
- while (0 < inLen) {
- register uint32_t in;
- uint32_t in2;
- if (pLastOutBuf < pOut)
- break;
- /* convert from UTF-8 to UCS-2 */
- if (*pIn == 0x00) {
- in=0x0000;
- ++pIn;
- --inLen;
- } else { /* 82U: */
- register uchar byte1=*pIn;
- if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */
- /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/
- in=byte1;
- ++pIn;
- --inLen;
- } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */
- if (inLen < 2) {
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- /* 2 bytes sequence:
- 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */
- register uchar byte2;
- ++pIn;
- byte2=*pIn;
- if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */
- register uchar work=byte1;
- work<<=6;
- byte2&=0x3F; /* 0b00111111; */
- byte2|=work;
-
- byte1&=0x1F; /* 0b00011111; */
- byte1>>=2;
- in=byte1;
- in<<=8;
- in+=byte2;
- inLen-=2;
- ++pIn;
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- *numSub+=numS;
- return -1;
- }
- } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */
- /* 3 bytes sequence:
- 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */
- register uchar byte2;
- register uchar byte3;
- if (inLen < 3) {
- if (inLen == 2 && (pIn[1] & 0xC0) != 0x80)
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- ++pIn;
- byte2=*pIn;
- ++pIn;
- byte3=*pIn;
- if ((byte2 & 0xC0) != 0x80 ||
- (byte3 & 0xC0) != 0x80 ||
- (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- *numSub+=numS;
- return -1;
- }
- {
- register uchar work=byte2;
- work<<=6;
- byte3&=0x3F; /* 0b00111111; */
- byte3|=work;
-
- byte2&=0x3F; /* 0b00111111; */
- byte2>>=2;
-
- byte1<<=4;
- in=byte1 | byte2;;
- in<<=8;
- in+=byte3;
- inLen-=3;
- ++pIn;
- }
- } else if ((0xF0 <= byte1 && byte1 <= 0xF4)) { /* (bytes1 & 11111000) == 0x1110000 */
- /* 4 bytes sequence
- 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx
- where uuuuu = wwww + 1 */
- register uchar byte2;
- register uchar byte3;
- register uchar byte4;
- if (inLen < 4) {
- if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) ||
- (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) ||
- (cd->toCcsid == 13488) )
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- ++pIn;
- byte2=*pIn;
- ++pIn;
- byte3=*pIn;
- ++pIn;
- byte4=*pIn;
- if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */
- (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */
- (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */
- register uchar work=byte2;
- if (byte1 == 0xF0 && byte2 < 0x90) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- /* iconv() returns 0 for 0xF4908080 and convert to 0x00
- } else if (byte1 == 0xF4 && byte2 > 0x8F) {
- errno=EINVAL;
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- */
- }
-
- work&=0x30; /* 0b00110000; */
- work>>=4;
- byte1&=0x07; /* 0b00000111; */
- byte1<<=2;
- byte1+=work; /* uuuuu */
- --byte1; /* wwww */
-
- work=byte1 & 0x0F;
- work>>=2;
- work+=0xD8; /* 0b11011011; */
- in=work;
- in<<=8;
-
- byte1<<=6;
- byte2<<=2;
- byte2&=0x3C; /* 0b00111100; */
- work=byte3;
- work>>=4;
- work&=0x03; /* 0b00000011; */
- work|=byte1;
- work|=byte2;
- in+=work;
-
- work=byte3;
- work>>=2;
- work&=0x03; /* 0b00000011; */
- work|=0xDC; /* 0b110111xx; */
- in2=work;
- in2<<=8;
-
- byte3<<=6;
- byte4&=0x3F; /* 0b00111111; */
- byte4|=byte3;
- in2+=byte4;
- inLen-=4;
- ++pIn;
-#ifdef match_with_GBK
- if ((0xD800 == in && in2 < 0xDC80) ||
- (0xD840 == in && in2 < 0xDC80) ||
- (0xD880 == in && in2 < 0xDC80) ||
- (0xD8C0 == in && in2 < 0xDC80) ||
- (0xD900 == in && in2 < 0xDC80) ||
- (0xD940 == in && in2 < 0xDC80) ||
- (0xD980 == in && in2 < 0xDC80) ||
- (0xD9C0 == in && in2 < 0xDC80) ||
- (0xDA00 == in && in2 < 0xDC80) ||
- (0xDA40 == in && in2 < 0xDC80) ||
- (0xDA80 == in && in2 < 0xDC80) ||
- (0xDAC0 == in && in2 < 0xDC80) ||
- (0xDB00 == in && in2 < 0xDC80) ||
- (0xDB40 == in && in2 < 0xDC80) ||
- (0xDB80 == in && in2 < 0xDC80) ||
- (0xDBC0 == in && in2 < 0xDC80)) {
-#else
- if ((0xD800 <= in && in <= 0xDBFF) &&
- (0xDC00 <= in2 && in2 <= 0xDFFF)) {
-#endif
- *pOut=subS;
- ++pOut;
- ++numS;
- continue;
- }
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- }
- } else if (0xF5 <= byte1 && byte1 <= 0xFF) { /* minic iconv() behavior */
- if (inLen < 4 ||
- (inLen >= 4 && byte1 == 0xF8 && pIn[1] < 0x90) ||
- pIn[1] < 0x80 || 0xBF < pIn[1] ||
- pIn[2] < 0x80 || 0xBF < pIn[2] ||
- pIn[3] < 0x80 || 0xBF < pIn[3] ) {
- if (inLen == 1)
- errno=EINVAL; /* 22 */
- else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80)
- errno=EILSEQ; /* 116 */
- else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80))
- errno=EILSEQ; /* 116 */
- else if (inLen >= 4 && (byte1 == 0xF8 || (pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80))
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
-
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- } else if ((pIn[1] == 0x80 || pIn[1] == 0x90 || pIn[1] == 0xA0 || pIn[1] == 0xB0) &&
- pIn[2] < 0x82) {
- *pOut=subS; /* Though returns replacement character, which iconv() does not return. */
- ++pOut;
- ++numS;
- pIn+=4;
- inLen-=4;
- continue;
- } else {
- *pOut=pSubD[0]; /* Though returns replacement character, which iconv() does not return. */
- ++pOut;
- *pOut=pSubD[1];
- ++pOut;
- ++numS;
- pIn+=4;
- inLen-=4;
- continue;
- /* iconv() returns 0 with strange 1 byte converted values */
- }
-
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- }
- /* end of UTF-8 to UCS-2 */
- if (in == 0x0000) {
- *pOut=0x00;
- ++pOut;
- } else {
- in<<=1;
- *pOut=dmapU2D[in];
- ++pOut;
- if (dmapU2D[in+1] == 0x00) { /* SBCS */
- if (dmapU2D[in] == subS) {
- in>>=1;
- if (in != cd->srcSubS)
- ++numS;
- }
- } else {
- *pOut=dmapU2D[in+1];
- ++pOut;
- if (dmapU2D[in] == pSubD[0] &&
- dmapU2D[in+1] == pSubD[1]) {
- in>>=1;
- if (in != cd->srcSubD)
- ++numS;
- }
- }
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_82U) {
- /* See http://unicode.org/versions/corrigendum1.html */
- /* convert from UTF-8 to UTF-16 can cover all conversion from UTF-8 to UCS-2 */
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- register size_t numS=0;
- while (0 < inLen) {
- if (pLastOutBuf < pOut)
- break;
- if (*pIn == 0x00) {
- *pOut=0x00;
- ++pOut;
- *pOut=0x00;
- ++pOut;
- ++pIn;
- --inLen;
- } else { /* 82U: */
- register uchar byte1=*pIn;
- if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */
- /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/
- *pOut=0x00;
- ++pOut;
- *pOut=byte1;
- ++pOut;
- ++pIn;
- --inLen;
- } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */
- if (inLen < 2) {
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- /* 2 bytes sequence:
- 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */
- register uchar byte2;
- ++pIn;
- byte2=*pIn;
- if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */
- register uchar work=byte1;
- work<<=6;
- byte2&=0x3F; /* 0b00111111; */
- byte2|=work;
-
- byte1&=0x1F; /* 0b00011111; */
- byte1>>=2;
- *pOut=byte1;
- ++pOut;
- *pOut=byte2;
- ++pOut;
- inLen-=2;
- ++pIn;
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-1;
- *numSub+=numS;
- return -1;
- }
- } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */
- /* 3 bytes sequence:
- 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */
- register uchar byte2;
- register uchar byte3;
- if (inLen < 3) {
- if (inLen == 2 && (pIn[1] & 0xC0) != 0x80)
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- ++pIn;
- byte2=*pIn;
- ++pIn;
- byte3=*pIn;
- if ((byte2 & 0xC0) != 0x80 ||
- (byte3 & 0xC0) != 0x80 ||
- (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-2;
- *numSub+=numS;
- return -1;
- }
- {
- register uchar work=byte2;
- work<<=6;
- byte3&=0x3F; /* 0b00111111; */
- byte3|=work;
-
- byte2&=0x3F; /* 0b00111111; */
- byte2>>=2;
-
- byte1<<=4;
- *pOut=byte1 | byte2;;
- ++pOut;
- *pOut=byte3;
- ++pOut;
- inLen-=3;
- ++pIn;
- }
- } else if ((0xF0 <= byte1 && byte1 <= 0xF4) || /* (bytes1 & 11111000) == 0x1110000 */
- ((byte1&=0xF7) && 0xF0 <= byte1 && byte1 <= 0xF4)) { /* minic iconv() behavior */
- /* 4 bytes sequence
- 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx
- where uuuuu = wwww + 1 */
- register uchar byte2;
- register uchar byte3;
- register uchar byte4;
- if (inLen < 4 || cd->toCcsid == 13488) {
- if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) ||
- (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) ||
- (cd->toCcsid == 13488) )
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- ++pIn;
- byte2=*pIn;
- ++pIn;
- byte3=*pIn;
- ++pIn;
- byte4=*pIn;
- if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */
- (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */
- (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */
- register uchar work=byte2;
- if (byte1 == 0xF0 && byte2 < 0x90) {
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- } else if (byte1 == 0xF4 && byte2 > 0x8F) {
- errno=EINVAL; /* 22 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- }
-
- work&=0x30; /* 0b00110000; */
- work>>=4;
- byte1&=0x07; /* 0b00000111; */
- byte1<<=2;
- byte1+=work; /* uuuuu */
- --byte1; /* wwww */
-
- work=byte1 & 0x0F;
- work>>=2;
- work+=0xD8; /* 0b11011011; */
- *pOut=work;
- ++pOut;
-
- byte1<<=6;
- byte2<<=2;
- byte2&=0x3C; /* 0b00111100; */
- work=byte3;
- work>>=4;
- work&=0x03; /* 0b00000011; */
- work|=byte1;
- work|=byte2;
- *pOut=work;
- ++pOut;
-
- work=byte3;
- work>>=2;
- work&=0x03; /* 0b00000011; */
- work|=0xDC; /* 0b110111xx; */
- *pOut=work;
- ++pOut;
-
- byte3<<=6;
- byte4&=0x3F; /* 0b00111111; */
- byte4|=byte3;
- *pOut=byte4;
- ++pOut;
- inLen-=4;
- ++pIn;
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn-3;
- *numSub+=numS;
- return -1;
- }
- } else if ((byte1 & 0xF0) == 0xF0) {
- if (cd->toCcsid == 13488) {
- errno=EILSEQ; /* 116 */
- } else {
- if (inLen == 1)
- errno=EINVAL; /* 22 */
- else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80)
- errno=EILSEQ; /* 116 */
- else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80))
- errno=EILSEQ; /* 116 */
- else if (inLen >= 4 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80))
- errno=EILSEQ; /* 116 */
- else
- errno=EINVAL; /* 22 */
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
-
- } else { /* invalid sequence */
- errno=EILSEQ; /* 116 */
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return -1;
- }
- }
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- *numSub+=numS;
- return 0;
- } else if (cd->cnv_dmap->codingSchema == DMAP_U28) {
- /* See http://unicode.org/versions/corrigendum1.html */
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- // register size_t numS=0;
- while (0 < inLen) {
- register uint32_t in;
- if (inLen == 1) {
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
- }
- if (pLastOutBuf < pOut)
- break;
- in=pIn[0];
- in<<=8;
- in+=pIn[1];
- if (in == 0x0000) {
- *pOut=0x00;
- ++pOut;
- } else if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */
- *pOut=in;
- ++pOut;
- } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */
- register uchar byte;
- in>>=6;
- in&=0x001F; /* 0b0000000000011111 */
- in|=0x00C0; /* 0b0000000011000000 */
- *pOut=in;
- ++pOut;
- byte=pIn[1];
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- } else {
- register uchar byte;
- register uchar work;
- byte=pIn[0];
- byte>>=4;
- byte|=0xE0; /* 0b11100000; */
- *pOut=byte;
- ++pOut;
-
- byte=pIn[0];
- byte<<=2;
- work=pIn[1];
- work>>=6;
- byte|=work;
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
-
- byte=pIn[1];
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- }
- pIn+=2;
- inLen-=2;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- // *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_T28) { /* UTF-16_UTF-8 */
- /* See http://unicode.org/versions/corrigendum1.html */
- register int inLen=*inBytesLeft;
- register char * pOut=*outBuf;
- register char * pIn=*inBuf;
- register char * pLastOutBuf = *outBuf + *outBytesLeft - 1;
- // register size_t numS=0;
- while (0 < inLen) {
- register uint32_t in;
- if (inLen == 1) {
- errno=EINVAL; /* 22 */
- *inBytesLeft=0;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- return 0;
- }
- if (pLastOutBuf < pOut)
- break;
- in=pIn[0];
- in<<=8;
- in+=pIn[1];
- if (in == 0x0000) {
- *pOut=0x00;
- ++pOut;
- } else if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */
- *pOut=in;
- ++pOut;
- } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */
- register uchar byte;
- in>>=6;
- in&=0x001F; /* 0b0000000000011111 */
- in|=0x00C0; /* 0b0000000011000000 */
- *pOut=in;
- ++pOut;
- byte=pIn[1];
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- } else if ((in & 0xFC00) == 0xD800) { /* in & 0b1111110000000000 == 0b1101100000000000, first surrogate character */
- if (0xDC00 <= in ) {
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-1;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
-
- } else if (inLen < 4) {
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-2;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn+2;
- return -1;
-
- } else if ((pIn[2] & 0xFC) != 0xDC) { /* pIn[2] & 0b11111100 == 0b11011100, second surrogate character */
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-2;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn+2;
- return -1;
-
- } else {
- register uchar byte;
- register uchar work;
- in>>=6;
- in&=0x000F; /* 0b0000000000001111 */
- byte=in; /* wwww */
- ++byte; /* uuuuu */
- work=byte; /* save uuuuu */
- byte>>=2;
- byte|=0xF0; /* 0b11110000; */
- *pOut=byte;
- ++pOut;
-
- byte=work;
- byte&=0x03; /* 0b00000011; */
- byte<<=4;
- byte|=0x80; /* 0b10000000; */
- work=pIn[1];
- work&=0x3C; /* 0b00111100; */
- work>>=2;
- byte|=work;
- *pOut=byte;
- ++pOut;
-
- byte=pIn[1];
- byte&=0x03; /* 0b00000011; */
- byte<<=4;
- byte|=0x80; /* 0b10000000; */
- work=pIn[2];
- work&=0x03; /* 0b00000011; */
- work<<=2;
- byte|=work;
- work=pIn[3];
- work>>=6;
- byte|=work;
- *pOut=byte;
- ++pOut;
-
- byte=pIn[3];
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- pIn+=2;
- inLen-=2;
- }
- } else if ((in & 0xFC00) == 0xDC00) { /* in & 0b11111100 == 0b11011100, second surrogate character */
- errno=EINVAL; /* 22 */
- *inBytesLeft=inLen-1;
- *outBytesLeft-=(pOut-*outBuf);
- *outBuf=pOut;
- *inBuf=pIn;
- return -1;
-
- } else {
- register uchar byte;
- register uchar work;
- byte=pIn[0];
- byte>>=4;
- byte|=0xE0; /* 0b11100000; */
- *pOut=byte;
- ++pOut;
-
- byte=pIn[0];
- byte<<=2;
- work=pIn[1];
- work>>=6;
- byte|=work;
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
-
- byte=pIn[1];
- byte&=0x3F; /* 0b00111111; */
- byte|=0x80; /* 0b10000000; */
- *pOut=byte;
- ++pOut;
- }
- pIn+=2;
- inLen-=2;
- }
- *outBytesLeft-=(pOut-*outBuf);
- *inBytesLeft=inLen;
- *outBuf=pOut;
- *inBuf=pIn;
- // *numSub+=numS;
- return 0;
-
- } else if (cd->cnv_dmap->codingSchema == DMAP_U2U) { /* UTF-16_UCS-2 */
- register int inLen=*inBytesLeft;
- register int outLen=*outBytesLeft;
- if (inLen <= outLen) {
- memcpy(*outBuf, *inBuf, inLen);
- (*outBytesLeft)-=inLen;
- (*inBuf)+=inLen;
- (*outBuf)+=inLen;
- *inBytesLeft=0;
- return 0;
- }
- memcpy(*outBuf, *inBuf, outLen);
- (*outBytesLeft)=0;
- (*inBuf)+=outLen;
- (*outBuf)+=outLen;
- *inBytesLeft-=outLen;
- return (*inBytesLeft);
-
- } else {
- return -1;
- }
- return 0;
-}
-
-
-#ifdef DEBUG
-inline size_t myconv(myconv_t cd ,
- char** inBuf,
- size_t* inBytesLeft,
- char** outBuf,
- size_t* outBytesLeft,
- size_t* numSub)
-{
- if (cd->converterType == CONVERTER_ICONV) {
- return myconv_iconv(cd,inBuf,inBytesLeft,outBuf,outBytesLeft,numSub);
- } else if (cd->converterType == CONVERTER_DMAP) {
- return myconv_dmap(cd,inBuf,inBytesLeft,outBuf,outBytesLeft,numSub);
- }
- return -1;
-}
-
-inline char * converterName(int32_t type)
-{
- if (type == CONVERTER_ICONV)
- return "iconv";
- else if (type == CONVERTER_DMAP)
- return "dmap";
-
- return "?????";
-}
-#else
-#define myconv(a,b,c,d,e,f) \
-(((a)->converterType == CONVERTER_ICONV)? myconv_iconv((a),(b),(c),(d),(e),(f)): (((a)->converterType == CONVERTER_DMAP)? myconv_dmap((a),(b),(c),(d),(e),(f)): -1))
-
-
-#define converterName(a) \
-(((a) == CONVERTER_ICONV)? "iconv": ((a) == CONVERTER_DMAP)? "dmap": "?????")
-#endif
-
-void initMyconv();
-void cleanupMyconv();
-
-#endif
diff --git a/storage/ibmdb2i/db2i_rir.cc b/storage/ibmdb2i/db2i_rir.cc
deleted file mode 100644
index 091c4d98383..00000000000
--- a/storage/ibmdb2i/db2i_rir.cc
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#include "ha_ibmdb2i.h"
-
-/* Helper function for records_in_range.
- Input: Bitmap of used key parts.
- Output: Number of used key parts. */
-
-static inline int getKeyCntFromMap(key_part_map keypart_map)
-{
- int cnt = 0;
- while (keypart_map)
- {
- keypart_map = keypart_map >> 1;
- cnt++;
- }
- return (cnt);
-}
-
-/**
- @brief
- Given a starting key and an ending key, estimate the number of rows that
- will exist between the two keys.
-
- INPUT
- inx Index to use
- min_key Min key. Is NULL if no min range
- max_key Max key. Is NULL if no max range
-
- NOTES
- min_key.flag can have one of the following values:
- HA_READ_KEY_EXACT Include the key in the range
- HA_READ_AFTER_KEY Don't include key in range
-
- max_key.flag can have one of the following values:
- HA_READ_BEFORE_KEY Don't include key in range
- HA_READ_AFTER_KEY Include all 'end_key' values in the range
-
- RETURN
- HA_POS_ERROR Error or the storage engine cannot estimate the number of rows
- 1 There are no matching keys in the given range
- n > 0 There are approximately n rows in the range
-*/
-ha_rows ha_ibmdb2i::records_in_range(uint inx,
- key_range *min_key,
- key_range *max_key)
-{
- DBUG_ENTER("ha_ibmdb2i::records_in_range");
- int rc = 0; // Return code
- ha_rows rows = 0; // Row count returned to caller of this method
- uint32 spcLen; // Length of space passed to DB2
- uint32 keyCnt; // Number of fields in the key composite
- uint32 literalCnt = 0; // Number of literals
- uint32 boundsOff; // Offset from beginning of space to range bounds
- uint32 litDefOff; // Offset from beginning of space to literal definitions
- uint32 literalsOff; // Offset from beginning of space to literal values
- uint32 cutoff = 0; // Early exit cutoff (currently not used)
- uint64 recCnt; // Row count from DB2
- uint16 rtnCode; // Return code from DB2
- Bounds* boundsPtr; // Pointer to a pair of range bounds
- Bound* boundPtr; // Pointer to a single (high or low) range bound
- LitDef* litDefPtr; // Pointer to a literal definition
- char* literalsPtr; // Pointer to the start of all literal values
- char* literalPtr; // Pointer to the start of this literal value
- char* tempPtr; // Temporary pointer
- char* tempMinPtr; // Temporary pointer into min_key
- int minKeyCnt = 0; // Number of fields in the min_key composite
- int maxKeyCnt = 0; // Number of fields in the max_key composite
- size_t tempLen = 0; // Temporary length
- uint16 DB2FieldWidth = 0; // DB2 field width
- uint32 workFieldLen = 0; // Length of workarea needed for CCSID conversions
- bool overrideInclusion; // Indicator for inclusion/exclusion
- char* endOfLiteralPtr; // Pointer to the end of this literal
- char* endOfMinPtr; // Pointer to end of min_key
- uint16 endByte = 0; // End byte of char or graphic literal (padding not included)
- bool reuseLiteral; // Indicator that hi and lo bounds use same literal
- char* minPtr = NULL; // Work pointer for traversing min_key
- char* maxPtr = NULL; // Work pointer for traversing max_key
- /*
- Handle the special case of 'x < null' anywhere in the key range. There are
- no values less than null, but return 1 so that MySQL does not assume
- the empty set for the query.
- */
- if (min_key != NULL && max_key != NULL &&
- min_key->flag == HA_READ_AFTER_KEY && max_key->flag == HA_READ_BEFORE_KEY &&
- min_key->length == max_key->length &&
- (memcmp((uchar*)min_key->key,(uchar*)max_key->key,min_key->length)==0))
- {
- DBUG_PRINT("ha_ibmdb2i::records_in_range",("Estimate 1 row for key %d; special case: < null", inx));
- DBUG_RETURN((ha_rows) 1 );
- }
- /*
- Determine the number of fields in the key composite.
- */
-
- if (min_key)
- {
- minKeyCnt = getKeyCntFromMap(min_key->keypart_map);
- minPtr = (char*)min_key->key;
- }
- if (max_key)
- {
- maxKeyCnt = getKeyCntFromMap(max_key->keypart_map);
- maxPtr = (char*)max_key->key;
- }
- keyCnt = maxKeyCnt >= minKeyCnt ? maxKeyCnt : minKeyCnt;
-
- /*
- Handle the special case where MySQL does not pass either a min or max
- key range. In this case, set the key count to 1 (knowing that there
- is at least one key field) to flow through and create one bounds structure.
- When both the min and max key ranges are nil, the bounds structure will
- specify positive and negative infinity and DB2 will estimate the total
- number of rows. */
-
- if (keyCnt == 0)
- keyCnt = 1;
-
- /*
- Allocate the space needed to pass range information to DB2. The
- space must be large enough to store the following:
- - one pair of bounds (high and low) per field in the key composite
- - one literal definition per literal value
- - the literal values
- - work area for literal CCSID conversions
- Since we don't know yet how many of these structures are needed,
- allocate enough space for the maximum that we will possibly need.
- The workarea for the literal conversion must be big enough to hold the
- largest of the DB2 key fields.
- */
- KEY& curKey = table->key_info[inx];
-
- for (int i = 0; i < keyCnt; i++)
- {
- DB2FieldWidth =
- db2Table->db2Field(curKey.key_part[i].field->field_index).getByteLengthInRecord();
- if (DB2FieldWidth > workFieldLen)
- workFieldLen = DB2FieldWidth; // Get length of largest DB2 field
- tempLen = tempLen + DB2FieldWidth; // Tally the DB2 field lengths
- }
- spcLen = (sizeof(Bounds)*keyCnt) + (sizeof(LitDef)*keyCnt*2) + (tempLen*2) + workFieldLen;
-
- ValidatedPointer<char> spcPtr(spcLen); // Pointer to space passed to DB2
- memset(spcPtr, 0, spcLen); // Clear the allocated space
- /*
- Set addressability to the various sections of the DB2 interface space.
- */
- boundsOff = 0; // Range bounds are at the start of the space
- litDefOff = sizeof(Bounds) * keyCnt; // Literal defs follow all the range bounds
- literalsOff = litDefOff + (sizeof(LitDef) * keyCnt * 2); // Literal values are last
- boundsPtr = (Bounds_t*)(void*)spcPtr; // Address first bounds structure
- tempPtr = (char*)((char*)spcPtr + litDefOff);
- litDefPtr = (LitDef_t*)tempPtr; // Address first literal definition
- tempPtr = (char*)((char*)spcPtr + literalsOff);
- literalsPtr = (char*)tempPtr; // Address start of literal values
- literalPtr = literalsPtr; // Address first literal value
- /*
- For each key part, build the low (min) and high (max) DB2 range bounds.
- If literals are specified in the MySQL range, build DB2 literal
- definitions and store the literal values for access by DB2.
-
- If no value is specified for a key part, assume infinity. Negative
- infinity will cause processing to start at the first index entry.
- Positive infinity will cause processing to end at the last index entry.
- When infinity is specified in a bound, inclusion/exclusion and position
- are ignored, and there is no literal definition or literal value for
- the bound.
-
- If the keypart value is null, the null indicator is set in the range
- bound and the other fields in the bound are ignored. When the bound is
- null, only index entries with the null value will be included in the
- estimate. If one bound is null, both bounds must be null. When the bound
- is not null, the data offset and length must be set, and the literal
- value stored for access by DB2.
- */
- for (int partsInUse = 0; partsInUse < keyCnt; ++partsInUse)
- {
- Field *field= curKey.key_part[partsInUse].field;
- overrideInclusion = false;
- reuseLiteral = false;
- endOfLiteralPtr = NULL;
- /*
- Build the low bound for the key range.
- */
- if ((partsInUse + 1) > minKeyCnt) // if no min_key info for this part
- boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where 3 between x and y
- else
- {
- if ((curKey.key_part[partsInUse].null_bit) && (char*)minPtr[0])
- { // min_key is null
- if (max_key == NULL ||
- ((partsInUse + 1) > maxKeyCnt)) // select...where x='ab' and y=null and z != 'c'
- boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where x not null or
- // select...where x > null
- else // max_key is not null
- {
- if (min_key->flag == HA_READ_KEY_EXACT)
- boundsPtr->LoBound.IsNull[0] = QMY_YES; // select...where x is null
- else
- {
- if ((char*)maxPtr[0])
- boundsPtr->LoBound.IsNull[0] = QMY_YES; // select...where a = null and b < 5 (max-before)
- // select...where a='a' and b is null and c !='a' (max-after)
- else
- boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where x < y
- }
- } // end min_key is null
- }
- else // min_key is not null
- {
- if (literalCnt) litDefPtr = litDefPtr + 1;
- literalCnt = literalCnt + 1;
- boundsPtr->LoBound.Position = literalCnt;
- /*
- Determine inclusion or exclusion.
- */
- if (min_key->flag == HA_READ_KEY_EXACT || //select...where a like 'this%'
-
- /* An example for the following conditions is 'select...where a = 5 and b > null'. */
-
- (max_key &&
- (memcmp((uchar*)minPtr,(uchar*)maxPtr,
- curKey.key_part[partsInUse].store_length)==0)))
-
- {
- if ((min_key->flag != HA_READ_KEY_EXACT) ||
- (max_key &&
- (memcmp((uchar*)minPtr,(uchar*)maxPtr,
- curKey.key_part[partsInUse].store_length)==0)))
- overrideInclusion = true; // Need inclusion for both min and max
- }
- else
- boundsPtr->LoBound.Embodiment[0] = QMY_EXCLUSION;
- litDefPtr->FieldNbr = field->field_index + 1;
- DB2Field& db2Field = db2Table->db2Field(field->field_index);
- litDefPtr->DataType = db2Field.getType();
- /*
- Convert the literal to DB2 format
- */
- if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data
- (field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data
- (litDefPtr->DataType == QMY_CHAR ||
- litDefPtr->DataType == QMY_VARCHAR ||
- litDefPtr->DataType == QMY_GRAPHIC ||
- litDefPtr->DataType == QMY_VARGRAPHIC))
- {
- // Most of the code is required by the considerable wrangling needed
- // to prepare partial keys for use by DB2
- // 1. UTF8 (CCSID 1208) data can be copied across unmodified if it is
- // utf8_bin. Otherwise, we need to convert the min and max
- // characters into the min and max characters employed
- // by the DB2 sort sequence. This is complicated by the fact that
- // the character widths are not always equal.
- // 2. Likewise, UCS2 (CCSID 13488) data can be copied across unmodified
- // if it is ucs2_bin or ucs2_general_ci. Otherwise, we need to
- // convert the min and max characters into the min and max characters
- // employed by the DB2 sort sequence.
- // 3. All other data will use standard iconv conversions. If an
- // unconvertible character is encountered, we assume it is the min
- // char and fill the remainder of the DB2 key with 0s. This may not
- // always be accurate, but it is probably sufficient for range
- // estimations.
- const char* keyData = minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0);
- char* db2Data = literalPtr;
- uint16 outLen = db2Field.getByteLengthInRecord();
- uint16 inLen;
- if (litDefPtr->DataType == QMY_VARCHAR ||
- litDefPtr->DataType == QMY_VARGRAPHIC)
- {
- inLen = *(uint8*)keyData + ((*(uint8*)(keyData+1)) << 8);
- keyData += 2;
- outLen -= sizeof(uint16);
- db2Data += sizeof(uint16);
- }
- else
- {
- inLen = field->max_display_length();
- }
-
- size_t convertedBytes = 0;
- if (db2Field.getCCSID() == 1208)
- {
- DBUG_ASSERT(inLen <= outLen);
- if (strcmp(field->charset()->name, "utf8_bin"))
- {
- const char* end = keyData+inLen;
- const char* curKey = keyData;
- char* curDB2 = db2Data;
- uint32 min = field->charset()->min_sort_char;
- while ((curKey < end) && (curDB2 < db2Data+outLen-3))
- {
- my_wc_t temp;
- int len = field->charset()->cset->mb_wc(field->charset(),
- &temp,
- (const uchar*)curKey,
- (const uchar*)end);
- if (temp != min)
- {
- DBUG_ASSERT(len <= 3);
- switch (len)
- {
- case 3: *(curDB2+2) = *(curKey+2);
- case 2: *(curDB2+1) = *(curKey+1);
- case 1: *(curDB2) = *(curKey);
- }
- curDB2 += len;
- }
- else
- {
- *(curDB2++) = 0xEF;
- *(curDB2++) = 0xBF;
- *(curDB2++) = 0xBF;
- }
- curKey += len;
- }
- convertedBytes = curDB2 - db2Data;
- }
- else
- {
- memcpy(db2Data, keyData, inLen);
- convertedBytes = inLen;
- }
- rc = 0;
- }
- else if (db2Field.getCCSID() == 13488)
- {
- DBUG_ASSERT(inLen <= outLen);
- if (strcmp(field->charset()->name, "ucs2_bin") &&
- strcmp(field->charset()->name, "ucs2_general_ci"))
- {
- const char* end = keyData+inLen;
- const uint16* curKey = (uint16*)keyData;
- uint16* curDB2 = (uint16*)db2Data;
- uint16 min = field->charset()->min_sort_char;
- while (curKey < (uint16*)end)
- {
- if (*curKey != min)
- *curDB2 = *curKey;
- else
- *curDB2 = 0xFFFF;
- ++curKey;
- ++curDB2;
- }
- }
- else
- {
- memcpy(db2Data, keyData, inLen);
- }
- convertedBytes = inLen;
- rc = 0;
- }
- else
- {
- rc = convertFieldChars(toDB2,
- field->field_index,
- keyData,
- db2Data,
- inLen,
- outLen,
- &convertedBytes,
- true);
-
- if (rc == DB2I_ERR_ILL_CHAR)
- {
- // If an illegal character is encountered, we fill the remainder
- // of the key with 0x00. This was implemented as a corollary to
- // Bug#45012, though it should probably remain even after that
- // bug is fixed.
- memset(db2Data+convertedBytes, 0x00, outLen-convertedBytes);
- convertedBytes = outLen;
- rc = 0;
- }
- }
-
- if (!rc &&
- (litDefPtr->DataType == QMY_VARGRAPHIC ||
- litDefPtr->DataType == QMY_VARCHAR))
- {
- *(uint16*)(db2Data-sizeof(uint16)) =
- convertedBytes / (litDefPtr->DataType == QMY_VARGRAPHIC ? 2 : 1);
- }
-
- }
- else // Non-character fields
- {
- rc = convertMySQLtoDB2(field,
- db2Field,
- literalPtr,
- (uchar*)minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0));
- }
-
- if (rc != 0) break;
- litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr);
- litDefPtr->Length = db2Field.getByteLengthInRecord();
- literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal
- }
- /* If there is a max_key value for this field, and if the max_key value is
- the same as the min_key value, then the low bound literal can be reused
- for the high bound literal. This eliminates the overhead of copying and
- converting the same value twice. */
- if (max_key && ((partsInUse + 1) <= maxKeyCnt) &&
- (memcmp((uchar*)minPtr,(uchar*)maxPtr,
- curKey.key_part[partsInUse].store_length)==0 || endOfLiteralPtr))
- reuseLiteral = true;
- minPtr += curKey.key_part[partsInUse].store_length;
- }
- /*
- Build the high bound for the key range.
- */
- if (max_key == NULL || ((partsInUse + 1) > maxKeyCnt))
- boundsPtr->HiBound.Infinity[0] = QMY_POS_INFINITY;
- else
- {
- if ((curKey.key_part[partsInUse].null_bit) && (char*)maxPtr[0])
- {
- if (min_key == NULL)
- boundsPtr->HiBound.Infinity[0] = QMY_POS_INFINITY;
- else
- boundsPtr->HiBound.IsNull[0] = QMY_YES; // select...where x is null
- }
- else // max_key field is not null
- {
- if (boundsPtr->LoBound.IsNull[0] == QMY_YES) // select where x < 10 or x is null
- {
- rc = HA_POS_ERROR;
- break;
- }
- if (!reuseLiteral)
- {
- if (literalCnt)
- litDefPtr = litDefPtr + 1;
- literalCnt = literalCnt + 1;
- litDefPtr->FieldNbr = field->field_index + 1;
- DB2Field& db2Field = db2Table->db2Field(field->field_index);
- litDefPtr->DataType = db2Field.getType();
- /*
- Convert the literal to DB2 format
- */
- if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data
- (field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data
- (litDefPtr->DataType == QMY_CHAR ||
- litDefPtr->DataType == QMY_VARCHAR ||
- litDefPtr->DataType == QMY_GRAPHIC ||
- litDefPtr->DataType == QMY_VARGRAPHIC))
- {
- // We need to handle char fields in a special way in order to account
- // for partial keys. Refer to the note above for a description of the
- // basic design.
- char* keyData = maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0);
- char* db2Data = literalPtr;
- uint16 outLen = db2Field.getByteLengthInRecord();
- uint16 inLen;
- if (litDefPtr->DataType == QMY_VARCHAR ||
- litDefPtr->DataType == QMY_VARGRAPHIC)
- {
- inLen = *(uint8*)keyData + ((*(uint8*)(keyData+1)) << 8);
- keyData += 2;
- outLen -= sizeof(uint16);
- db2Data += sizeof(uint16);
- }
- else
- {
- inLen = field->max_display_length();
- }
-
- size_t convertedBytes;
- if (db2Field.getCCSID() == 1208)
- {
- if (strcmp(field->charset()->name, "utf8_bin"))
- {
- const char* end = keyData+inLen;
- const char* curKey = keyData;
- char* curDB2 = db2Data;
- uint32 max = field->charset()->max_sort_char;
- while (curKey < end && (curDB2 < db2Data+outLen-3))
- {
- my_wc_t temp;
- int len = field->charset()->cset->mb_wc(field->charset(), &temp, (const uchar*)curKey, (const uchar*)end);
- if (temp != max)
- {
- DBUG_ASSERT(len <= 3);
- switch (len)
- {
- case 3: *(curDB2+2) = *(curKey+2);
- case 2: *(curDB2+1) = *(curKey+1);
- case 1: *(curDB2) = *(curKey);
- }
- curDB2 += len;
- }
- else
- {
- *(curDB2++) = 0xE4;
- *(curDB2++) = 0xB6;
- *(curDB2++) = 0xBF;
- }
- curKey += len;
- }
- convertedBytes = curDB2 - db2Data;
- }
- else
- {
- DBUG_ASSERT(inLen <= outLen);
- memcpy(db2Data, keyData, inLen);
- convertedBytes = inLen;
- }
- rc = 0;
- }
- else if (db2Field.getCCSID() == 13488)
- {
- if (strcmp(field->charset()->name, "ucs2_bin") &&
- strcmp(field->charset()->name, "ucs2_general_ci"))
- {
- char* end = keyData+inLen;
- uint16* curKey = (uint16*)keyData;
- uint16* curDB2 = (uint16*)db2Data;
- uint16 max = field->charset()->max_sort_char;
- while (curKey < (uint16*)end)
- {
- if (*curKey != max)
- *curDB2 = *curKey;
- else
- *curDB2 = 0x4DBF;
- ++curKey;
- ++curDB2;
- }
- }
- else
- {
- memcpy(db2Data, keyData, outLen);
- }
- rc = 0;
- }
- else
- {
- size_t substituteChars = 0;
- rc = convertFieldChars(toDB2,
- field->field_index,
- keyData,
- db2Data,
- inLen,
- outLen,
- &convertedBytes,
- true,
- &substituteChars);
-
- if (rc == DB2I_ERR_ILL_CHAR)
- {
- // If an illegal character is encountered, we fill the remainder
- // of the key with 0xFF. This was implemented to work around
- // Bug#45012, though it should probably remain even after that
- // bug is fixed.
- memset(db2Data+convertedBytes, 0xFF, outLen-convertedBytes);
- rc = 0;
- }
- else if ((substituteChars &&
- (litDefPtr->DataType == QMY_VARCHAR ||
- litDefPtr->DataType == QMY_CHAR)) ||
- strcmp(field->charset()->name, "cp1251_bulgarian_ci") == 0)
- {
- // When iconv translates the max_sort_char with a substitute
- // character, we have no way to know whether this affects
- // the sort order of the key. Therefore, to be safe, when
- // we know that substitute characters have been used in a
- // single-byte string, we traverse the translated key
- // in reverse, replacing substitue characters with 0xFF, which
- // always sorts with the greatest weight in DB2 sort sequences.
- // cp1251_bulgarian_ci is also handled this way because the
- // max_sort_char is a control character which does not sort
- // equivalently in DB2.
- DBUG_ASSERT(inLen == outLen);
- char* tmpKey = keyData + inLen - 1;
- char* tmpDB2 = db2Data + outLen - 1;
- while (*tmpKey == field->charset()->max_sort_char &&
- *tmpDB2 != 0xFF)
- {
- *tmpDB2 = 0xFF;
- --tmpKey;
- --tmpDB2;
- }
- }
- }
-
- if (!rc &&
- (litDefPtr->DataType == QMY_VARGRAPHIC ||
- litDefPtr->DataType == QMY_VARCHAR))
- {
- *(uint16*)(db2Data-sizeof(uint16)) =
- outLen / (litDefPtr->DataType == QMY_VARGRAPHIC ? 2 : 1);
- }
- }
- else
- {
- rc = convertMySQLtoDB2(field,
- db2Field,
- literalPtr,
- (uchar*)maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0));
- }
- if (rc != 0) break;
- litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr);
- litDefPtr->Length = db2Field.getByteLengthInRecord();
- literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal
- }
- boundsPtr->HiBound.Position = literalCnt;
- if (max_key->flag == HA_READ_BEFORE_KEY && !overrideInclusion)
- boundsPtr->HiBound.Embodiment[0] = QMY_EXCLUSION;
- }
- maxPtr += curKey.key_part[partsInUse].store_length;
- }
- /*
- Bump to the next field in the key composite.
- */
-
- if ((partsInUse+1) < keyCnt)
- boundsPtr = boundsPtr + 1;
- }
-
- /*
- Call DB2 to estimate the number of rows in the key range.
- */
- if (rc == 0)
- {
- rc = db2i_ileBridge::getBridgeForThread()->recordsInRange((indexHandles[inx] ? indexHandles[inx] : db2Table->indexFile(inx)->getMasterDefnHandle()),
- spcPtr,
- keyCnt,
- literalCnt,
- boundsOff,
- litDefOff,
- literalsOff,
- cutoff,
- (uint32_t)(literalPtr - (char*)spcPtr),
- endByte,
- &recCnt,
- &rtnCode);
- }
- /*
- Set the row count and return.
- Beware that if this method returns a zero row count, MySQL assumes the
- result set for the query is zero; never return a zero row count.
- */
- if ((rc == 0) && (rtnCode == QMY_SUCCESS || rtnCode == QMY_EARLY_EXIT))
- {
- rows = recCnt ? (ha_rows)recCnt : 1;
- }
-
- rows = (rows > 0 ? rows : HA_POS_ERROR);
-
- setIndexReadEstimate(inx, rows);
-
- DBUG_PRINT("ha_ibmdb2i::recordsInRange",("Estimate %d rows for key %d", uint32(rows), inx));
-
- DBUG_RETURN(rows);
-}
diff --git a/storage/ibmdb2i/db2i_safeString.h b/storage/ibmdb2i/db2i_safeString.h
deleted file mode 100644
index e353316c8fc..00000000000
--- a/storage/ibmdb2i/db2i_safeString.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-
-#ifndef DB2I_SAFESTRING_H
-#define DB2I_SAFESTRING_H
-
-
-#include <my_global.h>
-#include <string.h>
-
-/**
- @class SafeString
-
- This class was designed to provide safe, but lightweight, concatenation
- operations C strings inside pre-allocated buffers.
-*/
-class SafeString
-{
-public:
- SafeString(char* buffer, size_t size) :
- allocSize(size), curPos(0), buf(buffer)
- {
- DBUG_ASSERT(size > 0);
- buf[allocSize - 1] = 0xFF; // Set an overflow indicator
- }
-
- char* ptr() { return buf; }
- operator char*() { return buf; }
-
- SafeString& strcat(const char* str)
- {
- return this->strncat(str, strlen(str));
- }
-
- SafeString& strcat(char one)
- {
- if (curPos < allocSize - 2)
- {
- buf[curPos++] = one;
- }
- buf[curPos] = 0;
-
- return *this;
- }
-
- SafeString& strncat(const char* str, size_t len)
- {
- uint64 amountToCopy = min((allocSize-1) - curPos, len);
- memcpy(buf + curPos, str, amountToCopy);
- curPos += amountToCopy;
- buf[curPos] = 0;
- return *this;
- }
-
- bool overflowed() const { return (buf[allocSize - 1] == 0);}
-
-private:
- char* buf;
- uint64 curPos;
- size_t allocSize;
-};
-
-
-#endif
diff --git a/storage/ibmdb2i/db2i_sqlStatementStream.cc b/storage/ibmdb2i/db2i_sqlStatementStream.cc
deleted file mode 100644
index 92a8b03fd00..00000000000
--- a/storage/ibmdb2i/db2i_sqlStatementStream.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#include "db2i_sqlStatementStream.h"
-#include "as400_types.h"
-
-/**
- Add a statement to the statement stream, allocating additional memory as needed.
-
- @parm stmt The statement text
- @parm length The length of the statement text
- @parm fileSortSequence The DB2 sort sequence identifier, in EBCDIC
- @parm fileSortSequenceLibrary The DB2 sort sequence library, in EBCDIC
-
- @return Reference to this object
-*/
-SqlStatementStream& SqlStatementStream::addStatementInternal(const char* stmt,
- uint32 length,
- const char* fileSortSequence,
- const char* fileSortSequenceLibrary)
-{
- uint32 storageNeeded = length + sizeof(StmtHdr_t);
- storageNeeded = (storageNeeded + 3) & ~3; // We have to be 4-byte aligned.
- if (storageNeeded > storageRemaining())
- {
- // We overallocate new storage to reduce number of times reallocation is
- // needed.
- int newSize = curSize + 2 * storageNeeded;
- DBUG_PRINT("SqlStatementStream::addStatementInternal",
- ("PERF: Had to realloc! Old size=%d. New size=%d", curSize, newSize));
- char* old_space = block;
- char* new_space = (char*)getNewSpace(newSize);
- memcpy(new_space, old_space, curSize);
- ptr = new_space + (ptr - old_space);
- curSize = newSize;
- }
-
- DBUG_ASSERT((address64_t)ptr % 4 == 0);
-
- memcpy(((StmtHdr_t*)ptr)->SrtSeqNam,
- fileSortSequence,
- sizeof(((StmtHdr_t*)ptr)->SrtSeqNam));
- memcpy(((StmtHdr_t*)ptr)->SrtSeqSch,
- fileSortSequenceLibrary,
- sizeof(((StmtHdr_t*)ptr)->SrtSeqSch));
- ((StmtHdr_t*)ptr)->Length = length;
- memcpy(ptr + sizeof(StmtHdr_t), stmt, length);
-
- ptr += storageNeeded;
- ++statements;
-
- return *this;
-}
diff --git a/storage/ibmdb2i/db2i_sqlStatementStream.h b/storage/ibmdb2i/db2i_sqlStatementStream.h
deleted file mode 100644
index 11db41a6c5d..00000000000
--- a/storage/ibmdb2i/db2i_sqlStatementStream.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-#ifndef DB2I_SQLSTATEMENTSTREAM_H
-#define DB2I_SQLSTATEMENTSTREAM_H
-
-#include "db2i_charsetSupport.h"
-#include "qmyse.h"
-
-/**
- @class SqlStatementStream
-
- This class handles building the stream of SQL statements expected by the
- QMY_EXECUTE_IMMEDIATE and QMY_PREPARE_OPEN_CURSOR APIs.
- Memory allocation is handled internally.
-*/
-class SqlStatementStream
-{
- public:
- /**
- ctor to be used when multiple strings may be appended.
- */
- SqlStatementStream(uint32 firstStringSize) : statements(0)
- {
- curSize = firstStringSize + sizeof(StmtHdr_t);
- curSize = (curSize + 3) & ~3;
- ptr = (char*) getNewSpace(curSize);
- if (ptr == NULL)
- curSize = 0;
- }
-
- /**
- ctor to be used when only a single statement will be executed.
- */
- SqlStatementStream(const String& statement) : statements(0), block(NULL), curSize(0), ptr(0)
- {
- addStatement(statement);
- }
-
- /**
- ctor to be used when only a single statement will be executed.
- */
- SqlStatementStream(const char* statement) : statements(0), block(NULL), curSize(0), ptr(0)
- {
- addStatement(statement);
- }
-
- /**
- Append an SQL statement, specifiying the DB2 sort sequence under which
- the statement should be executed. This is important for CREATE TABLE
- and CREATE INDEX statements.
- */
- SqlStatementStream& addStatement(const String& append, const char* fileSortSequence, const char* fileSortSequenceLibrary)
- {
- char sortSeqEbcdic[10];
- char sortSeqLibEbcdic[10];
-
- DBUG_ASSERT(strlen(fileSortSequence) <= 10 &&
- strlen(fileSortSequenceLibrary) <= 10);
- memset(sortSeqEbcdic, 0x40, 10);
- memset(sortSeqLibEbcdic, 0x40, 10);
- convToEbcdic(fileSortSequence, sortSeqEbcdic, strlen(fileSortSequence));
- convToEbcdic(fileSortSequenceLibrary, sortSeqLibEbcdic, strlen(fileSortSequenceLibrary));
-
- return addStatementInternal(append.ptr(), append.length(), sortSeqEbcdic, sortSeqLibEbcdic);
- }
-
- /**
- Append an SQL statement using default (*HEX) sort sequence.
- */
- SqlStatementStream& addStatement(const String& append)
- {
- const char splatHEX[] = {0x5C, 0xC8, 0xC5, 0xE7, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // *HEX
- const char blanks[] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; //
-
- return addStatementInternal(append.ptr(), append.length(), splatHEX, blanks);
- }
-
- /**
- Append an SQL statement using default (*HEX) sort sequence.
- */
- SqlStatementStream& addStatement(const char* stmt)
- {
- const char splatHEX[] = {0x5C, 0xC8, 0xC5, 0xE7, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // *HEX
- const char blanks[] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; //
-
- return addStatementInternal(stmt, strlen(stmt), splatHEX, blanks);
- }
-
- char* getPtrToData() const { return block; }
- uint32 getStatementCount() const { return statements; }
- private:
- SqlStatementStream& addStatementInternal(const char* stmt,
- uint32 length,
- const char* fileSortSequence,
- const char* fileSortSequenceLibrary);
-
- uint32 storageRemaining() const
- {
- return (block == NULL ? 0 : curSize - (ptr - block));
- }
-
- char* getNewSpace(size_t size)
- {
- allocBase = (char*)sql_alloc(size + 15);
- block = (char*)roundToQuadWordBdy(allocBase);
- return block;
- }
-
- uint32 curSize; // The size of the usable memory.
- char* allocBase; // The allocated memory (with padding for aligment)
- char* block; // The usable memory chunck (aligned for ILE)
- char* ptr; // The current position within block.
- uint32 statements; // The number of statements that have been appended.
-};
-
-#endif
-
diff --git a/storage/ibmdb2i/db2i_validatedPointer.h b/storage/ibmdb2i/db2i_validatedPointer.h
deleted file mode 100644
index c4e31d1f11b..00000000000
--- a/storage/ibmdb2i/db2i_validatedPointer.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-#ifndef DB2I_VALIDATEDPOINTER_H
-#define DB2I_VALIDATEDPOINTER_H
-
-#include "db2i_ileBridge.h"
-
-/**
- @class ValidatedPointer
- @brief Encapsulates a pointer registered for usage by the QMYSE APIs
-
- @details As a performance optimization, to prevent pointer validation each
- time a particular pointer is thunked across to ILE, QMYSE allows us to
- "register" a pointer such that it is validated once and then subsequently
- referenced on QMYSE APIs by means of a handle value. This class should be
- used to manage memory allocation/registration/unregistration of these
- pointers. Using the alloc function guarantees that the resulting storage is
- 16-byte aligned, a requirement for many pointers passed to QMYSE.
-*/
-template <class T>
-class ValidatedPointer
-{
-public:
- ValidatedPointer<T>() : address(NULL), handle(NULL) {;}
-
- ValidatedPointer<T>(size_t size)
- {
- alloc(size);
- }
-
- ValidatedPointer<T>(T* ptr)
- {
- assign(ptr);
- }
-
- operator T*()
- {
- return address;
- };
-
- operator T*() const
- {
- return address;
- };
-
- operator void*()
- {
- return address;
- };
-
- operator ILEMemHandle()
- {
- return handle;
- }
-
- void alloc(size_t size)
- {
- address = (T*)malloc_aligned(size);
- if (address)
- db2i_ileBridge::registerPtr(address, &handle);
- mallocedHere = 1;
- }
-
- void assign(T* ptr)
- {
- address = ptr;
- db2i_ileBridge::registerPtr((void*)ptr, &handle);
- mallocedHere = 0;
- }
-
- void realloc(size_t size)
- {
- dealloc();
- alloc(size);
- }
-
- void reassign(T* ptr)
- {
- dealloc();
- assign(ptr);
- }
-
- void dealloc()
- {
- if (address)
- {
- db2i_ileBridge::unregisterPtr(handle);
-
- if (mallocedHere)
- free_aligned((void*)address);
- }
- address = NULL;
- handle = 0;
- }
-
- ~ValidatedPointer()
- {
- dealloc();
- }
-
-private:
- // Disable copy ctor and assignment operator, as these would break
- // the registration guarantees provided by the class.
- ValidatedPointer& operator= (const ValidatedPointer newVal);
- ValidatedPointer(ValidatedPointer& newCopy);
-
- ILEMemHandle handle;
- T* address;
- char mallocedHere;
-};
-
-
-/**
- @class ValidatedObject
- @brief This class allows users to instantiate and register a particular
- object in a single step.
-*/
-template<class T>
-class ValidatedObject : public ValidatedPointer<T>
-{
- public:
- ValidatedObject<T>() : ValidatedPointer<T>(&value) {;}
-
- T& operator= (const T newVal) { value = newVal; return value; }
-
- private:
- T value;
-};
-#endif
diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc
deleted file mode 100644
index f6f1e2bc568..00000000000
--- a/storage/ibmdb2i/ha_ibmdb2i.cc
+++ /dev/null
@@ -1,3374 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-
-/**
- @file ha_ibmdb2i.cc
-
- @brief
- The ha_ibmdb2i storage engine provides an interface from MySQL to IBM DB2 for i.
-
-*/
-
-#ifdef USE_PRAGMA_IMPLEMENTATION
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include "ha_ibmdb2i.h"
-#include "mysql_priv.h"
-#include <mysql/plugin.h>
-#include "db2i_ileBridge.h"
-#include "db2i_charsetSupport.h"
-#include <sys/utsname.h>
-#include "db2i_safeString.h"
-
-static const char __NOT_NULL_VALUE_EBCDIC = 0xF0; // '0'
-static const char __NULL_VALUE_EBCDIC = 0xF1; // '1'
-static const char __DEFAULT_VALUE_EBCDIC = 0xC4; // 'D'
-static const char BlankASPName[19] = " ";
-static const int DEFAULT_MAX_ROWS_TO_BUFFER = 4096;
-
-static const char SAVEPOINT_PREFIX[] = {0xD4, 0xE8, 0xE2, 0xD7}; // MYSP (in EBCDIC)
-
-OSVersion osVersion;
-
-
-// ================================================================
-// ================================================================
-// System variables
-static char* ibmdb2i_rdb_name;
-static MYSQL_SYSVAR_STR(rdb_name, ibmdb2i_rdb_name,
- PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY,
- "The name of the RDB to use",
- NULL,
- NULL,
- BlankASPName);
-
-static MYSQL_THDVAR_BOOL(transaction_unsafe,
- 0,
- "Disable support for commitment control",
- NULL,
- NULL,
- FALSE);
-
-static MYSQL_THDVAR_UINT(lob_alloc_size,
- 0,
- "Baseline allocation for lob read buffer",
- NULL,
- NULL,
- 2*1024*1024,
- 64*1024,
- 128*1024*1024,
- 1);
-
-static MYSQL_THDVAR_UINT(max_read_buffer_size,
- 0,
- "Maximum size of buffers used for read-ahead.",
- NULL,
- NULL,
- 1*1024*1024,
- 32*1024,
- 16*1024*1024,
- 1);
-
-static MYSQL_THDVAR_UINT(max_write_buffer_size,
- 0,
- "Maximum size of buffers used for bulk writes.",
- NULL,
- NULL,
- 8*1024*1024,
- 32*1024,
- 64*1024*1024,
- 1);
-
-static MYSQL_THDVAR_BOOL(compat_opt_time_as_duration,
- 0,
- "Control how new TIME columns should be defined in DB2. 0=time-of-day (default), 1=duration.",
- NULL,
- NULL,
- FALSE);
-
-static MYSQL_THDVAR_UINT(compat_opt_year_as_int,
- 0,
- "Control how new YEAR columns should be defined in DB2. 0=CHAR(4) (default), 1=SMALLINT.",
- NULL,
- NULL,
- 0,
- 0,
- 1,
- 1);
-
-static MYSQL_THDVAR_UINT(compat_opt_blob_cols,
- 0,
- "Control how new TEXT and BLOB columns should be defined in DB2. 0=CLOB/BLOB (default), 1=VARCHAR/VARBINARY",
- NULL,
- NULL,
- 0,
- 0,
- 1,
- 1);
-
-static MYSQL_THDVAR_UINT(compat_opt_allow_zero_date_vals,
- 0,
- "Allow substitute values to be used when storing a column with a 0000-00-00 date component. 0=No substitution (default), 1=Substitute '0001-01-01'",
- NULL,
- NULL,
- 0,
- 0,
- 1,
- 1);
-
-static MYSQL_THDVAR_BOOL(propagate_default_col_vals,
- 0,
- "Should DEFAULT column values be propagated to the DB2 table definition.",
- NULL,
- NULL,
- TRUE);
-
-static my_bool ibmdb2i_assume_exclusive_use;
-static MYSQL_SYSVAR_BOOL(assume_exclusive_use, ibmdb2i_assume_exclusive_use,
- 0,
- "Can MySQL assume that this process is the only one modifying the DB2 tables. ",
- NULL,
- NULL,
- FALSE);
-
-static MYSQL_THDVAR_BOOL(async_enabled,
- 0,
- "Should reads be done asynchronously when possible",
- NULL,
- NULL,
- TRUE);
-
-static MYSQL_THDVAR_UINT(create_index_option,
- 0,
- "Control whether additional indexes are created. 0=No (default), 1=Create additional *HEX-based index",
- NULL,
- NULL,
- 0,
- 0,
- 1,
- 1);
-
-/* static MYSQL_THDVAR_UINT(discovery_mode,
- 0,
- "Unsupported",
- NULL,
- NULL,
- 0,
- 0,
- 1,
- 1); */
-
-static uint32 ibmdb2i_system_trace;
-static MYSQL_SYSVAR_UINT(system_trace_level, ibmdb2i_system_trace,
- 0,
- "Set system tracing level",
- NULL,
- NULL,
- 0,
- 0,
- 63,
- 1);
-
-
-inline uint8 ha_ibmdb2i::getCommitLevel(THD* thd)
-{
- if (!THDVAR(thd, transaction_unsafe))
- {
- switch (thd_tx_isolation(thd))
- {
- case ISO_READ_UNCOMMITTED:
- return (accessIntent == QMY_READ_ONLY ? QMY_READ_UNCOMMITTED : QMY_REPEATABLE_READ);
- case ISO_READ_COMMITTED:
- return (accessIntent == QMY_READ_ONLY ? QMY_READ_COMMITTED : QMY_REPEATABLE_READ);
- case ISO_REPEATABLE_READ:
- return QMY_REPEATABLE_READ;
- case ISO_SERIALIZABLE:
- return QMY_SERIALIZABLE;
- }
- }
-
- return QMY_NONE;
-}
-
-inline uint8 ha_ibmdb2i::getCommitLevel()
-{
- return getCommitLevel(ha_thd());
-}
-
-//=====================================================================
-
-static handler *ibmdb2i_create_handler(handlerton *hton,
- TABLE_SHARE *table,
- MEM_ROOT *mem_root);
-static void ibmdb2i_drop_database(handlerton *hton, char* path);
-static int ibmdb2i_savepoint_set(handlerton *hton, THD* thd, void *sv);
-static int ibmdb2i_savepoint_rollback(handlerton *hton, THD* thd, void *sv);
-static int ibmdb2i_savepoint_release(handlerton *hton, THD* thd, void *sv);
-static uint ibmdb2i_alter_table_flags(uint flags);
-
-handlerton *ibmdb2i_hton;
-static bool was_ILE_inited;
-
-/* Tracks the number of open tables */
-static HASH ibmdb2i_open_tables;
-
-/* Mutex used to synchronize initialization of the hash */
-static pthread_mutex_t ibmdb2i_mutex;
-
-
-/**
- Create hash key for tracking open tables.
-*/
-
-static uchar* ibmdb2i_get_key(IBMDB2I_SHARE *share,size_t *length,
- bool not_used __attribute__((unused)))
-{
- *length=share->table_name_length;
- return (uchar*) share->table_name;
-}
-
-
-int ibmdb2i_close_connection(handlerton* hton, THD *thd)
-{
- DBUG_PRINT("ha_ibmdb2i::close_connection", ("Closing %d", thd->thread_id));
- db2i_ileBridge::getBridgeForThread(thd)->closeConnection(thd->thread_id);
- db2i_ileBridge::destroyBridgeForThread(thd);
-
- return 0;
-}
-
-
-static int ibmdb2i_init_func(void *p)
-{
- DBUG_ENTER("ibmdb2i_init_func");
-
- utsname tempName;
- uname(&tempName);
- osVersion.v = atoi(tempName.version);
- osVersion.r = atoi(tempName.release);
-
- was_ILE_inited = false;
- ibmdb2i_hton= (handlerton *)p;
- VOID(pthread_mutex_init(&ibmdb2i_mutex,MY_MUTEX_INIT_FAST));
- (void) my_hash_init(&ibmdb2i_open_tables,table_alias_charset,32,0,0,
- (my_hash_get_key) ibmdb2i_get_key,0,0);
-
- ibmdb2i_hton->state= SHOW_OPTION_YES;
- ibmdb2i_hton->create= ibmdb2i_create_handler;
- ibmdb2i_hton->drop_database= ibmdb2i_drop_database;
- ibmdb2i_hton->commit= ha_ibmdb2i::doCommit;
- ibmdb2i_hton->rollback= ha_ibmdb2i::doRollback;
- ibmdb2i_hton->savepoint_offset= 0;
- ibmdb2i_hton->savepoint_set= ibmdb2i_savepoint_set;
- ibmdb2i_hton->savepoint_rollback= ibmdb2i_savepoint_rollback;
- ibmdb2i_hton->savepoint_release= ibmdb2i_savepoint_release;
- ibmdb2i_hton->alter_table_flags=ibmdb2i_alter_table_flags;
- ibmdb2i_hton->close_connection=ibmdb2i_close_connection;
-
- int rc;
-
- rc = initCharsetSupport();
-
- if (!rc)
- rc = db2i_ileBridge::setup();
-
- if (!rc)
- {
- int nameLen = strlen(ibmdb2i_rdb_name);
- for (int i = 0; i < nameLen; ++i)
- {
- ibmdb2i_rdb_name[i] = my_toupper(system_charset_info, (uchar)ibmdb2i_rdb_name[i]);
- }
-
- rc = db2i_ileBridge::initILE(ibmdb2i_rdb_name, (uint16*)(((char*)&ibmdb2i_system_trace)+2));
- if (rc == 0)
- {
- was_ILE_inited = true;
- }
- }
-
- DBUG_RETURN(rc);
-}
-
-
-static int ibmdb2i_done_func(void *p)
-{
- int error= 0;
- DBUG_ENTER("ibmdb2i_done_func");
-
- if (ibmdb2i_open_tables.records)
- error= 1;
-
- if (was_ILE_inited)
- db2i_ileBridge::exitILE();
-
- db2i_ileBridge::takedown();
-
- doneCharsetSupport();
-
- my_hash_free(&ibmdb2i_open_tables);
- pthread_mutex_destroy(&ibmdb2i_mutex);
-
- DBUG_RETURN(0);
-}
-
-
-IBMDB2I_SHARE *ha_ibmdb2i::get_share(const char *table_name, TABLE *table)
-{
- IBMDB2I_SHARE *share;
- uint length;
- char *tmp_name;
-
- pthread_mutex_lock(&ibmdb2i_mutex);
- length=(uint) strlen(table_name);
-
- if (!(share=(IBMDB2I_SHARE*) my_hash_search(&ibmdb2i_open_tables,
- (uchar*)table_name,
- length)))
- {
- if (!(share=(IBMDB2I_SHARE *)
- my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &share, sizeof(*share),
- &tmp_name, length+1,
- NullS)))
- {
- pthread_mutex_unlock(&ibmdb2i_mutex);
- return NULL;
- }
-
- share->use_count=0;
- share->table_name_length=length;
- share->table_name=tmp_name;
- strmov(share->table_name,table_name);
- if (my_hash_insert(&ibmdb2i_open_tables, (uchar*) share))
- goto error;
- thr_lock_init(&share->lock);
- pthread_mutexattr_t mutexattr = MY_MUTEX_INIT_FAST;
- pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&share->mutex, &mutexattr);
-
- share->db2Table = new db2i_table(table->s, table_name);
- int32 rc = share->db2Table->initDB2Objects(table_name);
-
- if (rc)
- {
- delete share->db2Table;
- my_hash_delete(&ibmdb2i_open_tables, (uchar*) share);
- thr_lock_delete(&share->lock);
- my_errno = rc;
- goto error;
- }
-
- memset(&share->cachedStats, 0, sizeof(share->cachedStats));
- }
- share->use_count++;
- pthread_mutex_unlock(&ibmdb2i_mutex);
-
- db2Table = share->db2Table;
-
- return share;
-
-error:
- pthread_mutex_destroy(&share->mutex);
- my_free(share);
- pthread_mutex_unlock(&ibmdb2i_mutex);
-
- return NULL;
-}
-
-
-
-int ha_ibmdb2i::free_share(IBMDB2I_SHARE *share)
-{
- pthread_mutex_lock(&ibmdb2i_mutex);
- if (!--share->use_count)
- {
- delete share->db2Table;
- db2Table = NULL;
-
- my_hash_delete(&ibmdb2i_open_tables, (uchar*) share);
- thr_lock_delete(&share->lock);
- pthread_mutex_destroy(&share->mutex);
- my_free(share);
- pthread_mutex_unlock(&ibmdb2i_mutex);
- return 1;
- }
- pthread_mutex_unlock(&ibmdb2i_mutex);
-
- return 0;
-}
-
-static handler* ibmdb2i_create_handler(handlerton *hton,
- TABLE_SHARE *table,
- MEM_ROOT *mem_root)
-{
- return new (mem_root) ha_ibmdb2i(hton, table);
-}
-
-static void ibmdb2i_drop_database(handlerton *hton, char* path)
-{
- DBUG_ENTER("ha_ibmdb2i::ibmdb2i_drop_database");
- int rc = 0;
- char queryBuffer[200];
- String query(queryBuffer, sizeof(queryBuffer), system_charset_info);
- query.length(0);
- query.append(STRING_WITH_LEN(" DROP SCHEMA \""));
- query.append(path+2, strchr(path+2, '/')-(path+2));
- query.append('"');
-
- SqlStatementStream sqlStream(query);
-
- rc = db2i_ileBridge::getBridgeForThread()->execSQL(sqlStream.getPtrToData(),
- sqlStream.getStatementCount(),
- QMY_NONE,
- FALSE,
- TRUE);
- DBUG_VOID_RETURN;
-}
-
-inline static void genSavepointName(const void* sv, char* out)
-{
- *(uint32*)out = *(uint32*)SAVEPOINT_PREFIX;
- DBUG_ASSERT(sizeof(SAVEPOINT_PREFIX) == 4);
- out += sizeof(SAVEPOINT_PREFIX);
-
- longlong2str((longlong)sv, out, 10);
- while (*out)
- {
- out += 0xF0;
- ++out;
- }
-}
-
-
-/*********************************************************************
-Sets a transaction savepoint. */
-static int ibmdb2i_savepoint_set(handlerton* hton, THD* thd, void* sv)
-{
- DBUG_ENTER("ibmdb2i_savepoint_set");
- int rc = 0;
- if (!THDVAR(thd ,transaction_unsafe))
- {
- char name[64];
- genSavepointName(sv, name);
- DBUG_PRINT("ibmdb2i_savepoint_set",("Setting %s", name));
- rc = ha_ibmdb2i::doSavepointSet(thd, name);
- }
- DBUG_RETURN(rc);
-}
-
-
-/*********************************************************************
-Rollback a savepoint. */
-static int ibmdb2i_savepoint_rollback(handlerton* hton, THD* thd, void* sv)
-{
- DBUG_ENTER("ibmdb2i_savepoint_rollback");
- int rc = 0;
- if (!THDVAR(thd,transaction_unsafe))
- {
- char name[64];
- genSavepointName(sv, name);
- DBUG_PRINT("ibmdb2i_savepoint_rollback",("Rolling back %s", name));
- rc = ha_ibmdb2i::doSavepointRollback(thd, name);
- }
- DBUG_RETURN(rc);
-}
-
-
-/*********************************************************************
-Release a savepoint. */
-static int ibmdb2i_savepoint_release(handlerton* hton, THD* thd, void* sv)
-{
- DBUG_ENTER("ibmdb2i_savepoint_release");
- int rc = 0;
- if (!THDVAR(thd,transaction_unsafe))
- {
- char name[64];
- genSavepointName(sv, name);
- DBUG_PRINT("ibmdb2i_savepoint_release",("Releasing %s", name));
- rc = ha_ibmdb2i::doSavepointRelease(thd, name);
- }
- DBUG_RETURN(rc);
-}
-
-/* Thse flags allow for the online add and drop of an index via the CREATE INDEX,
- DROP INDEX, and ALTER TABLE statements. These flags indicate that MySQL is not
- required to lock the table before calling the storage engine to add or drop the
- index(s). */
-static uint ibmdb2i_alter_table_flags(uint flags)
-{
- return (HA_ONLINE_ADD_INDEX | HA_ONLINE_DROP_INDEX |
- HA_ONLINE_ADD_UNIQUE_INDEX | HA_ONLINE_DROP_UNIQUE_INDEX |
- HA_ONLINE_ADD_PK_INDEX | HA_ONLINE_DROP_PK_INDEX);
-}
-
-ha_ibmdb2i::ha_ibmdb2i(handlerton *hton, TABLE_SHARE *table_arg)
- :share(NULL), handler(hton, table_arg),
- activeHandle(0), dataHandle(0),
- activeReadBuf(NULL), activeWriteBuf(NULL),
- blobReadBuffers(NULL), accessIntent(QMY_UPDATABLE), currentRRN(0),
- releaseRowNeeded(FALSE),
- indexReadSizeEstimates(NULL),
- outstanding_start_bulk_insert(false),
- last_rnd_init_rc(0),
- last_index_init_rc(0),
- last_start_bulk_insert_rc(0),
- autoIncLockAcquired(false),
- got_auto_inc_values(false),
- next_identity_value(0),
- indexHandles(0),
- returnDupKeysImmediately(false),
- onDupUpdate(false),
- blobWriteBuffers(NULL),
- forceSingleRowRead(false)
- {
- activeReferences = 0;
- ref_length = sizeof(currentRRN);
- if (table_share && table_share->keys > 0)
- {
- indexHandles = (FILE_HANDLE*)my_malloc(table_share->keys * sizeof(FILE_HANDLE), MYF(MY_WME | MY_ZEROFILL));
- }
- clear_alloc_root(&conversionBufferMemroot);
- }
-
-
-ha_ibmdb2i::~ha_ibmdb2i()
-{
- DBUG_ASSERT(activeReferences == 0 || outstanding_start_bulk_insert);
-
- if (indexHandles)
- my_free(indexHandles);
- if (indexReadSizeEstimates)
- my_free(indexReadSizeEstimates);
-
- cleanupBuffers();
-}
-
-
-static const char *ha_ibmdb2i_exts[] = {
- FID_EXT,
- NullS
-};
-
-const char **ha_ibmdb2i::bas_ext() const
-{
- return ha_ibmdb2i_exts;
-}
-
-
-int ha_ibmdb2i::open(const char *name, int mode, uint test_if_locked)
-{
- DBUG_ENTER("ha_ibmdb2i::open");
-
- initBridge();
-
- dataHandle = bridge()->findAndRemovePreservedHandle(name, &share);
-
- if (share)
- db2Table = share->db2Table;
-
- if (!share && (!(share = get_share(name, table))))
- DBUG_RETURN(my_errno);
- thr_lock_data_init(&share->lock,&lock,NULL);
-
- info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
-
-
- DBUG_RETURN(0);
-}
-
-
-
-
-int ha_ibmdb2i::close(void)
-{
- DBUG_ENTER("ha_ibmdb2i::close");
- int32 rc = 0;
- bool preserveShare = false;
-
- db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread();
-
- if (dataHandle)
- {
- if (bridge->expectErrors(QMY_ERR_PEND_LOCKS)->deallocateFile(dataHandle, FALSE) == QMY_ERR_PEND_LOCKS)
- {
- bridge->preserveHandle(share->table_name, dataHandle, share);
- preserveShare = true;
- }
- dataHandle = 0;
- }
-
- for (int idx = 0; idx < table_share->keys; ++idx)
- {
- if (indexHandles[idx] != 0)
- {
- bridge->deallocateFile(indexHandles[idx], FALSE);
- }
- }
-
- cleanupBuffers();
-
- if (!preserveShare)
- {
- if (free_share(share))
- share = NULL;
- }
-
- DBUG_RETURN(rc);
-}
-
-
-
-int ha_ibmdb2i::write_row(uchar * buf)
-{
-
- DBUG_ENTER("ha_ibmdb2i::write_row");
-
- if (last_start_bulk_insert_rc)
- DBUG_RETURN( last_start_bulk_insert_rc );
-
- ha_statistic_increment(&SSV::ha_write_count);
- int rc = 0;
-
- bool fileHandleNeedsRelease = false;
-
- if (!activeHandle)
- {
- rc = useDataFile();
- if (rc) DBUG_RETURN(rc);
- fileHandleNeedsRelease = true;
- }
-
- if (!outstanding_start_bulk_insert)
- rc = prepWriteBuffer(1, getFileForActiveHandle());
-
- if (!rc)
- {
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
-
- char* writeBuffer = activeWriteBuf->addRow();
- rc = prepareRowForWrite(writeBuffer,
- writeBuffer+activeWriteBuf->getRowNullOffset(),
- true);
- if (rc == 0)
- {
- // If we are doing block inserts, if the MI is supposed to generate an auto_increment
- // (i.e. identity column) value for this record, and if this is not the first record in
- // the block, then store the value (that the MI will generate for the identity column)
- // into the MySQL write buffer. We can predetermine the value because the file is locked.
-
- if ((autoIncLockAcquired) && (default_identity_value) && (got_auto_inc_values))
- {
- if (unlikely((next_identity_value - 1) ==
- maxValueForField(table->next_number_field)))
- {
- rc = QMY_ERR_MAXVALUE;
- }
- else
- {
- rc = table->next_number_field->store((longlong) next_identity_value, TRUE);
- next_identity_value = next_identity_value + incrementByValue;
- }
- }
- // If the buffer is full, or if we locked the file and this is the first or last row
- // of a blocked insert, then flush the buffer.
- if (!rc && (activeWriteBuf->endOfBuffer()) ||
- ((autoIncLockAcquired) &&
- ((!got_auto_inc_values))) ||
- (returnDupKeysImmediately))
- rc = flushWrite(activeHandle, buf);
- }
- else
- activeWriteBuf->deleteRow();
- }
-
- if (fileHandleNeedsRelease)
- releaseActiveHandle();
-
- DBUG_RETURN(rc);
-}
-
-/**
- @brief
- Helper function used by write_row and update_row to prepare the MySQL
- row for insertion into DB2.
-*/
-int ha_ibmdb2i::prepareRowForWrite(char* data, char* nulls, bool honorIdentCols)
-{
- int rc = 0;
-
- // set null map all to non nulls
- memset(nulls,__NOT_NULL_VALUE_EBCDIC, table->s->fields);
- default_identity_value = FALSE;
-
- ulong sql_mode = ha_thd()->variables.sql_mode;
-
- my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
- for (Field **field = table->field; *field && !rc; ++field)
- {
- int fieldIndex = (*field)->field_index;
- if ((*field)->Field::is_null())
- {
- nulls[fieldIndex] = __NULL_VALUE_EBCDIC;
- }
- if (honorIdentCols && ((*field)->flags & AUTO_INCREMENT_FLAG) &&
- *field == table->next_number_field)
-// && ((!autoIncLockAcquired) || (!got_auto_inc_values)))
- {
- if (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)
- {
- if (!table->auto_increment_field_not_null)
- {
- nulls[fieldIndex] = __DEFAULT_VALUE_EBCDIC;
- default_identity_value = TRUE;
- }
- }
- else if ((*field)->val_int() == 0)
- {
- nulls[fieldIndex] = __DEFAULT_VALUE_EBCDIC;
- default_identity_value = TRUE;
- }
- }
-
- DB2Field& db2Field = db2Table->db2Field(fieldIndex);
- if (nulls[fieldIndex] == __NOT_NULL_VALUE_EBCDIC ||
- db2Field.isBlob())
- {
- rc = convertMySQLtoDB2(*field, db2Field, data + db2Field.getBufferOffset());
- }
- }
-
- if (!rc && db2Table->hasBlobs())
- rc = db2i_ileBridge::getBridgeForThread()->objectOverride(activeHandle,
- activeWriteBuf->ptr());
-
- dbug_tmp_restore_column_map(table->read_set, old_map);
-
- return rc;
-}
-
-
-
-int ha_ibmdb2i::update_row(const uchar * old_data, uchar * new_data)
-{
- DBUG_ENTER("ha_ibmdb2i::update_row");
- ha_statistic_increment(&SSV::ha_update_count);
- int rc;
-
- bool fileHandleNeedsRelease = false;
-
- if (!activeHandle)
- {
- rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle);
- if (rc) DBUG_RETURN(rc);
- fileHandleNeedsRelease = true;
- }
-
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
-
- char* writeBuf = activeWriteBuf->addRow();
- rc = prepareRowForWrite(writeBuf,
- writeBuf+activeWriteBuf->getRowNullOffset(),
- onDupUpdate);
-
- char* lastDupKeyNamePtr = NULL;
- uint32 lastDupKeyNameLen = 0;
-
- if (!rc)
- {
- rc = db2i_ileBridge::getBridgeForThread()->updateRow(activeHandle,
- currentRRN,
- activeWriteBuf->ptr(),
- &lastDupKeyRRN,
- &lastDupKeyNamePtr,
- &lastDupKeyNameLen);
- }
-
- if (lastDupKeyNameLen)
- {
- lastDupKeyID = getKeyFromName(lastDupKeyNamePtr, lastDupKeyNameLen);
- rrnAssocHandle = activeHandle;
- }
-
- if (fileHandleNeedsRelease)
- releaseActiveHandle();
-
- activeWriteBuf->resetAfterWrite();
-
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::delete_row(const uchar * buf)
-{
- DBUG_ENTER("ha_ibmdb2i::delete_row");
- ha_statistic_increment(&SSV::ha_delete_count);
-
- bool needReleaseFile = false;
- int rc = 0;
-
- if (!activeHandle) // In some circumstances, MySQL comes here after
- { // closing the active handle. We need to re-open.
- rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle);
- needReleaseFile = true;
- }
-
- if (likely(!rc))
- {
- rc = db2i_ileBridge::getBridgeForThread()->deleteRow(activeHandle,
- currentRRN);
- invalidateCachedStats();
- if (needReleaseFile)
- releaseActiveHandle();
- }
-
- DBUG_RETURN(rc);
-}
-
-
-
-int ha_ibmdb2i::index_init(uint idx, bool sorted)
-{
- DBUG_ENTER("ha_ibmdb2i::index_init");
-
- int& rc = last_index_init_rc;
- rc = 0;
-
- invalidDataFound=false;
- tweakReadSet();
-
- active_index=idx;
-
- rc = useIndexFile(idx);
-
- if (!rc)
- {
-// THD* thd = ha_thd();
-// if (accessIntent == QMY_UPDATABLE &&
-// thd_tx_isolation(thd) == ISO_REPEATABLE_READ &&
-// !THDVAR(thd, transaction_unsafe))
-// {
-// readAccessIntent = QMY_READ_ONLY;
-// }
-// else
-// {
- readAccessIntent = accessIntent;
-// }
-
- if (!rc && accessIntent != QMY_READ_ONLY)
- rc = prepWriteBuffer(1, db2Table->indexFile(idx));
-
- if (rc)
- releaseIndexFile(idx);
- }
-
- rrnAssocHandle= 0;
-
- DBUG_RETURN(rc);
-}
-
-
-
-int ha_ibmdb2i::index_read(uchar * buf, const uchar * key,
- uint key_len,
- enum ha_rkey_function find_flag)
-{
- DBUG_ENTER("ha_ibmdb2i::index_read");
-
- if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc);
-
- int rc;
-
- ha_rows estimatedRows = getIndexReadEstimate(active_index);
- rc = prepReadBuffer(estimatedRows, db2Table->indexFile(active_index), readAccessIntent);
- if (unlikely(rc)) DBUG_RETURN(rc);
-
- DBUG_ASSERT(activeReadBuf);
-
- keyBuf.allocBuf(activeReadBuf->getRowLength(),
- activeReadBuf->getRowNullOffset(),
- activeReadBuf->getRowLength());
- keyBuf.zeroBuf();
-
- char* db2KeyBufPtr = keyBuf.ptr();
- char* nullKeyMap = db2KeyBufPtr + activeReadBuf->getRowNullOffset();
-
- const uchar* keyBegin = key;
- int partsInUse;
-
- KEY& curKey = table->key_info[active_index];
-
- for (partsInUse = 0; partsInUse < curKey.key_parts, key - keyBegin < key_len; ++partsInUse)
- {
- Field* field = curKey.key_part[partsInUse].field;
- if ((curKey.key_part[partsInUse].null_bit) &&
- (char*)key[0])
- {
- if (field->flags & AUTO_INCREMENT_FLAG)
- {
- table->status = STATUS_NOT_FOUND;
- DBUG_RETURN(HA_ERR_END_OF_FILE);
- }
- else
- {
- nullKeyMap[partsInUse] = __NULL_VALUE_EBCDIC;
- }
- }
- else
- {
- nullKeyMap[partsInUse] = __NOT_NULL_VALUE_EBCDIC;
- convertMySQLtoDB2(field,
- db2Table->db2Field(field->field_index),
- db2KeyBufPtr,
- (uchar*)key+((curKey.key_part[partsInUse].null_bit)? 1 : 0) ); // + (curKey.key_parts+7) / 8);
- }
-
- db2KeyBufPtr += db2Table->db2Field(field->field_index).getByteLengthInRecord();
- key += curKey.key_part[partsInUse].store_length;
- }
-
- keyLen = db2KeyBufPtr - (char*)keyBuf.ptr();
-
- DBUG_PRINT("ha_ibmdb2i::index_read", ("find_flag: %d", find_flag));
-
- char readDirection = QMY_NEXT;
-
- switch (find_flag)
- {
- case HA_READ_AFTER_KEY:
- doInitialRead(QMY_AFTER_EQUAL, estimatedRows,
- keyBuf.ptr(), keyLen, partsInUse);
- break;
- case HA_READ_BEFORE_KEY:
- doInitialRead(QMY_BEFORE_EQUAL, estimatedRows,
- keyBuf.ptr(), keyLen, partsInUse);
- break;
- case HA_READ_KEY_OR_NEXT:
- doInitialRead(QMY_AFTER_OR_EQUAL, estimatedRows,
- keyBuf.ptr(), keyLen, partsInUse);
- break;
- case HA_READ_KEY_OR_PREV:
- DBUG_ASSERT(0); // This function is unused
- doInitialRead(QMY_BEFORE_OR_EQUAL, estimatedRows,
- keyBuf.ptr(), keyLen, partsInUse);
- break;
- case HA_READ_PREFIX_LAST_OR_PREV:
- doInitialRead(QMY_LAST_PREVIOUS, estimatedRows,
- keyBuf.ptr(), keyLen, partsInUse);
- readDirection = QMY_PREVIOUS;
- break;
- case HA_READ_PREFIX_LAST:
- doInitialRead(QMY_PREFIX_LAST, estimatedRows,
- keyBuf.ptr(), keyLen, partsInUse);
- readDirection = QMY_PREVIOUS;
- break;
- case HA_READ_KEY_EXACT:
- doInitialRead(QMY_EQUAL, estimatedRows, keyBuf.ptr(), keyLen, partsInUse);
- break;
- default:
- DBUG_ASSERT(0);
- return HA_ERR_GENERIC;
- break;
- }
-
- ha_statistic_increment(&SSV::ha_read_key_count);
- rc = readFromBuffer(buf, readDirection);
-
- table->status= (rc ? STATUS_NOT_FOUND: 0);
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::index_next(uchar * buf)
-{
- DBUG_ENTER("ha_ibmdb2i::index_next");
- ha_statistic_increment(&SSV::ha_read_next_count);
-
- int rc = readFromBuffer(buf, QMY_NEXT);
-
- table->status= (rc ? STATUS_NOT_FOUND: 0);
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::index_next_same(uchar *buf, const uchar *key, uint keylen)
-{
- DBUG_ENTER("ha_ibmdb2i::index_next_same");
- ha_statistic_increment(&SSV::ha_read_next_count);
-
- int rc = readFromBuffer(buf, QMY_NEXT_EQUAL);
-
- if (rc == HA_ERR_KEY_NOT_FOUND)
- {
- rc = HA_ERR_END_OF_FILE;
- }
-
- table->status= (rc ? STATUS_NOT_FOUND: 0);
- DBUG_RETURN(rc);
-}
-
-int ha_ibmdb2i::index_read_last(uchar * buf, const uchar * key, uint key_len)
-{
- DBUG_ENTER("ha_ibmdb2i::index_read_last");
- DBUG_RETURN(index_read(buf, key, key_len, HA_READ_PREFIX_LAST));
-}
-
-
-
-int ha_ibmdb2i::index_prev(uchar * buf)
-{
- DBUG_ENTER("ha_ibmdb2i::index_prev");
- ha_statistic_increment(&SSV::ha_read_prev_count);
-
- int rc = readFromBuffer(buf, QMY_PREVIOUS);
-
- table->status= (rc ? STATUS_NOT_FOUND: 0);
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::index_first(uchar * buf)
-{
- DBUG_ENTER("ha_ibmdb2i::index_first");
-
- if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc);
-
- int rc = prepReadBuffer(DEFAULT_MAX_ROWS_TO_BUFFER,
- db2Table->indexFile(active_index),
- readAccessIntent);
-
- if (rc == 0)
- {
- doInitialRead(QMY_FIRST, DEFAULT_MAX_ROWS_TO_BUFFER);
- ha_statistic_increment(&SSV::ha_read_first_count);
- rc = readFromBuffer(buf, QMY_NEXT);
- }
-
- table->status= (rc ? STATUS_NOT_FOUND: 0);
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::index_last(uchar * buf)
-{
- DBUG_ENTER("ha_ibmdb2i::index_last");
-
- if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc);
-
- int rc = prepReadBuffer(DEFAULT_MAX_ROWS_TO_BUFFER,
- db2Table->indexFile(active_index),
- readAccessIntent);
-
- if (rc == 0)
- {
- doInitialRead(QMY_LAST, DEFAULT_MAX_ROWS_TO_BUFFER);
- ha_statistic_increment(&SSV::ha_read_last_count);
- rc = readFromBuffer(buf, QMY_PREVIOUS);
- }
-
- table->status= (rc ? STATUS_NOT_FOUND: 0);
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::rnd_init(bool scan)
-{
- DBUG_ENTER("ha_ibmdb2i::rnd_init");
-
- int& rc = last_rnd_init_rc;
- rc = 0;
-
- tweakReadSet();
- invalidDataFound=false;
-
- uint32 rowsToBlockOnRead;
-
- if (!scan)
- {
- rowsToBlockOnRead = 1;
- }
- else
- {
- rowsToBlockOnRead = DEFAULT_MAX_ROWS_TO_BUFFER;
- }
-
- rc = useDataFile();
-
- if (!rc)
- {
-// THD* thd = ha_thd();
-// if (accessIntent == QMY_UPDATABLE &&
-// thd_tx_isolation(thd) == ISO_REPEATABLE_READ &&
-// !THDVAR(thd, transaction_unsafe))
-// {
-// readAccessIntent = QMY_READ_ONLY;
-// }
-// else
-// {
- readAccessIntent = accessIntent;
-// }
-
- rc = prepReadBuffer(rowsToBlockOnRead, db2Table->dataFile(), readAccessIntent);
-
- if (!rc && accessIntent != QMY_READ_ONLY)
- rc = prepWriteBuffer(1, db2Table->dataFile());
-
- if (!rc && scan)
- doInitialRead(QMY_FIRST, rowsToBlockOnRead);
-
- if (rc)
- releaseDataFile();
- }
-
- rrnAssocHandle= 0;
-
- DBUG_RETURN(0);
-}
-
-int ha_ibmdb2i::rnd_end()
-{
- DBUG_ENTER("ha_ibmdb2i::rnd_end");
-
- warnIfInvalidData();
- if (likely(activeReadBuf))
- activeReadBuf->endRead();
- if (last_rnd_init_rc == 0)
- releaseActiveHandle();
- last_rnd_init_rc = 0;
- DBUG_RETURN(0);
-}
-
-
-int32 ha_ibmdb2i::mungeDB2row(uchar* record, const char* dataPtr, const char* nullMapPtr, bool skipLOBs)
-{
- DBUG_ASSERT(dataPtr);
-
- my_bitmap_map *old_write_map= dbug_tmp_use_all_columns(table, table->write_set);
- my_bitmap_map *old_read_map;
-
- if (unlikely(readAllColumns))
- old_read_map = tmp_use_all_columns(table, table->read_set);
-
- resetCharacterConversionBuffers();
-
- my_ptrdiff_t old_ptr= (my_ptrdiff_t) (record - table->record[0]);
- int fieldIndex = 0;
- for (Field **field = table->field; *field; ++field, ++fieldIndex)
- {
- if (unlikely(old_ptr))
- (*field)->move_field_offset(old_ptr);
- if (nullMapPtr[fieldIndex] == __NULL_VALUE_EBCDIC ||
- (!bitmap_is_set(table->read_set, fieldIndex)) ||
- (skipLOBs && db2Table->db2Field(fieldIndex).isBlob()))
- {
- (*field)->set_null();
- }
- else
- {
- (*field)->set_notnull();
- convertDB2toMySQL(db2Table->db2Field(fieldIndex), *field, dataPtr);
- }
- if (unlikely(old_ptr))
- (*field)->move_field_offset(-old_ptr);
-
- }
-
- if (unlikely(readAllColumns))
- tmp_restore_column_map(table->read_set, old_read_map);
- dbug_tmp_restore_column_map(table->write_set, old_write_map);
-
- return 0;
-}
-
-
-int ha_ibmdb2i::rnd_next(uchar *buf)
-{
- DBUG_ENTER("ha_ibmdb2i::rnd_next");
-
- if (unlikely(last_rnd_init_rc)) DBUG_RETURN(last_rnd_init_rc);
- ha_statistic_increment(&SSV::ha_read_rnd_next_count);
-
- int rc;
-
- rc = readFromBuffer(buf, QMY_NEXT);
-
- table->status= (rc ? STATUS_NOT_FOUND: 0);
- DBUG_RETURN(rc);
-}
-
-
-void ha_ibmdb2i::position(const uchar *record)
-{
- DBUG_ENTER("ha_ibmdb2i::position");
- my_store_ptr(ref, ref_length, currentRRN);
- DBUG_VOID_RETURN;
-}
-
-
-int ha_ibmdb2i::rnd_pos(uchar * buf, uchar *pos)
-{
- DBUG_ENTER("ha_ibmdb2i::rnd_pos");
- if (unlikely(last_rnd_init_rc)) DBUG_RETURN( last_rnd_init_rc);
- ha_statistic_increment(&SSV::ha_read_rnd_count);
-
- currentRRN = my_get_ptr(pos, ref_length);
-
- tweakReadSet();
-
- int rc = 0;
-
- if (rrnAssocHandle &&
- (activeHandle != rrnAssocHandle))
- {
- if (activeHandle) releaseActiveHandle();
- rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle);
- }
-
- if (likely(rc == 0))
- {
- rc = prepReadBuffer(1, getFileForActiveHandle(), accessIntent);
-
- if (likely(rc == 0) && accessIntent == QMY_UPDATABLE)
- rc = prepWriteBuffer(1, getFileForActiveHandle());
-
- if (likely(rc == 0))
- {
- rc = db2i_ileBridge::getBridgeForThread()->readByRRN(activeHandle,
- activeReadBuf->ptr(),
- currentRRN,
- accessIntent,
- getCommitLevel());
-
- if (likely(rc == 0))
- {
- rrnAssocHandle = activeHandle;
- const char* readBuf = activeReadBuf->getRowN(0);
- rc = mungeDB2row(buf, readBuf, readBuf + activeReadBuf->getRowNullOffset(), false);
- releaseRowNeeded = TRUE;
- }
- }
- }
-
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::info(uint flag)
-{
- DBUG_ENTER("ha_ibmdb2i::info");
-
- uint16 infoRequested = 0;
- ValidatedPointer<char> rowKeySpcPtr; // Space pointer passed to DB2
- uint32 rowKeySpcLen; // Length of space passed to DB2
- THD* thd = ha_thd();
- int command = thd_sql_command(thd);
-
- if (flag & HA_STATUS_AUTO)
- stats.auto_increment_value = (ulonglong) 0;
-
- if (flag & HA_STATUS_ERRKEY)
- {
- errkey = lastDupKeyID;
- my_store_ptr(dup_ref, ref_length, lastDupKeyRRN);
- }
-
- if (flag & HA_STATUS_TIME)
- {
- if ((flag & HA_STATUS_NO_LOCK) &&
- ibmdb2i_assume_exclusive_use &&
- share &&
- (share->cachedStats.isInited(lastModTime)))
- stats.update_time = share->cachedStats.getUpdateTime();
- else
- infoRequested |= lastModTime;
- }
-
- if (flag & HA_STATUS_CONST)
- {
- stats.block_size=4096;
- infoRequested |= createTime;
-
- if (table->s->keys)
- {
- infoRequested |= rowsPerKey;
- rowKeySpcLen = (table->s->keys) * MAX_DB2_KEY_PARTS * sizeof(uint64);
- rowKeySpcPtr.alloc(rowKeySpcLen);
- memset(rowKeySpcPtr, 0, rowKeySpcLen); // Clear the allocated space
- }
- }
-
- if (flag & HA_STATUS_VARIABLE)
- {
- if ((flag & HA_STATUS_NO_LOCK) &&
- (command != SQLCOM_SHOW_TABLE_STATUS) &&
- ibmdb2i_assume_exclusive_use &&
- share &&
- (share->cachedStats.isInited(rowCount | deletedRowCount | meanRowLen | ioCount)) &&
- (share->cachedStats.getRowCount() >= 2))
- {
- stats.records = share->cachedStats.getRowCount();
- stats.deleted = share->cachedStats.getDelRowCount();
- stats.mean_rec_length = share->cachedStats.getMeanLength();
- stats.data_file_length = share->cachedStats.getAugmentedDataLength();
- }
- else
- {
- infoRequested |= rowCount | deletedRowCount | meanRowLen;
- if (command == SQLCOM_SHOW_TABLE_STATUS)
- infoRequested |= objLength;
- else
- infoRequested |= ioCount;
- }
- }
-
- int rc = 0;
-
- if (infoRequested)
- {
- DBUG_PRINT("ha_ibmdb2i::info",("Retrieving fresh stats %d", flag));
-
- initBridge(thd);
- rc = bridge()->retrieveTableInfo((dataHandle ? dataHandle : db2Table->dataFile()->getMasterDefnHandle()),
- infoRequested,
- stats,
- rowKeySpcPtr);
-
- if (!rc)
- {
- if ((flag & HA_STATUS_VARIABLE) &&
- (command != SQLCOM_SHOW_TABLE_STATUS))
- stats.data_file_length = stats.data_file_length * IO_SIZE;
-
- if ((ibmdb2i_assume_exclusive_use) &&
- (share) &&
- (command != SQLCOM_SHOW_TABLE_STATUS))
- {
- if (flag & HA_STATUS_VARIABLE)
- {
- share->cachedStats.cacheRowCount(stats.records);
- share->cachedStats.cacheDelRowCount(stats.deleted);
- share->cachedStats.cacheMeanLength(stats.mean_rec_length);
- share->cachedStats.cacheAugmentedDataLength(stats.data_file_length);
- }
-
- if (flag & HA_STATUS_TIME)
- {
- share->cachedStats.cacheUpdateTime(stats.update_time);
- }
- }
-
- if (flag & HA_STATUS_CONST)
- {
- ulong i; // Loop counter for indexes
- ulong j; // Loop counter for key parts
- RowKey* rowKeyPtr; // Pointer to 'number of unique rows' array for this index
-
- rowKeyPtr = (RowKey_t*)(void*)rowKeySpcPtr; // Address first array of DB2 row counts
- for (i = 0; i < table->s->keys; i++) // Do for each index, including primary
- {
- for (j = 0; j < table->key_info[i].key_parts; j++)
- {
- table->key_info[i].rec_per_key[j]= rowKeyPtr->RowKeyArray[j];
- }
- rowKeyPtr = rowKeyPtr + 1; // Address next array of DB2 row counts
- }
- }
- }
- else if (rc == HA_ERR_LOCK_WAIT_TIMEOUT && share)
- {
- // If we couldn't retrieve the info because the object was locked,
- // we'll do our best by returning the most recently cached data.
- if ((infoRequested & rowCount) &&
- share->cachedStats.isInited(rowCount))
- stats.records = share->cachedStats.getRowCount();
- if ((infoRequested & deletedRowCount) &&
- share->cachedStats.isInited(deletedRowCount))
- stats.deleted = share->cachedStats.getDelRowCount();
- if ((infoRequested & meanRowLen) &&
- share->cachedStats.isInited(meanRowLen))
- stats.mean_rec_length = share->cachedStats.getMeanLength();
- if ((infoRequested & lastModTime) &&
- share->cachedStats.isInited(lastModTime))
- stats.update_time = share->cachedStats.getUpdateTime();
-
- rc = 0;
- }
- }
-
- DBUG_RETURN(rc);
-}
-
-
-ha_rows ha_ibmdb2i::records()
-{
- DBUG_ENTER("ha_ibmdb2i::records");
- int rc;
- rc = bridge()->retrieveTableInfo((dataHandle ? dataHandle : db2Table->dataFile()->getMasterDefnHandle()),
- rowCount,
- stats);
-
- if (unlikely(rc))
- {
- if (rc == HA_ERR_LOCK_WAIT_TIMEOUT &&
- share &&
- (share->cachedStats.isInited(rowCount)))
- DBUG_RETURN(share->cachedStats.getRowCount());
- else
- DBUG_RETURN(HA_POS_ERROR);
- }
- else if (share)
- {
- share->cachedStats.cacheRowCount(stats.records);
- }
-
- DBUG_RETURN(stats.records);
-}
-
-
-int ha_ibmdb2i::extra(enum ha_extra_function operation)
-{
- DBUG_ENTER("ha_ibmdb2i::extra");
-
- switch(operation)
- {
- // Can these first five flags be replaced by attending to HA_EXTRA_WRITE_CACHE?
- case HA_EXTRA_NO_IGNORE_DUP_KEY:
- case HA_EXTRA_WRITE_CANNOT_REPLACE:
- {
- returnDupKeysImmediately = false;
- onDupUpdate = false;
- }
- break;
- case HA_EXTRA_INSERT_WITH_UPDATE:
- {
- returnDupKeysImmediately = true;
- onDupUpdate = true;
- }
- break;
- case HA_EXTRA_IGNORE_DUP_KEY:
- case HA_EXTRA_WRITE_CAN_REPLACE:
- returnDupKeysImmediately = true;
- break;
- case HA_EXTRA_FLUSH_CACHE:
- if (outstanding_start_bulk_insert)
- finishBulkInsert();
- break;
- }
-
-
- DBUG_RETURN(0);
-}
-
-/**
- @brief
- The DB2 storage engine will ignore a MySQL generated value and will generate
- a new value in SLIC. We arbitrarily set first_value to 1, and set the
- interval to infinity for better performance on multi-row inserts.
-*/
-void ha_ibmdb2i::get_auto_increment(ulonglong offset, ulonglong increment,
- ulonglong nb_desired_values,
- ulonglong *first_value,
- ulonglong *nb_reserved_values)
-{
- DBUG_ENTER("ha_ibmdb2i::get_auto_increment");
- *first_value= 1;
- *nb_reserved_values= ULONGLONG_MAX;
-}
-
-
-
-void ha_ibmdb2i::update_create_info(HA_CREATE_INFO *create_info)
-{
- DBUG_ENTER("ha_ibmdb2i::update_create_info");
-
- if ((!(create_info->used_fields & HA_CREATE_USED_AUTO)) &&
- (table->found_next_number_field != NULL))
- {
- initBridge();
-
- create_info->auto_increment_value= 1;
-
- ha_rows rowCount = records();
-
- if (rowCount == 0)
- {
- create_info->auto_increment_value = db2Table->getStartId();
- DBUG_VOID_RETURN;
- }
- else if (rowCount == HA_POS_ERROR)
- {
- DBUG_VOID_RETURN;
- }
-
- getNextIdVal(&create_info->auto_increment_value);
- }
- DBUG_VOID_RETURN;
-}
-
-
-int ha_ibmdb2i::getNextIdVal(ulonglong *value)
-{
- DBUG_ENTER("ha_ibmdb2i::getNextIdVal");
-
- char queryBuffer[MAX_DB2_COLNAME_LENGTH + MAX_DB2_QUALIFIEDNAME_LENGTH + 64];
- strcpy(queryBuffer, " SELECT CAST(MAX( ");
- convertMySQLNameToDB2Name(table->found_next_number_field->field_name,
- strend(queryBuffer),
- MAX_DB2_COLNAME_LENGTH+1);
- strcat(queryBuffer, ") AS BIGINT) FROM ");
- db2Table->getDB2QualifiedName(strend(queryBuffer));
- DBUG_ASSERT(strlen(queryBuffer) < sizeof(queryBuffer));
-
- SqlStatementStream sqlStream(queryBuffer);
- DBUG_PRINT("ha_ibmdb2i::getNextIdVal", ("Sent to DB2: %s",queryBuffer));
-
- int rc = 0;
- FILE_HANDLE fileHandle2;
- uint32 db2RowDataLen2;
- rc = bridge()->prepOpen(sqlStream.getPtrToData(),
- &fileHandle2,
- &db2RowDataLen2);
- if (likely(rc == 0))
- {
- IOReadBuffer rowBuffer(1, db2RowDataLen2);
- rc = bridge()->read(fileHandle2,
- rowBuffer.ptr(),
- QMY_READ_ONLY,
- QMY_NONE,
- QMY_FIRST);
-
- if (likely(rc == 0))
- {
- /* This check is here for the case where the table is not empty,
- but the auto_increment starting value has been changed since
- the last record was written. */
-
- longlong maxIdVal = *(longlong*)(rowBuffer.getRowN(0));
- if ((maxIdVal + 1) > db2Table->getStartId())
- *value = maxIdVal + 1;
- else
- *value = db2Table->getStartId();
- }
-
- bridge()->deallocateFile(fileHandle2);
- }
- DBUG_RETURN(rc);
-}
-
-
-/*
- Updates index cardinalities.
-*/
-int ha_ibmdb2i::analyze(THD* thd, HA_CHECK_OPT *check_opt)
-{
- DBUG_ENTER("ha_ibmdb2i::analyze");
- info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
- DBUG_RETURN(0);
-}
-
-int ha_ibmdb2i::optimize(THD* thd, HA_CHECK_OPT *check_opt)
-{
- DBUG_ENTER("ha_ibmdb2i::optimize");
-
- initBridge(thd);
-
- if (unlikely(records() == 0))
- DBUG_RETURN(0); // DB2 doesn't like to reorganize a table with no data.
-
- quiesceAllFileHandles();
-
- int32 rc = bridge()->optimizeTable(db2Table->dataFile()->getMasterDefnHandle());
- info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
-
- DBUG_RETURN(rc);
-}
-
-
-/**
- @brief
- Determines if an ALTER TABLE is allowed to switch the storage engine
- for this table. If the table has a foreign key or is referenced by a
- foreign key, then it cannot be switched.
-*/
-bool ha_ibmdb2i::can_switch_engines(void)
-/*=================================*/
-{
- DBUG_ENTER("ha_ibmdb2i::can_switch_engines");
-
- int rc = 0;
- FILE_HANDLE queryFile = 0;
- uint32 resultRowLen;
- uint count = 0;
- bool can_switch = FALSE; // 1 if changing storage engine is allowed
-
- const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL);
- const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL);
-
- String query(256);
- query.append(STRING_WITH_LEN(" SELECT COUNT(*) FROM SYSIBM.SQLFOREIGNKEYS WHERE ((PKTABLE_SCHEM = '"));
- query.append(libName+1, strlen(libName)-2); // Remove quotes from parent schema name
- query.append(STRING_WITH_LEN("' AND PKTABLE_NAME = '"));
- query.append(fileName+1,strlen(fileName)-2); // Remove quotes from file name
- query.append(STRING_WITH_LEN("') OR (FKTABLE_SCHEM = '"));
- query.append(libName+1,strlen(libName)-2); // Remove quotes from child schema
- query.append(STRING_WITH_LEN("' AND FKTABLE_NAME = '"));
- query.append(fileName+1,strlen(fileName)-2); // Remove quotes from child name
- query.append(STRING_WITH_LEN("'))"));
-
- SqlStatementStream sqlStream(query);
-
- rc = bridge()->prepOpen(sqlStream.getPtrToData(),
- &queryFile,
- &resultRowLen);
- if (rc == 0)
- {
- IOReadBuffer rowBuffer(1, resultRowLen);
-
- rc = bridge()->read(queryFile,
- rowBuffer.ptr(),
- QMY_READ_ONLY,
- QMY_NONE,
- QMY_FIRST);
- if (!rc)
- {
- count = *(uint*)(rowBuffer.getRowN(0));
- if (count == 0)
- can_switch = TRUE;
- }
-
- bridge()->deallocateFile(queryFile);
- }
- DBUG_RETURN(can_switch);
-}
-
-
-
-bool ha_ibmdb2i::check_if_incompatible_data(HA_CREATE_INFO *info,
- uint table_changes)
-{
- DBUG_ENTER("ha_ibmdb2i::check_if_incompatible_data");
- uint i;
- /* Check that auto_increment value and field definitions were
- not changed. */
- if ((info->used_fields & HA_CREATE_USED_AUTO &&
- info->auto_increment_value != 0) ||
- table_changes != IS_EQUAL_YES)
- DBUG_RETURN(COMPATIBLE_DATA_NO);
- /* Check if any fields were renamed. */
- for (i= 0; i < table->s->fields; i++)
- {
- Field *field= table->field[i];
- if (field->flags & FIELD_IS_RENAMED)
- {
- DBUG_PRINT("info", ("Field has been renamed, copy table"));
- DBUG_RETURN(COMPATIBLE_DATA_NO);
- }
- }
- DBUG_RETURN(COMPATIBLE_DATA_YES);
-}
-
-int ha_ibmdb2i::reset_auto_increment(ulonglong value)
- {
- DBUG_ENTER("ha_ibmdb2i::reset_auto_increment");
-
- int rc = 0;
-
- quiesceAllFileHandles();
-
- const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL);
- const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL);
-
- String query(512);
- query.append(STRING_WITH_LEN(" ALTER TABLE "));
- query.append(libName);
- query.append('.');
- query.append(fileName);
- query.append(STRING_WITH_LEN(" ALTER COLUMN "));
- char colName[MAX_DB2_COLNAME_LENGTH+1];
- convertMySQLNameToDB2Name(table->found_next_number_field->field_name,
- colName,
- sizeof(colName));
- query.append(colName);
-
- char restart_value[22];
- CHARSET_INFO *cs= &my_charset_bin;
- uint len = (uint)(cs->cset->longlong10_to_str)(cs,restart_value,sizeof(restart_value), 10, value);
- restart_value[len] = 0;
-
- query.append(STRING_WITH_LEN(" RESTART WITH "));
- query.append(restart_value);
-
- SqlStatementStream sqlStream(query);
- DBUG_PRINT("ha_ibmdb2i::reset_auto_increment", ("Sent to DB2: %s",query.c_ptr()));
-
- rc = db2i_ileBridge::getBridgeForThread()->execSQL(sqlStream.getPtrToData(),
- sqlStream.getStatementCount(),
- QMY_NONE, //getCommitLevel(),
- FALSE,
- FALSE,
- TRUE, //FALSE,
- dataHandle);
- if (rc == 0)
- db2Table->updateStartId(value);
-
- DBUG_RETURN(rc);
-}
-
-
-/**
- @brief
- This function receives an error code that was previously set by the handler.
- It returns to MySQL the error string associated with that error.
-*/
-bool ha_ibmdb2i::get_error_message(int error, String *buf)
-{
- DBUG_ENTER("ha_ibmdb2i::get_error_message");
- if ((error >= DB2I_FIRST_ERR && error <= DB2I_LAST_ERR) ||
- (error >= QMY_ERR_MIN && error <= QMY_ERR_MAX))
- {
- db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(ha_thd());
- char* errMsg = bridge->getErrorStorage();
- buf->copy(errMsg, strlen(errMsg),system_charset_info);
- bridge->freeErrorStorage();
- }
- DBUG_RETURN(FALSE);
-}
-
-
-int ha_ibmdb2i::delete_all_rows()
-{
- DBUG_ENTER("ha_ibmdb2i::delete_all_rows");
- int rc = 0;
- char queryBuffer[MAX_DB2_QUALIFIEDNAME_LENGTH + 64];
- strcpy(queryBuffer, " DELETE FROM ");
- db2Table->getDB2QualifiedName(strend(queryBuffer));
- DBUG_ASSERT(strlen(queryBuffer) < sizeof(queryBuffer));
-
- SqlStatementStream sqlStream(queryBuffer);
- DBUG_PRINT("ha_ibmdb2i::delete_all_rows", ("Sent to DB2: %s",queryBuffer));
- rc = bridge()->execSQL(sqlStream.getPtrToData(),
- sqlStream.getStatementCount(),
- getCommitLevel(),
- false,
- false,
- true,
- dataHandle);
-
- /* If this method was called on behalf of a TRUNCATE TABLE statement, and if */
- /* the table has an auto_increment field, then reset the starting value for */
- /* the auto_increment field to 1.
- */
- if (rc == 0 && thd_sql_command(ha_thd()) == SQLCOM_TRUNCATE &&
- table->found_next_number_field )
- rc = reset_auto_increment(1);
-
- invalidateCachedStats();
-
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::external_lock(THD *thd, int lock_type)
-{
- int rc = 0;
-
- DBUG_ENTER("ha_ibmdb2i::external_lock");
- DBUG_PRINT("ha_ibmdb2i::external_lock",("Lock type: %d", lock_type));
-
- if (lock_type == F_RDLCK)
- accessIntent = QMY_READ_ONLY;
- else if (lock_type == F_WRLCK)
- accessIntent = QMY_UPDATABLE;
-
- initBridge(thd);
- int command = thd_sql_command(thd);
-
- if (!THDVAR(thd,transaction_unsafe))
- {
- if (lock_type != F_UNLCK)
- {
- if (autoCommitIsOn(thd) == QMY_YES)
- {
- trans_register_ha(thd, FALSE, ibmdb2i_hton);
- }
- else
- {
- trans_register_ha(thd, TRUE, ibmdb2i_hton);
- if (likely(command != SQLCOM_CREATE_TABLE))
- {
- trans_register_ha(thd, FALSE, ibmdb2i_hton);
- bridge()->beginStmtTx();
- }
- }
- }
- }
-
- if (command == SQLCOM_LOCK_TABLES ||
- command == SQLCOM_ALTER_TABLE ||
- command == SQLCOM_UNLOCK_TABLES ||
- (accessIntent == QMY_UPDATABLE &&
- (command == SQLCOM_UPDATE ||
- command == SQLCOM_UPDATE_MULTI ||
- command == SQLCOM_DELETE ||
- command == SQLCOM_DELETE_MULTI ||
- command == SQLCOM_REPLACE ||
- command == SQLCOM_REPLACE_SELECT) &&
- getCommitLevel(thd) == QMY_NONE))
- {
- char action;
- char type;
- if (lock_type == F_UNLCK)
- {
- action = QMY_UNLOCK;
- type = accessIntent == QMY_READ_ONLY ? QMY_LSRD : QMY_LENR;
- }
- else
- {
- action = QMY_LOCK;
- type = lock_type == F_RDLCK ? QMY_LSRD : QMY_LENR;
- }
-
- DBUG_PRINT("ha_ibmdb2i::external_lock",("%socking table", action==QMY_LOCK ? "L" : "Unl"));
-
- if (!dataHandle)
- rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection);
-
- rc = bridge()->lockObj(dataHandle,
- 0,
- action,
- type,
- (command == SQLCOM_LOCK_TABLES ? QMY_NO : QMY_YES));
-
- }
-
- // Cache this away so we don't have to access it on each row operation
- cachedZeroDateOption = (enum_ZeroDate)THDVAR(thd, compat_opt_allow_zero_date_vals);
-
- DBUG_RETURN(rc);
-}
-
-
-THR_LOCK_DATA **ha_ibmdb2i::store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
- {
- if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
- lock_type <= TL_WRITE) && !(thd->in_lock_tables && thd_sql_command(thd) == SQLCOM_LOCK_TABLES))
- lock_type= TL_WRITE_ALLOW_WRITE;
- lock.type=lock_type;
- }
- *to++= &lock;
- return to;
-}
-
-
-int ha_ibmdb2i::delete_table(const char *name)
-{
- DBUG_ENTER("ha_ibmdb2i::delete_table");
- THD* thd = ha_thd();
- db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(thd);
-
- char db2Name[MAX_DB2_QUALIFIEDNAME_LENGTH];
- db2i_table::getDB2QualifiedNameFromPath(name, db2Name);
-
- String query(128);
- query.append(STRING_WITH_LEN(" DROP TABLE "));
- query.append(db2Name);
-
- if (thd_sql_command(thd) == SQLCOM_DROP_TABLE &&
- thd->lex->drop_mode == DROP_RESTRICT)
- query.append(STRING_WITH_LEN(" RESTRICT "));
- DBUG_PRINT("ha_ibmdb2i::delete_table", ("Sent to DB2: %s",query.c_ptr()));
-
- SqlStatementStream sqlStream(query);
-
- db2i_table::getDB2LibNameFromPath(name, db2Name);
- bool isTemporary = (strcmp(db2Name, DB2I_TEMP_TABLE_SCHEMA) == 0 ? TRUE : FALSE);
-
- int rc = bridge->execSQL(sqlStream.getPtrToData(),
- sqlStream.getStatementCount(),
- (isTemporary ? QMY_NONE : getCommitLevel(thd)),
- FALSE,
- FALSE,
- isTemporary);
-
- if (rc == HA_ERR_NO_SUCH_TABLE)
- {
- warning(thd, DB2I_ERR_TABLE_NOT_FOUND, name);
- rc = 0;
- }
-
- if (rc == 0)
- {
- db2i_table::deleteAssocFiles(name);
- }
-
- FILE_HANDLE savedHandle = bridge->findAndRemovePreservedHandle(name, &share);
- while (savedHandle)
- {
- bridge->deallocateFile(savedHandle, TRUE);
- DBUG_ASSERT(share);
- if (free_share(share))
- share = NULL;
- savedHandle = bridge->findAndRemovePreservedHandle(name, &share);
- }
-
- my_errno = rc;
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::rename_table(const char * from, const char * to)
-{
- DBUG_ENTER("ha_ibmdb2i::rename_table ");
-
- char db2FromFileName[MAX_DB2_FILENAME_LENGTH + 1];
- char db2ToFileName[MAX_DB2_FILENAME_LENGTH+1];
- char db2FromLibName[MAX_DB2_SCHEMANAME_LENGTH+1];
- char db2ToLibName[MAX_DB2_SCHEMANAME_LENGTH+1];
-
- db2i_table::getDB2LibNameFromPath(from, db2FromLibName);
- db2i_table::getDB2LibNameFromPath(to, db2ToLibName);
-
- if (strcmp(db2FromLibName, db2ToLibName) != 0 )
- {
- getErrTxt(DB2I_ERR_RENAME_MOVE,from,to);
- DBUG_RETURN(DB2I_ERR_RENAME_MOVE);
- }
-
- db2i_table::getDB2FileNameFromPath(from, db2FromFileName, db2i_table::ASCII_NATIVE);
- db2i_table::getDB2FileNameFromPath(to, db2ToFileName);
-
- char escapedFromFileName[2 * MAX_DB2_FILENAME_LENGTH + 1];
-
- uint o = 0;
- uint i = 1;
- do
- {
- escapedFromFileName[o++] = db2FromFileName[i];
- if (db2FromFileName[i] == '+')
- escapedFromFileName[o++] = '+';
- } while (db2FromFileName[++i]);
- escapedFromFileName[o-1] = 0;
-
-
- int rc = 0;
-
- char queryBuffer[sizeof(db2FromLibName) + 2 * sizeof(db2FromFileName) + 256];
- SafeString selectQuery(queryBuffer, sizeof(queryBuffer));
- selectQuery.strncat(STRING_WITH_LEN("SELECT CAST(INDEX_NAME AS VARCHAR(128) CCSID 1208) FROM QSYS2.SYSINDEXES WHERE INDEX_NAME LIKE '%+_+_+_%"));
- selectQuery.strcat(escapedFromFileName);
- selectQuery.strncat(STRING_WITH_LEN("' ESCAPE '+' AND TABLE_NAME='"));
- selectQuery.strncat(db2FromFileName+1, strlen(db2FromFileName)-2);
- selectQuery.strncat(STRING_WITH_LEN("' AND TABLE_SCHEMA='"));
- selectQuery.strncat(db2FromLibName+1, strlen(db2FromLibName)-2);
- selectQuery.strcat('\'');
- DBUG_ASSERT(!selectQuery.overflowed());
-
- SqlStatementStream indexQuery(selectQuery.ptr());
-
- FILE_HANDLE queryFile = 0;
- uint32 resultRowLen;
-
- initBridge();
- rc = bridge()->prepOpen(indexQuery.getPtrToData(),
- &queryFile,
- &resultRowLen);
-
- if (unlikely(rc))
- DBUG_RETURN(rc);
-
- IOReadBuffer rowBuffer(1, resultRowLen);
-
- int tableNameLen = strlen(db2FromFileName) - 2;
-
- SqlStatementStream renameQuery(64);
- String query;
- while (rc == 0)
- {
- query.length(0);
-
- rc = bridge()->read(queryFile,
- rowBuffer.ptr(),
- QMY_READ_ONLY,
- QMY_NONE,
- QMY_NEXT);
-
- if (!rc)
- {
- const char* rowData = rowBuffer.getRowN(0);
- char indexFileName[MAX_DB2_FILENAME_LENGTH];
- memset(indexFileName, 0, sizeof(indexFileName));
-
- uint16 fileNameLen = *(uint16*)(rowData);
- strncpy(indexFileName, rowData + sizeof(uint16), fileNameLen);
-
- int bytesToRetain = fileNameLen - tableNameLen;
- if (bytesToRetain <= 0)
- /* We can't handle index names in which the MySQL index name and
- the table name together are longer than the max index name. */
- {
- getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*");
- DBUG_RETURN(DB2I_ERR_INVALID_NAME);
- }
- char indexName[MAX_DB2_FILENAME_LENGTH];
- memset(indexName, 0, sizeof(indexName));
-
- strncpy(indexName,
- indexFileName,
- bytesToRetain);
-
- char db2IndexName[MAX_DB2_FILENAME_LENGTH+1];
-
- convertMySQLNameToDB2Name(indexFileName, db2IndexName, sizeof(db2IndexName));
-
- query.append(STRING_WITH_LEN("RENAME INDEX "));
- query.append(db2FromLibName);
- query.append('.');
- query.append(db2IndexName);
- query.append(STRING_WITH_LEN(" TO "));
- if (db2i_table::appendQualifiedIndexFileName(indexName, db2ToFileName, query, db2i_table::ASCII_SQL, typeNone) == -1)
- {
- getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*");
- DBUG_RETURN(DB2I_ERR_INVALID_NAME );
- }
- renameQuery.addStatement(query);
- DBUG_PRINT("ha_ibmdb2i::rename_table", ("Sent to DB2: %s",query.c_ptr_safe()));
- }
- }
-
-
- if (queryFile)
- bridge()->deallocateFile(queryFile);
-
- if (rc != HA_ERR_END_OF_FILE)
- DBUG_RETURN(rc);
-
- char db2Name[MAX_DB2_QUALIFIEDNAME_LENGTH];
-
- /* Rename the table */
- query.length(0);
- query.append(STRING_WITH_LEN(" RENAME TABLE "));
- db2i_table::getDB2QualifiedNameFromPath(from, db2Name);
- query.append(db2Name);
- query.append(STRING_WITH_LEN(" TO "));
- query.append(db2ToFileName);
- DBUG_PRINT("ha_ibmdb2i::rename_table", ("Sent to DB2: %s",query.c_ptr_safe()));
- renameQuery.addStatement(query);
- rc = bridge()->execSQL(renameQuery.getPtrToData(),
- renameQuery.getStatementCount(),
- getCommitLevel());
-
- if (!rc)
- db2i_table::renameAssocFiles(from, to);
-
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::create(const char *name, TABLE *table_arg,
- HA_CREATE_INFO *create_info)
-{
- DBUG_ENTER("ha_ibmdb2i::create");
-
- int rc;
- char fileSortSequence[11] = "*HEX";
- char fileSortSequenceLibrary[11] = "";
- char fileSortSequenceType = ' ';
- char libName[MAX_DB2_SCHEMANAME_LENGTH+1];
- char fileName[MAX_DB2_FILENAME_LENGTH+1];
- char colName[MAX_DB2_COLNAME_LENGTH+1];
- bool isTemporary;
- ulong auto_inc_value;
-
- db2i_table::getDB2LibNameFromPath(name, libName);
- db2i_table::getDB2FileNameFromPath(name, fileName);
-
- if (osVersion.v < 6)
- {
- if (strlen(libName) >
- MAX_DB2_V5R4_LIBNAME_LENGTH + (isOrdinaryIdentifier(libName) ? 2 : 0))
- {
- getErrTxt(DB2I_ERR_TOO_LONG_SCHEMA,libName, MAX_DB2_V5R4_LIBNAME_LENGTH);
- DBUG_RETURN(DB2I_ERR_TOO_LONG_SCHEMA);
- }
- }
- else if (strlen(libName) > MAX_DB2_V6R1_LIBNAME_LENGTH)
- {
- getErrTxt(DB2I_ERR_TOO_LONG_SCHEMA,libName, MAX_DB2_V6R1_LIBNAME_LENGTH);
- DBUG_RETURN(DB2I_ERR_TOO_LONG_SCHEMA);
- }
-
- String query(256);
-
- if (strcmp(libName, DB2I_TEMP_TABLE_SCHEMA))
- {
- query.append(STRING_WITH_LEN("CREATE TABLE "));
- query.append(libName);
- query.append('.');
- query.append(fileName);
- isTemporary = FALSE;
- }
- else
- {
- query.append(STRING_WITH_LEN("DECLARE GLOBAL TEMPORARY TABLE "));
- query.append(fileName);
- isTemporary = TRUE;
- }
- query.append(STRING_WITH_LEN(" ("));
-
- THD* thd = ha_thd();
- enum_TimeFormat timeFormat = (enum_TimeFormat)(THDVAR(thd, compat_opt_time_as_duration));
- enum_YearFormat yearFormat = (enum_YearFormat)(THDVAR(thd, compat_opt_year_as_int));
- enum_BlobMapping blobMapping = (enum_BlobMapping)(THDVAR(thd, compat_opt_blob_cols));
- enum_ZeroDate zeroDate = (enum_ZeroDate)(THDVAR(thd, compat_opt_allow_zero_date_vals));
- bool propagateDefaults = THDVAR(thd, propagate_default_col_vals);
-
- Field **field;
- for (field= table_arg->field; *field; field++)
- {
- if ( field != table_arg->field ) // Not the first one
- query.append(STRING_WITH_LEN(" , "));
-
- if (!convertMySQLNameToDB2Name((*field)->field_name, colName, sizeof(colName)))
- {
- getErrTxt(DB2I_ERR_INVALID_NAME,"field",(*field)->field_name);
- DBUG_RETURN(DB2I_ERR_INVALID_NAME );
- }
-
- query.append(colName);
- query.append(' ');
-
- if (rc = getFieldTypeMapping(*field,
- query,
- timeFormat,
- blobMapping,
- zeroDate,
- propagateDefaults,
- yearFormat))
- DBUG_RETURN(rc);
-
- if ( (*field)->flags & NOT_NULL_FLAG )
- {
- query.append(STRING_WITH_LEN(" NOT NULL "));
- }
- if ( (*field)->flags & AUTO_INCREMENT_FLAG )
- {
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- if (table_arg->part_info)
- {
- getErrTxt(DB2I_ERR_PART_AUTOINC);
- DBUG_RETURN(DB2I_ERR_PART_AUTOINC);
- }
-#endif
- query.append(STRING_WITH_LEN(" GENERATED BY DEFAULT AS IDENTITY ") );
- if (create_info->auto_increment_value != 0)
- {
- /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
- CREATE TABLE ...AUTO_INCREMENT = x; Set the starting
- value for the auto_increment column. */
- char stringValue[22];
- CHARSET_INFO *cs= &my_charset_bin;
- uint len = (uint)(cs->cset->longlong10_to_str)(cs,stringValue,sizeof(stringValue), 10, create_info->auto_increment_value);
- stringValue[len] = 0;
- query.append(STRING_WITH_LEN(" (START WITH "));
- query.append(stringValue);
-
- uint64 maxValue=maxValueForField(*field);
-
- if (maxValue)
- {
- len = (uint)(cs->cset->longlong10_to_str)(cs,stringValue,sizeof(stringValue), 10, maxValue);
- stringValue[len] = 0;
- query.append(STRING_WITH_LEN(" MAXVALUE "));
- query.append(stringValue);
- }
-
- query.append(STRING_WITH_LEN(") "));
- }
-
- }
- }
-
- String fieldDefinition(128);
-
- if (table_arg->s->primary_key != MAX_KEY && !isTemporary)
- {
- query.append(STRING_WITH_LEN(", PRIMARY KEY "));
- rc = buildIndexFieldList(fieldDefinition,
- table_arg->key_info[table_arg->s->primary_key],
- true,
- &fileSortSequenceType,
- fileSortSequence,
- fileSortSequenceLibrary);
- if (rc) DBUG_RETURN(rc);
- query.append(fieldDefinition);
- }
-
- rc = buildDB2ConstraintString(thd->lex,
- query,
- name,
- table_arg->field,
- &fileSortSequenceType,
- fileSortSequence,
- fileSortSequenceLibrary);
- if (rc) DBUG_RETURN (rc);
-
- query.append(STRING_WITH_LEN(" ) "));
-
- if (isTemporary)
- query.append(STRING_WITH_LEN(" ON COMMIT PRESERVE ROWS "));
-
- if (create_info->alias)
- generateAndAppendRCDFMT(create_info->alias, query);
- else if (((TABLE_LIST*)(thd->lex->select_lex.table_list.first))->table_name)
- generateAndAppendRCDFMT((char*)((TABLE_LIST*)(thd->lex->select_lex.table_list.first))->table_name, query);
-
- DBUG_PRINT("ha_ibmdb2i::create", ("Sent to DB2: %s",query.c_ptr()));
- SqlStatementStream sqlStream(query.length());
- sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary);
-
- if (table_arg->s->primary_key != MAX_KEY &&
- !isTemporary &&
- (THDVAR(thd, create_index_option)==1) &&
- (fileSortSequenceType != 'B') &&
- (fileSortSequenceType != ' '))
- {
- rc = generateShadowIndex(sqlStream,
- table_arg->key_info[table_arg->s->primary_key],
- libName,
- fileName,
- fieldDefinition);
- if (rc) DBUG_RETURN(rc);
- }
- for (uint i = 0; i < table_arg->s->keys; ++i)
- {
- if (i != table_arg->s->primary_key || isTemporary)
- {
- rc = buildCreateIndexStatement(sqlStream,
- table_arg->key_info[i],
- false,
- libName,
- fileName);
- if (rc) DBUG_RETURN (rc);
- }
- }
-
- bool noCommit = isTemporary || ((!autoCommitIsOn(thd)) && (thd_sql_command(thd) == SQLCOM_ALTER_TABLE));
-
- initBridge();
-
-// if (THDVAR(thd, discovery_mode) == 1)
-// bridge()->expectErrors(QMY_ERR_TABLE_EXISTS);
-
- rc = bridge()->execSQL(sqlStream.getPtrToData(),
- sqlStream.getStatementCount(),
- (isTemporary ? QMY_NONE : getCommitLevel(thd)),
- TRUE,
- FALSE,
- noCommit );
-
- if (unlikely(rc == QMY_ERR_MSGID) &&
- memcmp(bridge()->getErrorMsgID(), DB2I_SQL0350, 7) == 0)
- {
- my_error(ER_BLOB_USED_AS_KEY, MYF(0), "*unknown*");
- rc = ER_BLOB_USED_AS_KEY;
- }
-/* else if (unlikely(rc == QMY_ERR_TABLE_EXISTS) &&
- THDVAR(thd, discovery_mode) == 1)
- {
- db2i_table* temp = new db2i_table(table_arg->s, name);
- int32 rc = temp->fastInitForCreate(name);
- delete temp;
-
- if (!rc)
- warning(thd, DB2I_ERR_WARN_CREATE_DISCOVER);
-
- DBUG_RETURN(rc);
- }
-*/
-
- if (!rc && !isTemporary)
- {
- db2i_table* temp = new db2i_table(table_arg->s, name);
- rc = temp->fastInitForCreate(name);
- delete temp;
- if (rc)
- delete_table(name);
- }
-
- DBUG_RETURN(rc);
-}
-
-
-/**
- @brief
- Add an index on-line to a table. This method is called on behalf of
- a CREATE INDEX or ALTER TABLE statement.
- It is implemented via a composed DDL statement passed to DB2.
-*/
-int ha_ibmdb2i::add_index(TABLE *table_arg,
- KEY *key_info,
- uint num_of_keys)
-{
- DBUG_ENTER("ha_ibmdb2i::add_index");
-
- int rc;
- SqlStatementStream sqlStream(256);
- const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL);
- const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL);
-
- quiesceAllFileHandles();
-
- uint primaryKey = MAX_KEY;
- if (table_arg->s->primary_key >= MAX_KEY && !db2Table->isTemporary())
- {
- for (int i = 0; i < num_of_keys; ++i)
- {
- if (strcmp(key_info[i].name, "PRIMARY") == 0)
- {
- primaryKey = i;
- break;
- }
- else if (primaryKey == MAX_KEY &&
- key_info[i].flags & HA_NOSAME)
- {
- primaryKey = i;
- for (int j=0 ; j < key_info[i].key_parts ;j++)
- {
- uint fieldnr= key_info[i].key_part[j].fieldnr;
- if (table_arg->s->field[fieldnr]->null_ptr ||
- table_arg->s->field[fieldnr]->key_length() !=
- key_info[i].key_part[j].length)
- {
- primaryKey = MAX_KEY;
- break;
- }
- }
- }
- }
- }
-
-
- for (int i = 0; i < num_of_keys; ++i)
- {
- KEY& curKey= key_info[i];
- rc = buildCreateIndexStatement(sqlStream,
- curKey,
- (i == primaryKey),
- libName,
- fileName);
- if (rc) DBUG_RETURN (rc);
- }
-
- rc = bridge()->execSQL(sqlStream.getPtrToData(),
- sqlStream.getStatementCount(),
- getCommitLevel(),
- FALSE,
- FALSE,
- FALSE,
- dataHandle);
-
- /* Handle the case where a unique index is being created but an error occurs
- because the file contains duplicate key values. */
- if (rc == ER_DUP_ENTRY)
- print_keydup_error(MAX_KEY,ER(ER_DUP_ENTRY_WITH_KEY_NAME));
-
- DBUG_RETURN(rc);
-}
-
-/**
- @brief
- Drop an index on-line from a table. This method is called on behalf of
- a DROP INDEX or ALTER TABLE statement.
- It is implemented via a composed DDL statement passed to DB2.
-*/
-int ha_ibmdb2i::prepare_drop_index(TABLE *table_arg,
- uint *key_num, uint num_of_keys)
-{
- DBUG_ENTER("ha_ibmdb2i::prepare_drop_index");
- int rc;
- int i = 0;
- String query(64);
- SqlStatementStream sqlStream(64 * num_of_keys);
- SqlStatementStream shadowStream(64 * num_of_keys);
-
- quiesceAllFileHandles();
-
- const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL);
- const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL);
-
- while (i < num_of_keys)
- {
- query.length(0);
- DBUG_PRINT("info", ("ha_ibmdb2i::prepare_drop_index %u", key_num[i]));
- KEY& curKey= table_arg->key_info[key_num[i]];
- if (key_num[i] == table->s->primary_key && !db2Table->isTemporary())
- {
- query.append(STRING_WITH_LEN("ALTER TABLE "));
- query.append(libName);
- query.append(STRING_WITH_LEN("."));
- query.append(fileName);
- query.append(STRING_WITH_LEN(" DROP PRIMARY KEY"));
- }
- else
- {
- query.append(STRING_WITH_LEN("DROP INDEX "));
- query.append(libName);
- query.append(STRING_WITH_LEN("."));
- db2i_table::appendQualifiedIndexFileName(curKey.name, fileName, query);
- }
- DBUG_PRINT("ha_ibmdb2i::prepare_drop_index", ("Sent to DB2: %s",query.c_ptr_safe()));
- sqlStream.addStatement(query);
-
- query.length(0);
- query.append(STRING_WITH_LEN("DROP INDEX "));
- query.append(libName);
- query.append(STRING_WITH_LEN("."));
- db2i_table::appendQualifiedIndexFileName(curKey.name, fileName, query, db2i_table::ASCII_SQL, typeHex);
-
- DBUG_PRINT("ha_ibmdb2i::prepare_drop_index", ("Sent to DB2: %s",query.c_ptr_safe()));
- shadowStream.addStatement(query);
-
- ++i;
- }
-
- rc = bridge()->execSQL(sqlStream.getPtrToData(),
- sqlStream.getStatementCount(),
- getCommitLevel(),
- FALSE,
- FALSE,
- FALSE,
- dataHandle);
-
- if (rc == 0)
- bridge()->execSQL(shadowStream.getPtrToData(),
- shadowStream.getStatementCount(),
- getCommitLevel());
-
- DBUG_RETURN(rc);
-}
-
-
-void
-ha_ibmdb2i::unlock_row()
-{
- DBUG_ENTER("ha_ibmdb2i::unlock_row");
- DBUG_VOID_RETURN;
-}
-
-int
-ha_ibmdb2i::index_end()
-{
- DBUG_ENTER("ha_ibmdb2i::index_end");
- warnIfInvalidData();
- last_index_init_rc = 0;
- if (likely(activeReadBuf))
- activeReadBuf->endRead();
- if (likely(!last_index_init_rc))
- releaseIndexFile(active_index);
- active_index= MAX_KEY;
- DBUG_RETURN (0);
-}
-
-int ha_ibmdb2i::doCommit(handlerton *hton, THD *thd, bool all)
-{
- if (!THDVAR(thd, transaction_unsafe))
- {
- if (all || autoCommitIsOn(thd))
- {
- DBUG_PRINT("ha_ibmdb2i::doCommit",("Committing all"));
- return (db2i_ileBridge::getBridgeForThread(thd)->commitmentControl(QMY_COMMIT));
- }
- else
- {
- DBUG_PRINT("ha_ibmdb2i::doCommit",("Committing stmt"));
- return (db2i_ileBridge::getBridgeForThread(thd)->commitStmtTx());
- }
- }
-
- return (0);
-}
-
-
-int ha_ibmdb2i::doRollback(handlerton *hton, THD *thd, bool all)
-{
- if (!THDVAR(thd,transaction_unsafe))
- {
- if (all || autoCommitIsOn(thd))
- {
- DBUG_PRINT("ha_ibmdb2i::doRollback",("Rolling back all"));
- return ( db2i_ileBridge::getBridgeForThread(thd)->commitmentControl(QMY_ROLLBACK));
- }
- else
- {
- DBUG_PRINT("ha_ibmdb2i::doRollback",("Rolling back stmt"));
- return (db2i_ileBridge::getBridgeForThread(thd)->rollbackStmtTx());
- }
- }
- return (0);
-}
-
-
-void ha_ibmdb2i::start_bulk_insert(ha_rows rows)
-{
- DBUG_ENTER("ha_ibmdb2i::start_bulk_insert");
- DBUG_PRINT("ha_ibmdb2i::start_bulk_insert",("Rows hinted %d", rows));
- int rc;
- THD* thd = ha_thd();
- int command = thd_sql_command(thd);
-
- if (db2Table->hasBlobs() ||
- (command == SQLCOM_REPLACE || command == SQLCOM_REPLACE_SELECT))
- rows = 1;
- else if (rows == 0)
- rows = DEFAULT_MAX_ROWS_TO_BUFFER; // Shoot the moon
-
- // If we're doing a multi-row insert, binlogging is active, and the table has an
- // auto_increment column, then we'll attempt to lock the file while we perform a 'fast path' blocked
- // insert. If we can't get the lock, then we'll do a row-by-row 'slow path' insert instead. The reason is
- // because the MI generates the auto_increment (identity value), and if we can't lock the file,
- // then we can't predetermine what that value will be for insertion into the MySQL write buffer.
-
- if ((rows > 1) && // Multi-row insert
- (thd->options & OPTION_BIN_LOG) && // Binlogging is on
- (table->found_next_number_field)) // Table has an auto_increment column
- {
- if (!dataHandle)
- rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection);
-
- rc = bridge()->lockObj(dataHandle, 1, QMY_LOCK, QMY_LEAR, QMY_YES);
- if (rc==0) // Got the lock
- {
- autoIncLockAcquired = TRUE;
- got_auto_inc_values = FALSE;
- }
- else // Didn't get the lock
- rows = 1; // No problem, but don't block inserts
- }
-
- if (activeHandle == 0)
- {
- last_start_bulk_insert_rc = useDataFile();
- if (last_start_bulk_insert_rc == 0)
- last_start_bulk_insert_rc = prepWriteBuffer(rows, db2Table->dataFile());
- }
-
- if (last_start_bulk_insert_rc == 0)
- outstanding_start_bulk_insert = true;
- else
- {
- if (autoIncLockAcquired == TRUE)
- {
- bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LEAR, QMY_YES);
- autoIncLockAcquired = FALSE;
- }
- }
-
- DBUG_VOID_RETURN;
-}
-
-
-int ha_ibmdb2i::end_bulk_insert()
-{
- DBUG_ENTER("ha_ibmdb2i::end_bulk_insert");
- int rc = 0;
-
- if (outstanding_start_bulk_insert)
- {
- rc = finishBulkInsert();
- }
-
- my_errno = rc;
-
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::prepReadBuffer(ha_rows rowsToRead, const db2i_file* file, char intent)
-{
- DBUG_ENTER("ha_ibmdb2i::prepReadBuffer");
- DBUG_ASSERT(rowsToRead > 0);
-
- THD* thd = ha_thd();
- char cmtLvl = getCommitLevel(thd);
-
- const db2i_file::RowFormat* format;
- int rc = file->obtainRowFormat(activeHandle, intent, cmtLvl, &format);
-
- if (unlikely(rc)) DBUG_RETURN(rc);
-
- if (lobFieldsRequested())
- {
- forceSingleRowRead = true;
- rowsToRead = 1;
- }
-
- rowsToRead = min(stats.records+1,min(rowsToRead, DEFAULT_MAX_ROWS_TO_BUFFER));
-
- uint bufSize = min((format->readRowLen * rowsToRead), THDVAR(thd, max_read_buffer_size));
- multiRowReadBuf.allocBuf(format->readRowLen, format->readRowNullOffset, bufSize);
- activeReadBuf = &multiRowReadBuf;
-
- if (db2Table->hasBlobs())
- {
- if (!blobReadBuffers)
- blobReadBuffers = new BlobCollection(db2Table, THDVAR(thd, lob_alloc_size));
- rc = prepareReadBufferForLobs();
- if (rc) DBUG_RETURN(rc);
- }
-
-// if (accessIntent == QMY_UPDATABLE &&
-// thd_tx_isolation(thd) == ISO_REPEATABLE_READ &&
-// !THDVAR(thd, transaction_unsafe))
-// activeReadBuf->update(QMY_READ_ONLY, &releaseRowNeeded, QMY_REPEATABLE_READ);
-// else
- activeReadBuf->update(intent, &releaseRowNeeded, cmtLvl);
-
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::prepWriteBuffer(ha_rows rowsToWrite, const db2i_file* file)
-{
- DBUG_ENTER("ha_ibmdb2i::prepWriteBuffer");
- DBUG_ASSERT(accessIntent == QMY_UPDATABLE && rowsToWrite > 0);
-
- const db2i_file::RowFormat* format;
- int rc = file->obtainRowFormat(activeHandle,
- QMY_UPDATABLE,
- getCommitLevel(ha_thd()),
- &format);
-
- if (unlikely(rc)) DBUG_RETURN(rc);
-
- rowsToWrite = min(rowsToWrite, DEFAULT_MAX_ROWS_TO_BUFFER);
-
- uint bufSize = min((format->writeRowLen * rowsToWrite), THDVAR(ha_thd(), max_write_buffer_size));
- multiRowWriteBuf.allocBuf(format->writeRowLen, format->writeRowNullOffset, bufSize);
- activeWriteBuf = &multiRowWriteBuf;
-
- if (!blobWriteBuffers && db2Table->hasBlobs())
- {
- blobWriteBuffers = new ValidatedPointer<char>[db2Table->getBlobCount()];
- }
- DBUG_RETURN(rc);
-}
-
-
-int ha_ibmdb2i::flushWrite(FILE_HANDLE fileHandle, uchar* buf )
-{
- DBUG_ENTER("ha_ibmdb2i::flushWrite");
- int rc;
- int64 generatedIdValue = 0;
- bool IdValueWasGenerated = FALSE;
- char* lastDupKeyNamePtr = NULL;
- uint32 lastDupKeyNameLen = 0;
- int loopCnt = 0;
- bool retry_dup = FALSE;
-
- while (loopCnt == 0 || retry_dup == TRUE)
- {
- rc = bridge()->writeRows(fileHandle,
- activeWriteBuf->ptr(),
- getCommitLevel(),
- &generatedIdValue,
- &IdValueWasGenerated,
- &lastDupKeyRRN,
- &lastDupKeyNamePtr,
- &lastDupKeyNameLen,
- &incrementByValue);
- loopCnt++;
- retry_dup = FALSE;
- invalidateCachedStats();
- if (lastDupKeyNameLen)
- {
- rrnAssocHandle = fileHandle;
-
- int command = thd_sql_command(ha_thd());
-
- if (command == SQLCOM_REPLACE ||
- command == SQLCOM_REPLACE_SELECT)
- lastDupKeyID = 0;
- else
- {
- lastDupKeyID = getKeyFromName(lastDupKeyNamePtr, lastDupKeyNameLen);
-
- if (likely(lastDupKeyID != MAX_KEY))
- {
- uint16 failedRow = activeWriteBuf->rowsWritten()+1;
-
- if (buf && (failedRow != activeWriteBuf->rowCount()))
- {
- const char* badRow = activeWriteBuf->getRowN(failedRow-1);
- bool savedReadAllColumns = readAllColumns;
- readAllColumns = true;
- mungeDB2row(buf,
- badRow,
- badRow + activeWriteBuf->getRowNullOffset(),
- true);
- readAllColumns = savedReadAllColumns;
-
- if (table->found_next_number_field)
- {
- table->next_number_field->store(next_identity_value - (incrementByValue * (activeWriteBuf->rowCount() - (failedRow - 1))));
- }
- }
-
- if (default_identity_value && // Table has ID colm and generating a value
- (!autoIncLockAcquired || !got_auto_inc_values) &&
- // Writing first or only row in block
- loopCnt == 1 && // Didn't already retry
- lastDupKeyID == table->s->next_number_index) // Autoinc column is in failed index
- {
- if (alterStartWith() == 0) // Reset next Identity value to max+1
- retry_dup = TRUE; // Rtry the write operation
- }
- }
- else
- {
- char unknownIndex[MAX_DB2_FILENAME_LENGTH+1];
- convFromEbcdic(lastDupKeyNamePtr, unknownIndex, min(lastDupKeyNameLen, MAX_DB2_FILENAME_LENGTH));
- unknownIndex[min(lastDupKeyNameLen, MAX_DB2_FILENAME_LENGTH)] = 0;
- getErrTxt(DB2I_ERR_UNKNOWN_IDX, unknownIndex);
- }
- }
- }
- }
-
- if ((rc == 0 || rc == HA_ERR_FOUND_DUPP_KEY)
- && default_identity_value && IdValueWasGenerated &&
- (!autoIncLockAcquired || !got_auto_inc_values))
- {
- /* Save the generated identity value for the MySQL last_insert_id() function. */
- insert_id_for_cur_row = generatedIdValue;
-
- /* Store the value into MySQL's buf for row-based replication
- or for an 'on duplicate key update' clause. */
- table->next_number_field->store((longlong) generatedIdValue, TRUE);
- if (autoIncLockAcquired)
- {
- got_auto_inc_values = TRUE;
- next_identity_value = generatedIdValue + incrementByValue;
- }
- }
- else
- {
- if (!autoIncLockAcquired) // Don't overlay value for first row of a block
- insert_id_for_cur_row = 0;
- }
-
-
- activeWriteBuf->resetAfterWrite();
- DBUG_RETURN(rc);
-}
-
-int ha_ibmdb2i::alterStartWith()
-{
- DBUG_ENTER("ha_ibmdb2i::alterStartWith");
- int rc = 0;
- ulonglong nextIdVal;
- if (!dataHandle)
- rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection);
- if (!rc) {rc = bridge()->lockObj(dataHandle, 1, QMY_LOCK, QMY_LENR, QMY_YES);}
- if (!rc)
- {
- rc = getNextIdVal(&nextIdVal);
- if (!rc) {rc = reset_auto_increment(nextIdVal);}
- bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LENR, QMY_YES);
- }
- DBUG_RETURN(rc);
-}
-
-bool ha_ibmdb2i::lobFieldsRequested()
-{
- if (!db2Table->hasBlobs())
- {
- DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("No LOBs"));
- return (false);
- }
-
- if (readAllColumns)
- {
- DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("All cols requested"));
- return (true);
- }
-
- for (int i = 0; i < db2Table->getBlobCount(); ++i)
- {
- if (bitmap_is_set(table->read_set, db2Table->blobFields[i]))
- {
- DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("LOB requested"));
- return (true);
- }
- }
-
- DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("No LOBs requested"));
- return (false);
-}
-
-
-int ha_ibmdb2i::prepareReadBufferForLobs()
-{
- DBUG_ENTER("ha_ibmdb2i::prepareReadBufferForLobs");
- DBUG_ASSERT(db2Table->hasBlobs());
-
- uint32 activeLobFields = 0;
- DB2LobField* lobField;
- uint16 blobCount = db2Table->getBlobCount();
-
- char* readBuf = activeReadBuf->getRowN(0);
-
- for (int i = 0; i < blobCount; ++i)
- {
- int fieldID = db2Table->blobFields[i];
- DB2Field& db2Field = db2Table->db2Field(fieldID);
- lobField = db2Field.asBlobField(readBuf);
- if (readAllColumns ||
- bitmap_is_set(table->read_set, fieldID))
- {
- lobField->dataHandle = (ILEMemHandle)blobReadBuffers->getBufferPtr(fieldID);
- activeLobFields++;
- }
- else
- {
- lobField->dataHandle = NULL;
- }
- }
-
- if (activeLobFields == 0)
- {
- for (int i = 0; i < blobCount; ++i)
- {
- DB2Field& db2Field = db2Table->db2Field(db2Table->blobFields[i]);
- uint16 offset = db2Field.getBufferOffset() + db2Field.calcBlobPad();
-
- for (int r = 1; r < activeReadBuf->getRowCapacity(); ++r)
- {
- lobField = (DB2LobField*)(activeReadBuf->getRowN(r) + offset);
- lobField->dataHandle = NULL;
- }
- }
- }
-
- activeReadBuf->setRowsToProcess((activeLobFields ? 1 : activeReadBuf->getRowCapacity()));
- int rc = bridge()->objectOverride(activeHandle,
- activeReadBuf->ptr(),
- activeReadBuf->getRowLength());
- DBUG_RETURN(rc);
-}
-
-
-uint32 ha_ibmdb2i::adjustLobBuffersForRead()
-{
- DBUG_ENTER("ha_ibmdb2i::adjustLobBuffersForRead");
-
- char* readBuf = activeReadBuf->getRowN(0);
-
- for (int i = 0; i < db2Table->getBlobCount(); ++i)
- {
- DB2Field& db2Field = db2Table->db2Field(db2Table->blobFields[i]);
- DB2LobField* lobField = db2Field.asBlobField(readBuf);
- if (readAllColumns ||
- bitmap_is_set(table->read_set, db2Table->blobFields[i]))
- {
- lobField->dataHandle = (ILEMemHandle)blobReadBuffers->reallocBuffer(db2Table->blobFields[i], lobField->length);
-
- if (lobField->dataHandle == NULL)
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- }
- else
- {
- lobField->dataHandle = 0;
- }
- }
-
- int32 rc = bridge()->objectOverride(activeHandle,
- activeReadBuf->ptr());
- DBUG_RETURN(rc);
-}
-
-
-
-int ha_ibmdb2i::reset()
-{
- DBUG_ENTER("ha_ibmdb2i::reset");
-
- if (outstanding_start_bulk_insert)
- {
- finishBulkInsert();
- }
-
- if (activeHandle != 0)
- {
- releaseActiveHandle();
- }
-
- cleanupBuffers();
-
- db2i_ileBridge::getBridgeForThread(ha_thd())->freeErrorStorage();
-
- last_rnd_init_rc = last_index_init_rc = last_start_bulk_insert_rc = 0;
-
- returnDupKeysImmediately = false;
- onDupUpdate = false;
- forceSingleRowRead = false;
-
-#ifndef DBUG_OFF
- cachedBridge=NULL;
-#endif
-
- DBUG_RETURN(0);
-}
-
-
-int32 ha_ibmdb2i::buildCreateIndexStatement(SqlStatementStream& sqlStream,
- KEY& key,
- bool isPrimary,
- const char* db2LibName,
- const char* db2FileName)
-{
- DBUG_ENTER("ha_ibmdb2i::buildCreateIndexStatement");
-
- char fileSortSequence[11] = "*HEX";
- char fileSortSequenceLibrary[11] = "";
- char fileSortSequenceType = ' ';
- String query(256);
- query.length(0);
- int rc = 0;
-
- if (isPrimary)
- {
- query.append(STRING_WITH_LEN("ALTER TABLE "));
- query.append(db2LibName);
- query.append('.');
- query.append(db2FileName);
- query.append(STRING_WITH_LEN(" ADD PRIMARY KEY "));
- }
- else
- {
- query.append(STRING_WITH_LEN("CREATE"));
-
- if (key.flags & HA_NOSAME)
- query.append(STRING_WITH_LEN(" UNIQUE WHERE NOT NULL"));
-
- query.append(STRING_WITH_LEN(" INDEX "));
-
- query.append(db2LibName);
- query.append('.');
- if (db2i_table::appendQualifiedIndexFileName(key.name, db2FileName, query))
- {
- getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*");
- DBUG_RETURN(DB2I_ERR_INVALID_NAME );
- }
-
- query.append(STRING_WITH_LEN(" ON "));
-
- query.append(db2LibName);
- query.append('.');
- query.append(db2FileName);
- }
-
- String fieldDefinition(128);
- rc = buildIndexFieldList(fieldDefinition,
- key,
- isPrimary,
- &fileSortSequenceType,
- fileSortSequence,
- fileSortSequenceLibrary);
-
- if (rc) DBUG_RETURN(rc);
-
- query.append(fieldDefinition);
-
- if ((THDVAR(ha_thd(), create_index_option)==1) &&
- (fileSortSequenceType != 'B') &&
- (fileSortSequenceType != ' '))
- {
- rc = generateShadowIndex(sqlStream,
- key,
- db2LibName,
- db2FileName,
- fieldDefinition);
- if (rc) DBUG_RETURN(rc);
- }
-
- DBUG_PRINT("ha_ibmdb2i::buildCreateIndexStatement", ("Sent to DB2: %s",query.c_ptr_safe()));
- sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary);
-
- DBUG_RETURN(0);
-}
-
-/**
- Generate the SQL syntax for the list of fields to be assigned to the
- specified key. The corresponding sort sequence is also calculated.
-
- @param[out] appendHere The string to receive the generated SQL
- @param key The key to evaluate
- @param isPrimary True if this is being generated on behalf of the primary key
- @param[out] fileSortSequenceType The type of the associated sort sequence
- @param[out] fileSortSequence The name of the associated sort sequence
- @param[out] fileSortSequenceLibrary The library of the associated sort sequence
-
- @return 0 if successful; error value otherwise
-*/
-int32 ha_ibmdb2i::buildIndexFieldList(String& appendHere,
- const KEY& key,
- bool isPrimary,
- char* fileSortSequenceType,
- char* fileSortSequence,
- char* fileSortSequenceLibrary)
-{
- DBUG_ENTER("ha_ibmdb2i::buildIndexFieldList");
- appendHere.append(STRING_WITH_LEN(" ( "));
- for (int j = 0; j < key.key_parts; ++j)
- {
- char colName[MAX_DB2_COLNAME_LENGTH+1];
- if (j != 0)
- {
- appendHere.append(STRING_WITH_LEN(" , "));
- }
-
- KEY_PART_INFO& kpi = key.key_part[j];
- Field* field = kpi.field;
-
- convertMySQLNameToDB2Name(field->field_name,
- colName,
- sizeof(colName));
- appendHere.append(colName);
-
- int32 rc;
- rc = updateAssociatedSortSequence(field->charset(),
- fileSortSequenceType,
- fileSortSequence,
- fileSortSequenceLibrary);
- if (rc) DBUG_RETURN (rc);
- }
-
- appendHere.append(STRING_WITH_LEN(" ) "));
-
- DBUG_RETURN(0);
-}
-
-
-/**
- Generate an SQL statement that defines a *HEX sorted index to implement
- the ibmdb2i_create_index.
-
- @param[out] stream The stream to append the generated statement to
- @param key The key to evaluate
- @param[out] libName The library containg the table
- @param[out] fileName The DB2-compatible name of the table
- @param[out] fieldDefinition The list of the fields in the index, in SQL syntax
-
- @return 0 if successful; error value otherwise
-*/
-int32 ha_ibmdb2i::generateShadowIndex(SqlStatementStream& stream,
- const KEY& key,
- const char* libName,
- const char* fileName,
- const String& fieldDefinition)
-{
- String shadowQuery(256);
- shadowQuery.length(0);
- shadowQuery.append(STRING_WITH_LEN("CREATE INDEX "));
- shadowQuery.append(libName);
- shadowQuery.append('.');
- if (db2i_table::appendQualifiedIndexFileName(key.name, fileName, shadowQuery, db2i_table::ASCII_SQL, typeHex))
- {
- getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*");
- return DB2I_ERR_INVALID_NAME;
- }
- shadowQuery.append(STRING_WITH_LEN(" ON "));
- shadowQuery.append(libName);
- shadowQuery.append('.');
- shadowQuery.append(fileName);
- shadowQuery.append(fieldDefinition);
- DBUG_PRINT("ha_ibmdb2i::generateShadowIndex", ("Sent to DB2: %s",shadowQuery.c_ptr_safe()));
- stream.addStatement(shadowQuery,"*HEX","QSYS");
- return 0;
-}
-
-
-void ha_ibmdb2i::doInitialRead(char orientation,
- uint32 rowsToBuffer,
- ILEMemHandle key,
- int keyLength,
- int keyParts)
-{
- DBUG_ENTER("ha_ibmdb2i::doInitialRead");
-
- if (forceSingleRowRead)
- rowsToBuffer = 1;
- else
- rowsToBuffer = min(rowsToBuffer, activeReadBuf->getRowCapacity());
-
- activeReadBuf->newReadRequest(activeHandle,
- orientation,
- rowsToBuffer,
- THDVAR(ha_thd(), async_enabled),
- key,
- keyLength,
- keyParts);
- DBUG_VOID_RETURN;
-}
-
-
-int ha_ibmdb2i::start_stmt(THD *thd, thr_lock_type lock_type)
-{
- DBUG_ENTER("ha_ibmdb2i::start_stmt");
- initBridge(thd);
- if (!THDVAR(thd, transaction_unsafe))
- {
- trans_register_ha(thd, FALSE, ibmdb2i_hton);
-
- if (!autoCommitIsOn(thd))
- {
- bridge()->beginStmtTx();
- }
- }
-
- DBUG_RETURN(0);
-}
-
-int32 ha_ibmdb2i::handleLOBReadOverflow()
-{
- DBUG_ENTER("ha_ibmdb2i::handleLOBReadOverflow");
- DBUG_ASSERT(db2Table->hasBlobs() && (activeReadBuf->getRowCapacity() == 1));
-
- int32 rc = adjustLobBuffersForRead();
-
- if (!rc)
- {
- activeReadBuf->rewind();
- rc = bridge()->expectErrors(QMY_ERR_END_OF_BLOCK)
- ->read(activeHandle,
- activeReadBuf->ptr(),
- accessIntent,
- getCommitLevel(),
- QMY_SAME);
- releaseRowNeeded = TRUE;
-
- }
- DBUG_RETURN(rc);
-}
-
-
-int32 ha_ibmdb2i::finishBulkInsert()
-{
- int32 rc = 0;
-
- if (activeWriteBuf->rowCount() && activeHandle)
- rc = flushWrite(activeHandle, table->record[0]);
-
- if (activeHandle)
- releaseActiveHandle();
-
- if (autoIncLockAcquired == TRUE)
- {
- // We could check the return code on the unlock, but beware not
- // to overlay the return code from the flushwrite or we will mask
- // duplicate key errors..
- bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LEAR, QMY_YES);
- autoIncLockAcquired = FALSE;
- }
- outstanding_start_bulk_insert = false;
- multiRowWriteBuf.freeBuf();
- last_start_bulk_insert_rc = 0;
-
- resetCharacterConversionBuffers();
-
- return rc;
-}
-
-int ha_ibmdb2i::getKeyFromName(const char* name, size_t len)
-{
- for (int i = 0; i < table_share->keys; ++i)
- {
- const char* indexName = db2Table->indexFile(i)->getDB2FileName();
- if ((strncmp(name, indexName, len) == 0) &&
- (strlen(indexName) == len))
- {
- return i;
- }
- }
- return MAX_KEY;
-}
-
-/*
-Determine the number of I/O's it takes to read through the table.
- */
-double ha_ibmdb2i::scan_time()
- {
- DBUG_ENTER("ha_ibmdb2i::scan_time");
- DBUG_RETURN(ulonglong2double((stats.data_file_length)/IO_SIZE));
- }
-
-
-/**
- Estimate the number of I/O's it takes to read a set of ranges through
- an index.
-
- @param index
- @param ranges
- @param rows
-
- @return The estimate number of I/Os
-*/
-
-double ha_ibmdb2i::read_time(uint index, uint ranges, ha_rows rows)
-{
- DBUG_ENTER("ha_ibmdb2i::read_time");
- int rc;
- uint64 idxPageCnt = 0;
- double cost;
-
- if (unlikely(rows == HA_POS_ERROR))
- DBUG_RETURN(double(rows) + ranges);
-
- rc = bridge()->retrieveIndexInfo(db2Table->indexFile(index)->getMasterDefnHandle(),
- &idxPageCnt);
- if (!rc)
- {
- if ((idxPageCnt == 1) || // Retrieving rows in requested order or
- (ranges == rows)) // 'Sweep' full records retrieval
- cost = idxPageCnt/4;
- else
- {
- uint64 totalRecords = stats.records + 1;
- double dataPageCount = stats.data_file_length/IO_SIZE;
-
- cost = (rows * dataPageCount / totalRecords) +
- min(idxPageCnt, (log_2(idxPageCnt) * ranges +
- rows * (log_2(idxPageCnt) + log_2(rows) - log_2(totalRecords))));
- }
- }
- else
- {
- cost = rows2double(ranges+rows); // Use default costing
- }
- DBUG_RETURN(cost);
-}
-
-int ha_ibmdb2i::useIndexFile(int idx)
-{
- DBUG_ENTER("ha_ibmdb2i::useIndexFile");
-
- if (activeHandle)
- releaseActiveHandle();
-
- int rc = 0;
-
- if (!indexHandles[idx])
- rc = db2Table->indexFile(idx)->allocateNewInstance(&indexHandles[idx], curConnection);
-
- if (rc == 0)
- {
- activeHandle = indexHandles[idx];
- bumpInUseCounter(1);
- }
-
- DBUG_RETURN(rc);
-}
-
-
-ulong ha_ibmdb2i::index_flags(uint inx, uint part, bool all_parts) const
-{
- return HA_READ_NEXT | HA_READ_PREV | HA_KEYREAD_ONLY | HA_READ_ORDER | HA_READ_RANGE;
-}
-
-
-static struct st_mysql_sys_var* ibmdb2i_system_variables[] = {
- MYSQL_SYSVAR(rdb_name),
- MYSQL_SYSVAR(transaction_unsafe),
- MYSQL_SYSVAR(lob_alloc_size),
- MYSQL_SYSVAR(max_read_buffer_size),
- MYSQL_SYSVAR(max_write_buffer_size),
- MYSQL_SYSVAR(async_enabled),
- MYSQL_SYSVAR(assume_exclusive_use),
- MYSQL_SYSVAR(compat_opt_blob_cols),
- MYSQL_SYSVAR(compat_opt_time_as_duration),
- MYSQL_SYSVAR(compat_opt_allow_zero_date_vals),
- MYSQL_SYSVAR(compat_opt_year_as_int),
- MYSQL_SYSVAR(propagate_default_col_vals),
- MYSQL_SYSVAR(create_index_option),
-// MYSQL_SYSVAR(discovery_mode),
- MYSQL_SYSVAR(system_trace_level),
- NULL
-};
-
-
-struct st_mysql_storage_engine ibmdb2i_storage_engine=
-{ MYSQL_HANDLERTON_INTERFACE_VERSION };
-
-mysql_declare_plugin(ibmdb2i)
-{
- MYSQL_STORAGE_ENGINE_PLUGIN,
- &ibmdb2i_storage_engine,
- "IBMDB2I",
- "The IBM development team in Rochester, Minnesota",
- "IBM DB2 for i Storage Engine",
- PLUGIN_LICENSE_GPL,
- ibmdb2i_init_func, /* Plugin Init */
- ibmdb2i_done_func, /* Plugin Deinit */
- 0x0100 /* 1.0 */,
- NULL, /* status variables */
- ibmdb2i_system_variables, /* system variables */
- NULL /* config options */
-}
-mysql_declare_plugin_end;
-maria_declare_plugin(ibmdb2i)
-{
- MYSQL_STORAGE_ENGINE_PLUGIN,
- &ibmdb2i_storage_engine,
- "IBMDB2I",
- "The IBM development team in Rochester, Minnesota",
- "IBM DB2 for i Storage Engine",
- PLUGIN_LICENSE_GPL,
- ibmdb2i_init_func, /* Plugin Init */
- ibmdb2i_done_func, /* Plugin Deinit */
- 0x0100 /* 1.0 */,
- NULL, /* status variables */
- ibmdb2i_system_variables, /* system variables */
- "1.0", /* string version */
- MariaDB_PLUGIN_MATURITY_UNKNOWN /* maturity */
-}
-maria_declare_plugin_end;
diff --git a/storage/ibmdb2i/ha_ibmdb2i.h b/storage/ibmdb2i/ha_ibmdb2i.h
deleted file mode 100644
index b2a43232f2d..00000000000
--- a/storage/ibmdb2i/ha_ibmdb2i.h
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
-Licensed Materials - Property of IBM
-DB2 Storage Engine Enablement
-Copyright IBM Corporation 2007,2008
-All rights reserved
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- (a) Redistributions of source code must retain this list of conditions, the
- copyright notice in section {d} below, and the disclaimer following this
- list of conditions.
- (b) Redistributions in binary form must reproduce this list of conditions, the
- copyright notice in section (d) below, and the disclaimer following this
- list of conditions, in the documentation and/or other materials provided
- with the distribution.
- (c) The name of IBM may not be used to endorse or promote products derived from
- this software without specific prior written permission.
- (d) The text of the required copyright notice is:
- Licensed Materials - Property of IBM
- DB2 Storage Engine Enablement
- Copyright IBM Corporation 2007,2008
- All rights reserved
-
-THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-/** @file ha_ibmdb2i.h
-
- @brief
-
- @note
-
- @see
-*/
-
-#ifdef USE_PRAGMA_INTERFACE
-#pragma interface /* gcc class implementation */
-#endif
-
-#include "as400_types.h"
-#include "as400_protos.h"
-#include "db2i_global.h"
-#include "db2i_ileBridge.h"
-#include "builtins.h"
-#include "db2i_misc.h"
-#include "db2i_file.h"
-#include "db2i_blobCollection.h"
-#include "db2i_collationSupport.h"
-#include "db2i_validatedPointer.h"
-#include "db2i_ioBuffers.h"
-#include "db2i_errors.h"
-#include "db2i_sqlStatementStream.h"
-
-/** @brief
- IBMDB2I_SHARE is a structure that will be shared among all open handlers.
- It is used to describe the underlying table definition, and it caches
- table statistics.
-*/
-struct IBMDB2I_SHARE {
- char *table_name;
- uint table_name_length,use_count;
- pthread_mutex_t mutex;
- THR_LOCK lock;
-
- db2i_table* db2Table;
-
- class CStats
- {
- public:
- void cacheUpdateTime(time_t time)
- {update_time = time; initFlag |= lastModTime;}
- time_t getUpdateTime() const
- {return update_time;}
- void cacheRowCount(ha_rows rows)
- {records = rows; initFlag |= rowCount;}
- ha_rows getRowCount() const
- {return records;}
- void cacheDelRowCount(ha_rows rows)
- {deleted = rows; initFlag |= deletedRowCount;}
- ha_rows getDelRowCount() const
- {return deleted;}
- void cacheMeanLength(ulong len)
- {mean_rec_length = len; initFlag |= meanRowLen;}
- ulong getMeanLength()
- {return mean_rec_length;}
- void cacheAugmentedDataLength(ulong len)
- {data_file_length = len; initFlag |= ioCount;}
- ulong getAugmentedDataLength()
- {return data_file_length;}
- bool isInited(uint flags)
- {return initFlag & flags;}
- void invalidate(uint flags)
- {initFlag &= ~flags;}
-
- private:
- uint initFlag;
- time_t update_time;
- ha_rows records;
- ha_rows deleted;
- ulong mean_rec_length;
- ulong data_file_length;
- } cachedStats;
-
-};
-
-class ha_ibmdb2i: public handler
-{
- THR_LOCK_DATA lock; ///< MySQL lock
- IBMDB2I_SHARE *share; ///< Shared lock info
-
- // The record we are positioned on, together with the handle used to get
- // i.
- uint32 currentRRN;
- uint32 rrnAssocHandle;
-
- // Dup key values needed by info()
- uint32 lastDupKeyRRN;
- uint32 lastDupKeyID;
-
- bool returnDupKeysImmediately;
-
- // Dup key value need by update()
- bool onDupUpdate;
-
-
- db2i_table* db2Table;
-
- // The file handle of the PF or LF being accessed by the current operation.
- FILE_HANDLE activeHandle;
-
- // The file handle of the underlying PF
- FILE_HANDLE dataHandle;
-
- // Array of file handles belonging to the underlying LFs
- FILE_HANDLE* indexHandles;
-
- // Flag to indicate whether a call needs to be made to unlock a row when
- // a read operation has ended. DB2 will handle row unlocking as we move
- // through rows, but if an operation ends before we reach the end of a file,
- // DB2 needs to know to unlock the last row read.
- bool releaseRowNeeded;
-
- // Pointer to a definition of the layout of the row buffer for the file
- // described by activeHandle
- const db2i_file::RowFormat* activeFormat;
-
- IORowBuffer keyBuf;
- uint32 keyLen;
-
- IOWriteBuffer multiRowWriteBuf;
- IOAsyncReadBuffer multiRowReadBuf;
-
- IOAsyncReadBuffer* activeReadBuf;
- IOWriteBuffer* activeWriteBuf;
-
- BlobCollection* blobReadBuffers; // Dynamically allocated per query and used
- // to manage the buffers used for reading LOBs
- ValidatedPointer<char>* blobWriteBuffers;
-
- // Return codes are not used/honored by rnd_init and start_bulk_insert
- // so we need a way to signal the failure "downstream" to subsequent
- // functions.
- int last_rnd_init_rc;
- int last_index_init_rc;
- int last_start_bulk_insert_rc;
-
- // end_bulk_insert may get called twice for a single start_bulk_insert
- // This is our way to do cleanup only once.
- bool outstanding_start_bulk_insert;
-
- // Auto_increment 'increment by' value needed by write_row()
- uint32 incrementByValue;
- bool default_identity_value;
-
- // Flags and values used during write operations for auto_increment processing
- bool autoIncLockAcquired;
- bool got_auto_inc_values;
- uint64 next_identity_value;
-
- // The access intent indicated by the last external_locks() call.
- // May be either QMY_READ or QMY_UPDATABLE
- char accessIntent;
- char readAccessIntent;
-
- ha_rows* indexReadSizeEstimates;
-
- MEM_ROOT conversionBufferMemroot;
-
- bool forceSingleRowRead;
-
- bool readAllColumns;
-
- bool invalidDataFound;
-
- db2i_ileBridge* cachedBridge;
-
- ValidatedObject<volatile uint32> curConnection;
- uint16 activeReferences;
-
-public:
-
- ha_ibmdb2i(handlerton *hton, TABLE_SHARE *table_arg);
- ~ha_ibmdb2i();
-
- const char *table_type() const { return "IBMDB2I"; }
- const char *index_type(uint inx) { return "RADIX"; }
- const key_map *keys_to_use_for_scanning() { return &key_map_full; }
- const char **bas_ext() const;
-
- ulonglong table_flags() const
- {
- return HA_NULL_IN_KEY | HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY |
- HA_PARTIAL_COLUMN_READ |
- HA_DUPLICATE_POS | HA_NO_PREFIX_CHAR_KEYS |
- HA_HAS_RECORDS | HA_BINLOG_ROW_CAPABLE | HA_REQUIRES_KEY_COLUMNS_FOR_DELETE |
- HA_CAN_INDEX_BLOBS;
- }
-
- ulong index_flags(uint inx, uint part, bool all_parts) const;
-
-// Note that we do not implement max_supported_record_length.
-// We'll let create fail accordingly if the row is
-// too long. This allows us to hide the fact that varchars > 32K are being
-// implemented as DB2 LOBs.
-
- uint max_supported_keys() const { return 4000; }
- uint max_supported_key_parts() const { return MAX_DB2_KEY_PARTS; }
- uint max_supported_key_length() const { return 32767; }
- uint max_supported_key_part_length() const { return 32767; }
- double read_time(uint index, uint ranges, ha_rows rows);
- double scan_time();
- int open(const char *name, int mode, uint test_if_locked);
- int close(void);
- int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
- int delete_row(const uchar * buf);
- int index_init(uint idx, bool sorted);
- int index_read(uchar * buf, const uchar * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_next(uchar * buf);
- int index_read_last(uchar * buf, const uchar * key, uint key_len);
- int index_next_same(uchar *buf, const uchar *key, uint keylen);
- int index_prev(uchar * buf);
- int index_first(uchar * buf);
- int index_last(uchar * buf);
- int rnd_init(bool scan);
- int rnd_end();
- int rnd_next(uchar *buf);
- int rnd_pos(uchar * buf, uchar *pos);
- void position(const uchar *record);
- int info(uint);
- ha_rows records();
- int extra(enum ha_extra_function operation);
- int external_lock(THD *thd, int lock_type);
- int delete_all_rows(void);
- ha_rows records_in_range(uint inx, key_range *min_key,
- key_range *max_key);
- int delete_table(const char *from);
- int rename_table(const char * from, const char * to);
- int create(const char *name, TABLE *form,
- HA_CREATE_INFO *create_info);
- int updateFrm(TABLE *table_def, File file);
- int openTableDef(TABLE *table_def);
- int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys);
- int prepare_drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys);
- int final_drop_index(TABLE *table_arg) {return 0;}
- void get_auto_increment(ulonglong offset, ulonglong increment,
- ulonglong nb_desired_values,
- ulonglong *first_value,
- ulonglong *nb_reserved_values);
- int reset_auto_increment(ulonglong value);
- void restore_auto_increment(ulonglong prev_insert_id) {return;}
- void update_create_info(HA_CREATE_INFO *create_info);
- int getNextIdVal(ulonglong *value);
- int analyze(THD* thd,HA_CHECK_OPT* check_opt);
- int optimize(THD* thd, HA_CHECK_OPT* check_opt);
- bool can_switch_engines();
- void free_foreign_key_create_info(char* str);
- char* get_foreign_key_create_info();
- int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
- uint referenced_by_foreign_key();
- bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
- virtual bool get_error_message(int error, String *buf);
-
- THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
- enum thr_lock_type lock_type);
-
- bool low_byte_first() const { return 0; }
- void unlock_row();
- int index_end();
- int reset();
- static int doCommit(handlerton *hton, THD *thd, bool all);
- static int doRollback(handlerton *hton, THD *thd, bool all);
- void start_bulk_insert(ha_rows rows);
- int end_bulk_insert();
- int start_stmt(THD *thd, thr_lock_type lock_type);
-
- void initBridge(THD* thd = NULL)
- {
- if (thd == NULL) thd = ha_thd();
- DBUG_PRINT("ha_ibmdb2i::initBridge",("Initing bridge. Conn ID=%d", thd->thread_id));
- cachedBridge = db2i_ileBridge::getBridgeForThread(thd);
- }
-
- db2i_ileBridge* bridge() {DBUG_ASSERT(cachedBridge); return cachedBridge;}
-
- static uint8 autoCommitIsOn(THD* thd)
- { return (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ? QMY_NO : QMY_YES); }
-
- uint8 getCommitLevel();
- uint8 getCommitLevel(THD* thd);
-
- static int doSavepointSet(THD* thd, char* name)
- {
- return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_SET_SAVEPOINT,
- name);
- }
-
- static int doSavepointRollback(THD* thd, char* name)
- {
- return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_ROLLBACK_SAVEPOINT,
- name);
- }
-
- static int doSavepointRelease(THD* thd, char* name)
- {
- return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_RELEASE_SAVEPOINT,
- name);
- }
-
- // We can't guarantee that the rows we know about when this is called
- // will be the same number of rows that read returns (since DB2 activity
- // may insert additional rows). Therefore, we do as the Federated SE and
- // return the max possible.
- ha_rows estimate_rows_upper_bound()
- {
- return HA_POS_ERROR;
- }
-
-
-private:
-
- enum enum_TimeFormat
- {
- TIME_OF_DAY,
- DURATION
- };
-
- enum enum_BlobMapping
- {
- AS_BLOB,
- AS_VARCHAR
- };
-
- enum enum_ZeroDate
- {
- NO_SUBSTITUTE,
- SUBSTITUTE_0001_01_01
- };
-
- enum enum_YearFormat
- {
- CHAR4,
- SMALLINT
- };
-
- enum_ZeroDate cachedZeroDateOption;
-
- IBMDB2I_SHARE *get_share(const char *table_name, TABLE *table);
- int free_share(IBMDB2I_SHARE *share);
- int32 mungeDB2row(uchar* record, const char* dataPtr, const char* nullMapPtr, bool skipLOBs);
- int prepareRowForWrite(char* data, char* nulls, bool honorIdentCols);
- int prepareReadBufferForLobs();
- int32 prepareWriteBufferForLobs();
- uint32 adjustLobBuffersForRead();
- bool lobFieldsRequested();
- int convertFieldChars(enum_conversionDirection direction,
- uint16 fieldID,
- const char* input,
- char* output,
- size_t ilen,
- size_t olen,
- size_t* outDataLen,
- bool tacitErrors=FALSE,
- size_t* substChars=NULL);
-
- /**
- Fast integer log2 function
- */
- uint64 log_2(uint64 val)
- {
- uint64 exp = 0;
- while( (val >> exp) != 0)
- {
- exp++;
- }
- DBUG_ASSERT(exp-1 == (uint64)log2(val));
- return exp-1;
- }
-
- void bumpInUseCounter(uint16 amount)
- {
- activeReferences += amount;
- DBUG_PRINT("ha_ibmdb2i::bumpInUseCounter", ("activeReferences = %d", activeReferences));
- if (activeReferences)
- curConnection = (uint32)(ha_thd()->thread_id);
- else
- curConnection = 0;
- }
-
-
- int useDataFile()
- {
- DBUG_ENTER("ha_ibmdb2i::useDataFile");
-
- int rc = 0;
- if (!dataHandle)
- rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection);
- else if (activeHandle == dataHandle)
- DBUG_RETURN(0);
-
- DBUG_ASSERT(activeHandle == 0);
-
- if (likely(rc == 0))
- {
- activeHandle = dataHandle;
- bumpInUseCounter(1);
- }
-
- DBUG_RETURN(rc);
- }
-
- void releaseAnyLockedRows()
- {
- if (releaseRowNeeded)
- {
- DBUG_PRINT("ha_ibmdb2i::releaseAnyLockedRows", ("Releasing rows"));
- db2i_ileBridge::getBridgeForThread()->rrlslck(activeHandle, accessIntent);
- releaseRowNeeded = FALSE;
- }
- }
-
-
- void releaseDataFile()
- {
- DBUG_ENTER("ha_ibmdb2i::releaseDataFile");
- releaseAnyLockedRows();
- bumpInUseCounter(-1);
- DBUG_ASSERT((volatile int)activeReferences >= 0);
- activeHandle = 0;
- DBUG_VOID_RETURN;
- }
-
- int useIndexFile(int idx);
-
- void releaseIndexFile(int idx)
- {
- DBUG_ENTER("ha_ibmdb2i::releaseIndexFile");
- releaseAnyLockedRows();
- bumpInUseCounter(-1);
- DBUG_ASSERT((volatile int)activeReferences >= 0);
- activeHandle = 0;
- DBUG_VOID_RETURN;
- }
-
- FILE_HANDLE allocateFileHandle(char* database, char* table, int* activityReference, bool hasBlobs);
-
- int updateBuffers(const db2i_file::RowFormat* format, uint rowsToRead, uint rowsToWrite);
-
- int flushWrite(FILE_HANDLE fileHandle, uchar* buf = NULL);
-
- int alterStartWith();
-
- int buildDB2ConstraintString(LEX* lex,
- String& appendHere,
- const char* database,
- Field** fields,
- char* fileSortSequenceType,
- char* fileSortSequence,
- char* fileSortSequenceLibrary);
-
- void releaseWriteBuffer();
-
- void setIndexReadEstimate(uint index, ha_rows rows)
- {
- if (!indexReadSizeEstimates)
- {
- indexReadSizeEstimates = (ha_rows*)my_malloc(sizeof(ha_rows) * table->s->keys, MYF(MY_WME | MY_ZEROFILL));
- }
- indexReadSizeEstimates[index] = rows;
- }
-
- ha_rows getIndexReadEstimate(uint index)
- {
- if (indexReadSizeEstimates)
- return max(indexReadSizeEstimates[index], 1);
-
- return 10000; // Assume index scan if no estimate exists.
- }
-
-
- void quiesceAllFileHandles()
- {
- db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread();
- if (dataHandle)
- {
- bridge->quiesceFileInstance(dataHandle);
- }
-
- for (int idx = 0; idx < table_share->keys; ++idx)
- {
- if (indexHandles[idx] != 0)
- {
- bridge->quiesceFileInstance(indexHandles[idx]);
- }
- }
- }
-
- int32 buildCreateIndexStatement(SqlStatementStream& sqlStream,
- KEY& key,
- bool isPrimary,
- const char* db2LibName,
- const char* db2FileName);
-
- int32 buildIndexFieldList(String& appendHere,
- const KEY& key,
- bool isPrimary,
- char* fileSortSequenceType,
- char* fileSortSequence,
- char* fileSortSequenceLibrary);
-
- // Specify NULL for data when using the data pointed to by field
- int32 convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char* db2Buf, const uchar* data = NULL);
-
- int32 convertDB2toMySQL(const DB2Field& db2Field, Field* field, const char* buf);
- int getFieldTypeMapping(Field* field,
- String& mapping,
- enum_TimeFormat timeFormate,
- enum_BlobMapping blobMapping,
- enum_ZeroDate zeroDateHandling,
- bool propagateDefaults,
- enum_YearFormat yearFormat);
-
- int getKeyFromName(const char* name, size_t len);
-
- void releaseActiveHandle()
- {
- if (activeHandle == dataHandle)
- releaseDataFile();
- else
- releaseIndexFile(active_index);
- }
-
-
- int32 finishBulkInsert();
-
- void doInitialRead(char orientation,
- uint32 rowsToBuffer,
- ILEMemHandle key = 0,
- int keyLength = 0,
- int keyParts = 0);
-
-
- int32 readFromBuffer(uchar* destination, char orientation)
- {
- char* row;
- int32 rc = 0;
- row = activeReadBuf->readNextRow(orientation, currentRRN);
-
- if (unlikely(!row))
- {
- rc = activeReadBuf->lastrc();
- if (rc == QMY_ERR_LOB_SPACE_TOO_SMALL)
- {
- rc = handleLOBReadOverflow();
- if (rc == 0)
- {
- DBUG_ASSERT(activeReadBuf->rowCount() == 1);
- row = activeReadBuf->readNextRow(orientation, currentRRN);
-
- if (unlikely(!row))
- rc = activeReadBuf->lastrc();
- }
- }
- }
-
- if (likely(rc == 0))
- {
- rrnAssocHandle = activeHandle;
- rc = mungeDB2row(destination, row, row+activeReadBuf->getRowNullOffset(), false);
- }
- return rc;
- }
-
- int32 handleLOBReadOverflow();
-
- char* getCharacterConversionBuffer(int fieldId, int length)
- {
- if (unlikely(!alloc_root_inited(&conversionBufferMemroot)))
- init_alloc_root(&conversionBufferMemroot, 8192, 0);
-
- return (char*)alloc_root(&conversionBufferMemroot, length);;
- }
-
- void resetCharacterConversionBuffers()
- {
- if (alloc_root_inited(&conversionBufferMemroot))
- {
- free_root(&conversionBufferMemroot, MYF(MY_MARK_BLOCKS_FREE));
- }
- }
-
- void tweakReadSet()
- {
- THD* thd = ha_thd();
- int command = thd_sql_command(thd);
- if ((command == SQLCOM_UPDATE ||
- command == SQLCOM_UPDATE_MULTI) ||
- ((command == SQLCOM_DELETE ||
- command == SQLCOM_DELETE_MULTI) &&
- thd->options & OPTION_BIN_LOG))
- readAllColumns = TRUE;
- else
- readAllColumns = FALSE;
- }
-
- /**
-
- */
- int useFileByHandle(char intent,
- FILE_HANDLE handle)
- {
- DBUG_ENTER("ha_ibmdb2i::useFileByHandle");
-
- const db2i_file* file;
- if (handle == dataHandle)
- file = db2Table->dataFile();
- else
- {
- for (uint i = 0; i < table_share->keys; ++i)
- {
- if (indexHandles[i] == handle)
- {
- file = db2Table->indexFile(i);
- active_index = i;
- }
- }
- }
-
- int rc = file->obtainRowFormat(handle, intent, getCommitLevel(), &activeFormat);
- if (likely(rc == 0))
- {
- activeHandle = handle;
- bumpInUseCounter(1);
- }
-
- DBUG_RETURN(rc);
- }
-
- const db2i_file* getFileForActiveHandle() const
- {
- if (activeHandle == dataHandle)
- return db2Table->dataFile();
- else
- for (uint i = 0; i < table_share->keys; ++i)
- if (indexHandles[i] == activeHandle)
- return db2Table->indexFile(i);
- DBUG_ASSERT(0);
- return NULL;
- }
-
- int prepReadBuffer(ha_rows rowsToRead, const db2i_file* file, char intent);
- int prepWriteBuffer(ha_rows rowsToWrite, const db2i_file* file);
-
- void invalidateCachedStats()
- {
- share->cachedStats.invalidate(rowCount | deletedRowCount | objLength |
- meanRowLen | ioCount);
- }
-
- void warnIfInvalidData()
- {
- if (unlikely(invalidDataFound))
- {
- warning(ha_thd(), DB2I_ERR_INVALID_DATA, table->alias);
- }
- }
-
- /**
- Calculate the maximum value that a particular field can hold.
-
- This is used to anticipate overflows in the auto_increment processing.
-
- @param field The Field to be analyzed
-
- @return The maximum value
- */
- static uint64 maxValueForField(const Field* field)
- {
- uint64 maxValue=0;
- switch (field->type())
- {
- case MYSQL_TYPE_TINY:
- if (((const Field_num*)field)->unsigned_flag)
- maxValue = (1 << 8) - 1;
- else
- maxValue = (1 << 7) - 1;
- break;
- case MYSQL_TYPE_SHORT:
- if (((const Field_num*)field)->unsigned_flag)
- maxValue = (1 << 16) - 1;
- else
- maxValue = (1 << 15) - 1;
- break;
- case MYSQL_TYPE_INT24:
- if (((const Field_num*)field)->unsigned_flag)
- maxValue = (1 << 24) - 1;
- else
- maxValue = (1 << 23) - 1;
- break;
- case MYSQL_TYPE_LONG:
- if (((const Field_num*)field)->unsigned_flag)
- maxValue = (1LL << 32) - 1;
- else
- maxValue = (1 << 31) - 1;
- break;
- case MYSQL_TYPE_LONGLONG:
- if (((const Field_num*)field)->unsigned_flag)
- maxValue = ~(0LL);
- else
- maxValue = 1 << 63 - 1;
- break;
- }
-
- return maxValue;
- }
-
- void cleanupBuffers()
- {
- if (blobReadBuffers)
- {
- delete blobReadBuffers;
- blobReadBuffers = NULL;
- }
- if (blobWriteBuffers)
- {
- delete[] blobWriteBuffers;
- blobWriteBuffers = NULL;
- }
- if (alloc_root_inited(&conversionBufferMemroot))
- {
- free_root(&conversionBufferMemroot, MYF(0));
- }
- }
-
-
-/**
- Generate a valid RCDFMT name based on the name of the table.
-
- The RCDFMT name is devised by munging the name of the table,
- uppercasing all ascii alpha-numeric characters and replacing all other
- characters with underscores until up to ten characters have been generated.
-
- @param tableName The name of the table, as given on the MySQL
- CREATE TABLE statement
- @param[out] query The string to receive the generated RCDFMT name
-*/
- static void generateAndAppendRCDFMT(const char* tableName, String& query)
- {
- char rcdfmt[11];
-
- // The RCDFMT name must begin with an alpha character.
- // We enforce this by skipping to the first alpha character in the table
- // name. If no alpha character exists, we use 'X' for the RCDFMT name;
-
- while (*tableName &&
- (!my_isascii(*tableName) ||
- !my_isalpha(system_charset_info, *tableName)))
- {
- tableName += my_mbcharlen(system_charset_info, *tableName);
- }
-
- if (unlikely(!(*tableName)))
- {
- rcdfmt[0]= 'X';
- rcdfmt[1]= 0;
- }
- else
- {
- int r= 0;
- while ((r < sizeof(rcdfmt)-1) && *tableName)
- {
- if (my_isascii(*tableName) &&
- my_isalnum(system_charset_info, *tableName))
- rcdfmt[r] = my_toupper(system_charset_info, *tableName);
- else
- rcdfmt[r] = '_';
-
- ++r;
- tableName += my_mbcharlen(system_charset_info, *tableName);
- }
- rcdfmt[r]= 0;
- }
- query.append(STRING_WITH_LEN(" RCDFMT "));
- query.append(rcdfmt);
- }
-
- int32 generateShadowIndex(SqlStatementStream& stream,
- const KEY& key,
- const char* libName,
- const char* fileName,
- const String& fieldDefinition);
-};
diff --git a/storage/ibmdb2i/plug.in b/storage/ibmdb2i/plug.in
deleted file mode 100644
index 0913d72aabf..00000000000
--- a/storage/ibmdb2i/plug.in
+++ /dev/null
@@ -1,12 +0,0 @@
-MYSQL_STORAGE_ENGINE([ibmdb2i], [], [IBM DB2 for i Storage Engine],
- [IBM DB2 for i Storage Engine], [max,max-no-ndb])
-MYSQL_PLUGIN_DYNAMIC([ibmdb2i], [ha_ibmdb2i.la])
-
-AC_CHECK_HEADER([qlgusr.h],
- # qlgusr.h is just one of the headers from the i5/OS PASE environment; the
- # EBCDIC headers are in /QIBM/include, and have to be converted to ASCII
- # before cpp gets to them
- [:],
- # Missing PASE environment, can't build this engine
- [mysql_plugin_ibmdb2i=no
- with_plugin_ibmdb2i=no])
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 93665c39482..e529ecbb7a0 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -13,7 +13,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-# This is the CMakeLists for InnoDB Plugin
+# This is the CMakeLists for InnoDB
INCLUDE(CheckFunctionExists)
INCLUDE(CheckCSourceCompiles)
@@ -40,12 +40,9 @@ IF(UNIX)
ENDIF()
ENDIF()
-# Enable InnoDB's UNIV_DEBUG if MySQL's WITH_DEBUG[_FULL] is defined
-# enable when this bug is resolved:
-# Bug#54861 Additional connections not handled properly in mtr --embedded
-#IF(WITH_DEBUG)
-# ADD_DEFINITIONS("-DUNIV_DEBUG")
-#ENDIF()
+# Enable InnoDB's UNIV_DEBUG for debug builds
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DUNIV_DEBUG")
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DUNIV_DEBUG")
IF(NOT MSVC)
# either define HAVE_IB_GCC_ATOMIC_BUILTINS or not
@@ -127,9 +124,13 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
CHECK_FUNCTION_EXISTS(atomic_cas_ulong HAVE_ATOMIC_CAS_ULONG)
CHECK_FUNCTION_EXISTS(atomic_cas_32 HAVE_ATOMIC_CAS_32)
CHECK_FUNCTION_EXISTS(atomic_cas_64 HAVE_ATOMIC_CAS_64)
- CHECK_FUNCTION_EXISTS(atomic_add_long HAVE_ATOMIC_ADD_LONG)
- IF(HAVE_ATOMIC_CAS_ULONG AND HAVE_ATOMIC_CAS_32 AND
- HAVE_ATOMIC_CAS_64 AND HAVE_ATOMIC_ADD_LONG)
+ CHECK_FUNCTION_EXISTS(atomic_add_long_nv HAVE_ATOMIC_ADD_LONG_NV)
+ CHECK_FUNCTION_EXISTS(atomic_swap_uchar HAVE_ATOMIC_SWAP_UCHAR)
+ IF(HAVE_ATOMIC_CAS_ULONG AND
+ HAVE_ATOMIC_CAS_32 AND
+ HAVE_ATOMIC_CAS_64 AND
+ HAVE_ATOMIC_ADD_LONG_NV AND
+ HAVE_ATOMIC_SWAP_UCHAR)
SET(HAVE_IB_SOLARIS_ATOMICS 1)
ENDIF()
@@ -188,7 +189,7 @@ IF(SIZEOF_PTHREAD_T)
ENDIF()
IF(MSVC)
- ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DHAVE_IB_PAUSE_INSTRUCTION)
+ ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS)
ENDIF()
@@ -233,48 +234,25 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
os/os0file.c os/os0proc.c os/os0sync.c os/os0thread.c
page/page0cur.c page/page0page.c page/page0zip.c
que/que0que.c
- handler/ha_innodb.cc handler/handler0alter.cc handler/i_s.cc handler/mysql_addons.cc
+ handler/ha_innodb.cc handler/handler0alter.cc handler/i_s.cc
read/read0read.c
rem/rem0cmp.c rem/rem0rec.c
row/row0ext.c row/row0ins.c row/row0merge.c row/row0mysql.c row/row0purge.c row/row0row.c
row/row0sel.c row/row0uins.c row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
srv/srv0srv.c srv/srv0start.c
sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
- thr/thr0loc.c
trx/trx0i_s.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c
trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
usr/usr0sess.c
ut/ut0byte.c ut/ut0dbg.c ut/ut0list.c ut/ut0mem.c ut/ut0rbt.c ut/ut0rnd.c
- ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c)
+ ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c ut/ut0bh.c)
IF(WITH_INNODB)
# Legacy option
SET(WITH_INNOBASE_STORAGE_ENGINE TRUE)
ENDIF()
-
-#The plugin's CMakeLists.txt still needs to work with previous versions of MySQL.
-IF(EXISTS ${SOURCE_DIR}/storage/mysql_storage_engine.cmake)
- # Old plugin support on Windows only,
- # use tricks to force ha_innodb.dll name for DLL
- INCLUDE(${SOURCE_DIR}/storage/mysql_storage_engine.cmake)
- MYSQL_STORAGE_ENGINE(INNOBASE)
- GET_TARGET_PROPERTY(LIB_LOCATION ha_innobase LOCATION)
- IF(LIB_LOCATION)
- SET_TARGET_PROPERTIES(ha_innobase PROPERTIES OUTPUT_NAME ha_innodb)
- ENDIF()
-ELSEIF (MYSQL_VERSION_ID LESS "50137")
- # Windows only, no plugin support
- IF (NOT SOURCE_SUBLIBS)
- ADD_DEFINITIONS(-DMYSQL_SERVER)
- ADD_LIBRARY(innobase STATIC ${INNOBASE_SOURCES})
- # Require mysqld_error.h, which is built as part of the GenError
- ADD_DEPENDENCIES(innobase GenError)
- ENDIF()
-ELSE()
- # New plugin support, cross-platform , base name for shared module is "ha_innodb"
- MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE
- MODULE_ONLY
- MODULE_OUTPUT_NAME ha_innodb
- LINK_LIBRARIES ${ZLIB_LIBRARY})
-ENDIF()
+MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE
+ MODULE_ONLY
+ MODULE_OUTPUT_NAME ha_innodb
+ LINK_LIBRARIES ${ZLIB_LIBRARY})
diff --git a/storage/innobase/COPYING b/storage/innobase/COPYING
deleted file mode 100644
index 6b106e18fdb..00000000000
--- a/storage/innobase/COPYING
+++ /dev/null
@@ -1,351 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-Preamble
-========
-
-The licenses for most software are designed to take away your freedom
-to share and change it. By contrast, the GNU General Public License is
-intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
-When we speak of free software, we are referring to freedom, not price.
-Our General Public Licenses are designed to make sure that you have
-the freedom to distribute copies of free software (and charge for this
-service if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs; and that you know you can do these things.
-
-To protect your rights, we need to make restrictions that forbid anyone
-to deny you these rights or to ask you to surrender the rights. These
-restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-For example, if you distribute copies of such a program, whether gratis
-or for a fee, you must give the recipients all the rights that you
-have. You must make sure that they, too, receive or can get the source
-code. And you must show them these terms so they know their rights.
-
-We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-Finally, any free program is threatened constantly by software patents.
-We wish to avoid the danger that redistributors of a free program will
-individually obtain patent licenses, in effect making the program
-proprietary. To prevent this, we have made it clear that any patent
-must be licensed for everyone's free use or not licensed at all.
-
-The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- 0. This License applies to any program or other work which contains a
- notice placed by the copyright holder saying it may be distributed
- under the terms of this General Public License. The "Program",
- below, refers to any such program or work, and a "work based on
- the Program" means either the Program or any derivative work under
- copyright law: that is to say, a work containing the Program or a
- portion of it, either verbatim or with modifications and/or
- translated into another language. (Hereinafter, translation is
- included without limitation in the term "modification".) Each
- licensee is addressed as "you".
-
- Activities other than copying, distribution and modification are
- not covered by this License; they are outside its scope. The act
- of running the Program is not restricted, and the output from the
- Program is covered only if its contents constitute a work based on
- the Program (independent of having been made by running the
- Program). Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
- source code as you receive it, in any medium, provided that you
- conspicuously and appropriately publish on each copy an appropriate
- copyright notice and disclaimer of warranty; keep intact all the
- notices that refer to this License and to the absence of any
- warranty; and give any other recipients of the Program a copy of
- this License along with the Program.
-
- You may charge a fee for the physical act of transferring a copy,
- and you may at your option offer warranty protection in exchange
- for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
- of it, thus forming a work based on the Program, and copy and
- distribute such modifications or work under the terms of Section 1
- above, provided that you also meet all of these conditions:
-
- a. You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b. You must cause any work that you distribute or publish, that
- in whole or in part contains or is derived from the Program
- or any part thereof, to be licensed as a whole at no charge
- to all third parties under the terms of this License.
-
- c. If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display
- an announcement including an appropriate copyright notice and
- a notice that there is no warranty (or else, saying that you
- provide a warranty) and that users may redistribute the
- program under these conditions, and telling the user how to
- view a copy of this License. (Exception: if the Program
- itself is interactive but does not normally print such an
- announcement, your work based on the Program is not required
- to print an announcement.)
-
- These requirements apply to the modified work as a whole. If
- identifiable sections of that work are not derived from the
- Program, and can be reasonably considered independent and separate
- works in themselves, then this License, and its terms, do not
- apply to those sections when you distribute them as separate
- works. But when you distribute the same sections as part of a
- whole which is a work based on the Program, the distribution of
- the whole must be on the terms of this License, whose permissions
- for other licensees extend to the entire whole, and thus to each
- and every part regardless of who wrote it.
-
- Thus, it is not the intent of this section to claim rights or
- contest your rights to work written entirely by you; rather, the
- intent is to exercise the right to control the distribution of
- derivative or collective works based on the Program.
-
- In addition, mere aggregation of another work not based on the
- Program with the Program (or with a work based on the Program) on
- a volume of a storage or distribution medium does not bring the
- other work under the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
- under Section 2) in object code or executable form under the terms
- of Sections 1 and 2 above provided that you also do one of the
- following:
-
- a. Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of
- Sections 1 and 2 above on a medium customarily used for
- software interchange; or,
-
- b. Accompany it with a written offer, valid for at least three
- years, to give any third-party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a
- medium customarily used for software interchange; or,
-
- c. Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with
- such an offer, in accord with Subsection b above.)
-
- The source code for a work means the preferred form of the work for
- making modifications to it. For an executable work, complete
- source code means all the source code for all modules it contains,
- plus any associated interface definition files, plus the scripts
- used to control compilation and installation of the executable.
- However, as a special exception, the source code distributed need
- not include anything that is normally distributed (in either
- source or binary form) with the major components (compiler,
- kernel, and so on) of the operating system on which the executable
- runs, unless that component itself accompanies the executable.
-
- If distribution of executable or object code is made by offering
- access to copy from a designated place, then offering equivalent
- access to copy the source code from the same place counts as
- distribution of the source code, even though third parties are not
- compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
- except as expressly provided under this License. Any attempt
- otherwise to copy, modify, sublicense or distribute the Program is
- void, and will automatically terminate your rights under this
- License. However, parties who have received copies, or rights,
- from you under this License will not have their licenses
- terminated so long as such parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
- signed it. However, nothing else grants you permission to modify
- or distribute the Program or its derivative works. These actions
- are prohibited by law if you do not accept this License.
- Therefore, by modifying or distributing the Program (or any work
- based on the Program), you indicate your acceptance of this
- License to do so, and all its terms and conditions for copying,
- distributing or modifying the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
- Program), the recipient automatically receives a license from the
- original licensor to copy, distribute or modify the Program
- subject to these terms and conditions. You may not impose any
- further restrictions on the recipients' exercise of the rights
- granted herein. You are not responsible for enforcing compliance
- by third parties to this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
- infringement or for any other reason (not limited to patent
- issues), conditions are imposed on you (whether by court order,
- agreement or otherwise) that contradict the conditions of this
- License, they do not excuse you from the conditions of this
- License. If you cannot distribute so as to satisfy simultaneously
- your obligations under this License and any other pertinent
- obligations, then as a consequence you may not distribute the
- Program at all. For example, if a patent license would not permit
- royalty-free redistribution of the Program by all those who
- receive copies directly or indirectly through you, then the only
- way you could satisfy both it and this License would be to refrain
- entirely from distribution of the Program.
-
- If any portion of this section is held invalid or unenforceable
- under any particular circumstance, the balance of the section is
- intended to apply and the section as a whole is intended to apply
- in other circumstances.
-
- It is not the purpose of this section to induce you to infringe any
- patents or other property right claims or to contest validity of
- any such claims; this section has the sole purpose of protecting
- the integrity of the free software distribution system, which is
- implemented by public license practices. Many people have made
- generous contributions to the wide range of software distributed
- through that system in reliance on consistent application of that
- system; it is up to the author/donor to decide if he or she is
- willing to distribute software through any other system and a
- licensee cannot impose that choice.
-
- This section is intended to make thoroughly clear what is believed
- to be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
- certain countries either by patents or by copyrighted interfaces,
- the original copyright holder who places the Program under this
- License may add an explicit geographical distribution limitation
- excluding those countries, so that distribution is permitted only
- in or among countries not thus excluded. In such case, this
- License incorporates the limitation as if written in the body of
- this License.
-
- 9. The Free Software Foundation may publish revised and/or new
- versions of the General Public License from time to time. Such
- new versions will be similar in spirit to the present version, but
- may differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
- Program specifies a version number of this License which applies
- to it and "any later version", you have the option of following
- the terms and conditions either of that version or of any later
- version published by the Free Software Foundation. If the Program
- does not specify a version number of this License, you may choose
- any version ever published by the Free Software Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
- programs whose distribution conditions are different, write to the
- author to ask for permission. For software which is copyrighted
- by the Free Software Foundation, write to the Free Software
- Foundation; we sometimes make exceptions for this. Our decision
- will be guided by the two goals of preserving the free status of
- all derivatives of our free software and of promoting the sharing
- and reuse of software generally.
-
- NO WARRANTY
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
- WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
- LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
- HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
- WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
- NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
- QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
- PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
- SERVICING, REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
- WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
- MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE
- LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
- INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
- DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
- OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
- OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-How to Apply These Terms to Your New Programs
-=============================================
-
-If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these
-terms.
-
-To do so, attach the following notices to the program. It is safest to
-attach them to the start of each source file to most effectively convey
-the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
- Copyright (C) YYYY NAME OF AUTHOR
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the
-appropriate parts of the General Public License. Of course, the
-commands you use may be called something other than `show w' and `show
-c'; they could even be mouse-clicks or menu items--whatever suits your
-program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- SIGNATURE OF TY COON, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library,
-you may consider it more useful to permit linking proprietary
-applications with the library. If this is what you want to do, use the
-GNU Library General Public License instead of this License.
diff --git a/storage/innobase/COPYING.Sun_Microsystems b/storage/innobase/COPYING.Sun_Microsystems
deleted file mode 100644
index 5a77ef3ab73..00000000000
--- a/storage/innobase/COPYING.Sun_Microsystems
+++ /dev/null
@@ -1,31 +0,0 @@
-Portions of this software contain modifications contributed by
-Sun Microsystems, Inc. These contributions are used with the following
-license:
-
-Copyright (c) 2009, Sun Microsystems, Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
- * Neither the name of Sun Microsystems, Inc. nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/storage/innobase/Doxyfile b/storage/innobase/Doxyfile
index 62aa7dd8abc..7cf5048fa52 100644
--- a/storage/innobase/Doxyfile
+++ b/storage/innobase/Doxyfile
@@ -565,7 +565,7 @@ RECURSIVE = YES
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
-EXCLUDE = ut0auxconf_*
+EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
diff --git a/storage/innobase/Makefile.am b/storage/innobase/Makefile.am
deleted file mode 100644
index 674b3754e8c..00000000000
--- a/storage/innobase/Makefile.am
+++ /dev/null
@@ -1,339 +0,0 @@
-# Copyright (C) 2001, 2004, 2006 MySQL AB & Innobase Oy
-#
-# 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
-
-# Process this file with automake to create Makefile.in
-
-MYSQLDATAdir= $(localstatedir)
-MYSQLSHAREdir= $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-pkgplugindir= $(pkglibdir)/plugin
-INCLUDES= -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(srcdir)/include \
- -I$(top_srcdir)/sql \
- -I$(srcdir) @ZLIB_INCLUDES@
-
-DEFS= @DEFS@
-
-noinst_HEADERS= \
- handler/ha_innodb.h \
- handler/i_s.h \
- include/btr0btr.h \
- include/btr0btr.ic \
- include/btr0cur.h \
- include/btr0cur.ic \
- include/btr0pcur.h \
- include/btr0pcur.ic \
- include/btr0sea.h \
- include/btr0sea.ic \
- include/btr0types.h \
- include/buf0buddy.h \
- include/buf0buddy.ic \
- include/buf0buf.h \
- include/buf0buf.ic \
- include/buf0flu.h \
- include/buf0flu.ic \
- include/buf0lru.h \
- include/buf0lru.ic \
- include/buf0rea.h \
- include/buf0types.h \
- include/data0data.h \
- include/data0data.ic \
- include/data0type.h \
- include/data0type.ic \
- include/data0types.h \
- include/db0err.h \
- include/dict0boot.h \
- include/dict0boot.ic \
- include/dict0crea.h \
- include/dict0crea.ic \
- include/dict0dict.h \
- include/dict0dict.ic \
- include/dict0load.h \
- include/dict0load.ic \
- include/dict0mem.h \
- include/dict0mem.ic \
- include/dict0types.h \
- include/dyn0dyn.h \
- include/dyn0dyn.ic \
- include/eval0eval.h \
- include/eval0eval.ic \
- include/eval0proc.h \
- include/eval0proc.ic \
- include/fil0fil.h \
- include/fsp0fsp.h \
- include/fsp0fsp.ic \
- include/fsp0types.h \
- include/fut0fut.h \
- include/fut0fut.ic \
- include/fut0lst.h \
- include/fut0lst.ic \
- include/ha0ha.h \
- include/ha0ha.ic \
- include/ha0storage.h \
- include/ha0storage.ic \
- include/ha_prototypes.h \
- include/handler0alter.h \
- include/hash0hash.h \
- include/hash0hash.ic \
- include/ibuf0ibuf.h \
- include/ibuf0ibuf.ic \
- include/ibuf0types.h \
- include/lock0iter.h \
- include/lock0lock.h \
- include/lock0lock.ic \
- include/lock0priv.h \
- include/lock0priv.ic \
- include/lock0types.h \
- include/log0log.h \
- include/log0log.ic \
- include/log0recv.h \
- include/log0recv.ic \
- include/mach0data.h \
- include/mach0data.ic \
- include/mem0dbg.h \
- include/mem0dbg.ic \
- include/mem0mem.h \
- include/mem0mem.ic \
- include/mem0pool.h \
- include/mem0pool.ic \
- include/mtr0log.h \
- include/mtr0log.ic \
- include/mtr0mtr.h \
- include/mtr0mtr.ic \
- include/mtr0types.h \
- include/mysql_addons.h \
- include/os0file.h \
- include/os0file.ic \
- include/os0proc.h \
- include/os0proc.ic \
- include/os0sync.h \
- include/os0sync.ic \
- include/os0thread.h \
- include/os0thread.ic \
- include/page0cur.h \
- include/page0cur.ic \
- include/page0page.h \
- include/page0page.ic \
- include/page0types.h \
- include/page0zip.h \
- include/page0zip.ic \
- include/pars0grm.h \
- include/pars0opt.h \
- include/pars0opt.ic \
- include/pars0pars.h \
- include/pars0pars.ic \
- include/pars0sym.h \
- include/pars0sym.ic \
- include/pars0types.h \
- include/que0que.h \
- include/que0que.ic \
- include/que0types.h \
- include/read0read.h \
- include/read0read.ic \
- include/read0types.h \
- include/rem0cmp.h \
- include/rem0cmp.ic \
- include/rem0rec.h \
- include/rem0rec.ic \
- include/rem0types.h \
- include/row0ext.h \
- include/row0ext.ic \
- include/row0ins.h \
- include/row0ins.ic \
- include/row0merge.h \
- include/row0mysql.h \
- include/row0mysql.ic \
- include/row0purge.h \
- include/row0purge.ic \
- include/row0row.h \
- include/row0row.ic \
- include/row0sel.h \
- include/row0sel.ic \
- include/row0types.h \
- include/row0uins.h \
- include/row0uins.ic \
- include/row0umod.h \
- include/row0umod.ic \
- include/row0undo.h \
- include/row0undo.ic \
- include/row0upd.h \
- include/row0upd.ic \
- include/row0vers.h \
- include/row0vers.ic \
- include/srv0srv.h \
- include/srv0srv.ic \
- include/srv0start.h \
- include/sync0arr.h \
- include/sync0arr.ic \
- include/sync0rw.h \
- include/sync0rw.ic \
- include/sync0sync.h \
- include/sync0sync.ic \
- include/sync0types.h \
- include/thr0loc.h \
- include/thr0loc.ic \
- include/trx0i_s.h \
- include/trx0purge.h \
- include/trx0purge.ic \
- include/trx0rec.h \
- include/trx0rec.ic \
- include/trx0roll.h \
- include/trx0roll.ic \
- include/trx0rseg.h \
- include/trx0rseg.ic \
- include/trx0sys.h \
- include/trx0sys.ic \
- include/trx0trx.h \
- include/trx0trx.ic \
- include/trx0types.h \
- include/trx0undo.h \
- include/trx0undo.ic \
- include/trx0xa.h \
- include/univ.i \
- include/usr0sess.h \
- include/usr0sess.ic \
- include/usr0types.h \
- include/ut0auxconf.h \
- include/ut0byte.h \
- include/ut0byte.ic \
- include/ut0dbg.h \
- include/ut0list.h \
- include/ut0list.ic \
- include/ut0lst.h \
- include/ut0mem.h \
- include/ut0mem.ic \
- include/ut0rbt.h \
- include/ut0rnd.h \
- include/ut0rnd.ic \
- include/ut0sort.h \
- include/ut0ut.h \
- include/ut0ut.ic \
- include/ut0vec.h \
- include/ut0vec.ic \
- include/ut0wqueue.h \
- mem/mem0dbg.c
-
-EXTRA_LIBRARIES= libinnobase.a
-noinst_LIBRARIES= @plugin_innobase_static_target@
-libinnobase_a_SOURCES= \
- btr/btr0btr.c \
- btr/btr0cur.c \
- btr/btr0pcur.c \
- btr/btr0sea.c \
- buf/buf0buddy.c \
- buf/buf0buf.c \
- buf/buf0flu.c \
- buf/buf0lru.c \
- buf/buf0rea.c \
- data/data0data.c \
- data/data0type.c \
- dict/dict0boot.c \
- dict/dict0crea.c \
- dict/dict0dict.c \
- dict/dict0load.c \
- dict/dict0mem.c \
- dyn/dyn0dyn.c \
- eval/eval0eval.c \
- eval/eval0proc.c \
- fil/fil0fil.c \
- fsp/fsp0fsp.c \
- fut/fut0fut.c \
- fut/fut0lst.c \
- ha/ha0ha.c \
- ha/ha0storage.c \
- ha/hash0hash.c \
- handler/ha_innodb.cc \
- handler/handler0alter.cc \
- handler/i_s.cc \
- handler/mysql_addons.cc \
- ibuf/ibuf0ibuf.c \
- lock/lock0iter.c \
- lock/lock0lock.c \
- log/log0log.c \
- log/log0recv.c \
- mach/mach0data.c \
- mem/mem0mem.c \
- mem/mem0pool.c \
- mtr/mtr0log.c \
- mtr/mtr0mtr.c \
- os/os0file.c \
- os/os0proc.c \
- os/os0sync.c \
- os/os0thread.c \
- page/page0cur.c \
- page/page0page.c \
- page/page0zip.c \
- pars/lexyy.c \
- pars/pars0grm.c \
- pars/pars0opt.c \
- pars/pars0pars.c \
- pars/pars0sym.c \
- que/que0que.c \
- read/read0read.c \
- rem/rem0cmp.c \
- rem/rem0rec.c \
- row/row0ext.c \
- row/row0ins.c \
- row/row0merge.c \
- row/row0mysql.c \
- row/row0purge.c \
- row/row0row.c \
- row/row0sel.c \
- row/row0uins.c \
- row/row0umod.c \
- row/row0undo.c \
- row/row0upd.c \
- row/row0vers.c \
- srv/srv0srv.c \
- srv/srv0start.c \
- sync/sync0arr.c \
- sync/sync0rw.c \
- sync/sync0sync.c \
- thr/thr0loc.c \
- trx/trx0i_s.c \
- trx/trx0purge.c \
- trx/trx0rec.c \
- trx/trx0roll.c \
- trx/trx0rseg.c \
- trx/trx0sys.c \
- trx/trx0trx.c \
- trx/trx0undo.c \
- usr/usr0sess.c \
- ut/ut0byte.c \
- ut/ut0dbg.c \
- ut/ut0list.c \
- ut/ut0mem.c \
- ut/ut0rbt.c \
- ut/ut0rnd.c \
- ut/ut0ut.c \
- ut/ut0vec.c \
- ut/ut0wqueue.c
-
-libinnobase_a_CXXFLAGS= $(AM_CXXFLAGS)
-libinnobase_a_CFLAGS= $(AM_CFLAGS)
-
-EXTRA_LTLIBRARIES= ha_innodb.la
-pkgplugin_LTLIBRARIES= @plugin_innobase_shared_target@
-
-ha_innodb_la_LDFLAGS= -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
-ha_innodb_la_CXXFLAGS= -shared $(AM_CXXFLAGS) $(INNODB_DYNAMIC_CFLAGS)
-ha_innodb_la_CFLAGS= -shared $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
-ha_innodb_la_SOURCES= $(libinnobase_a_SOURCES)
-
-EXTRA_DIST= CMakeLists.txt plug.in \
- pars/make_bison.sh pars/make_flex.sh \
- pars/pars0grm.y pars/pars0lex.l
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
index cf384378edf..fb2509a62ff 100644
--- a/storage/innobase/btr/btr0btr.c
+++ b/storage/innobase/btr/btr0btr.c
@@ -42,6 +42,560 @@ Created 6/2/1994 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "trx0trx.h"
+#ifdef UNIV_BLOB_DEBUG
+# include "srv0srv.h"
+# include "ut0rbt.h"
+
+/** TRUE when messages about index->blobs modification are enabled. */
+static ibool btr_blob_dbg_msg;
+
+/** Issue a message about an operation on index->blobs.
+@param op operation
+@param b the entry being subjected to the operation
+@param ctx the context of the operation */
+#define btr_blob_dbg_msg_issue(op, b, ctx) \
+ fprintf(stderr, op " %u:%u:%u->%u %s(%u,%u,%u)\n", \
+ (b)->ref_page_no, (b)->ref_heap_no, \
+ (b)->ref_field_no, (b)->blob_page_no, ctx, \
+ (b)->owner, (b)->always_owner, (b)->del)
+
+/** Insert to index->blobs a reference to an off-page column.
+@param index the index tree
+@param b the reference
+@param ctx context (for logging) */
+UNIV_INTERN
+void
+btr_blob_dbg_rbt_insert(
+/*====================*/
+ dict_index_t* index, /*!< in/out: index tree */
+ const btr_blob_dbg_t* b, /*!< in: the reference */
+ const char* ctx) /*!< in: context (for logging) */
+{
+ if (btr_blob_dbg_msg) {
+ btr_blob_dbg_msg_issue("insert", b, ctx);
+ }
+ mutex_enter(&index->blobs_mutex);
+ rbt_insert(index->blobs, b, b);
+ mutex_exit(&index->blobs_mutex);
+}
+
+/** Remove from index->blobs a reference to an off-page column.
+@param index the index tree
+@param b the reference
+@param ctx context (for logging) */
+UNIV_INTERN
+void
+btr_blob_dbg_rbt_delete(
+/*====================*/
+ dict_index_t* index, /*!< in/out: index tree */
+ const btr_blob_dbg_t* b, /*!< in: the reference */
+ const char* ctx) /*!< in: context (for logging) */
+{
+ if (btr_blob_dbg_msg) {
+ btr_blob_dbg_msg_issue("delete", b, ctx);
+ }
+ mutex_enter(&index->blobs_mutex);
+ ut_a(rbt_delete(index->blobs, b));
+ mutex_exit(&index->blobs_mutex);
+}
+
+/**************************************************************//**
+Comparator for items (btr_blob_dbg_t) in index->blobs.
+The key in index->blobs is (ref_page_no, ref_heap_no, ref_field_no).
+@return negative, 0 or positive if *a<*b, *a=*b, *a>*b */
+static
+int
+btr_blob_dbg_cmp(
+/*=============*/
+ const void* a, /*!< in: first btr_blob_dbg_t to compare */
+ const void* b) /*!< in: second btr_blob_dbg_t to compare */
+{
+ const btr_blob_dbg_t* aa = a;
+ const btr_blob_dbg_t* bb = b;
+
+ ut_ad(aa != NULL);
+ ut_ad(bb != NULL);
+
+ if (aa->ref_page_no != bb->ref_page_no) {
+ return(aa->ref_page_no < bb->ref_page_no ? -1 : 1);
+ }
+ if (aa->ref_heap_no != bb->ref_heap_no) {
+ return(aa->ref_heap_no < bb->ref_heap_no ? -1 : 1);
+ }
+ if (aa->ref_field_no != bb->ref_field_no) {
+ return(aa->ref_field_no < bb->ref_field_no ? -1 : 1);
+ }
+ return(0);
+}
+
+/**************************************************************//**
+Add a reference to an off-page column to the index->blobs map. */
+UNIV_INTERN
+void
+btr_blob_dbg_add_blob(
+/*==================*/
+ const rec_t* rec, /*!< in: clustered index record */
+ ulint field_no, /*!< in: off-page column number */
+ ulint page_no, /*!< in: start page of the column */
+ dict_index_t* index, /*!< in/out: index tree */
+ const char* ctx) /*!< in: context (for logging) */
+{
+ btr_blob_dbg_t b;
+ const page_t* page = page_align(rec);
+
+ ut_a(index->blobs);
+
+ b.blob_page_no = page_no;
+ b.ref_page_no = page_get_page_no(page);
+ b.ref_heap_no = page_rec_get_heap_no(rec);
+ b.ref_field_no = field_no;
+ ut_a(b.ref_field_no >= index->n_uniq);
+ b.always_owner = b.owner = TRUE;
+ b.del = FALSE;
+ ut_a(!rec_get_deleted_flag(rec, page_is_comp(page)));
+ btr_blob_dbg_rbt_insert(index, &b, ctx);
+}
+
+/**************************************************************//**
+Add to index->blobs any references to off-page columns from a record.
+@return number of references added */
+UNIV_INTERN
+ulint
+btr_blob_dbg_add_rec(
+/*=================*/
+ const rec_t* rec, /*!< in: record */
+ dict_index_t* index, /*!< in/out: index */
+ const ulint* offsets,/*!< in: offsets */
+ const char* ctx) /*!< in: context (for logging) */
+{
+ ulint count = 0;
+ ulint i;
+ btr_blob_dbg_t b;
+ ibool del;
+
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
+ if (!rec_offs_any_extern(offsets)) {
+ return(0);
+ }
+
+ b.ref_page_no = page_get_page_no(page_align(rec));
+ b.ref_heap_no = page_rec_get_heap_no(rec);
+ del = (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) != 0);
+
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (rec_offs_nth_extern(offsets, i)) {
+ ulint len;
+ const byte* field_ref = rec_get_nth_field(
+ rec, offsets, i, &len);
+
+ ut_a(len != UNIV_SQL_NULL);
+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+ field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+ if (!memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE)) {
+ /* the column has not been stored yet */
+ continue;
+ }
+
+ b.ref_field_no = i;
+ b.blob_page_no = mach_read_from_4(
+ field_ref + BTR_EXTERN_PAGE_NO);
+ ut_a(b.ref_field_no >= index->n_uniq);
+ b.always_owner = b.owner
+ = !(field_ref[BTR_EXTERN_LEN]
+ & BTR_EXTERN_OWNER_FLAG);
+ b.del = del;
+
+ btr_blob_dbg_rbt_insert(index, &b, ctx);
+ count++;
+ }
+ }
+
+ return(count);
+}
+
+/**************************************************************//**
+Display the references to off-page columns.
+This function is to be called from a debugger,
+for example when a breakpoint on ut_dbg_assertion_failed is hit. */
+UNIV_INTERN
+void
+btr_blob_dbg_print(
+/*===============*/
+ const dict_index_t* index) /*!< in: index tree */
+{
+ const ib_rbt_node_t* node;
+
+ if (!index->blobs) {
+ return;
+ }
+
+ /* We intentionally do not acquire index->blobs_mutex here.
+ This function is to be called from a debugger, and the caller
+ should make sure that the index->blobs_mutex is held. */
+
+ for (node = rbt_first(index->blobs);
+ node != NULL; node = rbt_next(index->blobs, node)) {
+ const btr_blob_dbg_t* b
+ = rbt_value(btr_blob_dbg_t, node);
+ fprintf(stderr, "%u:%u:%u->%u%s%s%s\n",
+ b->ref_page_no, b->ref_heap_no, b->ref_field_no,
+ b->blob_page_no,
+ b->owner ? "" : "(disowned)",
+ b->always_owner ? "" : "(has disowned)",
+ b->del ? "(deleted)" : "");
+ }
+}
+
+/**************************************************************//**
+Remove from index->blobs any references to off-page columns from a record.
+@return number of references removed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_remove_rec(
+/*====================*/
+ const rec_t* rec, /*!< in: record */
+ dict_index_t* index, /*!< in/out: index */
+ const ulint* offsets,/*!< in: offsets */
+ const char* ctx) /*!< in: context (for logging) */
+{
+ ulint i;
+ ulint count = 0;
+ btr_blob_dbg_t b;
+
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
+ if (!rec_offs_any_extern(offsets)) {
+ return(0);
+ }
+
+ b.ref_page_no = page_get_page_no(page_align(rec));
+ b.ref_heap_no = page_rec_get_heap_no(rec);
+
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (rec_offs_nth_extern(offsets, i)) {
+ ulint len;
+ const byte* field_ref = rec_get_nth_field(
+ rec, offsets, i, &len);
+
+ ut_a(len != UNIV_SQL_NULL);
+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+ field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+ b.ref_field_no = i;
+ b.blob_page_no = mach_read_from_4(
+ field_ref + BTR_EXTERN_PAGE_NO);
+
+ switch (b.blob_page_no) {
+ case 0:
+ /* The column has not been stored yet.
+ The BLOB pointer must be all zero.
+ There cannot be a BLOB starting at
+ page 0, because page 0 is reserved for
+ the tablespace header. */
+ ut_a(!memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+ /* fall through */
+ case FIL_NULL:
+ /* the column has been freed already */
+ continue;
+ }
+
+ btr_blob_dbg_rbt_delete(index, &b, ctx);
+ count++;
+ }
+ }
+
+ return(count);
+}
+
+/**************************************************************//**
+Check that there are no references to off-page columns from or to
+the given page. Invoked when freeing or clearing a page.
+@return TRUE when no orphan references exist */
+UNIV_INTERN
+ibool
+btr_blob_dbg_is_empty(
+/*==================*/
+ dict_index_t* index, /*!< in: index */
+ ulint page_no) /*!< in: page number */
+{
+ const ib_rbt_node_t* node;
+ ibool success = TRUE;
+
+ if (!index->blobs) {
+ return(success);
+ }
+
+ mutex_enter(&index->blobs_mutex);
+
+ for (node = rbt_first(index->blobs);
+ node != NULL; node = rbt_next(index->blobs, node)) {
+ const btr_blob_dbg_t* b
+ = rbt_value(btr_blob_dbg_t, node);
+
+ if (b->ref_page_no != page_no && b->blob_page_no != page_no) {
+ continue;
+ }
+
+ fprintf(stderr,
+ "InnoDB: orphan BLOB ref%s%s%s %u:%u:%u->%u\n",
+ b->owner ? "" : "(disowned)",
+ b->always_owner ? "" : "(has disowned)",
+ b->del ? "(deleted)" : "",
+ b->ref_page_no, b->ref_heap_no, b->ref_field_no,
+ b->blob_page_no);
+
+ if (b->blob_page_no != page_no || b->owner || !b->del) {
+ success = FALSE;
+ }
+ }
+
+ mutex_exit(&index->blobs_mutex);
+ return(success);
+}
+
+/**************************************************************//**
+Count and process all references to off-page columns on a page.
+@return number of references processed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_op(
+/*============*/
+ const page_t* page, /*!< in: B-tree leaf page */
+ const rec_t* rec, /*!< in: record to start from
+ (NULL to process the whole page) */
+ dict_index_t* index, /*!< in/out: index */
+ const char* ctx, /*!< in: context (for logging) */
+ const btr_blob_dbg_op_f op) /*!< in: operation on records */
+{
+ ulint count = 0;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ rec_offs_init(offsets_);
+
+ ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
+ ut_a(!rec || page_align(rec) == page);
+
+ if (!index->blobs || !page_is_leaf(page)
+ || !dict_index_is_clust(index)) {
+ return(0);
+ }
+
+ if (rec == NULL) {
+ rec = page_get_infimum_rec(page);
+ }
+
+ do {
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ count += op(rec, index, offsets, ctx);
+ rec = page_rec_get_next_const(rec);
+ } while (!page_rec_is_supremum(rec));
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
+ return(count);
+}
+
+/**************************************************************//**
+Count and add to index->blobs any references to off-page columns
+from records on a page.
+@return number of references added */
+UNIV_INTERN
+ulint
+btr_blob_dbg_add(
+/*=============*/
+ const page_t* page, /*!< in: rewritten page */
+ dict_index_t* index, /*!< in/out: index */
+ const char* ctx) /*!< in: context (for logging) */
+{
+ btr_blob_dbg_assert_empty(index, page_get_page_no(page));
+
+ return(btr_blob_dbg_op(page, NULL, index, ctx, btr_blob_dbg_add_rec));
+}
+
+/**************************************************************//**
+Count and remove from index->blobs any references to off-page columns
+from records on a page.
+Used when reorganizing a page, before copying the records.
+@return number of references removed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_remove(
+/*================*/
+ const page_t* page, /*!< in: b-tree page */
+ dict_index_t* index, /*!< in/out: index */
+ const char* ctx) /*!< in: context (for logging) */
+{
+ ulint count;
+
+ count = btr_blob_dbg_op(page, NULL, index, ctx,
+ btr_blob_dbg_remove_rec);
+
+ /* Check that no references exist. */
+ btr_blob_dbg_assert_empty(index, page_get_page_no(page));
+
+ return(count);
+}
+
+/**************************************************************//**
+Restore in index->blobs any references to off-page columns
+Used when page reorganize fails due to compressed page overflow. */
+UNIV_INTERN
+void
+btr_blob_dbg_restore(
+/*=================*/
+ const page_t* npage, /*!< in: page that failed to compress */
+ const page_t* page, /*!< in: copy of original page */
+ dict_index_t* index, /*!< in/out: index */
+ const char* ctx) /*!< in: context (for logging) */
+{
+ ulint removed;
+ ulint added;
+
+ ut_a(page_get_page_no(npage) == page_get_page_no(page));
+ ut_a(page_get_space_id(npage) == page_get_space_id(page));
+
+ removed = btr_blob_dbg_remove(npage, index, ctx);
+ added = btr_blob_dbg_add(page, index, ctx);
+ ut_a(added == removed);
+}
+
+/**************************************************************//**
+Modify the 'deleted' flag of a record. */
+UNIV_INTERN
+void
+btr_blob_dbg_set_deleted_flag(
+/*==========================*/
+ const rec_t* rec, /*!< in: record */
+ dict_index_t* index, /*!< in/out: index */
+ const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
+ ibool del) /*!< in: TRUE=deleted, FALSE=exists */
+{
+ const ib_rbt_node_t* node;
+ btr_blob_dbg_t b;
+ btr_blob_dbg_t* c;
+ ulint i;
+
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_a(dict_index_is_clust(index));
+ ut_a(del == !!del);/* must be FALSE==0 or TRUE==1 */
+
+ if (!rec_offs_any_extern(offsets) || !index->blobs) {
+
+ return;
+ }
+
+ b.ref_page_no = page_get_page_no(page_align(rec));
+ b.ref_heap_no = page_rec_get_heap_no(rec);
+
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (rec_offs_nth_extern(offsets, i)) {
+ ulint len;
+ const byte* field_ref = rec_get_nth_field(
+ rec, offsets, i, &len);
+
+ ut_a(len != UNIV_SQL_NULL);
+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+ field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+ b.ref_field_no = i;
+ b.blob_page_no = mach_read_from_4(
+ field_ref + BTR_EXTERN_PAGE_NO);
+
+ switch (b.blob_page_no) {
+ case 0:
+ ut_a(memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+ /* page number 0 is for the
+ page allocation bitmap */
+ case FIL_NULL:
+ /* the column has been freed already */
+ ut_error;
+ }
+
+ mutex_enter(&index->blobs_mutex);
+ node = rbt_lookup(index->blobs, &b);
+ ut_a(node);
+
+ c = rbt_value(btr_blob_dbg_t, node);
+ /* The flag should be modified. */
+ c->del = del;
+ if (btr_blob_dbg_msg) {
+ b = *c;
+ mutex_exit(&index->blobs_mutex);
+ btr_blob_dbg_msg_issue("del_mk", &b, "");
+ } else {
+ mutex_exit(&index->blobs_mutex);
+ }
+ }
+ }
+}
+
+/**************************************************************//**
+Change the ownership of an off-page column. */
+UNIV_INTERN
+void
+btr_blob_dbg_owner(
+/*===============*/
+ const rec_t* rec, /*!< in: record */
+ dict_index_t* index, /*!< in/out: index */
+ const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
+ ulint i, /*!< in: ith field in rec */
+ ibool own) /*!< in: TRUE=owned, FALSE=disowned */
+{
+ const ib_rbt_node_t* node;
+ btr_blob_dbg_t b;
+ const byte* field_ref;
+ ulint len;
+
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_a(rec_offs_nth_extern(offsets, i));
+
+ field_ref = rec_get_nth_field(rec, offsets, i, &len);
+ ut_a(len != UNIV_SQL_NULL);
+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+ field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+ b.ref_page_no = page_get_page_no(page_align(rec));
+ b.ref_heap_no = page_rec_get_heap_no(rec);
+ b.ref_field_no = i;
+ b.owner = !(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG);
+ b.blob_page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO);
+
+ ut_a(b.owner == own);
+
+ mutex_enter(&index->blobs_mutex);
+ node = rbt_lookup(index->blobs, &b);
+ /* row_ins_clust_index_entry_by_modify() invokes
+ btr_cur_unmark_extern_fields() also for the newly inserted
+ references, which are all zero bytes until the columns are stored.
+ The node lookup must fail if and only if that is the case. */
+ ut_a(!memcmp(field_ref, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)
+ == !node);
+
+ if (node) {
+ btr_blob_dbg_t* c = rbt_value(btr_blob_dbg_t, node);
+ /* Some code sets ownership from TRUE to TRUE.
+ We do not allow changing ownership from FALSE to FALSE. */
+ ut_a(own || c->owner);
+
+ c->owner = own;
+ if (!own) {
+ c->always_owner = FALSE;
+ }
+ }
+
+ mutex_exit(&index->blobs_mutex);
+}
+#endif /* UNIV_BLOB_DEBUG */
+
/*
Latching strategy of the InnoDB B-tree
--------------------------------------
@@ -296,6 +850,7 @@ btr_page_create(
page_t* page = buf_block_get_frame(block);
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
if (UNIV_LIKELY_NULL(page_zip)) {
page_create_zip(block, index, level, mtr);
@@ -489,6 +1044,7 @@ btr_page_free_low(
modify clock */
buf_block_modify_clock_inc(block);
+ btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
if (dict_index_is_ibuf(index)) {
@@ -603,7 +1159,6 @@ btr_page_get_father_node_ptr_func(
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
- page_t* page;
dtuple_t* tuple;
rec_t* user_rec;
rec_t* node_ptr;
@@ -621,7 +1176,6 @@ btr_page_get_father_node_ptr_func(
level = btr_page_get_level(btr_cur_get_page(cursor), mtr);
- page = btr_cur_get_page(cursor);
user_rec = btr_cur_get_rec(cursor);
ut_a(page_rec_is_user_rec(user_rec));
tuple = dict_index_build_node_ptr(index, user_rec, 0, heap, level);
@@ -666,7 +1220,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);
@@ -776,6 +1330,14 @@ btr_create(
block = buf_page_get(space, zip_size, page_no,
RW_X_LATCH, mtr);
} else {
+#ifdef UNIV_BLOB_DEBUG
+ if ((type & DICT_CLUSTERED) && !index->blobs) {
+ mutex_create(PFS_NOT_INSTRUMENTED,
+ &index->blobs_mutex, SYNC_ANY_LATCH);
+ index->blobs = rbt_create(sizeof(btr_blob_dbg_t),
+ btr_blob_dbg_cmp);
+ }
+#endif /* UNIV_BLOB_DEBUG */
block = fseg_create(space, 0,
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
}
@@ -983,7 +1545,7 @@ btr_page_reorganize_low(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
#ifndef UNIV_HOTBACKUP
- temp_block = buf_block_alloc(buf_pool, 0);
+ temp_block = buf_block_alloc(buf_pool);
#else /* !UNIV_HOTBACKUP */
ut_ad(block == back_block1);
temp_block = back_block2;
@@ -1000,6 +1562,7 @@ btr_page_reorganize_low(
block->check_index_page_at_flush = TRUE;
#endif /* !UNIV_HOTBACKUP */
+ btr_blob_dbg_remove(page, index, "btr_page_reorganize");
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
@@ -1028,6 +1591,8 @@ btr_page_reorganize_low(
(!page_zip_compress(page_zip, page, index, NULL))) {
/* Restore the old page and exit. */
+ btr_blob_dbg_restore(page, temp_page, index,
+ "btr_page_reorganize_compress_fail");
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
/* Check that the bytes that we skip are identical. */
@@ -1161,6 +1726,7 @@ btr_page_empty(
#endif /* UNIV_ZIP_DEBUG */
btr_search_drop_page_hash_index(block);
+ btr_blob_dbg_remove(page, index, "btr_page_empty");
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
@@ -2501,6 +3067,7 @@ btr_lift_page_up(
index);
}
+ btr_blob_dbg_remove(page, index, "btr_lift_page_up");
lock_update_copy_and_discard(father_block, block);
/* Go upward to root page, decrementing levels by one. */
@@ -2762,6 +3329,7 @@ err_exit:
lock_update_merge_right(merge_block, orig_succ, block);
}
+ btr_blob_dbg_remove(page, index, "btr_compress");
mem_heap_free(heap);
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
@@ -2992,6 +3560,8 @@ btr_discard_page(
block);
}
+ btr_blob_dbg_remove(page, index, "btr_discard_page");
+
/* Free the file page */
btr_page_free(index, block, mtr);
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 9585cbdb942..69dd1e428e1 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -111,6 +111,18 @@ can be released by page reorganize, then it is reorganized */
/*--------------------------------------*/
#define BTR_BLOB_HDR_SIZE 8 /*!< Size of a BLOB
part header, in bytes */
+
+/** Estimated table level stats from sampled value.
+@param value sampled stats
+@param index index being sampled
+@param sample number of sampled rows
+@param ext_size external stored data size
+@param not_empty table not empty
+@return estimated table wide stats from sampled value */
+#define BTR_TABLE_STATS_FROM_SAMPLE(value, index, sample, ext_size, not_empty)\
+ (((value) * (ib_int64_t) index->stat_n_leaf_pages \
+ + (sample) - 1 + (ext_size) + (not_empty)) / ((sample) + (ext_size)))
+
/* @} */
#endif /* !UNIV_HOTBACKUP */
@@ -185,7 +197,7 @@ static
ulint
btr_rec_get_externally_stored_len(
/*==============================*/
- rec_t* rec, /*!< in: record */
+ const rec_t* rec, /*!< in: record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#endif /* !UNIV_HOTBACKUP */
@@ -390,7 +402,7 @@ btr_cur_search_to_nth_level(
ut_ad(level == 0 || mode == PAGE_CUR_LE);
ut_ad(dict_index_check_search_tuple(index, tuple));
- ut_ad(!dict_index_is_ibuf(index) || ibuf_inside());
+ ut_ad(!dict_index_is_ibuf(index) || ibuf_inside(mtr));
ut_ad(dtuple_check_typed(tuple));
#ifdef UNIV_DEBUG
@@ -1071,7 +1083,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
@@ -1744,7 +1756,7 @@ func_exit:
See if there is enough place in the page modification log to log
an update-in-place.
@return TRUE if enough place */
-static
+UNIV_INTERN
ibool
btr_cur_update_alloc_zip(
/*=====================*/
@@ -1874,7 +1886,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(index, update, thr,
+ NULL, NULL)) {
/* Remove possible hash index pointer to this record */
btr_search_update_hash_on_delete(cursor);
@@ -1976,6 +1989,9 @@ btr_cur_optimistic_update(
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
+#ifdef UNIV_BLOB_NULL_DEBUG
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+#endif /* UNIV_BLOB_NULL_DEBUG */
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
@@ -2416,8 +2432,8 @@ make_external:
record on its page? */
was_first = page_cur_is_before_first(page_cursor);
- /* The first parameter means that no lock checking and undo logging
- is made in the insert */
+ /* Lock checks and undo logging were already performed by
+ btr_cur_upd_lock_and_undo(). */
err = btr_cur_pessimistic_insert(BTR_NO_UNDO_LOG_FLAG
| BTR_NO_LOCKING_FLAG
@@ -2626,27 +2642,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) {
@@ -2658,13 +2671,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,
@@ -2672,17 +2684,16 @@ 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);
}
page_zip = buf_block_get_page_zip(block);
+ btr_blob_dbg_set_deleted_flag(rec, index, offsets, val);
btr_rec_set_deleted_flag(rec, page_zip, val);
trx = thr_get_trx(thr);
@@ -2699,10 +2710,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);
}
@@ -3248,7 +3255,7 @@ btr_estimate_n_rows_in_range_on_level(
performance with this code which is just an estimation. If we read
this many pages before reaching slot2->page_no then we estimate the
average from the pages scanned so far */
- #define N_PAGES_READ_LIMIT 10
+# define N_PAGES_READ_LIMIT 10
page_no = slot1->page_no;
level = slot1->page_level;
@@ -3260,9 +3267,14 @@ btr_estimate_n_rows_in_range_on_level(
mtr_start(&mtr);
- /* fetch the page */
- block = buf_page_get(space, zip_size, page_no, RW_S_LATCH,
- &mtr);
+ /* Fetch the page. Because we are not holding the
+ index->lock, the tree may have changed and we may be
+ attempting to read a page that is no longer part of
+ the B-tree. We pass BUF_GET_POSSIBLY_FREED in order to
+ silence a debug assertion about this. */
+ block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH,
+ NULL, BUF_GET_POSSIBLY_FREED,
+ __FILE__, __LINE__, &mtr);
page = buf_block_get_frame(block);
@@ -3277,9 +3289,17 @@ btr_estimate_n_rows_in_range_on_level(
|| btr_page_get_level_low(page) != level) {
/* The page got reused for something else */
+ mtr_commit(&mtr);
goto inexact;
}
+ /* It is possible but highly unlikely that the page was
+ originally written by an old version of InnoDB that did
+ not initialize FIL_PAGE_TYPE on other than B-tree pages.
+ For example, this could be an almost-empty BLOB page
+ that happens to contain the magic values in the fields
+ that we checked above. */
+
n_pages_read++;
if (page_no != slot1->page_no) {
@@ -3487,9 +3507,54 @@ btr_estimate_n_rows_in_range(
}
/*******************************************************************//**
+Record the number of non_null key values in a given index for
+each n-column prefix of the index where n < dict_index_get_n_unique(index).
+The estimates are eventually stored in the array:
+index->stat_n_non_null_key_vals. */
+static
+void
+btr_record_not_null_field_in_rec(
+/*=============================*/
+ rec_t* rec, /*!< in: physical record */
+ ulint n_unique, /*!< in: dict_index_get_n_unique(index),
+ number of columns uniquely determine
+ an index entry */
+ const ulint* offsets, /*!< in: rec_get_offsets(rec, index),
+ its size could be for all fields or
+ that of "n_unique" */
+ ib_int64_t* n_not_null) /*!< in/out: array to record number of
+ not null rows for n-column prefix */
+{
+ ulint i;
+
+ ut_ad(rec_offs_n_fields(offsets) >= n_unique);
+
+ if (n_not_null == NULL) {
+ return;
+ }
+
+ for (i = 0; i < n_unique; i++) {
+ ulint rec_len;
+ byte* field;
+
+ field = rec_get_nth_field(rec, offsets, i, &rec_len);
+
+ if (rec_len != UNIV_SQL_NULL) {
+ n_not_null[i]++;
+ } else {
+ /* Break if we hit the first NULL value */
+ break;
+ }
+ }
+}
+
+/*******************************************************************//**
Estimates the number of different key values in a given index, for
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
-The estimates are stored in the array index->stat_n_diff_key_vals. */
+The estimates are stored in the array index->stat_n_diff_key_vals.
+If innodb_stats_method is "nulls_ignored", we also record the number of
+non-null values for each prefix and store the estimates in
+array index->stat_n_non_null_key_vals. */
UNIV_INTERN
void
btr_estimate_number_of_different_key_vals(
@@ -3503,6 +3568,8 @@ btr_estimate_number_of_different_key_vals(
ulint matched_fields;
ulint matched_bytes;
ib_int64_t* n_diff;
+ ib_int64_t* n_not_null;
+ ibool stats_null_not_equal;
ullint n_sample_pages; /* number of pages to sample */
ulint not_empty_flag = 0;
ulint total_external_size = 0;
@@ -3511,16 +3578,43 @@ btr_estimate_number_of_different_key_vals(
ullint add_on;
mtr_t mtr;
mem_heap_t* heap = NULL;
- ulint offsets_rec_[REC_OFFS_NORMAL_SIZE];
- ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets_rec = offsets_rec_;
- ulint* offsets_next_rec= offsets_next_rec_;
- rec_offs_init(offsets_rec_);
- rec_offs_init(offsets_next_rec_);
+ ulint* offsets_rec = NULL;
+ ulint* offsets_next_rec = NULL;
n_cols = dict_index_get_n_unique(index);
- n_diff = mem_zalloc((n_cols + 1) * sizeof(ib_int64_t));
+ heap = mem_heap_create((sizeof *n_diff + sizeof *n_not_null)
+ * (n_cols + 1)
+ + dict_index_get_n_fields(index)
+ * (sizeof *offsets_rec
+ + sizeof *offsets_next_rec));
+
+ n_diff = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
+
+ n_not_null = NULL;
+
+ /* Check srv_innodb_stats_method setting, and decide whether we
+ need to record non-null value and also decide if NULL is
+ considered equal (by setting stats_null_not_equal value) */
+ switch (srv_innodb_stats_method) {
+ case SRV_STATS_NULLS_IGNORED:
+ n_not_null = mem_heap_zalloc(heap, (n_cols + 1)
+ * sizeof *n_not_null);
+ /* fall through */
+
+ case SRV_STATS_NULLS_UNEQUAL:
+ /* for both SRV_STATS_NULLS_IGNORED and SRV_STATS_NULLS_UNEQUAL
+ case, we will treat NULLs as unequal value */
+ stats_null_not_equal = TRUE;
+ break;
+
+ case SRV_STATS_NULLS_EQUAL:
+ stats_null_not_equal = FALSE;
+ break;
+
+ default:
+ ut_error;
+ }
/* It makes no sense to test more pages than are contained
in the index, thus we lower the number if it is too high */
@@ -3537,7 +3631,6 @@ btr_estimate_number_of_different_key_vals(
/* We sample some pages in the index to get an estimate */
for (i = 0; i < n_sample_pages; i++) {
- rec_t* supremum;
mtr_start(&mtr);
btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
@@ -3550,18 +3643,25 @@ btr_estimate_number_of_different_key_vals(
page = btr_cur_get_page(&cursor);
- supremum = page_get_supremum_rec(page);
rec = page_rec_get_next(page_get_infimum_rec(page));
- if (rec != supremum) {
+ if (!page_rec_is_supremum(rec)) {
not_empty_flag = 1;
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
ULINT_UNDEFINED, &heap);
+
+ if (n_not_null) {
+ btr_record_not_null_field_in_rec(
+ rec, n_cols, offsets_rec, n_not_null);
+ }
}
- while (rec != supremum) {
+ while (!page_rec_is_supremum(rec)) {
rec_t* next_rec = page_rec_get_next(rec);
- if (next_rec == supremum) {
+ if (page_rec_is_supremum(next_rec)) {
+ total_external_size +=
+ btr_rec_get_externally_stored_len(
+ rec, offsets_rec);
break;
}
@@ -3569,11 +3669,13 @@ btr_estimate_number_of_different_key_vals(
matched_bytes = 0;
offsets_next_rec = rec_get_offsets(next_rec, index,
offsets_next_rec,
- n_cols, &heap);
+ ULINT_UNDEFINED,
+ &heap);
cmp_rec_rec_with_match(rec, next_rec,
offsets_rec, offsets_next_rec,
- index, &matched_fields,
+ index, stats_null_not_equal,
+ &matched_fields,
&matched_bytes);
for (j = matched_fields + 1; j <= n_cols; j++) {
@@ -3583,6 +3685,12 @@ btr_estimate_number_of_different_key_vals(
n_diff[j]++;
}
+ if (n_not_null) {
+ btr_record_not_null_field_in_rec(
+ next_rec, n_cols, offsets_next_rec,
+ n_not_null);
+ }
+
total_external_size
+= btr_rec_get_externally_stored_len(
rec, offsets_rec);
@@ -3617,10 +3725,6 @@ btr_estimate_number_of_different_key_vals(
}
}
- offsets_rec = rec_get_offsets(rec, index, offsets_rec,
- ULINT_UNDEFINED, &heap);
- total_external_size += btr_rec_get_externally_stored_len(
- rec, offsets_rec);
mtr_commit(&mtr);
}
@@ -3632,17 +3736,11 @@ 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]
- * (ib_int64_t)index->stat_n_leaf_pages
- + n_sample_pages - 1
- + total_external_size
- + not_empty_flag)
- / (n_sample_pages
- + total_external_size));
+ = BTR_TABLE_STATS_FROM_SAMPLE(
+ n_diff[j], index, n_sample_pages,
+ total_external_size, not_empty_flag);
/* If the tree is small, smaller than
10 * n_sample_pages + total_external_size, then
@@ -3661,47 +3759,81 @@ 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);
+ /* Update the stat_n_non_null_key_vals[] with our
+ sampled result. stat_n_non_null_key_vals[] is created
+ and initialized to zero in dict_index_add_to_cache(),
+ along with stat_n_diff_key_vals[] array */
+ if (n_not_null != NULL && (j < n_cols)) {
+ index->stat_n_non_null_key_vals[j] =
+ BTR_TABLE_STATS_FROM_SAMPLE(
+ n_not_null[j], index, n_sample_pages,
+ total_external_size, not_empty_flag);
+ }
}
+
+ mem_heap_free(heap);
}
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
/***********************************************************//**
+Gets the offset of the pointer to the externally stored part of a field.
+@return offset of the pointer to the externally stored part */
+static
+ulint
+btr_rec_get_field_ref_offs(
+/*=======================*/
+ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
+ ulint n) /*!< in: index of the external field */
+{
+ ulint field_ref_offs;
+ ulint local_len;
+
+ ut_a(rec_offs_nth_extern(offsets, n));
+ field_ref_offs = rec_get_nth_field_offs(offsets, n, &local_len);
+ ut_a(local_len != UNIV_SQL_NULL);
+ ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
+
+ return(field_ref_offs + local_len - BTR_EXTERN_FIELD_REF_SIZE);
+}
+
+/** Gets a pointer to the externally stored part of a field.
+@param rec record
+@param offsets rec_get_offsets(rec)
+@param n index of the externally stored field
+@return pointer to the externally stored part */
+#define btr_rec_get_field_ref(rec, offsets, n) \
+ ((rec) + btr_rec_get_field_ref_offs(offsets, n))
+
+/***********************************************************//**
Gets the externally stored size of a record, in units of a database page.
@return externally stored part, in units of a database page */
static
ulint
btr_rec_get_externally_stored_len(
/*==============================*/
- rec_t* rec, /*!< in: record */
+ const rec_t* rec, /*!< in: record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ulint n_fields;
- byte* data;
- ulint local_len;
- ulint extern_len;
ulint total_extern_len = 0;
ulint i;
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+
+ if (!rec_offs_any_extern(offsets)) {
+ return(0);
+ }
+
n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) {
if (rec_offs_nth_extern(offsets, i)) {
- data = rec_get_nth_field(rec, offsets, i, &local_len);
-
- local_len -= BTR_EXTERN_FIELD_REF_SIZE;
-
- extern_len = mach_read_from_4(data + local_len
- + BTR_EXTERN_LEN + 4);
+ ulint extern_len = mach_read_from_4(
+ btr_rec_get_field_ref(rec, offsets, i)
+ + BTR_EXTERN_LEN + 4);
total_extern_len += ut_calc_align(extern_len,
UNIV_PAGE_SIZE);
@@ -3731,7 +3863,7 @@ btr_cur_set_ownership_of_extern_field(
ulint byte_val;
data = rec_get_nth_field(rec, offsets, i, &local_len);
-
+ ut_ad(rec_offs_nth_extern(offsets, i));
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
@@ -3741,6 +3873,9 @@ btr_cur_set_ownership_of_extern_field(
if (val) {
byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG);
} else {
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!(byte_val & BTR_EXTERN_OWNER_FLAG));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
}
@@ -3754,110 +3889,40 @@ btr_cur_set_ownership_of_extern_field(
} else {
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
}
+
+ btr_blob_dbg_owner(rec, index, offsets, i, val);
}
/*******************************************************************//**
-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:
- ;
}
}
@@ -3897,29 +3962,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.
@@ -4053,13 +4095,12 @@ btr_blob_free(
&& buf_block_get_space(block) == space
&& buf_block_get_page_no(block) == page_no) {
- if (buf_LRU_free_block(&block->page, all, NULL)
- != BUF_LRU_FREED
+ if (buf_LRU_free_block(&block->page, all) != BUF_LRU_FREED
&& all && block->page.zip.data) {
/* Attempt to deallocate the uncompressed page
if the whole block cannot be deallocted. */
- buf_LRU_free_block(&block->page, FALSE, NULL);
+ buf_LRU_free_block(&block->page, FALSE);
}
}
@@ -4072,11 +4113,11 @@ 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(
-/*============================*/
+btr_store_big_rec_extern_fields_func(
+/*=================================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
@@ -4085,11 +4126,17 @@ btr_store_big_rec_extern_fields(
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
- big_rec_t* big_rec_vec, /*!< in: vector containing fields
+#ifdef UNIV_DEBUG
+ mtr_t* local_mtr, /*!< in: mtr containing the
+ latch to rec and to the tree */
+#endif /* UNIV_DEBUG */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ibool update_in_place,/*! in: TRUE if the record is updated
+ in place (not delete+insert) */
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+ const big_rec_t*big_rec_vec) /*!< in: vector containing fields
to be stored externally */
- mtr_t* local_mtr __attribute__((unused))) /*!< in: mtr
- containing the latch to rec and to the
- tree */
+
{
ulint rec_page_no;
byte* field_ref;
@@ -4107,6 +4154,7 @@ btr_store_big_rec_extern_fields(
z_stream c_stream;
ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_ad(rec_offs_any_extern(offsets));
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
@@ -4138,21 +4186,37 @@ btr_store_big_rec_extern_fields(
ut_a(err == Z_OK);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* All pointers to externally stored columns in the record
+ must either be zero or they must be pointers to inherited
+ columns, owned by this record or an earlier record version. */
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (!rec_offs_nth_extern(offsets, i)) {
+ continue;
+ }
+ field_ref = btr_rec_get_field_ref(rec, offsets, i);
+
+ ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
+ /* Either this must be an update in place,
+ or the BLOB must be inherited, or the BLOB pointer
+ must be zero (will be written in this function). */
+ ut_a(update_in_place
+ || (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
+ || !memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+ }
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/* We have to create a file segment to the tablespace
for each field and put the pointer to the field in rec */
for (i = 0; i < big_rec_vec->n_fields; i++) {
- ut_ad(rec_offs_nth_extern(offsets,
- big_rec_vec->fields[i].field_no));
- {
- ulint local_len;
- field_ref = rec_get_nth_field(
- rec, offsets, big_rec_vec->fields[i].field_no,
- &local_len);
- ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
- local_len -= BTR_EXTERN_FIELD_REF_SIZE;
- field_ref += local_len;
- }
+ field_ref = btr_rec_get_field_ref(
+ rec, offsets, big_rec_vec->fields[i].field_no);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* A zero BLOB pointer should have been initially inserted. */
+ ut_a(!memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
extern_len = big_rec_vec->fields[i].len;
UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data,
extern_len);
@@ -4327,6 +4391,11 @@ btr_store_big_rec_extern_fields(
}
if (prev_page_no == FIL_NULL) {
+ btr_blob_dbg_add_blob(
+ rec, big_rec_vec->fields[i]
+ .field_no, page_no, index,
+ "store");
+
mach_write_to_4(field_ref
+ BTR_EXTERN_SPACE_ID,
space_id);
@@ -4402,6 +4471,11 @@ next_zip_page:
MLOG_4BYTES, &mtr);
if (prev_page_no == FIL_NULL) {
+ btr_blob_dbg_add_blob(
+ rec, big_rec_vec->fields[i]
+ .field_no, page_no, index,
+ "store");
+
mlog_write_ulint(field_ref
+ BTR_EXTERN_SPACE_ID,
space_id,
@@ -4434,6 +4508,23 @@ next_zip_page:
mem_heap_free(heap);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* All pointers to externally stored columns in the record
+ must be valid. */
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (!rec_offs_nth_extern(offsets, i)) {
+ continue;
+ }
+
+ field_ref = btr_rec_get_field_ref(rec, offsets, i);
+
+ /* The pointer must not be zero. */
+ ut_a(0 != memcmp(field_ref, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+ /* The column must not be disowned by this record. */
+ ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
+ }
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
return(DB_SUCCESS);
}
@@ -4456,6 +4547,7 @@ btr_check_blob_fil_page_type(
if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) {
ulint flags = fil_space_get_flags(space_id);
+#ifndef UNIV_DEBUG /* Improve debug test coverage */
if (UNIV_LIKELY
((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) {
/* Old versions of InnoDB did not initialize
@@ -4464,6 +4556,7 @@ btr_check_blob_fil_page_type(
a BLOB page that is in Antelope format.*/
return;
}
+#endif /* !UNIV_DEBUG */
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -4513,23 +4606,13 @@ btr_free_externally_stored_field(
ulint page_no;
ulint next_page_no;
mtr_t mtr;
-#ifdef UNIV_DEBUG
+
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains_page(local_mtr, field_ref,
MTR_MEMO_PAGE_X_FIX));
ut_ad(!rec || rec_offs_validate(rec, index, offsets));
-
- if (rec) {
- ulint local_len;
- const byte* f = rec_get_nth_field(rec, offsets,
- i, &local_len);
- ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
- local_len -= BTR_EXTERN_FIELD_REF_SIZE;
- f += local_len;
- ut_ad(f == field_ref);
- }
-#endif /* UNIV_DEBUG */
+ ut_ad(!rec || field_ref == btr_rec_get_field_ref(rec, offsets, i));
if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE))) {
@@ -4561,6 +4644,37 @@ btr_free_externally_stored_field(
rec_zip_size = 0;
}
+#ifdef UNIV_BLOB_DEBUG
+ if (!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)
+ && !((field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
+ && (rb_ctx == RB_NORMAL || rb_ctx == RB_RECOVERY))) {
+ /* This off-page column will be freed.
+ Check that no references remain. */
+
+ btr_blob_dbg_t b;
+
+ b.blob_page_no = mach_read_from_4(
+ field_ref + BTR_EXTERN_PAGE_NO);
+
+ if (rec) {
+ /* Remove the reference from the record to the
+ BLOB. If the BLOB were not freed, the
+ reference would be removed when the record is
+ removed. Freeing the BLOB will overwrite the
+ BTR_EXTERN_PAGE_NO in the field_ref of the
+ record with FIL_NULL, which would make the
+ btr_blob_dbg information inconsistent with the
+ record. */
+ b.ref_page_no = page_get_page_no(page_align(rec));
+ b.ref_heap_no = page_rec_get_heap_no(rec);
+ b.ref_field_no = i;
+ btr_blob_dbg_rbt_delete(index, &b, "free");
+ }
+
+ btr_blob_dbg_assert_empty(index, b.blob_page_no);
+ }
+#endif /* UNIV_BLOB_DEBUG */
+
for (;;) {
#ifdef UNIV_SYNC_DEBUG
buf_block_t* rec_block;
@@ -4572,12 +4686,10 @@ btr_free_externally_stored_field(
#ifdef UNIV_SYNC_DEBUG
rec_block =
#endif /* UNIV_SYNC_DEBUG */
- buf_page_get(page_get_space_id(
- page_align(field_ref)),
- rec_zip_size,
- page_get_page_no(
- page_align(field_ref)),
- RW_X_LATCH, &mtr);
+ buf_page_get(page_get_space_id(page_align(field_ref)),
+ rec_zip_size,
+ page_get_page_no(page_align(field_ref)),
+ RW_X_LATCH, &mtr);
buf_block_dbg_add_level(rec_block, SYNC_NO_ORDER_CHECK);
page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO);
@@ -4694,13 +4806,8 @@ btr_rec_free_externally_stored_fields(
for (i = 0; i < n_fields; i++) {
if (rec_offs_nth_extern(offsets, i)) {
- ulint len;
- byte* data
- = rec_get_nth_field(rec, offsets, i, &len);
- ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
-
btr_free_externally_stored_field(
- index, data + len - BTR_EXTERN_FIELD_REF_SIZE,
+ index, btr_rec_get_field_ref(rec, offsets, i),
rec, offsets, page_zip, i, rb_ctx, mtr);
}
}
@@ -4812,27 +4919,45 @@ btr_copy_blob_prefix(
/*******************************************************************//**
Copies the prefix of a compressed BLOB. The clustered index record
-that points to this BLOB must be protected by a lock or a page latch. */
+that points to this BLOB must be protected by a lock or a page latch.
+@return number of bytes written to buf */
static
-void
+ulint
btr_copy_zblob_prefix(
/*==================*/
- z_stream* d_stream,/*!< in/out: the decompressing stream */
+ byte* buf, /*!< out: the externally stored part of
+ the field, or a prefix of it */
+ ulint len, /*!< in: length of buf, in bytes */
ulint zip_size,/*!< in: compressed BLOB page size */
ulint space_id,/*!< in: space id of the BLOB pages */
ulint page_no,/*!< in: page number of the first BLOB page */
ulint offset) /*!< in: offset on the first BLOB page */
{
- ulint page_type = FIL_PAGE_TYPE_ZBLOB;
+ ulint page_type = FIL_PAGE_TYPE_ZBLOB;
+ mem_heap_t* heap;
+ int err;
+ z_stream d_stream;
+
+ d_stream.next_out = buf;
+ d_stream.avail_out = len;
+ d_stream.next_in = Z_NULL;
+ d_stream.avail_in = 0;
+
+ /* Zlib inflate needs 32 kilobytes for the default
+ window size, plus a few kilobytes for small objects. */
+ heap = mem_heap_create(40000);
+ page_zip_set_alloc(&d_stream, heap);
ut_ad(ut_is_2pow(zip_size));
ut_ad(zip_size >= PAGE_ZIP_MIN_SIZE);
ut_ad(zip_size <= UNIV_PAGE_SIZE);
ut_ad(space_id);
+ err = inflateInit(&d_stream);
+ ut_a(err == Z_OK);
+
for (;;) {
buf_page_t* bpage;
- int err;
ulint next_page_no;
/* There is no latch on bpage directly. Instead,
@@ -4848,7 +4973,7 @@ btr_copy_zblob_prefix(
" compressed BLOB"
" page %lu space %lu\n",
(ulong) page_no, (ulong) space_id);
- return;
+ goto func_exit;
}
if (UNIV_UNLIKELY
@@ -4874,13 +4999,13 @@ btr_copy_zblob_prefix(
offset += 4;
}
- d_stream->next_in = bpage->zip.data + offset;
- d_stream->avail_in = zip_size - offset;
+ d_stream.next_in = bpage->zip.data + offset;
+ d_stream.avail_in = zip_size - offset;
- err = inflate(d_stream, Z_NO_FLUSH);
+ err = inflate(&d_stream, Z_NO_FLUSH);
switch (err) {
case Z_OK:
- if (!d_stream->avail_out) {
+ if (!d_stream.avail_out) {
goto end_of_blob;
}
break;
@@ -4897,13 +5022,13 @@ inflate_error:
" compressed BLOB"
" page %lu space %lu returned %d (%s)\n",
(ulong) page_no, (ulong) space_id,
- err, d_stream->msg);
+ err, d_stream.msg);
case Z_BUF_ERROR:
goto end_of_blob;
}
if (next_page_no == FIL_NULL) {
- if (!d_stream->avail_in) {
+ if (!d_stream.avail_in) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: unexpected end of"
@@ -4912,7 +5037,7 @@ inflate_error:
(ulong) page_no,
(ulong) space_id);
} else {
- err = inflate(d_stream, Z_FINISH);
+ err = inflate(&d_stream, Z_FINISH);
switch (err) {
case Z_STREAM_END:
case Z_BUF_ERROR:
@@ -4924,7 +5049,7 @@ inflate_error:
end_of_blob:
buf_page_release_zip(bpage);
- return;
+ goto func_exit;
}
buf_page_release_zip(bpage);
@@ -4936,6 +5061,12 @@ end_of_blob:
offset = FIL_PAGE_NEXT;
page_type = FIL_PAGE_TYPE_ZBLOB2;
}
+
+func_exit:
+ inflateEnd(&d_stream);
+ mem_heap_free(heap);
+ UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
+ return(d_stream.total_out);
}
/*******************************************************************//**
@@ -4961,28 +5092,8 @@ btr_copy_externally_stored_field_prefix_low(
}
if (UNIV_UNLIKELY(zip_size)) {
- int err;
- z_stream d_stream;
- mem_heap_t* heap;
-
- /* Zlib inflate needs 32 kilobytes for the default
- window size, plus a few kilobytes for small objects. */
- heap = mem_heap_create(40000);
- page_zip_set_alloc(&d_stream, heap);
-
- err = inflateInit(&d_stream);
- ut_a(err == Z_OK);
-
- d_stream.next_out = buf;
- d_stream.avail_out = len;
- d_stream.avail_in = 0;
-
- btr_copy_zblob_prefix(&d_stream, zip_size,
- space_id, page_no, offset);
- inflateEnd(&d_stream);
- mem_heap_free(heap);
- UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
- return(d_stream.total_out);
+ return(btr_copy_zblob_prefix(buf, len, zip_size,
+ space_id, page_no, offset));
} else {
return(btr_copy_blob_prefix(buf, len, space_id,
page_no, offset));
diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
index 8f5f9b839b5..93573a300e4 100644
--- a/storage/innobase/btr/btr0sea.c
+++ b/storage/innobase/btr/btr0sea.c
@@ -151,7 +151,7 @@ btr_search_check_free_space_in_heap(void)
be enough free space in the hash table. */
if (heap->free_block == NULL) {
- buf_block_t* block = buf_block_alloc(NULL, 0);
+ buf_block_t* block = buf_block_alloc(NULL);
rw_lock_x_lock(&btr_search_latch);
@@ -1213,8 +1213,8 @@ btr_search_drop_page_hash_when_freed(
having to fear a deadlock. */
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
- BUF_GET_IF_IN_POOL, __FILE__, __LINE__,
- &mtr);
+ BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
+ &mtr);
/* Because the buffer pool mutex was released by
buf_page_peek_if_search_hashed(), it is possible that the
block was removed from the buffer pool by another thread
diff --git a/storage/innobase/buf/buf0buddy.c b/storage/innobase/buf/buf0buddy.c
index 5dc0780cbdd..75ba832c7e5 100644
--- a/storage/innobase/buf/buf0buddy.c
+++ b/storage/innobase/buf/buf0buddy.c
@@ -281,7 +281,7 @@ buf_buddy_alloc_from(
/**********************************************************************//**
Allocate a block. The thread calling this function must hold
-buf_pool->mutex and must not hold buf_pool_zip_mutex or any block->mutex.
+buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex.
The buf_pool->mutex may only be released and reacquired if lru != NULL.
@return allocated block, possibly NULL if lru==NULL */
UNIV_INTERN
@@ -327,7 +327,7 @@ buf_buddy_alloc_low(
/* Try replacing an uncompressed page in the buffer pool. */
buf_pool_mutex_exit(buf_pool);
- block = buf_LRU_get_free_block(buf_pool, 0);
+ block = buf_LRU_get_free_block(buf_pool);
*lru = TRUE;
buf_pool_mutex_enter(buf_pool);
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index ab3c1abf490..52358c52853 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -172,7 +172,7 @@ The chain of modified blocks (buf_pool->flush_list) contains the blocks
holding file pages that have been modified in the memory
but not written to disk yet. The block with the oldest modification
which has not yet been written to disk is at the end of the chain.
-The access to this list is protected by flush_list_mutex.
+The access to this list is protected by buf_pool->flush_list_mutex.
The chain of unmodified compressed blocks (buf_pool->zip_clean)
contains the control blocks (buf_page_t) of those compressed pages
@@ -246,8 +246,8 @@ static const int WAIT_FOR_READ = 5000;
/** Number of attemtps made to read in a page in the buffer pool */
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
-/** The buffer buf_pool of the database */
-UNIV_INTERN buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS];
+/** The buffer pools of the database */
+UNIV_INTERN buf_pool_t* buf_pool_ptr;
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
static ulint buf_dbg_counter = 0; /*!< This is used to insert validation
@@ -416,9 +416,9 @@ UNIV_INTERN
buf_block_t*
buf_block_alloc(
/*============*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- ulint zip_size) /*!< in: compressed page size in bytes,
- or 0 if uncompressed tablespace */
+ buf_pool_t* buf_pool) /*!< in/out: buffer pool instance,
+ or NULL for round-robin selection
+ of the buffer pool */
{
buf_block_t* block;
ulint index;
@@ -431,7 +431,7 @@ buf_block_alloc(
buf_pool = buf_pool_from_array(index);
}
- block = buf_LRU_get_free_block(buf_pool, zip_size);
+ block = buf_LRU_get_free_block(buf_pool);
buf_block_set_state(block, BUF_BLOCK_MEMORY);
@@ -536,7 +536,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),
@@ -858,16 +858,16 @@ buf_block_init(
block->frame = frame;
- block->page.buf_pool = buf_pool;
+ block->page.buf_pool_index = buf_pool_index(buf_pool);
block->page.state = BUF_BLOCK_NOT_USED;
block->page.buf_fix_count = 0;
block->page.io_fix = BUF_IO_NONE;
block->modify_clock = 0;
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
block->page.file_page_was_freed = FALSE;
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
block->check_index_page_at_flush = FALSE;
block->index = NULL;
@@ -1233,7 +1233,7 @@ buf_pool_init_instance(
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
-
+
buf_pool->last_printout_time = ut_time();
}
/* 2. Initialize flushing fields
@@ -1280,8 +1280,6 @@ buf_pool_free_instance(
mem_free(buf_pool->chunks);
hash_table_free(buf_pool->page_hash);
hash_table_free(buf_pool->zip_hash);
- mem_free(buf_pool);
- buf_pool = NULL;
}
/********************************************************************//**
@@ -1294,25 +1292,23 @@ buf_pool_init(
ulint total_size, /*!< in: size of the total pool in bytes */
ulint n_instances) /*!< in: number of instances */
{
- ulint i;
+ ulint i;
+ const ulint size = total_size / n_instances;
+
+ ut_ad(n_instances > 0);
+ ut_ad(n_instances <= MAX_BUFFER_POOLS);
+ ut_ad(n_instances == srv_buf_pool_instances);
/* We create an extra buffer pool instance, this instance is used
for flushing the flush lists, to keep track of n_flush for all
the buffer pools and also used as a waiting object during flushing. */
- for (i = 0; i < n_instances; i++) {
- buf_pool_t* ptr;
- ulint size;
+ buf_pool_ptr = mem_zalloc(n_instances * sizeof *buf_pool_ptr);
- ptr = mem_zalloc(sizeof(*ptr));
-
- size = total_size / n_instances;
-
- buf_pool_ptr[i] = ptr;
+ for (i = 0; i < n_instances; i++) {
+ buf_pool_t* ptr = &buf_pool_ptr[i];
if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
- mem_free(buf_pool_ptr[i]);
-
/* Free all the instances created so far. */
buf_pool_free(i);
@@ -1341,8 +1337,10 @@ buf_pool_free(
for (i = 0; i < n_instances; i++) {
buf_pool_free_instance(buf_pool_from_array(i));
- buf_pool_ptr[i] = NULL;
}
+
+ mem_free(buf_pool_ptr);
+ buf_pool_ptr = NULL;
}
/********************************************************************//**
@@ -1367,11 +1365,11 @@ buf_pool_drop_hash_index_instance(
/* block->is_hashed cannot be modified
when we have an x-latch on btr_search_latch;
see the comment in buf0buf.h */
-
+
if (!block->is_hashed) {
continue;
}
-
+
/* To follow the latching order, we
have to release btr_search_latch
before acquiring block->latch. */
@@ -1380,14 +1378,14 @@ buf_pool_drop_hash_index_instance(
we must rescan all blocks, because
some may become hashed again. */
*released_search_latch = TRUE;
-
+
rw_lock_x_lock(&block->lock);
-
+
/* This should be guaranteed by the
callers, which will be holding
btr_search_enabled_mutex. */
ut_ad(!btr_search_enabled);
-
+
/* Because we did not buffer-fix the
block by calling buf_block_get_gen(),
it is possible that the block has been
@@ -1397,7 +1395,7 @@ buf_pool_drop_hash_index_instance(
block is mapped to. All we want to do
is to drop any hash entries referring
to the page. */
-
+
/* It is possible that
block->page.state != BUF_FILE_PAGE.
Even that does not matter, because
@@ -1405,18 +1403,18 @@ buf_pool_drop_hash_index_instance(
check block->is_hashed before doing
anything. block->is_hashed can only
be set on uncompressed file pages. */
-
+
btr_search_drop_page_hash_index(block);
-
+
rw_lock_x_unlock(&block->lock);
-
+
rw_lock_x_lock(&btr_search_latch);
-
+
ut_ad(!btr_search_enabled);
}
}
}
-
+
/********************************************************************//**
Drops the adaptive hash index. To prevent a livelock, this function
is only to be called while holding btr_search_latch and while
@@ -1625,7 +1623,7 @@ shrink_again:
buf_LRU_make_block_old(&block->page);
dirty++;
- } else if (buf_LRU_free_block(&block->page, TRUE, NULL)
+ } else if (buf_LRU_free_block(&block->page, TRUE)
!= BUF_LRU_FREED) {
nonfree++;
}
@@ -1882,8 +1880,8 @@ buf_pool_watch_set(
ut_ad(!bpage->in_page_hash);
ut_ad(bpage->buf_fix_count == 0);
- /* bpage is pointing to buf_pool_watch[],
- which is protected by buf_pool_mutex.
+ /* bpage is pointing to buf_pool->watch[],
+ which is protected by buf_pool->mutex.
Normally, buf_page_t objects are protected by
buf_block_t::mutex or buf_pool->zip_mutex or both. */
@@ -1992,30 +1990,30 @@ buf_pool_resize(void)
ulint min_change_size = 1048576 * srv_buf_pool_instances;
buf_pool_mutex_enter_all();
-
+
if (srv_buf_pool_old_size == srv_buf_pool_size) {
-
+
buf_pool_mutex_exit_all();
return;
} else if (srv_buf_pool_curr_size + min_change_size
> srv_buf_pool_size) {
-
+
change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
/ UNIV_PAGE_SIZE;
buf_pool_mutex_exit_all();
-
+
/* Disable adaptive hash indexes and empty the index
in order to free up memory in the buffer pool chunks. */
buf_pool_shrink(change_size);
} else if (srv_buf_pool_curr_size + min_change_size
< srv_buf_pool_size) {
-
+
/* Enlarge the buffer pool by at least one megabyte */
-
+
change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
buf_pool_mutex_exit_all();
@@ -2028,10 +2026,10 @@ buf_pool_resize(void)
return;
}
-
+
buf_pool_page_hash_rebuild();
}
-
+
/****************************************************************//**
Remove the sentinel block for the watch before replacing it with a real block.
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
@@ -2231,7 +2229,7 @@ buf_page_peek_if_search_hashed(
return(is_hashed);
}
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
This function should be called when we free a file page and want the
@@ -2254,6 +2252,8 @@ buf_page_set_file_page_was_freed(
if (bpage) {
ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
+ /* bpage->file_page_was_freed can already hold
+ when this code is invoked from dict_drop_index_tree() */
bpage->file_page_was_freed = TRUE;
}
@@ -2291,7 +2291,7 @@ buf_page_reset_file_page_was_freed(
return(bpage);
}
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/********************************************************************//**
Get read access to a compressed page (usually of type
@@ -2316,9 +2316,6 @@ buf_page_get_zip(
unsigned access_time;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
-#ifndef UNIV_LOG_DEBUG
- ut_ad(!ibuf_inside());
-#endif
buf_pool->stat.n_page_gets++;
for (;;) {
@@ -2368,8 +2365,7 @@ err_exit:
mutex_enter(block_mutex);
/* Discard the uncompressed page frame if possible. */
- if (buf_LRU_free_block(bpage, FALSE, NULL)
- == BUF_LRU_FREED) {
+ if (buf_LRU_free_block(bpage, FALSE) == BUF_LRU_FREED) {
mutex_exit(block_mutex);
goto lookup;
@@ -2393,7 +2389,7 @@ got_block:
buf_page_set_accessed_make_young(bpage, access_time);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(!bpage->file_page_was_freed);
#endif
@@ -2534,16 +2530,19 @@ buf_block_align_instance(
/* TODO: protect buf_pool->chunks with a mutex (it will
currently remain constant after buf_pool_init()) */
for (chunk = buf_pool->chunks, i = buf_pool->n_chunks; i--; chunk++) {
- lint offs = ptr - chunk->blocks->frame;
+ ulint offs;
- if (UNIV_UNLIKELY(offs < 0)) {
+ if (UNIV_UNLIKELY(ptr < chunk->blocks->frame)) {
continue;
}
+ /* else */
+
+ offs = ptr - chunk->blocks->frame;
offs >>= UNIV_PAGE_SIZE_SHIFT;
- if (UNIV_LIKELY((ulint) offs < chunk->size)) {
+ if (UNIV_LIKELY(offs < chunk->size)) {
buf_block_t* block = &chunk->blocks[offs];
/* The function buf_chunk_init() invokes
@@ -2720,7 +2719,7 @@ buf_page_get_gen(
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
buf_block_t* guess, /*!< in: guessed block or NULL */
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
- BUF_GET_NO_LATCH, or
+ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or
BUF_GET_IF_IN_POOL_OR_WATCH */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
@@ -2739,15 +2738,27 @@ buf_page_get_gen(
ut_ad((rw_latch == RW_S_LATCH)
|| (rw_latch == RW_X_LATCH)
|| (rw_latch == RW_NO_LATCH));
- ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
- ut_ad(mode == BUF_GET
- || mode == BUF_GET_IF_IN_POOL
- || mode == BUF_GET_NO_LATCH
- || mode == BUF_GET_IF_IN_POOL_OR_WATCH);
+#ifdef UNIV_DEBUG
+ switch (mode) {
+ case BUF_GET_NO_LATCH:
+ ut_ad(rw_latch == RW_NO_LATCH);
+ break;
+ case BUF_GET:
+ case BUF_GET_IF_IN_POOL:
+ case BUF_PEEK_IF_IN_POOL:
+ case BUF_GET_IF_IN_POOL_OR_WATCH:
+ case BUF_GET_POSSIBLY_FREED:
+ break;
+ default:
+ ut_error;
+ }
+#endif /* UNIV_DEBUG */
ut_ad(zip_size == fil_space_get_zip_size(space));
ut_ad(ut_is_2pow(zip_size));
#ifndef UNIV_LOG_DEBUG
- ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
+ ut_ad(!ibuf_inside(mtr)
+ || ibuf_page_low(space, zip_size, offset,
+ FALSE, file, line, NULL));
#endif
buf_pool->stat.n_page_gets++;
fold = buf_page_address_fold(space, offset);
@@ -2802,6 +2813,7 @@ loop2:
buf_pool_mutex_exit(buf_pool);
if (mode == BUF_GET_IF_IN_POOL
+ || mode == BUF_PEEK_IF_IN_POOL
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
return(NULL);
@@ -2842,7 +2854,8 @@ got_block:
must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
- if (must_read && mode == BUF_GET_IF_IN_POOL) {
+ if (must_read && (mode == BUF_GET_IF_IN_POOL
+ || mode == BUF_PEEK_IF_IN_POOL)) {
/* The page is being read to buffer pool,
but we cannot wait around for the read to
@@ -2876,7 +2889,7 @@ wait_until_unfixed:
Try again later. */
buf_pool_mutex_exit(buf_pool);
os_thread_sleep(WAIT_FOR_READ);
-
+
goto loop;
}
@@ -2884,7 +2897,7 @@ wait_until_unfixed:
buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_mutex);
- block = buf_LRU_get_free_block(buf_pool, 0);
+ block = buf_LRU_get_free_block(buf_pool);
ut_a(block);
buf_pool_mutex_enter(buf_pool);
@@ -2965,6 +2978,7 @@ wait_until_unfixed:
mutex_exit(&buf_pool->zip_mutex);
buf_pool->n_pend_unzip++;
+ bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
buf_pool_mutex_exit(buf_pool);
@@ -3008,9 +3022,51 @@ wait_until_unfixed:
bytes. */
UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
#endif
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+ if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
+ && ibuf_debug) {
+ /* Try to evict the block from the buffer pool, to use the
+ insert buffer (change buffer) as much as possible. */
- buf_block_buf_fix_inc(block, file, line);
+ if (buf_LRU_free_block(&block->page, TRUE) == BUF_LRU_FREED) {
+ mutex_exit(&block->mutex);
+ if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
+ /* Set the watch, as it would have
+ been set if the page were not in the
+ buffer pool in the first place. */
+ block = (buf_block_t*) buf_pool_watch_set(
+ space, offset, fold);
+
+ if (UNIV_LIKELY_NULL(block)) {
+
+ /* The page entered the buffer
+ pool for some reason. Try to
+ evict it again. */
+ goto got_block;
+ }
+ }
+ buf_pool_mutex_exit(buf_pool);
+ fprintf(stderr,
+ "innodb_change_buffering_debug evict %u %u\n",
+ (unsigned) space, (unsigned) offset);
+ return(NULL);
+ } else if (buf_flush_page_try(buf_pool, block)) {
+ fprintf(stderr,
+ "innodb_change_buffering_debug flush %u %u\n",
+ (unsigned) space, (unsigned) offset);
+ guess = block;
+ goto loop;
+ }
+
+ /* Failed to evict the page; change it directly */
+ }
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+ buf_block_buf_fix_inc(block, file, line);
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
+ ut_a(mode == BUF_GET_POSSIBLY_FREED
+ || !block->page.file_page_was_freed);
+#endif
mutex_exit(&block->mutex);
/* Check if this is the first access to the page */
@@ -3019,11 +3075,9 @@ wait_until_unfixed:
buf_pool_mutex_exit(buf_pool);
- buf_page_set_accessed_make_young(&block->page, access_time);
-
-#ifdef UNIV_DEBUG_FILE_ACCESSES
- ut_a(!block->page.file_page_was_freed);
-#endif
+ if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL)) {
+ buf_page_set_accessed_make_young(&block->page, access_time);
+ }
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 5771 || buf_validate());
@@ -3072,11 +3126,12 @@ wait_until_unfixed:
mtr_memo_push(mtr, block, fix_type);
- if (!access_time) {
+ if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL) && !access_time) {
/* In the case of a first access, try to apply linear
read-ahead */
- buf_read_ahead_linear(space, zip_size, offset);
+ buf_read_ahead_linear(space, zip_size, offset,
+ ibuf_inside(mtr));
}
#ifdef UNIV_IBUF_COUNT_DEBUG
@@ -3133,7 +3188,7 @@ buf_page_optimistic_get(
access_time = buf_page_is_accessed(&block->page);
buf_page_set_accessed_make_young(&block->page, access_time);
- ut_ad(!ibuf_inside()
+ ut_ad(!ibuf_inside(mtr)
|| ibuf_page(buf_block_get_space(block),
buf_block_get_zip_size(block),
buf_block_get_page_no(block), NULL));
@@ -3180,7 +3235,7 @@ buf_page_optimistic_get(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE);
#endif
if (UNIV_UNLIKELY(!access_time)) {
@@ -3189,7 +3244,8 @@ buf_page_optimistic_get(
buf_read_ahead_linear(buf_block_get_space(block),
buf_block_get_zip_size(block),
- buf_block_get_page_no(block));
+ buf_block_get_page_no(block),
+ ibuf_inside(mtr));
}
#ifdef UNIV_IBUF_COUNT_DEBUG
@@ -3265,7 +3321,7 @@ buf_page_get_known_nowait(
buf_pool_mutex_exit(buf_pool);
}
- ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
+ ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
if (rw_latch == RW_S_LATCH) {
success = rw_lock_s_lock_nowait(&(block->lock),
@@ -3292,7 +3348,7 @@ buf_page_get_known_nowait(
ut_a(block->page.buf_fix_count > 0);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE);
#endif
@@ -3378,9 +3434,9 @@ buf_page_try_get_func(
ut_a(block->page.buf_fix_count > 0);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE);
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
buf_pool->stat.n_page_gets++;
@@ -3409,9 +3465,9 @@ buf_page_init_low(
bpage->newest_modification = 0;
bpage->oldest_modification = 0;
HASH_INVALIDATE(bpage, hash);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
bpage->file_page_was_freed = FALSE;
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
}
/********************************************************************//**
@@ -3530,14 +3586,13 @@ buf_page_init_for_read(
/* It is a read-ahead within an ibuf routine */
ut_ad(!ibuf_bitmap_page(zip_size, offset));
- ut_ad(ibuf_inside());
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
if (!recv_no_ibuf_operations
&& !ibuf_page(space, zip_size, offset, &mtr)) {
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
return(NULL);
}
@@ -3549,7 +3604,7 @@ buf_page_init_for_read(
&& UNIV_LIKELY(!recv_recovery_is_on())) {
block = NULL;
} else {
- block = buf_LRU_get_free_block(buf_pool, 0);
+ block = buf_LRU_get_free_block(buf_pool);
ut_ad(block);
ut_ad(buf_pool_from_block(block) == buf_pool);
}
@@ -3645,7 +3700,7 @@ err_exit:
bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
/* Initialize the buf_pool pointer. */
- bpage->buf_pool = buf_pool;
+ bpage->buf_pool_index = buf_pool_index(buf_pool);
/* If buf_buddy_alloc() allocated storage from the LRU list,
it released and reacquired buf_pool->mutex. Thus, we must
@@ -3661,6 +3716,7 @@ err_exit:
/* The block was added by some other thread. */
watch_page = NULL;
+ bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
buf_buddy_free(buf_pool, data, zip_size);
@@ -3721,7 +3777,7 @@ func_exit:
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
}
ut_ad(!bpage || buf_page_in_file(bpage));
@@ -3755,7 +3811,7 @@ buf_page_create(
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad(space || !zip_size);
- free_block = buf_LRU_get_free_block(buf_pool, 0);
+ free_block = buf_LRU_get_free_block(buf_pool);
fold = buf_page_address_fold(space, offset);
@@ -3770,9 +3826,9 @@ buf_page_create(
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(space, offset) == 0);
#endif
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
block->page.file_page_was_freed = FALSE;
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/* Page can be found in buf_pool */
buf_pool_mutex_exit(buf_pool);
@@ -4000,7 +4056,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) {
@@ -4749,29 +4805,209 @@ buf_get_modified_ratio_pct(void)
buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
-
+
/* 1 + is there to avoid division by zero */
return(ratio);
}
+/*******************************************************************//**
+Aggregates a pool stats information with the total buffer pool stats */
+static
+void
+buf_stats_aggregate_pool_info(
+/*==========================*/
+ buf_pool_info_t* total_info, /*!< in/out: the buffer pool
+ info to store aggregated
+ result */
+ const buf_pool_info_t* pool_info) /*!< in: individual buffer pool
+ stats info */
+{
+ ut_a(total_info && pool_info);
+
+ /* Nothing to copy if total_info is the same as pool_info */
+ if (total_info == pool_info) {
+ return;
+ }
+
+ total_info->pool_size += pool_info->pool_size;
+ total_info->lru_len += pool_info->lru_len;
+ total_info->old_lru_len += pool_info->old_lru_len;
+ total_info->free_list_len += pool_info->free_list_len;
+ total_info->flush_list_len += pool_info->flush_list_len;
+ total_info->n_pend_unzip += pool_info->n_pend_unzip;
+ total_info->n_pend_reads += pool_info->n_pend_reads;
+ total_info->n_pending_flush_lru += pool_info->n_pending_flush_lru;
+ total_info->n_pending_flush_list += pool_info->n_pending_flush_list;
+ total_info->n_pending_flush_single_page +=
+ pool_info->n_pending_flush_single_page;
+ total_info->n_pages_made_young += pool_info->n_pages_made_young;
+ total_info->n_pages_not_made_young += pool_info->n_pages_not_made_young;
+ total_info->n_pages_read += pool_info->n_pages_read;
+ total_info->n_pages_created += pool_info->n_pages_created;
+ total_info->n_pages_written += pool_info->n_pages_written;
+ total_info->n_page_gets += pool_info->n_page_gets;
+ total_info->n_ra_pages_read += pool_info->n_ra_pages_read;
+ total_info->n_ra_pages_evicted += pool_info->n_ra_pages_evicted;
+ total_info->page_made_young_rate += pool_info->page_made_young_rate;
+ total_info->page_not_made_young_rate +=
+ pool_info->page_not_made_young_rate;
+ total_info->pages_read_rate += pool_info->pages_read_rate;
+ total_info->pages_created_rate += pool_info->pages_created_rate;
+ total_info->pages_written_rate += pool_info->pages_written_rate;
+ total_info->n_page_get_delta += pool_info->n_page_get_delta;
+ total_info->page_read_delta += pool_info->page_read_delta;
+ total_info->young_making_delta += pool_info->young_making_delta;
+ total_info->not_young_making_delta += pool_info->not_young_making_delta;
+ total_info->pages_readahead_rate += pool_info->pages_readahead_rate;
+ total_info->pages_evicted_rate += pool_info->pages_evicted_rate;
+ total_info->unzip_lru_len += pool_info->unzip_lru_len;
+ total_info->io_sum += pool_info->io_sum;
+ total_info->io_cur += pool_info->io_cur;
+ total_info->unzip_sum += pool_info->unzip_sum;
+ total_info->unzip_cur += pool_info->unzip_cur;
+}
+/*******************************************************************//**
+Collect buffer pool stats information for a buffer pool. Also
+record aggregated stats if there are more than one buffer pool
+in the server */
+static
+void
+buf_stats_get_pool_info(
+/*====================*/
+ buf_pool_t* buf_pool, /*!< in: buffer pool */
+ ulint pool_id, /*!< in: buffer pool ID */
+ buf_pool_info_t* all_pool_info) /*!< in/out: buffer pool info
+ to fill */
+{
+ buf_pool_info_t* pool_info;
+ time_t current_time;
+ double time_elapsed;
+
+ /* Find appropriate pool_info to store stats for this buffer pool */
+ pool_info = &all_pool_info[pool_id];
+
+ buf_pool_mutex_enter(buf_pool);
+ buf_flush_list_mutex_enter(buf_pool);
+
+ pool_info->pool_unique_id = pool_id;
+
+ pool_info->pool_size = buf_pool->curr_size;
+
+ pool_info->lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
+
+ pool_info->old_lru_len = buf_pool->LRU_old_len;
+
+ pool_info->free_list_len = UT_LIST_GET_LEN(buf_pool->free);
+
+ pool_info->flush_list_len = UT_LIST_GET_LEN(buf_pool->flush_list);
+
+ pool_info->n_pend_unzip = UT_LIST_GET_LEN(buf_pool->unzip_LRU);
+
+ pool_info->n_pend_reads = buf_pool->n_pend_reads;
+
+ pool_info->n_pending_flush_lru =
+ (buf_pool->n_flush[BUF_FLUSH_LRU]
+ + buf_pool->init_flush[BUF_FLUSH_LRU]);
+
+ pool_info->n_pending_flush_list =
+ (buf_pool->n_flush[BUF_FLUSH_LIST]
+ + buf_pool->init_flush[BUF_FLUSH_LIST]);
+
+ pool_info->n_pending_flush_single_page =
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
+
+ buf_flush_list_mutex_exit(buf_pool);
+
+ current_time = time(NULL);
+ time_elapsed = 0.001 + difftime(current_time,
+ buf_pool->last_printout_time);
+
+ pool_info->n_pages_made_young = buf_pool->stat.n_pages_made_young;
+
+ pool_info->n_pages_not_made_young =
+ buf_pool->stat.n_pages_not_made_young;
+
+ pool_info->n_pages_read = buf_pool->stat.n_pages_read;
+
+ pool_info->n_pages_created = buf_pool->stat.n_pages_created;
+
+ pool_info->n_pages_written = buf_pool->stat.n_pages_written;
+
+ pool_info->n_page_gets = buf_pool->stat.n_page_gets;
+
+ pool_info->n_ra_pages_read = buf_pool->stat.n_ra_pages_read;
+
+ pool_info->n_ra_pages_evicted = buf_pool->stat.n_ra_pages_evicted;
+
+ pool_info->page_made_young_rate =
+ (buf_pool->stat.n_pages_made_young
+ - buf_pool->old_stat.n_pages_made_young) / time_elapsed;
+
+ pool_info->page_not_made_young_rate =
+ (buf_pool->stat.n_pages_not_made_young
+ - buf_pool->old_stat.n_pages_not_made_young) / time_elapsed;
+
+ pool_info->pages_read_rate =
+ (buf_pool->stat.n_pages_read
+ - buf_pool->old_stat.n_pages_read) / time_elapsed;
+
+ pool_info->pages_created_rate =
+ (buf_pool->stat.n_pages_created
+ - buf_pool->old_stat.n_pages_created) / time_elapsed;
+
+ pool_info->pages_written_rate =
+ (buf_pool->stat.n_pages_written
+ - buf_pool->old_stat.n_pages_written) / time_elapsed;
+
+ pool_info->n_page_get_delta = buf_pool->stat.n_page_gets
+ - buf_pool->old_stat.n_page_gets;
+
+ if (pool_info->n_page_get_delta) {
+ pool_info->page_read_delta = buf_pool->stat.n_pages_read
+ - buf_pool->old_stat.n_pages_read;
+
+ pool_info->young_making_delta =
+ buf_pool->stat.n_pages_made_young
+ - buf_pool->old_stat.n_pages_made_young;
+
+ pool_info->not_young_making_delta =
+ buf_pool->stat.n_pages_not_made_young
+ - buf_pool->old_stat.n_pages_not_made_young;
+ }
+
+ pool_info->pages_readahead_rate =
+ (buf_pool->stat.n_ra_pages_read
+ - buf_pool->old_stat.n_ra_pages_read) / time_elapsed;
+
+ pool_info->pages_evicted_rate =
+ (buf_pool->stat.n_ra_pages_evicted
+ - buf_pool->old_stat.n_ra_pages_evicted) / time_elapsed;
+
+ pool_info->unzip_lru_len = UT_LIST_GET_LEN(buf_pool->unzip_LRU);
+
+ pool_info->io_sum = buf_LRU_stat_sum.io;
+
+ pool_info->io_cur = buf_LRU_stat_cur.io;
+
+ pool_info->unzip_sum = buf_LRU_stat_sum.unzip;
+
+ pool_info->unzip_cur = buf_LRU_stat_cur.unzip;
+
+ buf_refresh_io_stats(buf_pool);
+ buf_pool_mutex_exit(buf_pool);
+}
+
/*********************************************************************//**
Prints info of the buffer i/o. */
UNIV_INTERN
void
buf_print_io_instance(
/*==================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
+ buf_pool_info_t*pool_info, /*!< in: buffer pool info */
FILE* file) /*!< in/out: buffer where to print */
{
- time_t current_time;
- double time_elapsed;
- ulint n_gets_diff;
-
- ut_ad(buf_pool);
-
- buf_pool_mutex_enter(buf_pool);
- buf_flush_list_mutex_enter(buf_pool);
+ ut_ad(pool_info);
fprintf(file,
"Buffer pool size %lu\n"
@@ -4781,70 +5017,42 @@ buf_print_io_instance(
"Modified db pages %lu\n"
"Pending reads %lu\n"
"Pending writes: LRU %lu, flush list %lu, single page %lu\n",
- (ulong) buf_pool->curr_size,
- (ulong) UT_LIST_GET_LEN(buf_pool->free),
- (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
- (ulong) buf_pool->LRU_old_len,
- (ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
- (ulong) buf_pool->n_pend_reads,
- (ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
- + buf_pool->init_flush[BUF_FLUSH_LRU],
- (ulong) buf_pool->n_flush[BUF_FLUSH_LIST]
- + buf_pool->init_flush[BUF_FLUSH_LIST],
- (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
-
- buf_flush_list_mutex_exit(buf_pool);
-
- current_time = time(NULL);
- time_elapsed = 0.001 + difftime(current_time,
- buf_pool->last_printout_time);
+ pool_info->pool_size,
+ pool_info->free_list_len,
+ pool_info->lru_len,
+ pool_info->old_lru_len,
+ pool_info->flush_list_len,
+ pool_info->n_pend_reads,
+ pool_info->n_pending_flush_lru,
+ pool_info->n_pending_flush_list,
+ pool_info->n_pending_flush_single_page);
fprintf(file,
"Pages made young %lu, not young %lu\n"
"%.2f youngs/s, %.2f non-youngs/s\n"
"Pages read %lu, created %lu, written %lu\n"
"%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
- (ulong) buf_pool->stat.n_pages_made_young,
- (ulong) buf_pool->stat.n_pages_not_made_young,
- (buf_pool->stat.n_pages_made_young
- - buf_pool->old_stat.n_pages_made_young)
- / time_elapsed,
- (buf_pool->stat.n_pages_not_made_young
- - buf_pool->old_stat.n_pages_not_made_young)
- / time_elapsed,
- (ulong) buf_pool->stat.n_pages_read,
- (ulong) buf_pool->stat.n_pages_created,
- (ulong) buf_pool->stat.n_pages_written,
- (buf_pool->stat.n_pages_read
- - buf_pool->old_stat.n_pages_read)
- / time_elapsed,
- (buf_pool->stat.n_pages_created
- - buf_pool->old_stat.n_pages_created)
- / time_elapsed,
- (buf_pool->stat.n_pages_written
- - buf_pool->old_stat.n_pages_written)
- / time_elapsed);
-
- n_gets_diff = buf_pool->stat.n_page_gets
- - buf_pool->old_stat.n_page_gets;
-
- if (n_gets_diff) {
+ pool_info->n_pages_made_young,
+ pool_info->n_pages_not_made_young,
+ pool_info->page_made_young_rate,
+ pool_info->page_not_made_young_rate,
+ pool_info->n_pages_read,
+ pool_info->n_pages_created,
+ pool_info->n_pages_written,
+ pool_info->pages_read_rate,
+ pool_info->pages_created_rate,
+ pool_info->pages_written_rate);
+
+ if (pool_info->n_page_get_delta) {
fprintf(file,
"Buffer pool hit rate %lu / 1000,"
" young-making rate %lu / 1000 not %lu / 1000\n",
- (ulong)
- (1000 - ((1000 * (buf_pool->stat.n_pages_read
- - buf_pool->old_stat.n_pages_read))
- / (buf_pool->stat.n_page_gets
- - buf_pool->old_stat.n_page_gets))),
- (ulong)
- (1000 * (buf_pool->stat.n_pages_made_young
- - buf_pool->old_stat.n_pages_made_young)
- / n_gets_diff),
- (ulong)
- (1000 * (buf_pool->stat.n_pages_not_made_young
- - buf_pool->old_stat.n_pages_not_made_young)
- / n_gets_diff));
+ (ulong) (1000 - (1000 * pool_info->page_read_delta
+ / pool_info->n_page_get_delta)),
+ (ulong) (1000 * pool_info->young_making_delta
+ / pool_info->n_page_get_delta),
+ (ulong) (1000 * pool_info->not_young_making_delta
+ / pool_info->n_page_get_delta));
} else {
fputs("No buffer pool page gets since the last printout\n",
file);
@@ -4853,25 +5061,17 @@ buf_print_io_instance(
/* Statistics about read ahead algorithm */
fprintf(file, "Pages read ahead %.2f/s,"
" evicted without access %.2f/s\n",
- (buf_pool->stat.n_ra_pages_read
- - buf_pool->old_stat.n_ra_pages_read)
- / time_elapsed,
- (buf_pool->stat.n_ra_pages_evicted
- - buf_pool->old_stat.n_ra_pages_evicted)
- / time_elapsed);
+ pool_info->pages_readahead_rate,
+ pool_info->pages_evicted_rate);
/* Print some values to help us with visualizing what is
happening with LRU eviction. */
fprintf(file,
"LRU len: %lu, unzip_LRU len: %lu\n"
"I/O sum[%lu]:cur[%lu], unzip sum[%lu]:cur[%lu]\n",
- UT_LIST_GET_LEN(buf_pool->LRU),
- UT_LIST_GET_LEN(buf_pool->unzip_LRU),
- buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
- buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
-
- buf_refresh_io_stats(buf_pool);
- buf_pool_mutex_exit(buf_pool);
+ pool_info->lru_len, pool_info->unzip_lru_len,
+ pool_info->io_sum, pool_info->io_cur,
+ pool_info->unzip_sum, pool_info->unzip_cur);
}
/*********************************************************************//**
@@ -4882,14 +5082,58 @@ buf_print_io(
/*=========*/
FILE* file) /*!< in/out: buffer where to print */
{
- ulint i;
+ ulint i;
+ buf_pool_info_t* pool_info;
+ buf_pool_info_t* pool_info_total;
+
+ /* If srv_buf_pool_instances is greater than 1, allocate
+ one extra buf_pool_info_t, the last one stores
+ aggregated/total values from all pools */
+ if (srv_buf_pool_instances > 1) {
+ pool_info = (buf_pool_info_t*) mem_zalloc((
+ srv_buf_pool_instances + 1) * sizeof *pool_info);
+
+ pool_info_total = &pool_info[srv_buf_pool_instances];
+ } else {
+ ut_a(srv_buf_pool_instances == 1);
+ pool_info_total = pool_info = (buf_pool_info_t*) mem_zalloc(
+ sizeof *pool_info)
+ }
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
- buf_print_io_instance(buf_pool, file);
+
+ /* Fetch individual buffer pool info and calculate
+ aggregated stats along the way */
+ buf_stats_get_pool_info(buf_pool, i, pool_info);
+
+ /* If we have more than one buffer pool, store
+ the aggregated stats */
+ if (srv_buf_pool_instances > 1) {
+ buf_stats_aggregate_pool_info(pool_info_total,
+ &pool_info[i]);
+ }
}
+
+ /* Print the aggreate buffer pool info */
+ buf_print_io_instance(pool_info_total, file);
+
+ /* If there are more than one buffer pool, print each individual pool
+ info */
+ if (srv_buf_pool_instances > 1) {
+ fputs("----------------------\n"
+ "INDIVIDUAL BUFFER POOL INFO\n"
+ "----------------------\n", file);
+
+ for (i = 0; i < srv_buf_pool_instances; i++) {
+ fprintf(file, "---BUFFER POOL %lu\n", i);
+ buf_print_io_instance(&pool_info[i], file);
+ }
+ }
+
+ mem_free(pool_info);
}
/**********************************************************************//**
@@ -4944,7 +5188,7 @@ buf_all_freed(void)
return(TRUE);
}
-
+
/*********************************************************************//**
Checks that there currently are no pending i/o-operations for the buffer
pool.
diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
index 7b51fc60fcc..ebe96a82a10 100644
--- a/storage/innobase/buf/buf0flu.c
+++ b/storage/innobase/buf/buf0flu.c
@@ -88,6 +88,34 @@ ibool
buf_flush_validate_low(
/*===================*/
buf_pool_t* buf_pool); /*!< in: Buffer pool instance */
+
+/******************************************************************//**
+Validates the flush list some of the time.
+@return TRUE if ok or the check was skipped */
+static
+ibool
+buf_flush_validate_skip(
+/*====================*/
+ buf_pool_t* buf_pool) /*!< in: Buffer pool instance */
+{
+/** Try buf_flush_validate_low() every this many times */
+# define BUF_FLUSH_VALIDATE_SKIP 23
+
+ /** The buf_flush_validate_low() call skip counter.
+ Use a signed type because of the race condition below. */
+ static int buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP;
+
+ /* There is a race condition below, but it does not matter,
+ because this call is only for heuristic purposes. We want to
+ reduce the call frequency of the costly buf_flush_validate_low()
+ check in debug builds. */
+ if (--buf_flush_validate_count > 0) {
+ return(TRUE);
+ }
+
+ buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP;
+ return(buf_flush_validate_low(buf_pool));
+}
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//**
@@ -133,12 +161,18 @@ buf_flush_delete_from_flush_rbt(
/*============================*/
buf_page_t* bpage) /*!< in: bpage to be removed. */
{
+#ifdef UNIV_DEBUG
ibool ret = FALSE;
+#endif /* UNIV_DEBUG */
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
ut_ad(buf_flush_list_mutex_own(buf_pool));
- ret = rbt_delete(buf_pool->flush_rbt, &bpage);
+#ifdef UNIV_DEBUG
+ ret =
+#endif /* UNIV_DEBUG */
+ rbt_delete(buf_pool->flush_rbt, &bpage);
+
ut_ad(ret);
}
@@ -287,7 +321,7 @@ buf_flush_insert_into_flush_list(
}
#endif /* UNIV_DEBUG_VALGRIND */
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- ut_a(buf_flush_validate_low(buf_pool));
+ ut_a(buf_flush_validate_skip(buf_pool));
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
buf_flush_list_mutex_exit(buf_pool);
@@ -315,7 +349,7 @@ buf_flush_insert_sorted_into_flush_list(
buf_flush_list_mutex_enter(buf_pool);
- /* The field in_LRU_list is protected by buf_pool_mutex, which
+ /* The field in_LRU_list is protected by buf_pool->mutex, which
we are not holding. However, while a block is in the flush
list, it is dirty and cannot be discarded, not from the
page_hash or from the LRU list. At most, the uncompressed
@@ -509,7 +543,7 @@ buf_flush_remove(
bpage->oldest_modification = 0;
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- ut_a(buf_flush_validate_low(buf_pool));
+ ut_a(buf_flush_validate_skip(buf_pool));
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
buf_flush_list_mutex_exit(buf_pool);
@@ -1055,7 +1089,7 @@ buf_flush_write_block_low(
ut_ad(buf_page_in_file(bpage));
- /* We are not holding buf_pool_mutex or block_mutex here.
+ /* We are not holding buf_pool->mutex or block_mutex here.
Nevertheless, it is safe to access bpage, because it is
io_fixed and oldest_modification != 0. Thus, it cannot be
relocated in the buffer pool or removed from flush_list or
@@ -1126,6 +1160,83 @@ buf_flush_write_block_low(
}
}
+# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+/********************************************************************//**
+Writes a flushable page asynchronously from the buffer pool to a file.
+NOTE: buf_pool->mutex and block->mutex must be held upon entering this
+function, and they will be released by this function after flushing.
+This is loosely based on buf_flush_batch() and buf_flush_page().
+@return TRUE if the page was flushed and the mutexes released */
+UNIV_INTERN
+ibool
+buf_flush_page_try(
+/*===============*/
+ buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
+ buf_block_t* block) /*!< in/out: buffer control block */
+{
+ ut_ad(buf_pool_mutex_own(buf_pool));
+ ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
+ ut_ad(mutex_own(&block->mutex));
+
+ if (!buf_flush_ready_for_flush(&block->page, BUF_FLUSH_LRU)) {
+ return(FALSE);
+ }
+
+ if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0
+ || buf_pool->init_flush[BUF_FLUSH_LRU]) {
+ /* There is already a flush batch of the same type running */
+ return(FALSE);
+ }
+
+ buf_pool->init_flush[BUF_FLUSH_LRU] = TRUE;
+
+ buf_page_set_io_fix(&block->page, BUF_IO_WRITE);
+
+ buf_page_set_flush_type(&block->page, BUF_FLUSH_LRU);
+
+ if (buf_pool->n_flush[BUF_FLUSH_LRU]++ == 0) {
+
+ os_event_reset(buf_pool->no_flush[BUF_FLUSH_LRU]);
+ }
+
+ /* VERY IMPORTANT:
+ Because any thread may call the LRU flush, even when owning
+ locks on pages, to avoid deadlocks, we must make sure that the
+ s-lock is acquired on the page without waiting: this is
+ accomplished because buf_flush_ready_for_flush() must hold,
+ and that requires the page not to be bufferfixed. */
+
+ rw_lock_s_lock_gen(&block->lock, BUF_IO_WRITE);
+
+ /* Note that the s-latch is acquired before releasing the
+ buf_pool mutex: this ensures that the latch is acquired
+ immediately. */
+
+ mutex_exit(&block->mutex);
+ buf_pool_mutex_exit(buf_pool);
+
+ /* Even though block is not protected by any mutex at this
+ point, it is safe to access block, because it is io_fixed and
+ oldest_modification != 0. Thus, it cannot be relocated in the
+ buffer pool or removed from flush_list or LRU_list. */
+
+ buf_flush_write_block_low(&block->page);
+
+ buf_pool_mutex_enter(buf_pool);
+ buf_pool->init_flush[BUF_FLUSH_LRU] = FALSE;
+
+ if (buf_pool->n_flush[BUF_FLUSH_LRU] == 0) {
+ /* The running flush batch has ended */
+ os_event_set(buf_pool->no_flush[BUF_FLUSH_LRU]);
+ }
+
+ buf_pool_mutex_exit(buf_pool);
+ buf_flush_buffered_writes();
+
+ return(TRUE);
+}
+# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
NOTE: in simulated aio we must call
@@ -1605,7 +1716,7 @@ buf_flush_batch(
ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
#ifdef UNIV_SYNC_DEBUG
ut_ad((flush_type != BUF_FLUSH_LIST)
- || sync_thread_levels_empty_gen(TRUE));
+ || sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */
buf_pool_mutex_enter(buf_pool);
@@ -2110,12 +2221,12 @@ buf_flush_validate_low(
ut_ad(bpage->in_flush_list);
- /* A page in flush_list can be in BUF_BLOCK_REMOVE_HASH
- state. This happens when a page is in the middle of
- being relocated. In that case the original descriptor
- can have this state and still be in the flush list
- waiting to acquire the flush_list_mutex to complete
- the relocation. */
+ /* A page in buf_pool->flush_list can be in
+ BUF_BLOCK_REMOVE_HASH state. This happens when a page
+ is in the middle of being relocated. In that case the
+ original descriptor can have this state and still be
+ in the flush list waiting to acquire the
+ buf_pool->flush_list_mutex to complete the relocation. */
ut_a(buf_page_in_file(bpage)
|| buf_page_get_state(bpage) == BUF_BLOCK_REMOVE_HASH);
ut_a(om > 0);
diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
index e1d4b5081b8..64afcecfe3c 100644
--- a/storage/innobase/buf/buf0lru.c
+++ b/storage/innobase/buf/buf0lru.c
@@ -247,74 +247,78 @@ buf_LRU_drop_page_hash_for_tablespace(
sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE);
buf_pool_mutex_enter(buf_pool);
+ num_entries = 0;
scan_again:
- num_entries = 0;
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) {
- mutex_t* block_mutex = buf_page_get_mutex(bpage);
buf_page_t* prev_bpage;
+ ibool is_fixed;
- mutex_enter(block_mutex);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
ut_a(buf_page_in_file(bpage));
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
|| bpage->space != id
- || bpage->buf_fix_count > 0
|| bpage->io_fix != BUF_IO_NONE) {
- /* We leave the fixed pages as is in this scan.
- To be dealt with later in the final scan. */
- mutex_exit(block_mutex);
+ /* Compressed pages are never hashed.
+ Skip blocks of other tablespaces.
+ Skip I/O-fixed blocks (to be dealt with later). */
+next_page:
+ bpage = prev_bpage;
+ continue;
+ }
+
+ mutex_enter(&((buf_block_t*) bpage)->mutex);
+ is_fixed = bpage->buf_fix_count > 0
+ || !((buf_block_t*) bpage)->is_hashed;
+ mutex_exit(&((buf_block_t*) bpage)->mutex);
+
+ if (is_fixed) {
goto next_page;
}
- if (((buf_block_t*) bpage)->is_hashed) {
+ /* Store the page number so that we can drop the hash
+ index in a batch later. */
+ page_arr[num_entries] = bpage->offset;
+ ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
+ ++num_entries;
- /* Store the offset(i.e.: page_no) in the array
- so that we can drop hash index in a batch
- later. */
- page_arr[num_entries] = bpage->offset;
- mutex_exit(block_mutex);
- ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
- ++num_entries;
+ if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
+ goto next_page;
+ }
- if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
- goto next_page;
- }
+ /* Array full. We release the buf_pool->mutex to obey
+ the latching order. */
+ buf_pool_mutex_exit(buf_pool);
- /* Array full. We release the buf_pool->mutex to
- obey the latching order. */
- buf_pool_mutex_exit(buf_pool);
+ buf_LRU_drop_page_hash_batch(
+ id, zip_size, page_arr, num_entries);
- buf_LRU_drop_page_hash_batch(
- id, zip_size, page_arr, num_entries);
+ num_entries = 0;
- num_entries = 0;
+ buf_pool_mutex_enter(buf_pool);
- buf_pool_mutex_enter(buf_pool);
- } else {
- mutex_exit(block_mutex);
- }
+ /* Note that we released the buf_pool mutex above
+ after reading the prev_bpage during processing of a
+ page_hash_batch (i.e.: when the array was full).
+ Because prev_bpage could belong to a compressed-only
+ block, it may have been relocated, and thus the
+ pointer cannot be trusted. Because bpage is of type
+ buf_block_t, it is safe to dereference.
-next_page:
- /* Note that we may have released the buf_pool mutex
- above after reading the prev_bpage during processing
- of a page_hash_batch (i.e.: when the array was full).
- This means that prev_bpage can change in LRU list.
- This is OK because this function is a 'best effort'
- to drop as many search hash entries as possible and
- it does not guarantee that ALL such entries will be
- dropped. */
- bpage = prev_bpage;
+ bpage can change in the LRU list. This is OK because
+ this function is a 'best effort' to drop as many
+ search hash entries as possible and it does not
+ guarantee that ALL such entries will be dropped. */
/* If, however, bpage has been removed from LRU list
to the free list then we should restart the scan.
bpage->state is protected by buf_pool mutex. */
- if (bpage && !buf_page_in_file(bpage)) {
- ut_a(num_entries == 0);
+ if (bpage
+ && buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
goto scan_again;
}
}
@@ -356,8 +360,8 @@ scan_again:
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
/* bpage->space and bpage->io_fix are protected by
- buf_pool_mutex and block_mutex. It is safe to check
- them while holding buf_pool_mutex only. */
+ buf_pool->mutex and block_mutex. It is safe to check
+ them while holding buf_pool->mutex only. */
if (buf_page_get_space(bpage) != id) {
/* Skip this block, as it does not belong to
@@ -403,7 +407,7 @@ scan_again:
/* Descriptors of uncompressed
blocks will not be relocated,
because we are holding the
- buf_pool_mutex. */
+ buf_pool->mutex. */
break;
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
@@ -603,7 +607,7 @@ buf_LRU_free_from_unzip_LRU_list(
ut_ad(block->page.in_LRU_list);
mutex_enter(&block->mutex);
- freed = buf_LRU_free_block(&block->page, FALSE, NULL);
+ freed = buf_LRU_free_block(&block->page, FALSE);
mutex_exit(&block->mutex);
switch (freed) {
@@ -666,7 +670,7 @@ buf_LRU_free_from_common_LRU_list(
mutex_enter(block_mutex);
accessed = buf_page_is_accessed(bpage);
- freed = buf_LRU_free_block(bpage, TRUE, NULL);
+ freed = buf_LRU_free_block(bpage, TRUE);
mutex_exit(block_mutex);
switch (freed) {
@@ -858,9 +862,7 @@ UNIV_INTERN
buf_block_t*
buf_LRU_get_free_block(
/*===================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- ulint zip_size) /*!< in: compressed page size in bytes,
- or 0 if uncompressed tablespace */
+ buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */
{
buf_block_t* block = NULL;
ibool freed;
@@ -936,31 +938,11 @@ loop:
/* If there is a block in the free list, take it */
block = buf_LRU_get_free_only(buf_pool);
- if (block) {
+ buf_pool_mutex_exit(buf_pool);
+ if (block) {
ut_ad(buf_pool_from_block(block) == buf_pool);
-
-#ifdef UNIV_DEBUG
- block->page.zip.m_start =
-#endif /* UNIV_DEBUG */
- block->page.zip.m_end =
- block->page.zip.m_nonempty =
- block->page.zip.n_blobs = 0;
-
- if (UNIV_UNLIKELY(zip_size)) {
- ibool lru;
- page_zip_set_size(&block->page.zip, zip_size);
-
- block->page.zip.data = buf_buddy_alloc(
- buf_pool, zip_size, &lru);
-
- UNIV_MEM_DESC(block->page.zip.data, zip_size, block);
- } else {
- page_zip_set_size(&block->page.zip, 0);
- block->page.zip.data = NULL;
- }
-
- buf_pool_mutex_exit(buf_pool);
+ memset(&block->page.zip, 0, sizeof block->page.zip);
if (started_monitor) {
srv_print_innodb_monitor = mon_value_was;
@@ -972,8 +954,6 @@ loop:
/* If no block was in the free list, search from the end of the LRU
list and try to free a block there */
- buf_pool_mutex_exit(buf_pool);
-
freed = buf_LRU_search_and_free_block(buf_pool, n_iterations);
if (freed > 0) {
@@ -1443,10 +1423,10 @@ Try to free a block. If bpage is a descriptor of a compressed-only
page, the descriptor object will be freed as well.
NOTE: If this function returns BUF_LRU_FREED, it will temporarily
-release buf_pool_mutex. Furthermore, the page frame will no longer be
+release buf_pool->mutex. Furthermore, the page frame will no longer be
accessible via bpage.
-The caller must hold buf_pool_mutex and buf_page_get_mutex(bpage) and
+The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
release these two mutexes after the call. No other
buf_page_get_mutex() may be held when calling this function.
@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or
@@ -1456,12 +1436,8 @@ enum buf_lru_free_block_status
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
- ibool zip, /*!< in: TRUE if should remove also the
+ ibool zip) /*!< in: TRUE if should remove also the
compressed page of an uncompressed page */
- ibool* buf_pool_mutex_released)
- /*!< in: pointer to a variable that will
- be assigned TRUE if buf_pool_mutex
- was temporarily released, or NULL */
{
buf_page_t* b = NULL;
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
@@ -1638,10 +1614,6 @@ alloc:
b->io_fix = BUF_IO_READ;
}
- if (buf_pool_mutex_released) {
- *buf_pool_mutex_released = TRUE;
- }
-
buf_pool_mutex_exit(buf_pool);
mutex_exit(block_mutex);
@@ -1921,6 +1893,7 @@ buf_LRU_block_remove_hashed_page(
buf_pool, bpage->zip.data,
page_zip_get_size(&bpage->zip));
+ bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_free(buf_pool, bpage, sizeof(*bpage));
buf_pool_mutex_exit_allow(buf_pool);
@@ -2076,6 +2049,7 @@ buf_LRU_stat_update(void)
buf_LRU_stat_t* item;
buf_pool_t* buf_pool;
ibool evict_started = FALSE;
+ buf_LRU_stat_t cur_stat;
/* If we haven't started eviction yet then don't update stats. */
for (i = 0; i < srv_buf_pool_instances; i++) {
@@ -2097,12 +2071,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);
func_exit:
/* Clear the current entry. */
diff --git a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
index 82b45172988..eeaa21ae9ef 100644
--- a/storage/innobase/buf/buf0rea.c
+++ b/storage/innobase/buf/buf0rea.c
@@ -236,10 +236,10 @@ UNIV_INTERN
ulint
buf_read_ahead_linear(
/*==================*/
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
- ulint offset) /*!< in: page number of a page; NOTE: the current thread
- must want access to this page (see NOTE 3 above) */
+ ulint space, /*!< in: space id */
+ ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
+ ulint offset, /*!< in: page number; see NOTE 3 above */
+ ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf routine */
{
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ib_int64_t tablespace_version;
@@ -429,11 +429,9 @@ buf_read_ahead_linear(
/* If we got this far, read-ahead can be sensible: do it */
- if (ibuf_inside()) {
- ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
- } else {
- ibuf_mode = BUF_READ_ANY_PAGE;
- }
+ ibuf_mode = inside_ibuf
+ ? BUF_READ_IBUF_PAGES_ONLY | OS_AIO_SIMULATED_WAKE_LATER
+ : BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER;
count = 0;
@@ -450,7 +448,7 @@ buf_read_ahead_linear(
if (!ibuf_bitmap_page(zip_size, i)) {
count += buf_read_page_low(
&err, FALSE,
- ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
+ ibuf_mode,
space, zip_size, FALSE, tablespace_version, i);
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
@@ -520,7 +518,6 @@ buf_read_ibuf_merge_pages(
{
ulint i;
- ut_ad(!ibuf_inside());
#ifdef UNIV_IBUF_DEBUG
ut_a(n_stored < UNIV_PAGE_SIZE);
#endif
@@ -530,7 +527,7 @@ buf_read_ibuf_merge_pages(
buf_pool_t* buf_pool;
ulint zip_size = fil_space_get_zip_size(space_ids[i]);
- buf_pool = buf_pool_get(space_ids[i], space_versions[i]);
+ buf_pool = buf_pool_get(space_ids[i], page_nos[i]);
while (buf_pool->n_pend_reads
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
diff --git a/storage/innobase/compile-innodb b/storage/innobase/compile-innodb
index 23e7f98e50c..988c862465d 100755
--- a/storage/innobase/compile-innodb
+++ b/storage/innobase/compile-innodb
@@ -22,4 +22,4 @@ MYSQL_ROOT="$(dirname ${0})/../.."
cd ${MYSQL_ROOT}
cmake -DWITH_INNOBASE_STORAGE_ENGINE:BOOL=ON
-make -j4
+make -j$(nproc)
diff --git a/storage/innobase/data/data0data.c b/storage/innobase/data/data0data.c
index 0ef0cfa554a..6d07fc249fa 100644
--- a/storage/innobase/data/data0data.c
+++ b/storage/innobase/data/data0data.c
@@ -585,7 +585,8 @@ dtuple_convert_big_rec(
if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
/* up to MySQL 5.1: store a 768-byte prefix locally */
- local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
+ local_len = BTR_EXTERN_FIELD_REF_SIZE
+ + DICT_ANTELOPE_MAX_INDEX_COL_LEN;
} else {
/* new-format table: do not store any BLOB prefix locally */
local_len = BTR_EXTERN_FIELD_REF_SIZE;
@@ -757,7 +758,10 @@ dtuple_convert_back_big_rec(
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
- ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
+ /* Only in REDUNDANT and COMPACT format, we store
+ up to DICT_ANTELOPE_MAX_INDEX_COL_LEN (768) bytes
+ locally */
+ ut_ad(local_len <= DICT_ANTELOPE_MAX_INDEX_COL_LEN);
dfield_set_data(dfield,
(char*) b->data - local_len,
diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
index 1a332ea9329..9a528d679a7 100644
--- a/storage/innobase/dict/dict0crea.c
+++ b/storage/innobase/dict/dict0crea.c
@@ -659,9 +659,9 @@ dict_create_index_tree_step(
/* printf("Created a new index tree in space %lu root page %lu\n",
index->space, index->page_no); */
- page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
- DICT_SYS_INDEXES_PAGE_NO_FIELD,
- node->page_no, &mtr);
+ page_rec_write_field(btr_pcur_get_rec(&pcur),
+ DICT_SYS_INDEXES_PAGE_NO_FIELD,
+ node->page_no, &mtr);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
@@ -731,9 +731,8 @@ dict_drop_index_tree(
root_page_no); */
btr_free_root(space, zip_size, root_page_no, mtr);
- page_rec_write_index_page_no(rec,
- DICT_SYS_INDEXES_PAGE_NO_FIELD,
- FIL_NULL, mtr);
+ page_rec_write_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
+ FIL_NULL, mtr);
}
/*******************************************************************//**
@@ -828,7 +827,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:
@@ -836,8 +835,8 @@ create:
in SYS_INDEXES, so that the database will not get into an
inconsistent state in case it crashes between the mtr_commit()
below and the following mtr_commit() call. */
- page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
- FIL_NULL, mtr);
+ page_rec_write_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
+ FIL_NULL, mtr);
/* We will need to commit the mini-transaction in order to avoid
deadlocks in the btr_create() call, because otherwise we would
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 6c9182b1242..1e3aed92cf7 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -53,7 +53,7 @@ UNIV_INTERN dict_index_t* dict_ind_compact;
#include "rem0cmp.h"
#include "row0merge.h"
#include "m_ctype.h" /* my_isspace() */
-#include "ha_prototypes.h" /* innobase_strcasecmp() */
+#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
#include <ctype.h>
@@ -74,6 +74,7 @@ UNIV_INTERN rw_lock_t dict_operation_lock;
#ifdef UNIV_PFS_RWLOCK
UNIV_INTERN mysql_pfs_key_t dict_operation_lock_key;
UNIV_INTERN mysql_pfs_key_t index_tree_rw_lock_key;
+UNIV_INTERN mysql_pfs_key_t dict_table_stats_latch_key;
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_PFS_MUTEX
@@ -91,9 +92,18 @@ UNIV_INTERN mysql_pfs_key_t dict_foreign_err_mutex_key;
/** 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
-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
@@ -254,43 +264,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_ull(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_ull(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;
+ }
}
/********************************************************************//**
@@ -682,9 +714,9 @@ dict_init(void)
mutex_create(dict_foreign_err_mutex_key,
&dict_foreign_err_mutex, SYNC_ANY_LATCH);
- for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
- mutex_create(PFS_NOT_INSTRUMENTED,
- &dict_index_stat_mutex[i], SYNC_INDEX_TREE);
+ for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
+ rw_lock_create(dict_table_stats_latch_key,
+ &dict_table_stats_latches[i], SYNC_INDEX_TREE);
}
}
@@ -715,12 +747,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);
@@ -917,7 +948,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)));
@@ -929,7 +960,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;
}
@@ -979,11 +1010,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);
@@ -1050,13 +1081,13 @@ dict_table_rename_in_cache(
/* Allocate a longer name buffer;
TODO: store buf len to save memory */
- foreign->foreign_table_name
- = mem_heap_alloc(foreign->heap,
- ut_strlen(table->name) + 1);
+ foreign->foreign_table_name = mem_heap_strdup(
+ foreign->heap, table->name);
+ dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
+ } else {
+ strcpy(foreign->foreign_table_name, table->name);
+ dict_mem_foreign_table_name_lookup_set(foreign, FALSE);
}
-
- strcpy(foreign->foreign_table_name, table->name);
-
if (strchr(foreign->id, '/')) {
ulint db_len;
char* old_id;
@@ -1122,12 +1153,14 @@ dict_table_rename_in_cache(
/* Allocate a longer name buffer;
TODO: store buf len to save memory */
- foreign->referenced_table_name = mem_heap_alloc(
- foreign->heap, strlen(table->name) + 1);
+ foreign->referenced_table_name = mem_heap_strdup(
+ foreign->heap, table->name);
+ dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
+ } else {
+ /* Use the same buffer */
+ strcpy(foreign->referenced_table_name, table->name);
+ dict_mem_referenced_table_name_lookup_set(foreign, FALSE);
}
-
- strcpy(foreign->referenced_table_name, table->name);
-
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
@@ -1319,36 +1352,63 @@ dict_index_too_big_for_undo(
ulint fixed_size
= dict_col_get_fixed_size(col,
dict_table_is_comp(table));
+ ulint max_prefix
+ = col->max_prefix;
if (fixed_size) {
/* Fixed-size columns are stored locally. */
max_size = fixed_size;
} else if (max_size <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
/* Short columns are stored locally. */
- } else if (!col->ord_part) {
+ } else if (!col->ord_part
+ || (col->max_prefix
+ < (ulint) DICT_MAX_FIELD_LEN_BY_FORMAT(table))) {
/* See if col->ord_part would be set
- because of new_index. */
+ because of new_index. Also check if the new
+ index could have longer prefix on columns
+ that already had ord_part set */
ulint j;
for (j = 0; j < new_index->n_uniq; j++) {
if (dict_index_get_nth_col(
new_index, j) == col) {
+ const dict_field_t* field
+ = dict_index_get_nth_field(
+ new_index, j);
+
+ if (field->prefix_len
+ > col->max_prefix) {
+ max_prefix =
+ field->prefix_len;
+ }
goto is_ord_part;
}
}
+ if (col->ord_part) {
+ goto is_ord_part;
+ }
+
/* This is not an ordering column in any index.
Thus, it can be stored completely externally. */
max_size = BTR_EXTERN_FIELD_REF_SIZE;
} else {
+ ulint max_field_len;
is_ord_part:
+ max_field_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+
/* This is an ordering column in some index.
A long enough prefix must be written to the
undo log. See trx_undo_page_fetch_ext(). */
+ max_size = ut_min(max_size, max_field_len);
+
+ /* We only store the needed prefix length in undo log */
+ if (max_prefix) {
+ ut_ad(dict_table_get_format(table)
+ >= DICT_TF_FORMAT_ZIP);
- if (max_size > REC_MAX_INDEX_COL_LEN) {
- max_size = REC_MAX_INDEX_COL_LEN;
+ max_size = ut_min(max_prefix, max_size);
}
max_size += BTR_EXTERN_FIELD_REF_SIZE;
@@ -1602,15 +1662,16 @@ too_big:
/* In dtuple_convert_big_rec(), variable-length columns
that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
may be chosen for external storage. If the column appears
- in an ordering column of an index, a longer prefix of
- REC_MAX_INDEX_COL_LEN will be copied to the undo log
- by trx_undo_page_report_modify() and
+ in an ordering column of an index, a longer prefix determined
+ by dict_max_field_len_store_undo() will be copied to the undo
+ log by trx_undo_page_report_modify() and
trx_undo_page_fetch_ext(). It suffices to check the
capacity of the undo log whenever new_index includes
a column prefix on a column that may be stored externally. */
if (field->prefix_len /* prefix index */
- && !col->ord_part /* not yet ordering column */
+ && (!col->ord_part /* not yet ordering column */
+ || field->prefix_len > col->max_prefix)
&& !dict_col_get_fixed_size(col, TRUE) /* variable-length */
&& dict_col_get_max_size(col)
> BTR_EXTERN_FIELD_REF_SIZE * 2 /* long enough */) {
@@ -1627,11 +1688,17 @@ too_big:
}
undo_size_ok:
- /* Flag the ordering columns */
+ /* Flag the ordering columns and also set column max_prefix */
for (i = 0; i < n_ord; i++) {
+ const dict_field_t* field
+ = dict_index_get_nth_field(new_index, i);
+
+ field->col->ord_part = 1;
- dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
+ if (field->prefix_len > field->col->max_prefix) {
+ field->col->max_prefix = field->prefix_len;
+ }
}
/* Add the new index as the last index for the table */
@@ -1655,6 +1722,12 @@ undo_size_ok:
new_index->heap,
(1 + dict_index_get_n_unique(new_index))
* sizeof(ib_int64_t));
+
+ new_index->stat_n_non_null_key_vals = mem_heap_zalloc(
+ new_index->heap,
+ (1 + dict_index_get_n_unique(new_index))
+ * sizeof(*new_index->stat_n_non_null_key_vals));
+
/* Give some sensible values to stat_n_... in case we do
not calculate statistics quickly enough */
@@ -1828,14 +1901,14 @@ dict_index_add_col(
variable-length fields, so that the extern flag can be embedded in
the length word. */
- if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) {
+ if (field->fixed_len > DICT_MAX_FIXED_COL_LEN) {
field->fixed_len = 0;
}
-#if DICT_MAX_INDEX_COL_LEN != 768
+#if DICT_MAX_FIXED_COL_LEN != 768
/* The comparison limit above must be constant. If it were
changed, the disk format of some fixed-length columns would
change, which would be a disaster. */
-# error "DICT_MAX_INDEX_COL_LEN != 768"
+# error "DICT_MAX_FIXED_COL_LEN != 768"
#endif
if (!(col->prtype & DATA_NOT_NULL)) {
@@ -2553,10 +2626,10 @@ dict_foreign_add_to_cache(
ut_ad(mutex_own(&(dict_sys->mutex)));
for_table = dict_table_check_if_in_cache_low(
- foreign->foreign_table_name);
+ foreign->foreign_table_name_lookup);
ref_table = dict_table_check_if_in_cache_low(
- foreign->referenced_table_name);
+ foreign->referenced_table_name_lookup);
ut_a(for_table || ref_table);
if (for_table) {
@@ -2673,7 +2746,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 {
@@ -2985,19 +3058,25 @@ dict_scan_table_name(
memcpy(ref, database_name, database_name_len);
ref[database_name_len] = '/';
memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
-#ifndef __WIN__
- if (srv_lower_case_table_names) {
-#endif /* !__WIN__ */
- /* The table name is always put to lower case on Windows. */
+
+ /* Values; 0 = Store and compare as given; case sensitive
+ 1 = Store and compare in lower; case insensitive
+ 2 = Store as given, compare in lower; case semi-sensitive */
+ if (innobase_get_lower_case_table_names() == 2) {
innobase_casedn_str(ref);
-#ifndef __WIN__
+ *table = dict_table_get_low(ref);
+ memcpy(ref, database_name, database_name_len);
+ ref[database_name_len] = '/';
+ memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
+ } else {
+ if (innobase_get_lower_case_table_names() == 1) {
+ innobase_casedn_str(ref);
+ }
+ *table = dict_table_get_low(ref);
}
-#endif /* !__WIN__ */
*success = TRUE;
*ref_name = ref;
- *table = dict_table_get_low(ref);
-
return(ptr);
}
@@ -3453,7 +3532,7 @@ col_loop1:
start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
- return(DB_CANNOT_ADD_CONSTRAINT);
+ return(DB_CHILD_NO_INDEX);
}
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
@@ -3486,8 +3565,10 @@ col_loop1:
}
foreign->foreign_table = table;
- foreign->foreign_table_name = mem_heap_strdup(foreign->heap,
- table->name);
+ foreign->foreign_table_name = mem_heap_strdup(
+ foreign->heap, table->name);
+ dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
+
foreign->foreign_index = index;
foreign->n_fields = (unsigned int) i;
foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
@@ -3734,7 +3815,7 @@ try_find_index:
start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
- return(DB_CANNOT_ADD_CONSTRAINT);
+ return(DB_PARENT_NO_INDEX);
}
} else {
ut_a(trx->check_foreigns == FALSE);
@@ -3744,8 +3825,9 @@ try_find_index:
foreign->referenced_index = index;
foreign->referenced_table = referenced_table;
- foreign->referenced_table_name
- = mem_heap_strdup(foreign->heap, referenced_table_name);
+ foreign->referenced_table_name = mem_heap_strdup(
+ foreign->heap, referenced_table_name);
+ dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
i * sizeof(void*));
@@ -4198,15 +4280,15 @@ 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 size;
ulint sum_of_index_sizes = 0;
if (table->ibd_file_missing) {
@@ -4221,14 +4303,6 @@ dict_update_statistics_low(
return;
}
- /* If we have set a high innodb_force_recovery level, do not calculate
- statistics, as a badly corrupted index can cause a crash in it. */
-
- if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
-
- return;
- }
-
/* Find out the sizes of the indexes and how many different values
for the key they approximately have */
@@ -4240,36 +4314,64 @@ dict_update_statistics_low(
return;
}
- while (index) {
- size = btr_get_size(index, BTR_TOTAL_SIZE);
+ dict_table_stats_lock(table, RW_X_LATCH);
- index->stat_index_size = size;
+ if (only_calc_if_missing_stats && table->stat_initialized) {
+ dict_table_stats_unlock(table, RW_X_LATCH);
+ return;
+ }
- sum_of_index_sizes += size;
+ do {
+ if (UNIV_LIKELY
+ (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
+ || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
+ && dict_index_is_clust(index)))) {
+ ulint size;
+ size = btr_get_size(index, BTR_TOTAL_SIZE);
- size = btr_get_size(index, BTR_N_LEAF_PAGES);
+ index->stat_index_size = size;
- if (size == 0) {
- /* The root node of the tree is a leaf */
- size = 1;
- }
+ sum_of_index_sizes += size;
- index->stat_n_leaf_pages = size;
+ size = btr_get_size(index, BTR_N_LEAF_PAGES);
+
+ if (size == 0) {
+ /* The root node of the tree is a leaf */
+ size = 1;
+ }
+
+ index->stat_n_leaf_pages = size;
+
+ btr_estimate_number_of_different_key_vals(index);
+ } else {
+ /* If we have set a high innodb_force_recovery
+ level, do not calculate statistics, as a badly
+ corrupted index can cause a crash in it.
+ Initialize some bogus index cardinality
+ statistics, so that the data can be queried in
+ various means, also via secondary indexes. */
+ ulint i;
- btr_estimate_number_of_different_key_vals(index);
+ sum_of_index_sizes++;
+ index->stat_index_size = index->stat_n_leaf_pages = 1;
+
+ for (i = dict_index_get_n_unique(index); i; ) {
+ index->stat_n_diff_key_vals[i--] = 1;
+ }
+
+ memset(index->stat_n_non_null_key_vals, 0,
+ (1 + dict_index_get_n_unique(index))
+ * sizeof(*index->stat_n_non_null_key_vals));
+ }
index = dict_table_get_next_index(index);
- }
+ } while (index);
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
@@ -4278,18 +4380,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);
}
/**********************************************************************//**
@@ -4369,7 +4461,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"
@@ -4397,6 +4491,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) {
@@ -4445,8 +4541,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];
@@ -4454,8 +4548,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 %llu, fields %lu/%lu,"
" uniq %lu, type %lu\n"
@@ -4550,8 +4642,8 @@ dict_print_info_on_foreign_key_in_create_format(
fputs(") REFERENCES ", file);
- if (dict_tables_have_same_db(foreign->foreign_table_name,
- foreign->referenced_table_name)) {
+ if (dict_tables_have_same_db(foreign->foreign_table_name_lookup,
+ foreign->referenced_table_name_lookup)) {
/* Do not print the database name of the referenced table */
ut_print_name(file, trx, TRUE,
dict_remove_db_name(
@@ -4798,7 +4890,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 +4902,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;
}
@@ -4942,8 +5041,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/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index 3caa05891b4..a76f1f93202 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/dict/dict0load.c
@@ -40,6 +40,7 @@ Created 4/24/1996 Heikki Tuuri
#include "rem0cmp.h"
#include "srv0start.h"
#include "srv0srv.h"
+#include "ha_prototypes.h" /* innobase_casedn_str() */
/** Following are six InnoDB system tables */
@@ -346,7 +347,8 @@ dict_process_sys_tables_rec(
/* Update statistics if DICT_TABLE_UPDATE_STATS
is set */
- dict_update_statistics_low(*table, TRUE);
+ dict_update_statistics(*table, FALSE /* update even if
+ initialized */);
}
return(NULL);
@@ -427,17 +429,19 @@ dict_process_sys_fields_rec(
mach_write_to_8(last_index_id, last_id);
err_msg = dict_load_field_low(buf, NULL, sys_field,
- pos, last_index_id, heap, rec);
+ pos, last_index_id, heap, rec, NULL, 0);
*index_id = mach_read_from_8(buf);
return(err_msg);
}
+
+#ifdef FOREIGN_NOT_USED
/********************************************************************//**
This function parses a SYS_FOREIGN record and populate a dict_foreign_t
structure with the information from the record. For detail information
-about SYS_FOREIGN fields, please refer to dict_load_foreign() function
+about SYS_FOREIGN fields, please refer to dict_load_foreign() function.
@return error message, or NULL on success */
UNIV_INTERN
const char*
@@ -465,6 +469,11 @@ dict_process_sys_foreign_rec(
err_len:
return("incorrect column length in SYS_FOREIGN");
}
+
+ /* This recieves a dict_foreign_t* that points to a stack variable.
+ So mem_heap_free(foreign->heap) is not used as elsewhere.
+ Since the heap used here is freed elsewhere, foreign->heap
+ is not assigned. */
foreign->id = mem_heap_strdupl(heap, (const char*) field, len);
rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
@@ -476,6 +485,9 @@ err_len:
goto err_len;
}
+ /* The _lookup versions of the referenced and foreign table names
+ are not assigned since they are not used in this dict_foreign_t */
+
field = rec_get_nth_field_old(rec, 3/*FOR_NAME*/, &len);
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
goto err_len;
@@ -501,6 +513,9 @@ err_len:
return(NULL);
}
+#endif /* FOREIGN_NOT_USED */
+
+#ifdef FOREIGN_NOT_USED
/********************************************************************//**
This function parses a SYS_FOREIGN_COLS record and extract necessary
information from the record and return to caller.
@@ -564,6 +579,8 @@ err_len:
return(NULL);
}
+#endif /* FOREIGN_NOT_USED */
+
/********************************************************************//**
Determine the flags of a table described in SYS_TABLES.
@return compressed page size in kilobytes; or 0 if the tablespace is
@@ -977,6 +994,9 @@ dict_load_columns(
/** Error message for a delete-marked record in dict_load_field_low() */
static const char* dict_load_field_del = "delete-marked record in SYS_FIELDS";
+static const char* dict_load_field_too_big = "column prefix exceeds maximum"
+ " limit";
+
/********************************************************************//**
Loads an index field definition from a SYS_FIELDS record to
dict_index_t.
@@ -998,7 +1018,12 @@ dict_load_field_low(
byte* last_index_id, /*!< in: last index id */
mem_heap_t* heap, /*!< in/out: memory heap
for temporary storage */
- const rec_t* rec) /*!< in: SYS_FIELDS record */
+ const rec_t* rec, /*!< in: SYS_FIELDS record */
+ char* addition_err_str,/*!< out: additional error message
+ that requires information to be
+ filled, or NULL */
+ ulint err_str_len) /*!< in: length of addition_err_str
+ in bytes */
{
const byte* field;
ulint len;
@@ -1078,6 +1103,19 @@ err_len:
goto err_len;
}
+ if (prefix_len > REC_VERSION_56_MAX_INDEX_COL_LEN) {
+ if (addition_err_str) {
+ ut_snprintf(addition_err_str, err_str_len,
+ "index field '%s' has a prefix length"
+ " of %lu bytes",
+ mem_heap_strdupl(
+ heap, (const char*) field, len),
+ (ulong) prefix_len);
+ }
+
+ return(dict_load_field_too_big);
+ }
+
if (index) {
dict_mem_index_add_field(
index, mem_heap_strdupl(heap, (const char*) field, len),
@@ -1137,14 +1175,16 @@ dict_load_fields(
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
for (i = 0; i < index->n_fields; i++) {
- const char* err_msg;
+ const char* err_msg;
+ char addition_err_str[1024];
rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur));
err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
- heap, rec);
+ heap, rec, addition_err_str,
+ sizeof(addition_err_str));
if (err_msg == dict_load_field_del) {
/* There could be delete marked records in
@@ -1153,7 +1193,24 @@ dict_load_fields(
goto next_rec;
} else if (err_msg) {
- fprintf(stderr, "InnoDB: %s\n", err_msg);
+ if (err_msg == dict_load_field_too_big) {
+ fprintf(stderr, "InnoDB: Error: load index"
+ " '%s' failed.\n"
+ "InnoDB: %s,\n"
+ "InnoDB: which exceeds the"
+ " maximum limit of %lu bytes.\n"
+ "InnoDB: Please use server that"
+ " supports long index prefix\n"
+ "InnoDB: or turn on"
+ " innodb_force_recovery to load"
+ " the table\n",
+ index->name, addition_err_str,
+ (ulong) (REC_VERSION_56_MAX_INDEX_COL_LEN));
+
+ } else {
+ fprintf(stderr, "InnoDB: %s\n", err_msg);
+ }
+
error = DB_CORRUPTION;
goto func_exit;
}
@@ -1306,7 +1363,10 @@ ulint
dict_load_indexes(
/*==============*/
dict_table_t* table, /*!< in/out: table */
- mem_heap_t* heap) /*!< in: memory heap for temporary storage */
+ mem_heap_t* heap, /*!< in: memory heap for temporary storage */
+ dict_err_ignore_t ignore_err)
+ /*!< in: error to be ignored when
+ loading the index definition */
{
dict_table_t* sys_indexes;
dict_index_t* sys_index;
@@ -1389,10 +1449,22 @@ dict_load_indexes(
"InnoDB: but the index tree has been freed!\n",
index->name, table->name);
+ if (ignore_err & DICT_ERR_IGNORE_INDEX_ROOT) {
+ /* If caller can tolerate this error,
+ we will continue to load the index and
+ let caller deal with this error. However
+ mark the index and table corrupted */
+ index->corrupted = TRUE;
+ table->corrupted = TRUE;
+ fprintf(stderr,
+ "InnoDB: Index is corrupt but forcing"
+ " load into data dictionary\n");
+ } else {
corrupted:
- dict_mem_index_free(index);
- error = DB_CORRUPTION;
- goto func_exit;
+ dict_mem_index_free(index);
+ error = DB_CORRUPTION;
+ goto func_exit;
+ }
} else if (!dict_index_is_clust(index)
&& NULL == dict_table_get_first_index(table)) {
@@ -1414,7 +1486,26 @@ corrupted:
of the database server */
dict_mem_index_free(index);
} else {
- dict_load_fields(index, heap);
+ error = dict_load_fields(index, heap);
+
+ if (error != DB_SUCCESS) {
+
+ fprintf(stderr, "InnoDB: Error: load index '%s'"
+ " for table '%s' failed\n",
+ index->name, table->name);
+
+ /* If the force recovery flag is set, and
+ if the failed index is not the primary index, we
+ will continue and open other indexes */
+ if (srv_force_recovery
+ && !dict_index_is_clust(index)) {
+ error = DB_SUCCESS;
+ goto next_rec;
+ } else {
+ goto func_exit;
+ }
+ }
+
error = dict_index_add_to_cache(table, index,
index->page, FALSE);
/* The data dictionary tables should never contain
@@ -1535,7 +1626,7 @@ err_len:
"InnoDB: in InnoDB data dictionary"
" has unknown type %lx.\n",
(ulong) flags);
- return(NULL);
+ return("incorrect flags in SYS_TABLES");
}
} else {
flags = 0;
@@ -1601,7 +1692,10 @@ dict_load_table(
/*============*/
const char* name, /*!< in: table name in the
databasename/tablename format */
- ibool cached) /*!< in: TRUE=add to cache, FALSE=do not */
+ ibool cached, /*!< in: TRUE=add to cache, FALSE=do not */
+ dict_err_ignore_t ignore_err)
+ /*!< in: error to be ignored when loading
+ table and its indexes' definition */
{
dict_table_t* table;
dict_table_t* sys_tables;
@@ -1716,7 +1810,7 @@ err_exit:
mem_heap_empty(heap);
- err = dict_load_indexes(table, heap);
+ err = dict_load_indexes(table, heap, ignore_err);
/* Initialize table foreign_child value. Its value could be
changed when dict_load_foreigns() is called below */
@@ -1733,13 +1827,22 @@ err_exit:
if (err != DB_SUCCESS) {
dict_table_remove_from_cache(table);
table = NULL;
+ } else {
+ table->fk_max_recusive_level = 0;
}
- } else if (!srv_force_recovery) {
- dict_table_remove_from_cache(table);
- table = NULL;
- }
+ } else {
+ dict_index_t* index;
- table->fk_max_recusive_level = 0;
+ /* Make sure that at least the clustered index was loaded.
+ Otherwise refuse to load the table */
+ index = dict_table_get_first_index(table);
+
+ if (!srv_force_recovery || !index
+ || !dict_index_is_clust(index)) {
+ dict_table_remove_from_cache(table);
+ table = NULL;
+ }
+ }
#if 0
if (err != DB_SUCCESS && table != NULL) {
@@ -1851,7 +1954,7 @@ dict_load_table_on_id(
field = rec_get_nth_field_old(rec, 1, &len);
/* Load the table definition to memory */
table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
- TRUE);
+ TRUE, DICT_ERR_IGNORE_NONE);
func_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
@@ -1876,7 +1979,7 @@ dict_load_sys_table(
heap = mem_heap_create(1000);
- dict_load_indexes(table, heap);
+ dict_load_indexes(table, heap, DICT_ERR_IGNORE_NONE);
mem_heap_free(heap);
}
@@ -2055,12 +2158,15 @@ dict_load_foreign(
foreign->id = mem_heap_strdup(foreign->heap, id);
field = rec_get_nth_field_old(rec, 3, &len);
+
foreign->foreign_table_name = mem_heap_strdupl(
foreign->heap, (char*) field, len);
+ dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
field = rec_get_nth_field_old(rec, 4, &len);
foreign->referenced_table_name = mem_heap_strdupl(
foreign->heap, (char*) field, len);
+ dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
@@ -2068,7 +2174,7 @@ dict_load_foreign(
dict_load_foreign_cols(id, foreign);
ref_table = dict_table_check_if_in_cache_low(
- foreign->referenced_table_name);
+ foreign->referenced_table_name_lookup);
/* We could possibly wind up in a deep recursive calls if
we call dict_table_get_low() again here if there
@@ -2101,7 +2207,7 @@ dict_load_foreign(
have to load it so that we are able to make type comparisons
in the next function call. */
- for_table = dict_table_get_low(foreign->foreign_table_name);
+ for_table = dict_table_get_low(foreign->foreign_table_name_lookup);
if (for_table && ref_table && check_recursive) {
/* This is to record the longest chain of ancesters
@@ -2220,10 +2326,12 @@ loop:
/* Since table names in SYS_FOREIGN are stored in a case-insensitive
order, we have to check that the table name matches also in a binary
string comparison. On Unix, MySQL allows table names that only differ
- in character case. */
-
- if (0 != ut_memcmp(field, table_name, len)) {
+ in character case. If lower_case_table_names=2 then what is stored
+ may not be the same case, but the previous comparison showed that they
+ match with no-case. */
+ if ((innobase_get_lower_case_table_names() != 2)
+ && (0 != ut_memcmp(field, table_name, len))) {
goto next_rec;
}
diff --git a/storage/innobase/dict/dict0mem.c b/storage/innobase/dict/dict0mem.c
index bbb8f810f44..982cca5a796 100644
--- a/storage/innobase/dict/dict0mem.c
+++ b/storage/innobase/dict/dict0mem.c
@@ -33,9 +33,13 @@ Created 1/8/1996 Heikki Tuuri
#include "data0type.h"
#include "mach0data.h"
#include "dict0dict.h"
+#include "ha_prototypes.h" /* innobase_casedn_str()*/
#ifndef UNIV_HOTBACKUP
# include "lock0lock.h"
#endif /* !UNIV_HOTBACKUP */
+#ifdef UNIV_BLOB_DEBUG
+# include "ut0rbt.h"
+#endif /* UNIV_BLOB_DEBUG */
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
creating a table or index object */
@@ -228,6 +232,7 @@ dict_mem_fill_column_struct(
column->ind = (unsigned int) col_pos;
column->ord_part = 0;
+ column->max_prefix = 0;
column->mtype = (unsigned int) mtype;
column->prtype = (unsigned int) prtype;
column->len = (unsigned int) col_len;
@@ -288,6 +293,60 @@ dict_mem_foreign_create(void)
}
/**********************************************************************//**
+Sets the foreign_table_name_lookup pointer based on the value of
+lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup
+will point to foreign_table_name. If 2, then another string is
+allocated from foreign->heap and set to lower case. */
+UNIV_INTERN
+void
+dict_mem_foreign_table_name_lookup_set(
+/*===================================*/
+ dict_foreign_t* foreign, /*!< in/out: foreign struct */
+ ibool do_alloc) /*!< in: is an alloc needed */
+{
+ if (innobase_get_lower_case_table_names() == 2) {
+ if (do_alloc) {
+ foreign->foreign_table_name_lookup = mem_heap_alloc(
+ foreign->heap,
+ strlen(foreign->foreign_table_name) + 1);
+ }
+ strcpy(foreign->foreign_table_name_lookup,
+ foreign->foreign_table_name);
+ innobase_casedn_str(foreign->foreign_table_name_lookup);
+ } else {
+ foreign->foreign_table_name_lookup
+ = foreign->foreign_table_name;
+ }
+}
+
+/**********************************************************************//**
+Sets the referenced_table_name_lookup pointer based on the value of
+lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup
+will point to referenced_table_name. If 2, then another string is
+allocated from foreign->heap and set to lower case. */
+UNIV_INTERN
+void
+dict_mem_referenced_table_name_lookup_set(
+/*======================================*/
+ dict_foreign_t* foreign, /*!< in/out: foreign struct */
+ ibool do_alloc) /*!< in: is an alloc needed */
+{
+ if (innobase_get_lower_case_table_names() == 2) {
+ if (do_alloc) {
+ foreign->referenced_table_name_lookup = mem_heap_alloc(
+ foreign->heap,
+ strlen(foreign->referenced_table_name) + 1);
+ }
+ strcpy(foreign->referenced_table_name_lookup,
+ foreign->referenced_table_name);
+ innobase_casedn_str(foreign->referenced_table_name_lookup);
+ } else {
+ foreign->referenced_table_name_lookup
+ = foreign->referenced_table_name;
+ }
+}
+
+/**********************************************************************//**
Adds a field definition to an index. NOTE: does not take a copy
of the column name if the field is a column. The memory occupied
by the column name may be released only after publishing the index. */
@@ -324,6 +383,12 @@ dict_mem_index_free(
{
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
+#ifdef UNIV_BLOB_DEBUG
+ if (index->blobs) {
+ mutex_free(&index->blobs_mutex);
+ rbt_free(index->blobs);
+ }
+#endif /* UNIV_BLOB_DEBUG */
mem_heap_free(index->heap);
}
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
index 710f0ac8603..196f4bd3f42 100644
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/fil/fil0fil.c
@@ -299,6 +299,34 @@ struct fil_system_struct {
initialized. */
static fil_system_t* fil_system = NULL;
+#ifdef UNIV_DEBUG
+/** Try fil_validate() every this many times */
+# define FIL_VALIDATE_SKIP 17
+
+/******************************************************************//**
+Checks the consistency of the tablespace cache some of the time.
+@return TRUE if ok or the check was skipped */
+static
+ibool
+fil_validate_skip(void)
+/*===================*/
+{
+ /** The fil_validate() call skip counter. Use a signed type
+ because of the race condition below. */
+ static int fil_validate_count = FIL_VALIDATE_SKIP;
+
+ /* There is a race condition below, but it does not matter,
+ because this call is only for heuristic purposes. We want to
+ reduce the call frequency of the costly fil_validate() check
+ in debug builds. */
+ if (--fil_validate_count > 0) {
+ return(TRUE);
+ }
+
+ fil_validate_count = FIL_VALIDATE_SKIP;
+ return(fil_validate());
+}
+#endif /* UNIV_DEBUG */
/********************************************************************//**
NOTE: you must call fil_mutex_enter_and_prepare_for_io() first!
@@ -339,14 +367,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
@@ -827,7 +856,8 @@ fil_node_close_file(
ut_a(node->open);
ut_a(node->n_pending == 0);
ut_a(node->n_pending_flushes == 0);
- ut_a(node->modification_counter == node->flush_counter);
+ ut_a(node->modification_counter == node->flush_counter
+ || srv_fast_shutdown == 2);
ret = os_file_close(node->handle);
ut_a(ret);
@@ -1140,6 +1170,7 @@ try_again:
space = fil_space_get_by_name(name);
if (UNIV_LIKELY_NULL(space)) {
+ ibool success;
ulint namesake_id;
ut_print_timestamp(stderr);
@@ -1178,9 +1209,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;
}
@@ -1331,15 +1363,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);
@@ -1350,8 +1381,6 @@ fil_space_free(
" from the cache but\n"
"InnoDB: it is not there.\n", (ulong) id);
- mutex_exit(&fil_system->mutex);
-
return(FALSE);
}
@@ -1386,8 +1415,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));
@@ -1633,25 +1662,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);
@@ -2271,6 +2302,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
@@ -2283,7 +2327,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);
@@ -2291,6 +2339,8 @@ try_again:
if (!success) {
success = os_file_delete_if_exists(path);
}
+ } else {
+ rw_lock_x_unlock(&space->latch);
}
if (success) {
@@ -2318,6 +2368,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
@@ -4261,15 +4336,13 @@ fil_io(
#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE
# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE"
#endif
- ut_ad(fil_validate());
+ ut_ad(fil_validate_skip());
#ifndef UNIV_HOTBACKUP
# ifndef UNIV_LOG_DEBUG
/* ibuf bitmap pages must be read in the sync aio mode: */
ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE)
|| !ibuf_bitmap_page(zip_size, block_offset)
|| sync || is_log);
- ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE)
- || ibuf_page(space_id, zip_size, block_offset, NULL));
# endif /* UNIV_LOG_DEBUG */
if (sync) {
mode = OS_AIO_SYNC;
@@ -4420,7 +4493,7 @@ fil_io(
mutex_exit(&fil_system->mutex);
- ut_ad(fil_validate());
+ ut_ad(fil_validate_skip());
}
return(DB_SUCCESS);
@@ -4444,7 +4517,7 @@ fil_aio_wait(
void* message;
ulint type;
- ut_ad(fil_validate());
+ ut_ad(fil_validate_skip());
if (srv_use_native_aio) {
srv_set_io_thread_op_info(segment, "native aio handle");
@@ -4455,8 +4528,8 @@ fil_aio_wait(
ret = os_aio_linux_handle(segment, &fil_node,
&message, &type);
#else
- ret = 0; /* Eliminate compiler warning */
ut_error;
+ ret = 0; /* Eliminate compiler warning */
#endif
} else {
srv_set_io_thread_op_info(segment, "simulated aio handle");
@@ -4466,6 +4539,10 @@ fil_aio_wait(
}
ut_a(ret);
+ if (UNIV_UNLIKELY(fil_node == NULL)) {
+ ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
+ return;
+ }
srv_set_io_thread_op_info(segment, "complete io for fil node");
@@ -4475,7 +4552,7 @@ fil_aio_wait(
mutex_exit(&fil_system->mutex);
- ut_ad(fil_validate());
+ ut_ad(fil_validate_skip());
/* Do the i/o handling */
/* IMPORTANT: since i/o handling for reads will read also the insert
@@ -4788,7 +4865,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/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
index 3efe147b998..3f09732a676 100644
--- a/storage/innobase/fsp/fsp0fsp.c
+++ b/storage/innobase/fsp/fsp0fsp.c
@@ -3097,13 +3097,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);
@@ -3271,7 +3321,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;
}
@@ -3385,9 +3435,9 @@ fseg_free_page(
fseg_free_page_low(seg_inode, space, zip_size, page, mtr);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_set_file_page_was_freed(space, page);
-#endif
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
}
/**********************************************************************//**
@@ -3453,13 +3503,13 @@ fseg_free_extent(
fsp_free_extent(space, zip_size, page, mtr);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
for (i = 0; i < FSP_EXTENT_SIZE; i++) {
buf_page_set_file_page_was_freed(space,
first_page_in_extent + i);
}
-#endif
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
}
/**********************************************************************//**
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c32d8fc4ae9..3561d824e81 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
+Copyright (c) 2000, 2011, MySQL AB & Innobase Oy. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -32,7 +32,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/* TODO list for the InnoDB handler in 5.0:
- - Remove the flag trx->active_trans and look at trx->conc_state
- fix savepoint functions to use savepoint storage area
- Find out what kind of problems the OS X case-insensitivity causes to
table and database names; should we 'normalize' the names like we do
@@ -52,6 +51,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <mysql/plugin.h>
#include <mysql/innodb_priv.h>
#include <mysql/psi/psi.h>
+#include <my_sys.h>
/** @file ha_innodb.cc */
@@ -82,7 +82,6 @@ extern "C" {
#include "fil0fil.h"
#include "trx0xa.h"
#include "row0merge.h"
-#include "thr0loc.h"
#include "dict0boot.h"
#include "ha_prototypes.h"
#include "ut0mem.h"
@@ -96,10 +95,6 @@ extern "C" {
# define MYSQL_PLUGIN_IMPORT /* nothing */
# endif /* MYSQL_PLUGIN_IMPORT */
-#if MYSQL_VERSION_ID < 50124
-bool check_global_access(THD *thd, ulong want_access);
-#endif /* MYSQL_VERSION_ID < 50124 */
-
/** to protect innobase_open_files */
static mysql_mutex_t innobase_share_mutex;
/** to force correct commit order in binlog */
@@ -171,12 +166,32 @@ static my_bool innobase_locks_unsafe_for_binlog = FALSE;
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_large_prefix = FALSE;
static char* internal_innobase_data_file_path = NULL;
static char* innodb_version_str = (char*) INNODB_VERSION_STR;
+/** Possible values for system variable "innodb_stats_method". The values
+are defined the same as its corresponding MyISAM system variable
+"myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
+static const char* innodb_stats_method_names[] = {
+ "nulls_equal",
+ "nulls_unequal",
+ "nulls_ignored",
+ NullS
+};
+
+/** Used to define an enumerate type of the system variable innodb_stats_method.
+This is the same as "myisam_stats_method_typelib" */
+static TYPELIB innodb_stats_method_typelib = {
+ array_elements(innodb_stats_method_names) - 1,
+ "innodb_stats_method_typelib",
+ innodb_stats_method_names,
+ NULL
+};
+
/* The following counter is used to convey information to InnoDB
about server activity: in selects it is not sensible to call
srv_active_wake_master_thread after each fetch or search, we only do
@@ -241,7 +256,6 @@ static PSI_mutex_info all_innodb_mutexes[] = {
{&ibuf_mutex_key, "ibuf_mutex", 0},
{&ibuf_pessimistic_insert_mutex_key,
"ibuf_pessimistic_insert_mutex", 0},
- {&ios_mutex_key, "ios_mutex", 0},
{&kernel_mutex_key, "kernel_mutex", 0},
{&log_sys_mutex_key, "log_sys_mutex", 0},
# ifdef UNIV_MEM_DEBUG
@@ -249,7 +263,7 @@ static PSI_mutex_info all_innodb_mutexes[] = {
# endif /* UNIV_MEM_DEBUG */
{&mem_pool_mutex_key, "mem_pool_mutex", 0},
{&mutex_list_mutex_key, "mutex_list_mutex", 0},
- {&purge_sys_mutex_key, "purge_sys_mutex", 0},
+ {&purge_sys_bh_mutex_key, "purge_sys_bh_mutex", 0},
{&recv_sys_mutex_key, "recv_sys_mutex", 0},
{&rseg_mutex_key, "rseg_mutex", 0},
# ifdef UNIV_SYNC_DEBUG
@@ -266,7 +280,6 @@ static PSI_mutex_info all_innodb_mutexes[] = {
{&sync_thread_mutex_key, "sync_thread_mutex", 0},
# endif /* UNIV_SYNC_DEBUG */
{&trx_doublewrite_mutex_key, "trx_doublewrite_mutex", 0},
- {&thr_local_mutex_key, "thr_local_mutex", 0},
{&trx_undo_mutex_key, "trx_undo_mutex", 0}
};
# endif /* UNIV_PFS_MUTEX */
@@ -291,7 +304,8 @@ static PSI_rwlock_info all_innodb_rwlocks[] = {
{&checkpoint_lock_key, "checkpoint_lock", 0},
{&trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0},
{&trx_purge_latch_key, "trx_purge_latch", 0},
- {&index_tree_rw_lock_key, "index_tree_rw_lock", 0}
+ {&index_tree_rw_lock_key, "index_tree_rw_lock", 0},
+ {&dict_table_stats_latch_key, "dict_table_stats", 0}
};
# endif /* UNIV_PFS_RWLOCK */
@@ -674,6 +688,8 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_rows_read, SHOW_LONG},
{"rows_updated",
(char*) &export_vars.innodb_rows_updated, SHOW_LONG},
+ {"truncated_status_writes",
+ (char*) &export_vars.innodb_truncated_status_writes, SHOW_LONG},
{NullS, NullS, SHOW_LONG}
};
@@ -889,7 +905,7 @@ int
convert_error_code_to_mysql(
/*========================*/
int error, /*!< in: InnoDB error code */
- ulint flags, /*!< in: InnoDB table flags, or 0 */
+ ulint flags, /*!< in: InnoDB table flags, or 0 */
THD* thd) /*!< in: user thread handle or NULL */
{
switch (error) {
@@ -964,6 +980,8 @@ convert_error_code_to_mysql(
return(HA_ERR_ROW_IS_REFERENCED);
case DB_CANNOT_ADD_CONSTRAINT:
+ case DB_CHILD_NO_INDEX:
+ case DB_PARENT_NO_INDEX:
return(HA_ERR_CANNOT_ADD_FOREIGN);
case DB_CANNOT_DROP_CONSTRAINT:
@@ -991,6 +1009,11 @@ convert_error_code_to_mysql(
& DICT_TF_COMPACT) / 2);
return(HA_ERR_TO_BIG_ROW);
+ case DB_TOO_BIG_INDEX_COL:
+ my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
+ DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
+ return(HA_ERR_INDEX_COL_TOO_LONG);
+
case DB_NO_SAVEPOINT:
return(HA_ERR_NO_SAVEPOINT);
@@ -1129,6 +1152,20 @@ innobase_strcasecmp(
}
/******************************************************************//**
+Strip dir name from a full path name and return only the file name
+@return file name or "null" if no file name */
+extern "C" UNIV_INTERN
+const char*
+innobase_basename(
+/*==============*/
+ const char* path_name) /*!< in: full path name */
+{
+ const char* name = base_name(path_name);
+
+ return((name) ? name : "null");
+}
+
+/******************************************************************//**
Makes all characters in a NUL-terminated UTF-8 string lower case. */
extern "C" UNIV_INTERN
void
@@ -1168,6 +1205,20 @@ innobase_get_stmt(
return(stmt->str);
}
+/**********************************************************************//**
+Get the current setting of the lower_case_table_names global parameter from
+mysqld.cc. We do a dirty read because for one there is no synchronization
+object and secondly there is little harm in doing so even if we get a torn
+read.
+@return value of lower_case_table_names */
+extern "C" UNIV_INTERN
+ulint
+innobase_get_lower_case_table_names(void)
+/*=====================================*/
+{
+ return(lower_case_table_names);
+}
+
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
/*******************************************************************//**
@@ -1284,7 +1335,7 @@ innobase_mysql_tmpfile(void)
#ifdef _WIN32
/* Note that on Windows, the integer returned by mysql_tmpfile
- has no relation to C runtime file descriptor. Here, we need
+ has no relation to C runtime file descriptor. Here, we need
to call my_get_osfhandle to get the HANDLE and then convert it
to C runtime filedescriptor. */
{
@@ -1511,7 +1562,7 @@ Gets the InnoDB transaction handle for a MySQL handler object, creates
an InnoDB transaction struct if the corresponding MySQL thread struct still
lacks one.
@return InnoDB transaction handle */
-static
+static inline
trx_t*
check_trx_exists(
/*=============*/
@@ -1533,6 +1584,77 @@ check_trx_exists(
return(trx);
}
+/*********************************************************************//**
+Note that a transaction has been registered with MySQL.
+@return true if transaction is registered with MySQL 2PC coordinator */
+static inline
+bool
+trx_is_registered_for_2pc(
+/*=========================*/
+ const trx_t* trx) /* in: transaction */
+{
+ return(trx->is_registered == 1);
+}
+
+/*********************************************************************//**
+Note that a transaction owns the prepare_commit_mutex. */
+static inline
+void
+trx_owns_prepare_commit_mutex_set(
+/*==============================*/
+ trx_t* trx) /* in: transaction */
+{
+ ut_a(trx_is_registered_for_2pc(trx));
+ trx->owns_prepare_mutex = 1;
+}
+
+/*********************************************************************//**
+Note that a transaction has been registered with MySQL 2PC coordinator. */
+static inline
+void
+trx_register_for_2pc(
+/*==================*/
+ trx_t* trx) /* in: transaction */
+{
+ trx->is_registered = 1;
+ ut_ad(trx->owns_prepare_mutex == 0);
+}
+
+/*********************************************************************//**
+Note that a transaction has been deregistered. */
+static inline
+void
+trx_deregister_from_2pc(
+/*====================*/
+ trx_t* trx) /* in: transaction */
+{
+ trx->is_registered = 0;
+ trx->owns_prepare_mutex = 0;
+}
+
+/*********************************************************************//**
+Check whether atransaction owns the prepare_commit_mutex.
+@return true if transaction owns the prepare commit mutex */
+static inline
+bool
+trx_has_prepare_commit_mutex(
+/*=========================*/
+ const trx_t* trx) /* in: transaction */
+{
+ return(trx->owns_prepare_mutex == 1);
+}
+
+/*********************************************************************//**
+Check if transaction is started.
+@reutrn true if transaction is in state started */
+static
+bool
+trx_is_started(
+/*===========*/
+ trx_t* trx) /* in: transaction */
+{
+ return(trx->conc_state != TRX_NOT_STARTED);
+}
/*********************************************************************//**
Construct ha_innobase handler. */
@@ -1596,48 +1718,31 @@ ha_innobase::update_thd()
}
/*********************************************************************//**
-Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
-roll back the statement if the statement results in an error. This MUST be
-called for every SQL statement that may be rolled back by MySQL. Calling this
-several times to register the same statement is allowed, too. */
+Registers an InnoDB transaction with the MySQL 2PC coordinator, so that
+the MySQL XA code knows to call the InnoDB prepare and commit, or rollback
+for the transaction. This MUST be called for every transaction for which
+the user may call commit or rollback. Calling this several times to register
+the same transaction is allowed, too. This function also registers the
+current SQL statement. */
static inline
void
-innobase_register_stmt(
-/*===================*/
- handlerton* hton, /*!< in: Innobase hton */
- THD* thd) /*!< in: MySQL thd (connection) object */
+innobase_register_trx(
+/*==================*/
+ handlerton* hton, /* in: Innobase handlerton */
+ THD* thd, /* in: MySQL thd (connection) object */
+ trx_t* trx) /* in: transaction to register */
{
- DBUG_ASSERT(hton == innodb_hton_ptr);
- /* Register the statement */
trans_register_ha(thd, FALSE, hton);
-}
-
-/*********************************************************************//**
-Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
-to call the InnoDB prepare and commit, or rollback for the transaction. This
-MUST be called for every transaction for which the user may call commit or
-rollback. Calling this several times to register the same transaction is
-allowed, too.
-This function also registers the current SQL statement. */
-static inline
-void
-innobase_register_trx_and_stmt(
-/*===========================*/
- handlerton *hton, /*!< in: Innobase handlerton */
- THD* thd) /*!< in: MySQL thd (connection) object */
-{
- /* NOTE that actually innobase_register_stmt() registers also
- the transaction in the AUTOCOMMIT=1 mode. */
- innobase_register_stmt(hton, thd);
+ if (!trx_is_registered_for_2pc(trx)
+ && thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
- if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
-
- /* No autocommit mode, register for a transaction */
trans_register_ha(thd, TRUE, hton);
}
-}
+ trx_register_for_2pc(trx);
+}
+
/* BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
------------------------------------------------------------
@@ -1783,14 +1888,8 @@ innobase_query_caching_of_table_permitted(
#ifdef __WIN__
innobase_casedn_str(norm_name);
#endif
- /* The call of row_search_.. will start a new transaction if it is
- not yet started */
- if (trx->active_trans == 0) {
-
- innobase_register_trx_and_stmt(innodb_hton_ptr, thd);
- trx->active_trans = 1;
- }
+ innobase_register_trx(innodb_hton_ptr, thd, trx);
if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
@@ -1850,11 +1949,7 @@ innobase_convert_identifier(
FALSE=id is an UTF-8 string */
{
char nz[NAME_LEN + 1];
-#if MYSQL_VERSION_ID >= 50141
char nz2[NAME_LEN + 1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH];
-#else /* MYSQL_VERSION_ID >= 50141 */
- char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
-#endif /* MYSQL_VERSION_ID >= 50141 */
const char* s = id;
int q;
@@ -1872,13 +1967,9 @@ innobase_convert_identifier(
nz[idlen] = 0;
s = nz2;
-#if MYSQL_VERSION_ID >= 50141
idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2,
EXPLAIN_PARTITIONS_AS_COMMENT);
goto no_quote;
-#else /* MYSQL_VERSION_ID >= 50141 */
- idlen = filename_to_tablename(nz, nz2, sizeof nz2);
-#endif /* MYSQL_VERSION_ID >= 50141 */
}
/* See if the identifier needs to be quoted. */
@@ -1889,9 +1980,7 @@ innobase_convert_identifier(
}
if (q == EOF) {
-#if MYSQL_VERSION_ID >= 50141
no_quote:
-#endif /* MYSQL_VERSION_ID >= 50141 */
if (UNIV_UNLIKELY(idlen > buflen)) {
idlen = buflen;
}
@@ -2057,14 +2146,7 @@ ha_innobase::init_table_handle_for_HANDLER(void)
trx_assign_read_view(prebuilt->trx);
- /* Set the MySQL flag to mark that there is an active transaction */
-
- if (prebuilt->trx->active_trans == 0) {
-
- innobase_register_trx_and_stmt(ht, user_thd);
-
- prebuilt->trx->active_trans = 1;
- }
+ innobase_register_trx(ht, user_thd, prebuilt->trx);
/* We did the necessary inits in this function, no need to repeat them
in row_search_for_mysql */
@@ -2135,13 +2217,13 @@ innobase_init(
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
-#ifdef UNIV_DEBUG
+#ifndef DBUG_OFF
static const char test_filename[] = "-@";
char test_tablename[sizeof test_filename
+ sizeof srv_mysql50_table_name_prefix];
if ((sizeof test_tablename) - 1
!= filename_to_tablename(test_filename, test_tablename,
- sizeof test_tablename)
+ sizeof test_tablename, true)
|| strncmp(test_tablename,
srv_mysql50_table_name_prefix,
sizeof srv_mysql50_table_name_prefix)
@@ -2151,7 +2233,7 @@ innobase_init(
sql_print_error("tablename encoding has been changed");
goto error;
}
-#endif /* UNIV_DEBUG */
+#endif /* DBUG_OFF */
/* Check that values don't overflow on 32-bit systems. */
if (sizeof(ulint) == 4) {
@@ -2544,11 +2626,13 @@ innobase_alter_table_flags(
/*=======================*/
uint flags)
{
- return(HA_ONLINE_ADD_INDEX_NO_WRITES
- | HA_ONLINE_DROP_INDEX_NO_WRITES
- | HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES
- | HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES
- | HA_ONLINE_ADD_PK_INDEX_NO_WRITES);
+ return(HA_INPLACE_ADD_INDEX_NO_READ_WRITE
+ | HA_INPLACE_ADD_INDEX_NO_WRITE
+ | HA_INPLACE_DROP_INDEX_NO_READ_WRITE
+ | HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE
+ | HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE
+ | HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE
+ | HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE);
}
/*****************************************************************//**
@@ -2559,12 +2643,10 @@ innobase_commit_low(
/*================*/
trx_t* trx) /*!< in: transaction handle */
{
- if (trx->conc_state == TRX_NOT_STARTED) {
+ if (trx_is_started(trx)) {
- return;
+ trx_commit_for_mysql(trx);
}
-
- trx_commit_for_mysql(trx);
}
/*****************************************************************//**
@@ -2577,7 +2659,7 @@ static
int
innobase_start_trx_and_assign_read_view(
/*====================================*/
- handlerton *hton, /*!< in: Innodb handlerton */
+ handlerton *hton, /*!< in: Innodb handlerton */
THD* thd) /*!< in: MySQL thread handle of the user for whom
the transaction should be committed */
{
@@ -2606,10 +2688,7 @@ innobase_start_trx_and_assign_read_view(
/* Set the MySQL flag to mark that there is an active transaction */
- if (trx->active_trans == 0) {
- innobase_register_trx_and_stmt(hton, thd);
- trx->active_trans = 1;
- }
+ innobase_register_trx(hton, current_thd, trx);
DBUG_RETURN(0);
}
@@ -2622,7 +2701,7 @@ static
int
innobase_commit(
/*============*/
- handlerton *hton, /*!< in: Innodb handlerton */
+ handlerton *hton, /*!< in: Innodb handlerton */
THD* thd, /*!< in: MySQL thread handle of the user for whom
the transaction should be committed */
bool all) /*!< in: TRUE - commit transaction
@@ -2643,29 +2722,19 @@ innobase_commit(
trx_search_latch_release_if_reserved(trx);
}
- /* The flag trx->active_trans is set to 1 in
+ /* Transaction is deregistered only in a commit or a rollback. If
+ it is deregistered we know there cannot be resources to be freed
+ and we could return immediately. For the time being, we play safe
+ and do the cleanup though there should be nothing to clean up. */
- 1. ::external_lock(),
- 2. ::start_stmt(),
- 3. innobase_query_caching_of_table_permitted(),
- 4. innobase_savepoint(),
- 5. ::init_table_handle_for_HANDLER(),
- 6. innobase_start_trx_and_assign_read_view(),
- 7. ::transactional_table_lock()
+ if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
- and it is only set to 0 in a commit or a rollback. If it is 0 we know
- there cannot be resources to be freed and we could return immediately.
- For the time being, we play safe and do the cleanup though there should
- be nothing to clean up. */
-
- if (trx->active_trans == 0
- && trx->conc_state != TRX_NOT_STARTED) {
-
- sql_print_error("trx->active_trans == 0, but"
- " trx->conc_state != TRX_NOT_STARTED");
+ sql_print_error("Transaction not registered for MySQL 2PC, "
+ "but transaction is active");
}
+
if (all
- || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
+ || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
/* We were instructed to commit the whole transaction, or
this is an SQL statement end and autocommit is on */
@@ -2720,15 +2789,15 @@ retry:
mysql_mutex_unlock(&commit_cond_m);
}
- if (trx->active_trans == 2) {
-
+ if (trx_has_prepare_commit_mutex(trx)) {
+
mysql_mutex_unlock(&prepare_commit_mutex);
- }
+ }
+
+ trx_deregister_from_2pc(trx);
/* Now do a write + flush of logs. */
trx_commit_complete_for_mysql(trx);
- trx->active_trans = 0;
-
} else {
/* We just mark the SQL statement ended and do not do a
transaction commit */
@@ -2797,10 +2866,10 @@ innobase_rollback(
row_unlock_table_autoinc_for_mysql(trx);
if (all
- || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
+ || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
error = trx_rollback_for_mysql(trx);
- trx->active_trans = 0;
+ trx_deregister_from_2pc(trx);
} else {
error = trx_rollback_last_sql_stat_for_mysql(trx);
}
@@ -2943,8 +3012,8 @@ innobase_savepoint(
innobase_release_stat_resources(trx);
- /* cannot happen outside of transaction */
- DBUG_ASSERT(trx->active_trans);
+ /* Cannot happen outside of transaction */
+ DBUG_ASSERT(trx_is_registered_for_2pc(trx));
/* TODO: use provided savepoint data area to store savepoint data */
char name[64];
@@ -2974,16 +3043,15 @@ innobase_close_connection(
ut_a(trx);
- if (trx->active_trans == 0
- && trx->conc_state != TRX_NOT_STARTED) {
+ if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
- sql_print_error("trx->active_trans == 0, but"
- " trx->conc_state != TRX_NOT_STARTED");
+ sql_print_error("Transaction not registered for MySQL 2PC, "
+ "but transaction is active");
}
- if (trx->conc_state != TRX_NOT_STARTED &&
- global_system_variables.log_warnings) {
+ if (trx_is_started(trx) && global_system_variables.log_warnings) {
+
sql_print_warning(
"MySQL is closing a connection that has an active "
"InnoDB transaction. %llu row modifications will "
@@ -2993,7 +3061,6 @@ innobase_close_connection(
innobase_rollback_trx(trx);
- thr_local_free(trx->mysql_thread_id);
trx_free_for_mysql(trx);
DBUG_RETURN(0);
@@ -3887,7 +3954,11 @@ UNIV_INTERN
uint
ha_innobase::max_supported_key_part_length() const
{
- return(DICT_MAX_INDEX_COL_LEN - 1);
+ /* A table format specific index column length check will be performed
+ at ha_innobase::add_index() and row_create_index_for_mysql() */
+ return(innobase_large_prefix
+ ? REC_VERSION_56_MAX_INDEX_COL_LEN
+ : REC_ANTELOPE_MAX_INDEX_COL_LEN - 1);
}
/******************************************************************//**
@@ -4626,17 +4697,18 @@ include_field:
n_requested_fields++;
templ->col_no = i;
+ templ->clust_rec_field_no = dict_col_get_clust_pos(
+ col, clust_index);
+ ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED);
if (index == clust_index) {
- templ->rec_field_no = dict_col_get_clust_pos(
- col, index);
+ templ->rec_field_no = templ->clust_rec_field_no;
} else {
templ->rec_field_no = dict_index_get_nth_col_pos(
index, i);
- }
-
- if (templ->rec_field_no == ULINT_UNDEFINED) {
- prebuilt->need_to_access_clustered = TRUE;
+ if (templ->rec_field_no == ULINT_UNDEFINED) {
+ prebuilt->need_to_access_clustered = TRUE;
+ }
}
if (field->null_ptr) {
@@ -4686,9 +4758,7 @@ skip_field:
for (i = 0; i < n_requested_fields; i++) {
templ = prebuilt->mysql_template + i;
- templ->rec_field_no = dict_col_get_clust_pos(
- &index->table->cols[templ->col_no],
- clust_index);
+ templ->rec_field_no = templ->clust_rec_field_no;
}
}
}
@@ -4884,7 +4954,7 @@ no_commit:
/* Altering to InnoDB format */
innobase_commit(ht, user_thd, 1);
/* Note that this transaction is still active. */
- prebuilt->trx->active_trans = 1;
+ trx_register_for_2pc(prebuilt->trx);
/* We will need an IX lock on the destination table. */
prebuilt->sql_stat_start = TRUE;
} else {
@@ -4900,7 +4970,7 @@ no_commit:
locks, so they have to be acquired again. */
innobase_commit(ht, user_thd, 1);
/* Note that this transaction is still active. */
- prebuilt->trx->active_trans = 1;
+ trx_register_for_2pc(prebuilt->trx);
/* Re-acquire the table lock on the source table. */
row_lock_table_for_mysql(prebuilt, src_table, mode);
/* We will need an IX lock on the destination table. */
@@ -6198,9 +6268,16 @@ create_table_def(
DBUG_PRINT("enter", ("table_name: %s", table_name));
ut_a(trx->mysql_thd != NULL);
- if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(table_name,
- (THD*) trx->mysql_thd)) {
- 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;
@@ -6485,6 +6562,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
@@ -6499,9 +6630,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);
@@ -6513,10 +6644,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:
@@ -6524,127 +6653,70 @@ 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 */
+ /* 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,
- 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,
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: cannot specify"
- " ROW_FORMAT = %s with"
- " KEY_BLOCK_SIZE.",
- row_format_name);
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_format > Antelope.");
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);
@@ -6694,7 +6766,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");
@@ -6732,52 +6804,28 @@ ha_innobase::create(
DBUG_RETURN(HA_ERR_TO_BIG_ROW);
}
- /* Get the transaction associated with the current thd, or create one
- if not yet created */
-
- parent_trx = check_trx_exists(thd);
-
- /* In case MySQL calls this in the middle of a SELECT query, release
- possible adaptive hash latch to avoid deadlocks of threads */
-
- trx_search_latch_release_if_reserved(parent_trx);
-
- trx = innobase_trx_allocate(thd);
-
- if (lower_case_table_names) {
- srv_lower_case_table_names = TRUE;
- } else {
- srv_lower_case_table_names = FALSE;
- }
-
strcpy(name2, name);
normalize_table_name(norm_name, name2);
- /* Latch the InnoDB data dictionary exclusively so that no deadlocks
- or lock waits can happen in it during a table create operation.
- Drop table etc. do this latching in row0mysql.c. */
-
- row_mysql_lock_data_dictionary(trx);
-
/* Create the table definition in InnoDB */
flags = 0;
/* Validate create options if innodb_strict_mode is set. */
if (!create_options_are_valid(thd, form, create_info)) {
- error = ER_ILLEGAL_HA_CREATE_OPTION;
- goto cleanup;
+ DBUG_RETURN(ER_ILLEGAL_HA_CREATE_OPTION);
}
- 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. */
ulint ssize, ksize;
ulint key_block_size = create_info->key_block_size;
+ /* Set 'flags' to the correct key_block_size.
+ It will be zero if key_block_size is an invalid number.*/
for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
ssize++, ksize <<= 1) {
if (key_block_size == ksize) {
@@ -6790,40 +6838,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) {
- /* KEY_BLOCK_SIZE was specified. */
- if (!(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) {
- /* ROW_FORMAT was not specified;
- default to ROW_FORMAT=COMPRESSED */
- 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
@@ -6831,8 +6879,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.",
@@ -6840,8 +6887,8 @@ ha_innobase::create(
flags = 0;
}
} else {
- /* No KEY_BLOCK_SIZE */
- if (row_type == ROW_TYPE_COMPRESSED) {
+ /* flags == 0 means no KEY_BLOCK_SIZE.*/
+ if (row_format == ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT=COMPRESSED without
KEY_BLOCK_SIZE implies half the
maximum KEY_BLOCK_SIZE. */
@@ -6856,49 +6903,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;
@@ -6918,16 +6956,37 @@ ha_innobase::create(
/* Check for name conflicts (with reserved name) for
any user indices to be created. */
- if (innobase_index_name_is_reserved(trx, form->key_info,
+ if (innobase_index_name_is_reserved(thd, form->key_info,
form->s->keys)) {
- error = -1;
- goto cleanup;
+ DBUG_RETURN(-1);
+ }
+
+ if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
+ DBUG_RETURN(HA_ERR_GENERIC);
}
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
flags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
}
+ /* Get the transaction associated with the current thd, or create one
+ if not yet created */
+
+ parent_trx = check_trx_exists(thd);
+
+ /* In case MySQL calls this in the middle of a SELECT query, release
+ possible adaptive hash latch to avoid deadlocks of threads */
+
+ trx_search_latch_release_if_reserved(parent_trx);
+
+ trx = innobase_trx_allocate(thd);
+
+ /* Latch the InnoDB data dictionary exclusively so that no deadlocks
+ or lock waits can happen in it during a table create operation.
+ Drop table etc. do this latching in row0mysql.c. */
+
+ row_mysql_lock_data_dictionary(trx);
+
error = create_table_def(trx, form, norm_name,
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
flags);
@@ -6964,8 +7023,8 @@ ha_innobase::create(
if (i != (uint) primary_key_no) {
- if ((error = create_index(trx, form, flags, norm_name,
- i))) {
+ if ((error = create_index(trx, form, flags,
+ norm_name, i))) {
goto cleanup;
}
}
@@ -6978,6 +7037,29 @@ ha_innobase::create(
trx, stmt, stmt_len, norm_name,
create_info->options & HA_LEX_CREATE_TMP_TABLE);
+ switch (error) {
+
+ case DB_PARENT_NO_INDEX:
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_CANNOT_ADD_FOREIGN,
+ "Create table '%s' with foreign key constraint"
+ " failed. There is no index in the referenced"
+ " table where the referenced columns appear"
+ " as the first columns.\n", norm_name);
+ break;
+
+ case DB_CHILD_NO_INDEX:
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_CANNOT_ADD_FOREIGN,
+ "Create table '%s' with foreign key constraint"
+ " failed. There is no index in the referencing"
+ " table where referencing columns appear"
+ " as the first columns.\n", norm_name);
+ break;
+ }
+
error = convert_error_code_to_mysql(error, flags, NULL);
if (error) {
@@ -7012,23 +7094,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);
@@ -7093,33 +7177,21 @@ Deletes all rows of an InnoDB table.
@return error number */
UNIV_INTERN
int
-ha_innobase::delete_all_rows(void)
+ha_innobase::truncate(void)
/*==============================*/
{
int error;
- DBUG_ENTER("ha_innobase::delete_all_rows");
+ DBUG_ENTER("ha_innobase::truncate");
/* Get the transaction associated with the current thd, or create one
if not yet created, and update prebuilt->trx */
update_thd(ha_thd());
- if (thd_sql_command(user_thd) != SQLCOM_TRUNCATE) {
- fallback:
- /* We only handle TRUNCATE TABLE t as a special case.
- DELETE FROM t will have to use ha_innobase::delete_row(),
- because DELETE is transactional while TRUNCATE is not. */
- DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
- }
-
/* Truncate the table in InnoDB */
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
- if (error == DB_ERROR) {
- /* Cannot truncate; resort to ha_innobase::delete_row() */
- goto fallback;
- }
error = convert_error_code_to_mysql(error, prebuilt->table->flags,
NULL);
@@ -7169,12 +7241,6 @@ ha_innobase::delete_table(
trx = innobase_trx_allocate(thd);
- if (lower_case_table_names) {
- srv_lower_case_table_names = TRUE;
- } else {
- srv_lower_case_table_names = FALSE;
- }
-
name_len = strlen(name);
ut_a(name_len < 1000);
@@ -7296,12 +7362,6 @@ innobase_rename_table(
char* norm_to;
char* norm_from;
- if (lower_case_table_names) {
- srv_lower_case_table_names = TRUE;
- } else {
- srv_lower_case_table_names = FALSE;
- }
-
// Magic number 64 arbitrary
norm_to = (char*) my_malloc(strlen(to) + 64, MYF(0));
norm_from = (char*) my_malloc(strlen(from) + 64, MYF(0));
@@ -7536,6 +7596,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");
@@ -7555,10 +7616,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
@@ -7707,41 +7770,90 @@ innobase_get_mysql_key_number_for_index(
return(0);
}
+
+/*********************************************************************//**
+Calculate Record Per Key value. Need to exclude the NULL value if
+innodb_stats_method is set to "nulls_ignored"
+@return estimated record per key value */
+static
+ha_rows
+innodb_rec_per_key(
+/*===============*/
+ dict_index_t* index, /*!< in: dict_index_t structure */
+ ulint i, /*!< in: the column we are
+ calculating rec per key */
+ ha_rows records) /*!< in: estimated total records */
+{
+ ha_rows rec_per_key;
+
+ ut_ad(i < dict_index_get_n_unique(index));
+
+ /* Note the stat_n_diff_key_vals[] stores the diff value with
+ n-prefix indexing, so it is always stat_n_diff_key_vals[i + 1] */
+ if (index->stat_n_diff_key_vals[i + 1] == 0) {
+
+ rec_per_key = records;
+ } else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) {
+ ib_int64_t num_null;
+
+ /* Number of rows with NULL value in this
+ field */
+ num_null = records - index->stat_n_non_null_key_vals[i];
+
+ /* In theory, index->stat_n_non_null_key_vals[i]
+ should always be less than the number of records.
+ Since this is statistics value, the value could
+ have slight discrepancy. But we will make sure
+ the number of null values is not a negative number. */
+ num_null = (num_null < 0) ? 0 : num_null;
+
+ /* If the number of NULL values is the same as or
+ large than that of the distinct values, we could
+ consider that the table consists mostly of NULL value.
+ Set rec_per_key to 1. */
+ if (index->stat_n_diff_key_vals[i + 1] <= num_null) {
+ rec_per_key = 1;
+ } else {
+ /* Need to exclude rows with NULL values from
+ rec_per_key calculation */
+ rec_per_key = (ha_rows)(
+ (records - num_null)
+ / (index->stat_n_diff_key_vals[i + 1]
+ - num_null));
+ }
+ } else {
+ rec_per_key = (ha_rows)
+ (records / index->stat_n_diff_key_vals[i + 1]);
+ }
+
+ return(rec_per_key);
+}
+
/*********************************************************************//**
Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. */
UNIV_INTERN
int
-ha_innobase::info(
-/*==============*/
- uint flag) /*!< in: what information MySQL requests */
+ha_innobase::info_low(
+/*==================*/
+ uint flag, /*!< in: what information MySQL
+ requests */
+ bool called_from_analyze) /* in: TRUE if called from
+ ::analyze() */
{
dict_table_t* ib_table;
dict_index_t* index;
ha_rows rec_per_key;
ib_int64_t n_rows;
- ulong j;
- ulong i;
char path[FN_REFLEN];
os_file_stat_t stat_info;
-
DBUG_ENTER("info");
/* If we are forcing recovery at a high level, we will suppress
statistics calculation on tables, because that may crash the
server if an index is badly corrupted. */
- if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
-
- /* We return success (0) instead of HA_ERR_CRASHED,
- because we want MySQL to process this query and not
- stop, like it would do if it received the error code
- HA_ERR_CRASHED. */
-
- DBUG_RETURN(0);
- }
-
/* We do not know if MySQL can call this function before calling
external_lock(). To be safe, update the thd of the current table
handle. */
@@ -7758,13 +7870,15 @@ ha_innobase::info(
ib_table = prebuilt->table;
if (flag & HA_STATUS_TIME) {
- if (innobase_stats_on_metadata) {
+ if (called_from_analyze || innobase_stats_on_metadata) {
/* In sql_show we call with this flag: update
then statistics so that they are up-to-date */
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";
}
@@ -7783,6 +7897,9 @@ ha_innobase::info(
}
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
@@ -7832,29 +7949,33 @@ ha_innobase::info(
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.
- We do not update delete_length if no locking is requested
- so the "old" value can remain. delete_length is initialized
- to 0 in the ha_statistics' constructor. */
- if (!(flag & HA_STATUS_NO_LOCK)) {
-
- /* lock the data dictionary to avoid races with
- ibd_file_missing and tablespace_discarded */
- row_mysql_lock_data_dictionary(prebuilt->trx);
-
- /* 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 {
+ See Bug#38185. */
+ if (flag & HA_STATUS_NO_LOCK
+ || !(flag & HA_STATUS_VARIABLE_EXTRA)) {
+ /* We do not update delete_length if no
+ locking is requested so the "old" value can
+ remain. delete_length is initialized to 0 in
+ the ha_statistics' constructor. Also we only
+ need delete_length to be set when
+ HA_STATUS_VARIABLE_EXTRA is set */
+ } else if (UNIV_UNLIKELY
+ (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE)) {
+ /* Avoid accessing the tablespace if
+ innodb_crash_recovery is set to a high value. */
+ stats.delete_length = 0;
+ } else {
+ ullint avail_space;
+
+ avail_space = fsp_get_available_space_in_free_extents(
+ ib_table->space);
+ if (avail_space == ULLINT_UNDEFINED) {
THD* thd;
thd = ha_thd();
@@ -7871,9 +7992,9 @@ ha_innobase::info(
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;
@@ -7886,6 +8007,7 @@ ha_innobase::info(
}
if (flag & HA_STATUS_CONST) {
+ ulong i;
/* Verify the number of index in InnoDB and MySQL
matches up. If prebuilt->clust_index_was_generated
holds, InnoDB defines GEN_CLUST_INDEX internally */
@@ -7901,7 +8023,10 @@ ha_innobase::info(
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
index mapping with the index translation table.
The identity of index (match up index name with
@@ -7937,17 +8062,8 @@ ha_innobase::info(
break;
}
- dict_index_stat_mutex_enter(index);
-
- if (index->stat_n_diff_key_vals[j + 1] == 0) {
-
- rec_per_key = stats.records;
- } else {
- rec_per_key = (ha_rows)(stats.records /
- index->stat_n_diff_key_vals[j + 1]);
- }
-
- dict_index_stat_mutex_exit(index);
+ rec_per_key = innodb_rec_per_key(
+ index, j, stats.records);
/* Since MySQL seems to favor table scans
too much over index searches, we pretend
@@ -7965,6 +8081,13 @@ ha_innobase::info(
(ulong) rec_per_key;
}
}
+
+ dict_table_stats_unlock(ib_table, RW_S_LATCH);
+ }
+
+ if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+ goto func_exit;
}
if (flag & HA_STATUS_ERRKEY) {
@@ -7987,11 +8110,24 @@ ha_innobase::info(
stats.auto_increment_value = innobase_peek_autoinc();
}
+func_exit:
prebuilt->trx->op_info = (char*)"";
DBUG_RETURN(0);
}
+/*********************************************************************//**
+Returns statistics information of the table to the MySQL interpreter,
+in various fields of the handle object. */
+UNIV_INTERN
+int
+ha_innobase::info(
+/*==============*/
+ uint flag) /*!< in: what information MySQL requests */
+{
+ return(info_low(flag, false /* not called from analyze */));
+}
+
/**********************************************************************//**
Updates index cardinalities of the table, based on 8 random dives into
each index tree. This does NOT calculate exact statistics on the table.
@@ -8004,7 +8140,8 @@ ha_innobase::analyze(
HA_CHECK_OPT* check_opt) /*!< in: currently ignored */
{
/* Simply call ::info() with all the flags */
- info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+ info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
+ true /* called from analyze */);
return(0);
}
@@ -8305,8 +8442,6 @@ ha_innobase::get_foreign_key_create_info(void)
flen = ftell(srv_dict_tmpfile);
if (flen < 0) {
flen = 0;
- } else if (flen > 64000 - 1) {
- flen = 64000 - 1;
}
/* allocate buffer for the string, and
@@ -8326,136 +8461,199 @@ ha_innobase::get_foreign_key_create_info(void)
}
+/***********************************************************************//**
+Maps a InnoDB foreign key constraint to a equivalent MySQL foreign key info.
+@return pointer to foreign key info */
+static
+FOREIGN_KEY_INFO*
+get_foreign_key_info(
+/*=================*/
+ THD* thd, /*!< in: user thread handle */
+ dict_foreign_t* foreign) /*!< in: foreign key constraint */
+{
+ FOREIGN_KEY_INFO f_key_info;
+ FOREIGN_KEY_INFO* pf_key_info;
+ uint i = 0;
+ ulint len;
+ char tmp_buff[NAME_LEN+1];
+ char name_buff[NAME_LEN+1];
+ const char* ptr;
+ LEX_STRING* referenced_key_name;
+ LEX_STRING* name = NULL;
+
+ ptr = dict_remove_db_name(foreign->id);
+ f_key_info.foreign_id = thd_make_lex_string(thd, 0, ptr,
+ (uint) strlen(ptr), 1);
+
+ /* Name format: database name, '/', table name, '\0' */
+
+ /* Referenced (parent) database name */
+ len = dict_get_db_name_len(foreign->referenced_table_name);
+ ut_a(len < sizeof(tmp_buff));
+ ut_memcpy(tmp_buff, foreign->referenced_table_name, len);
+ tmp_buff[len] = 0;
+
+ len = filename_to_tablename(tmp_buff, name_buff, sizeof(name_buff));
+ f_key_info.referenced_db = thd_make_lex_string(thd, 0, name_buff, len, 1);
+
+ /* Referenced (parent) table name */
+ ptr = dict_remove_db_name(foreign->referenced_table_name);
+ len = filename_to_tablename(ptr, name_buff, sizeof(name_buff));
+ f_key_info.referenced_table = thd_make_lex_string(thd, 0, name_buff, len, 1);
+
+ /* Dependent (child) database name */
+ len = dict_get_db_name_len(foreign->foreign_table_name);
+ ut_a(len < sizeof(tmp_buff));
+ ut_memcpy(tmp_buff, foreign->foreign_table_name, len);
+ tmp_buff[len] = 0;
+
+ len = filename_to_tablename(tmp_buff, name_buff, sizeof(name_buff));
+ f_key_info.foreign_db = thd_make_lex_string(thd, 0, name_buff, len, 1);
+
+ /* Dependent (child) table name */
+ ptr = dict_remove_db_name(foreign->foreign_table_name);
+ len = filename_to_tablename(ptr, name_buff, sizeof(name_buff));
+ f_key_info.foreign_table = thd_make_lex_string(thd, 0, name_buff, len, 1);
+
+ do {
+ ptr = foreign->foreign_col_names[i];
+ name = thd_make_lex_string(thd, name, ptr,
+ (uint) strlen(ptr), 1);
+ f_key_info.foreign_fields.push_back(name);
+ ptr = foreign->referenced_col_names[i];
+ name = thd_make_lex_string(thd, name, ptr,
+ (uint) strlen(ptr), 1);
+ f_key_info.referenced_fields.push_back(name);
+ } while (++i < foreign->n_fields);
+
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
+ len = 7;
+ ptr = "CASCADE";
+ } else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
+ len = 8;
+ ptr = "SET NULL";
+ } else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
+ len = 9;
+ ptr = "NO ACTION";
+ } else {
+ len = 8;
+ ptr = "RESTRICT";
+ }
+
+ f_key_info.delete_method = thd_make_lex_string(thd,
+ f_key_info.delete_method,
+ ptr, len, 1);
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
+ len = 7;
+ ptr = "CASCADE";
+ } else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
+ len = 8;
+ ptr = "SET NULL";
+ } else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
+ len = 9;
+ ptr = "NO ACTION";
+ } else {
+ len = 8;
+ ptr = "RESTRICT";
+ }
+
+ f_key_info.update_method = thd_make_lex_string(thd,
+ f_key_info.update_method,
+ ptr, len, 1);
+
+ if (foreign->referenced_index && foreign->referenced_index->name) {
+ referenced_key_name = thd_make_lex_string(thd,
+ f_key_info.referenced_key_name,
+ foreign->referenced_index->name,
+ (uint) strlen(foreign->referenced_index->name),
+ 1);
+ } else {
+ referenced_key_name = NULL;
+ }
+
+ f_key_info.referenced_key_name = referenced_key_name;
+
+ pf_key_info = (FOREIGN_KEY_INFO *) thd_memdup(thd, &f_key_info,
+ sizeof(FOREIGN_KEY_INFO));
+
+ return(pf_key_info);
+}
+
+/*******************************************************************//**
+Gets the list of foreign keys in this table.
+@return always 0, that is, always succeeds */
UNIV_INTERN
int
-ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
-{
- dict_foreign_t* foreign;
-
- DBUG_ENTER("get_foreign_key_list");
- ut_a(prebuilt != NULL);
- update_thd(ha_thd());
- prebuilt->trx->op_info = (char*)"getting list of foreign keys";
- trx_search_latch_release_if_reserved(prebuilt->trx);
- mutex_enter(&(dict_sys->mutex));
- foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
-
- while (foreign != NULL) {
- uint i;
- FOREIGN_KEY_INFO f_key_info;
- LEX_STRING *name= 0;
- uint ulen;
- char uname[NAME_LEN+1]; /* Unencoded name */
- char db_name[NAME_LEN+1];
- const char *tmp_buff;
-
- tmp_buff= foreign->id;
- i= 0;
- while (tmp_buff[i] != '/')
- i++;
- tmp_buff+= i + 1;
- f_key_info.forein_id = thd_make_lex_string(thd, 0,
- tmp_buff, (uint) strlen(tmp_buff), 1);
- tmp_buff= foreign->referenced_table_name;
-
- /* Database name */
- i= 0;
- while (tmp_buff[i] != '/')
- {
- db_name[i]= tmp_buff[i];
- i++;
- }
- db_name[i]= 0;
- ulen= filename_to_tablename(db_name, uname, sizeof(uname));
- f_key_info.referenced_db = thd_make_lex_string(thd, 0,
- uname, ulen, 1);
-
- /* Table name */
- tmp_buff+= i + 1;
- ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
- f_key_info.referenced_table = thd_make_lex_string(thd, 0,
- uname, ulen, 1);
-
- for (i= 0;;) {
- tmp_buff= foreign->foreign_col_names[i];
- name = thd_make_lex_string(thd, name,
- tmp_buff, (uint) strlen(tmp_buff), 1);
- f_key_info.foreign_fields.push_back(name);
- tmp_buff= foreign->referenced_col_names[i];
- name = thd_make_lex_string(thd, name,
- tmp_buff, (uint) strlen(tmp_buff), 1);
- f_key_info.referenced_fields.push_back(name);
- if (++i >= foreign->n_fields)
- break;
- }
-
- ulong length;
- if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
- {
- length=7;
- tmp_buff= "CASCADE";
- }
- else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
- {
- length=8;
- tmp_buff= "SET NULL";
- }
- else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
- {
- length=9;
- tmp_buff= "NO ACTION";
- }
- else
- {
- length=8;
- tmp_buff= "RESTRICT";
- }
- f_key_info.delete_method = thd_make_lex_string(
- thd, f_key_info.delete_method, tmp_buff, length, 1);
-
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
- {
- length=7;
- tmp_buff= "CASCADE";
- }
- else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
- {
- length=8;
- tmp_buff= "SET NULL";
- }
- else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
- {
- length=9;
- tmp_buff= "NO ACTION";
- }
- else
- {
- length=8;
- tmp_buff= "RESTRICT";
- }
- f_key_info.update_method = thd_make_lex_string(
- thd, f_key_info.update_method, tmp_buff, length, 1);
- if (foreign->referenced_index &&
- foreign->referenced_index->name)
- {
- f_key_info.referenced_key_name = thd_make_lex_string(
- thd, f_key_info.referenced_key_name,
- foreign->referenced_index->name,
- (uint) strlen(foreign->referenced_index->name), 1);
- }
- else
- f_key_info.referenced_key_name= 0;
-
- FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
- thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO));
- f_key_list->push_back(pf_key_info);
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
- mutex_exit(&(dict_sys->mutex));
- prebuilt->trx->op_info = (char*)"";
+ha_innobase::get_foreign_key_list(
+/*==============================*/
+ THD* thd, /*!< in: user thread handle */
+ List<FOREIGN_KEY_INFO>* f_key_list) /*!< out: foreign key list */
+{
+ FOREIGN_KEY_INFO* pf_key_info;
+ dict_foreign_t* foreign;
+
+ ut_a(prebuilt != NULL);
+ update_thd(ha_thd());
+
+ prebuilt->trx->op_info = "getting list of foreign keys";
+
+ trx_search_latch_release_if_reserved(prebuilt->trx);
+
+ mutex_enter(&(dict_sys->mutex));
+
+ for (foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
+ foreign != NULL;
+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ pf_key_info = get_foreign_key_info(thd, foreign);
+ if (pf_key_info) {
+ f_key_list->push_back(pf_key_info);
+ }
+ }
+
+ mutex_exit(&(dict_sys->mutex));
+
+ prebuilt->trx->op_info = "";
+
+ return(0);
+}
+
+/*******************************************************************//**
+Gets the set of foreign keys where this table is the referenced table.
+@return always 0, that is, always succeeds */
+UNIV_INTERN
+int
+ha_innobase::get_parent_foreign_key_list(
+/*=====================================*/
+ THD* thd, /*!< in: user thread handle */
+ List<FOREIGN_KEY_INFO>* f_key_list) /*!< out: foreign key list */
+{
+ FOREIGN_KEY_INFO* pf_key_info;
+ dict_foreign_t* foreign;
+
+ ut_a(prebuilt != NULL);
+ update_thd(ha_thd());
+
+ prebuilt->trx->op_info = "getting list of referencing foreign keys";
+
+ trx_search_latch_release_if_reserved(prebuilt->trx);
+
+ mutex_enter(&(dict_sys->mutex));
+
+ for (foreign = UT_LIST_GET_FIRST(prebuilt->table->referenced_list);
+ foreign != NULL;
+ foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ pf_key_info = get_foreign_key_info(thd, foreign);
+ if (pf_key_info) {
+ f_key_list->push_back(pf_key_info);
+ }
+ }
+
+ mutex_exit(&(dict_sys->mutex));
+
+ prebuilt->trx->op_info = "";
- DBUG_RETURN(0);
+ return(0);
}
/*****************************************************************//**
@@ -8646,39 +8844,30 @@ ha_innobase::start_stmt(
prepared for an update of a row */
prebuilt->select_lock_type = LOCK_X;
- } else {
- if (trx->isolation_level != TRX_ISO_SERIALIZABLE
- && thd_sql_command(thd) == SQLCOM_SELECT
- && lock_type == TL_READ) {
- /* For other than temporary tables, we obtain
- no lock for consistent read (plain SELECT). */
+ } else if (trx->isolation_level != TRX_ISO_SERIALIZABLE
+ && thd_sql_command(thd) == SQLCOM_SELECT
+ && lock_type == TL_READ) {
- prebuilt->select_lock_type = LOCK_NONE;
- } else {
- /* Not a consistent read: restore the
- select_lock_type value. The value of
- stored_select_lock_type was decided in:
- 1) ::store_lock(),
- 2) ::external_lock(),
- 3) ::init_table_handle_for_HANDLER(), and
- 4) ::transactional_table_lock(). */
+ /* For other than temporary tables, we obtain
+ no lock for consistent read (plain SELECT). */
- prebuilt->select_lock_type =
- prebuilt->stored_select_lock_type;
- }
- }
+ prebuilt->select_lock_type = LOCK_NONE;
+ } else {
+ /* Not a consistent read: restore the
+ select_lock_type value. The value of
+ stored_select_lock_type was decided in:
+ 1) ::store_lock(),
+ 2) ::external_lock(),
+ 3) ::init_table_handle_for_HANDLER(), and
+ 4) ::transactional_table_lock(). */
- trx->detailed_error[0] = '\0';
+ prebuilt->select_lock_type = prebuilt->stored_select_lock_type;
+ }
- /* Set the MySQL flag to mark that there is an active transaction */
- if (trx->active_trans == 0) {
+ *trx->detailed_error = 0;
- innobase_register_trx_and_stmt(ht, thd);
- trx->active_trans = 1;
- } else {
- innobase_register_stmt(ht, thd);
- }
+ innobase_register_trx(ht, thd, trx);
return(0);
}
@@ -8767,22 +8956,14 @@ ha_innobase::external_lock(
if (lock_type != F_UNLCK) {
/* MySQL is setting a new table lock */
- trx->detailed_error[0] = '\0';
+ *trx->detailed_error = 0;
- /* Set the MySQL flag to mark that there is an active
- transaction */
- if (trx->active_trans == 0) {
-
- innobase_register_trx_and_stmt(ht, thd);
- trx->active_trans = 1;
- } else if (trx->n_mysql_tables_in_use == 0) {
- innobase_register_stmt(ht, thd);
- }
+ innobase_register_trx(ht, thd, trx);
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
- && prebuilt->select_lock_type == LOCK_NONE
- && thd_test_options(thd,
- OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
+ && prebuilt->select_lock_type == LOCK_NONE
+ && thd_test_options(
+ thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
/* To get serializable execution, we let InnoDB
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
@@ -8852,19 +9033,20 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked = 0;
prebuilt->used_in_HANDLER = FALSE;
- if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
- if (trx->active_trans != 0) {
+ if (!thd_test_options(
+ thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
+
+ if (trx_is_started(trx)) {
innobase_commit(ht, thd, TRUE);
}
- } else {
- if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
- && trx->global_read_view) {
- /* At low transaction isolation levels we let
- each consistent read set its own snapshot */
+ } else if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ && trx->global_read_view) {
- read_view_close_for_mysql(trx);
- }
+ /* At low transaction isolation levels we let
+ each consistent read set its own snapshot */
+
+ read_view_close_for_mysql(trx);
}
}
@@ -8933,12 +9115,7 @@ ha_innobase::transactional_table_lock(
/* MySQL is setting a new transactional table lock */
- /* Set the MySQL flag to mark that there is an active transaction */
- if (trx->active_trans == 0) {
-
- innobase_register_trx_and_stmt(ht, thd);
- trx->active_trans = 1;
- }
+ innobase_register_trx(ht, thd, trx);
if (THDVAR(thd, table_locks) && thd_in_lock_tables(thd)) {
ulint error = DB_SUCCESS;
@@ -8951,7 +9128,8 @@ ha_innobase::transactional_table_lock(
DBUG_RETURN((int) error);
}
- if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
+ if (thd_test_options(
+ thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
/* Store the current undo_no of the transaction
so that we know where to roll back if we have
@@ -8989,7 +9167,7 @@ innodb_show_status(
{
trx_t* trx;
static const char truncated_msg[] = "... truncated...\n";
- const long MAX_STATUS_SIZE = 64000;
+ const long MAX_STATUS_SIZE = 1048576;
ulint trx_list_start = ULINT_UNDEFINED;
ulint trx_list_end = ULINT_UNDEFINED;
@@ -9019,6 +9197,7 @@ innodb_show_status(
if (flen > MAX_STATUS_SIZE) {
usable_len = MAX_STATUS_SIZE;
+ srv_truncated_status_writes++;
} else {
usable_len = flen;
}
@@ -9112,7 +9291,8 @@ innodb_mutex_show_status(
if (mutex->count_using > 0) {
buf1len= my_snprintf(buf1, sizeof(buf1),
"%s:%s",
- mutex->cmutex_name, mutex->cfile_name);
+ mutex->cmutex_name,
+ innobase_basename(mutex->cfile_name));
buf2len= my_snprintf(buf2, sizeof(buf2),
"count=%lu, spin_waits=%lu,"
" spin_rounds=%lu, "
@@ -9142,7 +9322,8 @@ innodb_mutex_show_status(
}
#else /* UNIV_DEBUG */
buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s:%lu",
- mutex->cfile_name, (ulong) mutex->cline);
+ innobase_basename(mutex->cfile_name),
+ (ulong) mutex->cline);
buf2len= (uint) my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
(ulong) mutex->count_os_wait);
@@ -9158,7 +9339,8 @@ innodb_mutex_show_status(
if (block_mutex) {
buf1len = (uint) my_snprintf(buf1, sizeof buf1,
"combined %s:%lu",
- block_mutex->cfile_name,
+ innobase_basename(
+ block_mutex->cfile_name),
(ulong) block_mutex->cline);
buf2len = (uint) my_snprintf(buf2, sizeof buf2,
"os_waits=%lu",
@@ -9189,7 +9371,8 @@ innodb_mutex_show_status(
}
buf1len = my_snprintf(buf1, sizeof buf1, "%s:%lu",
- lock->cfile_name, (ulong) lock->cline);
+ innobase_basename(lock->cfile_name),
+ (ulong) lock->cline);
buf2len = my_snprintf(buf2, sizeof buf2, "os_waits=%lu",
(ulong) lock->count_os_wait);
@@ -9204,7 +9387,8 @@ innodb_mutex_show_status(
if (block_lock) {
buf1len = (uint) my_snprintf(buf1, sizeof buf1,
"combined %s:%lu",
- block_lock->cfile_name,
+ innobase_basename(
+ block_lock->cfile_name),
(ulong) block_lock->cline);
buf2len = (uint) my_snprintf(buf2, sizeof buf2,
"os_waits=%lu",
@@ -9574,7 +9758,7 @@ ha_innobase::innobase_get_autoinc(
}
/*******************************************************************//**
-This function reads the global auto-inc counter. It doesn't use the
+This function reads the global auto-inc counter. It doesn't use the
AUTOINC lock even if the lock mode is set to TRADITIONAL.
@return the autoinc value */
UNIV_INTERN
@@ -9594,7 +9778,11 @@ ha_innobase::innobase_peek_autoinc(void)
auto_inc = dict_table_autoinc_read(innodb_table);
- ut_a(auto_inc > 0);
+ if (auto_inc == 0) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: AUTOINC next value generation "
+ "is disabled for '%s'\n", innodb_table->name);
+ }
dict_table_autoinc_unlock(innodb_table);
@@ -9987,19 +10175,19 @@ innobase_xa_prepare(
innobase_release_stat_resources(trx);
- if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
+ if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
- sql_print_error("trx->active_trans == 0, but trx->conc_state != "
- "TRX_NOT_STARTED");
+ sql_print_error("Transaction not registered for MySQL 2PC, "
+ "but transaction is active");
}
if (all
- || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
+ || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
/* We were instructed to prepare the whole transaction, or
this is an SQL statement end and autocommit is on */
- ut_ad(trx->active_trans);
+ ut_ad(trx_is_registered_for_2pc(trx));
error = (int) trx_prepare_for_mysql(trx);
} else {
@@ -10023,9 +10211,10 @@ innobase_xa_prepare(
srv_active_wake_master_thread();
- if (thd_sql_command(thd) != SQLCOM_XA_PREPARE &&
- (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
- {
+ if (thd_sql_command(thd) != SQLCOM_XA_PREPARE
+ && (all
+ || !thd_test_options(
+ thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
/* For ibbackup to work the order of transactions in binlog
and InnoDB must be the same. Consider the situation
@@ -10046,7 +10235,7 @@ innobase_xa_prepare(
will be between XA PREPARE and XA COMMIT, and we don't want
to block for undefined period of time. */
mysql_mutex_lock(&prepare_commit_mutex);
- trx->active_trans = 2;
+ trx_owns_prepare_commit_mutex_set(trx);
}
return(error);
@@ -10081,8 +10270,8 @@ static
int
innobase_commit_by_xid(
/*===================*/
- handlerton *hton,
- XID* xid) /*!< in: X/Open XA transaction identification */
+ handlerton* hton,
+ XID* xid) /*!< in: X/Open XA transaction identification */
{
trx_t* trx;
@@ -10092,7 +10281,7 @@ innobase_commit_by_xid(
if (trx) {
innobase_commit_low(trx);
-
+ trx_free_for_background(trx);
return(XA_OK);
} else {
return(XAER_NOTA);
@@ -10118,7 +10307,9 @@ innobase_rollback_by_xid(
trx = trx_get_trx_by_xid(xid);
if (trx) {
- return(innobase_rollback_trx(trx));
+ int ret = innobase_rollback_trx(trx);
+ trx_free_for_background(trx);
+ return(ret);
} else {
return(XAER_NOTA);
}
@@ -10751,19 +10942,19 @@ static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
return 0;
}
-/***********************************************************************
+/*********************************************************************//**
This function checks each index name for a table against reserved
-system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
-this function pushes an warning message to the client, and returns true. */
+system default primary index name 'GEN_CLUST_INDEX'. If a name
+matches, this function pushes an warning message to the client,
+and returns true.
+@return true if the index name matches the reserved name */
extern "C" UNIV_INTERN
bool
innobase_index_name_is_reserved(
/*============================*/
- /* out: true if an index name
- matches the reserved name */
- const trx_t* trx, /* in: InnoDB transaction handle */
- const KEY* key_info, /* in: Indexes to be created */
- ulint num_of_keys) /* in: Number of indexes to
+ THD* thd, /*!< in/out: MySQL connection */
+ const KEY* key_info, /*!< in: Indexes to be created */
+ ulint num_of_keys) /*!< in: Number of indexes to
be created. */
{
const KEY* key;
@@ -10775,7 +10966,7 @@ innobase_index_name_is_reserved(
if (innobase_strcasecmp(key->name,
innobase_index_reserve_name) == 0) {
/* Push warning to mysql */
- push_warning_printf((THD*) trx->mysql_thd,
+ push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WRONG_NAME_FOR_INDEX,
"Cannot Create Index with name "
@@ -10827,16 +11018,23 @@ static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
static MYSQL_SYSVAR_ULONG(purge_batch_size, srv_purge_batch_size,
PLUGIN_VAR_OPCMDARG,
- "Number of UNDO logs to purge in one batch from the history list. "
- "Default is 20",
+ "Number of UNDO log pages to purge in one batch from the history list.",
NULL, NULL,
20, /* Default setting */
1, /* Minimum value */
5000, 0); /* Maximum value */
+static MYSQL_SYSVAR_ULONG(rollback_segments, srv_rollback_segments,
+ PLUGIN_VAR_OPCMDARG,
+ "Number of UNDO logs to use.",
+ NULL, NULL,
+ 128, /* Default setting */
+ 1, /* Minimum value */
+ TRX_SYS_N_RSEGS, 0); /* Maximum value */
+
static MYSQL_SYSVAR_ULONG(purge_threads, srv_n_purge_threads,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
- "Purge threads can be either 0 or 1. Default is 0.",
+ "Purge threads can be either 0 or 1.",
NULL, NULL,
0, /* Default setting */
0, /* Minimum value */
@@ -10851,13 +11049,13 @@ static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
static MYSQL_SYSVAR_BOOL(file_per_table, srv_file_per_table,
PLUGIN_VAR_NOCMDARG,
"Stores each InnoDB table to an .ibd file in the database dir.",
- NULL, NULL, TRUE);
+ NULL, NULL, FALSE);
static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name,
PLUGIN_VAR_RQCMDARG,
"File format to use for new tables in .ibd files.",
innodb_file_format_name_validate,
- innodb_file_format_name_update, "Barracuda");
+ innodb_file_format_name_update, "Antelope");
/* "innobase_file_format_check" decides whether we would continue
booting the server if the file format stamped on the system
@@ -10891,6 +11089,11 @@ static MYSQL_SYSVAR_STR(flush_method, innobase_file_flush_method,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"With which method to flush data.", NULL, NULL, NULL);
+static MYSQL_SYSVAR_BOOL(large_prefix, innobase_large_prefix,
+ PLUGIN_VAR_NOCMDARG,
+ "Support large index prefix length of REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes.",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Force InnoDB to not use next-key locking, to use only row-level locking.",
@@ -11102,6 +11305,20 @@ static MYSQL_SYSVAR_STR(change_buffering, innobase_change_buffering,
innodb_change_buffering_validate,
innodb_change_buffering_update, "all");
+static MYSQL_SYSVAR_ENUM(stats_method, srv_innodb_stats_method,
+ PLUGIN_VAR_RQCMDARG,
+ "Specifies how InnoDB index statistics collection code should "
+ "treat NULLs. Possible values are NULLS_EQUAL (default), "
+ "NULLS_UNEQUAL and NULLS_IGNORED",
+ NULL, NULL, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib);
+
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
+ PLUGIN_VAR_RQCMDARG,
+ "Debug flags for InnoDB change buffering (0=none)",
+ NULL, NULL, 0, 0, 1, 0);
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
PLUGIN_VAR_RQCMDARG,
"Number of pages that must be accessed sequentially for InnoDB to "
@@ -11130,6 +11347,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(flush_log_at_trx_commit),
MYSQL_SYSVAR(flush_method),
MYSQL_SYSVAR(force_recovery),
+ MYSQL_SYSVAR(large_prefix),
MYSQL_SYSVAR(locks_unsafe_for_binlog),
MYSQL_SYSVAR(lock_wait_timeout),
#ifdef UNIV_LOG_ARCHIVE
@@ -11151,6 +11369,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(stats_on_metadata),
MYSQL_SYSVAR(stats_sample_pages),
MYSQL_SYSVAR(adaptive_hash_index),
+ MYSQL_SYSVAR(stats_method),
MYSQL_SYSVAR(replication_delay),
MYSQL_SYSVAR(status_file),
MYSQL_SYSVAR(strict_mode),
@@ -11165,10 +11384,14 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(use_sys_malloc),
MYSQL_SYSVAR(use_native_aio),
MYSQL_SYSVAR(change_buffering),
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+ MYSQL_SYSVAR(change_buffering_debug),
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
MYSQL_SYSVAR(read_ahead_threshold),
MYSQL_SYSVAR(io_capacity),
MYSQL_SYSVAR(purge_threads),
MYSQL_SYSVAR(purge_batch_size),
+ MYSQL_SYSVAR(rollback_segments),
NULL
};
@@ -11177,7 +11400,7 @@ mysql_declare_plugin(innobase)
MYSQL_STORAGE_ENGINE_PLUGIN,
&innobase_storage_engine,
innobase_hton_name,
- "Innobase Oy",
+ plugin_author,
"Supports transactions, row-level locking, and foreign keys",
PLUGIN_LICENSE_GPL,
innobase_init, /* Plugin Init */
@@ -11193,15 +11416,7 @@ i_s_innodb_lock_waits,
i_s_innodb_cmp,
i_s_innodb_cmp_reset,
i_s_innodb_cmpmem,
-i_s_innodb_cmpmem_reset,
-i_s_innodb_sys_tables,
-i_s_innodb_sys_tablestats,
-i_s_innodb_sys_indexes,
-i_s_innodb_sys_columns,
-i_s_innodb_sys_fields,
-i_s_innodb_sys_foreign,
-i_s_innodb_sys_foreign_cols
-
+i_s_innodb_cmpmem_reset
mysql_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 8f118199ad8..7ab91a12e81 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -109,6 +109,7 @@ class ha_innobase: public handler
ulint innobase_update_autoinc(ulonglong auto_inc);
void innobase_initialize_autoinc();
dict_index_t* innobase_get_index(uint keynr);
+ int info_low(uint flag, bool called_from_analyze);
/* Init values for the class: */
public:
@@ -178,13 +179,15 @@ class ha_innobase: public handler
void update_create_info(HA_CREATE_INFO* create_info);
int create(const char *name, register TABLE *form,
HA_CREATE_INFO *create_info);
- int delete_all_rows();
+ int truncate();
int delete_table(const char *name);
int rename_table(const char* from, const char* to);
int check(THD* thd, HA_CHECK_OPT* check_opt);
char* update_table_comment(const char* comment);
char* get_foreign_key_create_info();
int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
+ int get_parent_foreign_key_list(THD *thd,
+ List<FOREIGN_KEY_INFO> *f_key_list);
bool can_switch_engines();
uint referenced_by_foreign_key();
void free_foreign_key_create_info(char* str);
@@ -212,7 +215,9 @@ class ha_innobase: public handler
bool primary_key_is_clustered();
int cmp_ref(const uchar *ref1, const uchar *ref2);
/** Fast index creation (smart ALTER TABLE) @see handler0alter.cc @{ */
- int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys);
+ int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
+ handler_add_index **add);
+ int final_add_index(handler_add_index *add, bool commit);
int prepare_drop_index(TABLE *table_arg, uint *key_num,
uint num_of_keys);
int final_drop_index(TABLE *table_arg);
@@ -273,14 +278,13 @@ int thd_binlog_format(const MYSQL_THD thd);
*/
void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all);
-#if MYSQL_VERSION_ID > 50140
/**
Check if binary logging is filtered for thread's current db.
@param thd Thread handle
@retval 1 the query is not filtered, 0 otherwise.
*/
bool thd_binlog_filter_ok(const MYSQL_THD thd);
-#endif /* MYSQL_VERSION_ID > 50140 */
+
/**
Check if the query may generate row changes which
may end up in the binary.
@@ -319,15 +323,14 @@ innobase_trx_allocate(
This function checks each index name for a table against reserved
system default primary index name 'GEN_CLUST_INDEX'. If a name
matches, this function pushes an warning message to the client,
-and returns true. */
+and returns true.
+@return true if the index name matches the reserved name */
extern "C"
bool
innobase_index_name_is_reserved(
/*============================*/
- /* out: true if the index name
- matches the reserved name */
- const trx_t* trx, /* in: InnoDB transaction handle */
- const KEY* key_info, /* in: Indexes to be created */
- ulint num_of_keys); /* in: Number of indexes to
+ THD* thd, /*!< in/out: MySQL connection */
+ const KEY* key_info, /*!< in: Indexes to be created */
+ ulint num_of_keys); /*!< in: Number of indexes to
be created. */
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 3744d16570c..6d5b7b4668f 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -539,7 +539,7 @@ innobase_create_key_def(
if (!new_primary && (key_info->flags & HA_NOSAME)
&& (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
&& row_table_got_default_clust_index(table)) {
- uint key_part = key_info->key_parts;
+ uint key_part = key_info->key_parts;
new_primary = TRUE;
@@ -595,6 +595,27 @@ innobase_create_key_def(
}
/*******************************************************************//**
+Check each index column size, make sure they do not exceed the max limit
+@return HA_ERR_INDEX_COL_TOO_LONG if index column size exceeds limit */
+static
+int
+innobase_check_column_length(
+/*=========================*/
+ const dict_table_t*table, /*!< in: table definition */
+ const KEY* key_info) /*!< in: Indexes to be created */
+{
+ ulint max_col_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+
+ for (ulint key_part = 0; key_part < key_info->key_parts; key_part++) {
+ if (key_info->key_part[key_part].length > max_col_len) {
+ my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0), max_col_len);
+ return(HA_ERR_INDEX_COL_TOO_LONG);
+ }
+ }
+ return(0);
+}
+
+/*******************************************************************//**
Create a temporary tablename using query id, thread id, and id
@return temporary tablename */
static
@@ -619,6 +640,18 @@ innobase_create_temporary_tablename(
return(name);
}
+class ha_innobase_add_index : public handler_add_index
+{
+public:
+ /** table where the indexes are being created */
+ dict_table_t* indexed_table;
+ ha_innobase_add_index(TABLE* table, KEY* key_info, uint num_of_keys,
+ dict_table_t* indexed_table_arg) :
+ handler_add_index(table, key_info, num_of_keys),
+ indexed_table (indexed_table_arg) {}
+ ~ha_innobase_add_index() {}
+};
+
/*******************************************************************//**
Create indexes.
@return 0 or error number */
@@ -626,12 +659,15 @@ UNIV_INTERN
int
ha_innobase::add_index(
/*===================*/
- TABLE* table, /*!< in: Table where indexes are created */
- KEY* key_info, /*!< in: Indexes to be created */
- uint num_of_keys) /*!< in: Number of indexes to be created */
+ TABLE* table, /*!< in: Table where indexes
+ are created */
+ KEY* key_info, /*!< in: Indexes
+ to be created */
+ uint num_of_keys, /*!< in: Number of indexes
+ to be created */
+ handler_add_index** add) /*!< out: context */
{
dict_index_t** index; /*!< Index to be created */
- dict_table_t* innodb_table; /*!< InnoDB table in dictionary */
dict_table_t* indexed_table; /*!< Table where indexes are created */
merge_index_def_t* index_defs; /*!< Index definitions */
mem_heap_t* heap; /*!< Heap for index definitions */
@@ -647,50 +683,57 @@ ha_innobase::add_index(
ut_a(key_info);
ut_a(num_of_keys);
+ *add = NULL;
+
if (srv_created_new_raw || srv_force_recovery) {
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
update_thd();
- heap = mem_heap_create(1024);
-
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads. */
trx_search_latch_release_if_reserved(prebuilt->trx);
- trx_start_if_not_started(prebuilt->trx);
- /* Create a background transaction for the operations on
- the data dictionary tables. */
- trx = innobase_trx_allocate(user_thd);
- trx_start_if_not_started(trx);
+ /* Check if the index name is reserved. */
+ if (innobase_index_name_is_reserved(user_thd, key_info, num_of_keys)) {
+ DBUG_RETURN(-1);
+ }
- innodb_table = indexed_table
- = dict_table_get(prebuilt->table->name, FALSE);
+ indexed_table = dict_table_get(prebuilt->table->name, FALSE);
- if (UNIV_UNLIKELY(!innodb_table)) {
- error = HA_ERR_NO_SUCH_TABLE;
- goto err_exit;
+ if (UNIV_UNLIKELY(!indexed_table)) {
+ DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
- /* Check if the index name is reserved. */
- if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
- error = -1;
- } else {
- /* Check that index keys are sensible */
- error = innobase_check_index_keys(key_info, num_of_keys,
- innodb_table);
- }
+ ut_a(indexed_table == prebuilt->table);
+
+ /* Check that index keys are sensible */
+ error = innobase_check_index_keys(key_info, num_of_keys, prebuilt->table);
if (UNIV_UNLIKELY(error)) {
-err_exit:
- mem_heap_free(heap);
- trx_general_rollback_for_mysql(trx, NULL);
- trx_free_for_mysql(trx);
- trx_commit_for_mysql(prebuilt->trx);
DBUG_RETURN(error);
}
+ /* Check each index's column length to make sure they do not
+ exceed limit */
+ for (ulint i = 0; i < num_of_keys; i++) {
+ error = innobase_check_column_length(prebuilt->table,
+ &key_info[i]);
+
+ if (error) {
+ DBUG_RETURN(error);
+ }
+ }
+
+ heap = mem_heap_create(1024);
+ trx_start_if_not_started(prebuilt->trx);
+
+ /* Create a background transaction for the operations on
+ the data dictionary tables. */
+ trx = innobase_trx_allocate(user_thd);
+ trx_start_if_not_started(trx);
+
/* Create table containing all indexes to be built in this
alter table add index so that they are in the correct order
in the table. */
@@ -698,7 +741,7 @@ err_exit:
num_of_idx = num_of_keys;
index_defs = innobase_create_key_def(
- trx, innodb_table, heap, key_info, num_of_idx);
+ trx, prebuilt->table, heap, key_info, num_of_idx);
new_primary = DICT_CLUSTERED & index_defs[0].ind_type;
@@ -712,7 +755,7 @@ err_exit:
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
/* Acquire a lock on the table before creating any indexes. */
- error = row_merge_lock_table(prebuilt->trx, innodb_table,
+ error = row_merge_lock_table(prebuilt->trx, prebuilt->table,
new_primary ? LOCK_X : LOCK_S);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
@@ -726,7 +769,7 @@ err_exit:
row_mysql_lock_data_dictionary(trx);
dict_locked = TRUE;
- ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
+ ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
/* If a new primary key is defined for the table we need
to drop the original table and rebuild all indexes. */
@@ -734,15 +777,15 @@ err_exit:
if (UNIV_UNLIKELY(new_primary)) {
/* This transaction should be the only one
operating on the table. */
- ut_a(innodb_table->n_mysql_handles_opened == 1);
+ ut_a(prebuilt->table->n_mysql_handles_opened == 1);
char* new_table_name = innobase_create_temporary_tablename(
- heap, '1', innodb_table->name);
+ heap, '1', prebuilt->table->name);
/* Clone the table. */
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
indexed_table = row_merge_create_temporary_table(
- new_table_name, index_defs, innodb_table, trx);
+ new_table_name, index_defs, prebuilt->table, trx);
if (!indexed_table) {
@@ -756,14 +799,19 @@ err_exit:
break;
default:
error = convert_error_code_to_mysql(
- trx->error_state, innodb_table->flags,
+ trx->error_state,
+ prebuilt->table->flags,
user_thd);
}
- ut_d(dict_table_check_for_dup_indexes(innodb_table,
+ ut_d(dict_table_check_for_dup_indexes(prebuilt->table,
FALSE));
+ mem_heap_free(heap);
+ trx_general_rollback_for_mysql(trx, NULL);
row_mysql_unlock_data_dictionary(trx);
- goto err_exit;
+ trx_free_for_mysql(trx);
+ trx_commit_for_mysql(prebuilt->trx);
+ DBUG_RETURN(error);
}
trx->table_id = indexed_table->id;
@@ -771,25 +819,19 @@ err_exit:
/* Create the indexes in SYS_INDEXES and load into dictionary. */
- for (ulint i = 0; i < num_of_idx; i++) {
+ for (num_created = 0; num_created < num_of_idx; num_created++) {
- index[i] = row_merge_create_index(trx, indexed_table,
- &index_defs[i]);
+ index[num_created] = row_merge_create_index(
+ trx, indexed_table, &index_defs[num_created]);
- if (!index[i]) {
+ if (!index[num_created]) {
error = trx->error_state;
goto error_handling;
}
-
- num_created++;
}
ut_ad(error == DB_SUCCESS);
- /* We will need to rebuild index translation table. Set
- valid index entry count in the translation table to zero */
- share->idx_trans_tbl.index_count = 0;
-
/* Commit the data dictionary transaction in order to release
the table locks on the system tables. This means that if
MySQL crashes while creating a new primary key inside
@@ -807,7 +849,7 @@ err_exit:
if (UNIV_UNLIKELY(new_primary)) {
/* A primary key is to be built. Acquire an exclusive
table lock also on the table that is being created. */
- ut_ad(indexed_table != innodb_table);
+ ut_ad(indexed_table != prebuilt->table);
error = row_merge_lock_table(prebuilt->trx, indexed_table,
LOCK_X);
@@ -821,7 +863,7 @@ err_exit:
/* Read the clustered index of the table and build indexes
based on this information using temporary files and merge sort. */
error = row_merge_build_indexes(prebuilt->trx,
- innodb_table, indexed_table,
+ prebuilt->table, indexed_table,
index, num_of_idx, table);
error_handling:
@@ -829,63 +871,15 @@ error_handling:
dictionary which were defined. */
switch (error) {
- const char* old_name;
- char* tmp_name;
case DB_SUCCESS:
ut_a(!dict_locked);
- row_mysql_lock_data_dictionary(trx);
- dict_locked = TRUE;
+ ut_d(mutex_enter(&dict_sys->mutex));
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
-
- if (!new_primary) {
- error = row_merge_rename_indexes(trx, indexed_table);
-
- if (error != DB_SUCCESS) {
- row_merge_drop_indexes(trx, indexed_table,
- index, num_created);
- }
-
- goto convert_error;
- }
-
- /* If a new primary key was defined for the table and
- there was no error at this point, we can now rename
- the old table as a temporary table, rename the new
- temporary table as the old table and drop the old table. */
- old_name = innodb_table->name;
- tmp_name = innobase_create_temporary_tablename(heap, '2',
- old_name);
-
- error = row_merge_rename_tables(innodb_table, indexed_table,
- tmp_name, trx);
-
- if (error != DB_SUCCESS) {
-
- row_merge_drop_table(trx, indexed_table);
-
- switch (error) {
- case DB_TABLESPACE_ALREADY_EXISTS:
- case DB_DUPLICATE_KEY:
- innobase_convert_tablename(tmp_name);
- my_error(HA_ERR_TABLE_EXIST, MYF(0), tmp_name);
- error = HA_ERR_TABLE_EXIST;
- break;
- default:
- goto convert_error;
- }
- break;
- }
-
- trx_commit_for_mysql(prebuilt->trx);
- row_prebuilt_free(prebuilt, TRUE);
- prebuilt = row_create_prebuilt(indexed_table);
-
- indexed_table->n_mysql_handles_opened++;
-
- error = row_merge_drop_table(trx, innodb_table);
- innodb_table = indexed_table;
- goto convert_error;
+ ut_d(mutex_exit(&dict_sys->mutex));
+ *add = new ha_innobase_add_index(table, key_info, num_of_keys,
+ indexed_table);
+ break;
case DB_TOO_BIG_RECORD:
my_error(HA_ERR_TO_BIG_ROW, MYF(0));
@@ -901,7 +895,7 @@ error:
trx->error_state = DB_SUCCESS;
if (new_primary) {
- if (indexed_table != innodb_table) {
+ if (indexed_table != prebuilt->table) {
row_merge_drop_table(trx, indexed_table);
}
} else {
@@ -913,30 +907,161 @@ error:
row_merge_drop_indexes(trx, indexed_table,
index, num_created);
}
-
-convert_error:
- error = convert_error_code_to_mysql(error,
- innodb_table->flags,
- user_thd);
}
- mem_heap_free(heap);
trx_commit_for_mysql(trx);
if (prebuilt->trx) {
trx_commit_for_mysql(prebuilt->trx);
}
if (dict_locked) {
- ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
row_mysql_unlock_data_dictionary(trx);
}
trx_free_for_mysql(trx);
+ mem_heap_free(heap);
/* There might be work for utility threads.*/
srv_active_wake_master_thread();
- DBUG_RETURN(error);
+ DBUG_RETURN(convert_error_code_to_mysql(error, prebuilt->table->flags,
+ user_thd));
+}
+
+/*******************************************************************//**
+Finalize or undo add_index().
+@return 0 or error number */
+UNIV_INTERN
+int
+ha_innobase::final_add_index(
+/*=========================*/
+ handler_add_index* add_arg,/*!< in: context from add_index() */
+ bool commit) /*!< in: true=commit, false=rollback */
+{
+ ha_innobase_add_index* add;
+ trx_t* trx;
+ int err = 0;
+
+ DBUG_ENTER("ha_innobase::final_add_index");
+
+ ut_ad(add_arg);
+ add = static_cast<class ha_innobase_add_index*>(add_arg);
+
+ /* Create a background transaction for the operations on
+ the data dictionary tables. */
+ trx = innobase_trx_allocate(user_thd);
+ trx_start_if_not_started(trx);
+
+ /* Flag this transaction as a dictionary operation, so that
+ the data dictionary will be locked in crash recovery. */
+ trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
+
+ /* Latch the InnoDB data dictionary exclusively so that no deadlocks
+ or lock waits can happen in it during an index create operation. */
+ row_mysql_lock_data_dictionary(trx);
+
+ if (add->indexed_table != prebuilt->table) {
+ ulint error;
+
+ /* We copied the table (new_primary). */
+ if (commit) {
+ mem_heap_t* heap;
+ char* tmp_name;
+
+ heap = mem_heap_create(1024);
+
+ /* A new primary key was defined for the table
+ and there was no error at this point. We can
+ now rename the old table as a temporary table,
+ rename the new temporary table as the old
+ table and drop the old table. */
+ tmp_name = innobase_create_temporary_tablename(
+ heap, '2', prebuilt->table->name);
+
+ error = row_merge_rename_tables(
+ prebuilt->table, add->indexed_table,
+ tmp_name, trx);
+
+ switch (error) {
+ case DB_TABLESPACE_ALREADY_EXISTS:
+ case DB_DUPLICATE_KEY:
+ innobase_convert_tablename(tmp_name);
+ my_error(HA_ERR_TABLE_EXIST, MYF(0), tmp_name);
+ err = HA_ERR_TABLE_EXIST;
+ break;
+ default:
+ err = convert_error_code_to_mysql(
+ error, prebuilt->table->flags,
+ user_thd);
+ break;
+ }
+
+ mem_heap_free(heap);
+ }
+
+ if (!commit || err) {
+ error = row_merge_drop_table(trx, add->indexed_table);
+ trx_commit_for_mysql(prebuilt->trx);
+ } else {
+ dict_table_t* old_table = prebuilt->table;
+ trx_commit_for_mysql(prebuilt->trx);
+ row_prebuilt_free(prebuilt, TRUE);
+ error = row_merge_drop_table(trx, old_table);
+ add->indexed_table->n_mysql_handles_opened++;
+ prebuilt = row_create_prebuilt(add->indexed_table);
+ }
+
+ err = convert_error_code_to_mysql(
+ error, prebuilt->table->flags, user_thd);
+ } else {
+ /* We created secondary indexes (!new_primary). */
+
+ if (commit) {
+ err = convert_error_code_to_mysql(
+ row_merge_rename_indexes(trx, prebuilt->table),
+ prebuilt->table->flags, user_thd);
+ }
+
+ if (!commit || err) {
+ dict_index_t* index;
+ dict_index_t* next_index;
+
+ for (index = dict_table_get_first_index(
+ prebuilt->table);
+ index; index = next_index) {
+
+ next_index = dict_table_get_next_index(index);
+
+ if (*index->name == TEMP_INDEX_PREFIX) {
+ row_merge_drop_index(
+ index, prebuilt->table, trx);
+ }
+ }
+ }
+ }
+
+ /* If index is successfully built, we will need to rebuild index
+ translation table. Set valid index entry count in the translation
+ table to zero. */
+ if (err == 0 && commit) {
+ share->idx_trans_tbl.index_count = 0;
+ }
+
+ trx_commit_for_mysql(trx);
+ if (prebuilt->trx) {
+ trx_commit_for_mysql(prebuilt->trx);
+ }
+
+ ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
+ row_mysql_unlock_data_dictionary(trx);
+
+ trx_free_for_mysql(trx);
+
+ /* There might be work for utility threads.*/
+ srv_active_wake_master_thread();
+
+ delete add;
+ DBUG_RETURN(err);
}
/*******************************************************************//**
@@ -1016,12 +1141,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/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index cd84b78bd9d..de5cc682078 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -36,11 +36,9 @@ Created July 18, 2007 Vasil Dimov
#include <mysql/innodb_priv.h>
extern "C" {
-#include "btr0pcur.h" /* for file sys_tables related info. */
#include "btr0types.h"
#include "buf0buddy.h" /* for i_s_cmpmem */
#include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
-#include "dict0load.h" /* for file sys_tables related info. */
#include "dict0mem.h"
#include "dict0types.h"
#include "ha_prototypes.h" /* for innobase_convert_name() */
@@ -49,8 +47,6 @@ extern "C" {
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
}
-static const char plugin_author[] = "Innobase Oy";
-
#define OK(expr) \
if ((expr) != 0) { \
DBUG_RETURN(1); \
@@ -497,8 +493,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();
+ }
/* trx_operation_state */
OK(field_store_string(fields[IDX_TRX_OPERATION_STATE],
@@ -761,16 +765,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];
@@ -1062,7 +1057,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, "Innobase Oy"),
+ STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -1784,1629 +1779,3 @@ i_s_common_deinit(
DBUG_RETURN(0);
}
-
-/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLES */
-static ST_FIELD_INFO innodb_sys_tables_fields_info[] =
-{
-#define SYS_TABLE_ID 0
- {STRUCT_FLD(field_name, "TABLE_ID"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLE_NAME 1
- {STRUCT_FLD(field_name, "NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLE_FLAG 2
- {STRUCT_FLD(field_name, "FLAG"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLE_NUM_COLUMN 3
- {STRUCT_FLD(field_name, "N_COLS"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLE_SPACE 4
- {STRUCT_FLD(field_name, "SPACE"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
- END_OF_ST_FIELD_INFO
-};
-
-/**********************************************************************//**
-Populate information_schema.innodb_sys_tables table with information
-from SYS_TABLES.
-@return 0 on success */
-static
-int
-i_s_dict_fill_sys_tables(
-/*=====================*/
- THD* thd, /*!< in: thread */
- dict_table_t* table, /*!< in: table */
- TABLE* table_to_fill) /*!< in/out: fill this table */
-{
- Field** fields;
-
- DBUG_ENTER("i_s_dict_fill_sys_tables");
-
- fields = table_to_fill->field;
-
- OK(fields[SYS_TABLE_ID]->store(longlong(table->id), TRUE));
-
- OK(field_store_string(fields[SYS_TABLE_NAME], table->name));
-
- OK(fields[SYS_TABLE_FLAG]->store(table->flags));
-
- OK(fields[SYS_TABLE_NUM_COLUMN]->store(table->n_cols));
-
- OK(fields[SYS_TABLE_SPACE]->store(table->space));
-
- OK(schema_table_store_record(thd, table_to_fill));
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Function to go through each record in SYS_TABLES table, and fill the
-information_schema.innodb_sys_tables table with related table information
-@return 0 on success */
-static
-int
-i_s_sys_tables_fill_table(
-/*======================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- mem_heap_t* heap;
- mtr_t mtr;
-
- DBUG_ENTER("i_s_sys_tables_fill_table");
-
- /* deny access to non-superusers */
- if (check_global_access(thd, PROCESS_ACL)) {
-
- DBUG_RETURN(0);
- }
-
- heap = mem_heap_create(1000);
- mutex_enter(&(dict_sys->mutex));
- mtr_start(&mtr);
-
- rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
-
- while (rec) {
- const char* err_msg;
- dict_table_t* table_rec;
-
- /* Create and populate a dict_table_t structure with
- information from SYS_TABLES row */
- err_msg = dict_process_sys_tables_rec(
- heap, rec, &table_rec, DICT_TABLE_LOAD_FROM_RECORD);
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
-
- if (!err_msg) {
- i_s_dict_fill_sys_tables(thd, table_rec, tables->table);
- } else {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_FIND_SYSTEM_REC,
- err_msg);
- }
-
- /* Since dict_process_sys_tables_rec() is called with
- DICT_TABLE_LOAD_FROM_RECORD, the table_rec is created in
- dict_process_sys_tables_rec(), we will need to free it */
- if (table_rec) {
- dict_mem_table_free(table_rec);
- }
-
- mem_heap_empty(heap);
-
- /* Get the next record */
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
- rec = dict_getnext_system(&pcur, &mtr);
- }
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- mem_heap_free(heap);
-
- DBUG_RETURN(0);
-}
-
-/*******************************************************************//**
-Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tables
-@return 0 on success */
-static
-int
-innodb_sys_tables_init(
-/*===================*/
- void* p) /*!< in/out: table schema object */
-{
- ST_SCHEMA_TABLE* schema;
-
- DBUG_ENTER("innodb_sys_tables_init");
-
- schema = (ST_SCHEMA_TABLE*) p;
-
- schema->fields_info = innodb_sys_tables_fields_info;
- schema->fill_table = i_s_sys_tables_fill_table;
-
- DBUG_RETURN(0);
-}
-
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables =
-{
- /* the plugin type (a MYSQL_XXX_PLUGIN value) */
- /* int */
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-
- /* pointer to type-specific plugin descriptor */
- /* void* */
- STRUCT_FLD(info, &i_s_info),
-
- /* plugin name */
- /* const char* */
- STRUCT_FLD(name, "INNODB_SYS_TABLES"),
-
- /* plugin author (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(author, plugin_author),
-
- /* general descriptive text (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(descr, "InnoDB SYS_TABLES"),
-
- /* the plugin license (PLUGIN_LICENSE_XXX) */
- /* int */
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-
- /* the function to invoke when plugin is loaded */
- /* int (*)(void*); */
- STRUCT_FLD(init, innodb_sys_tables_init),
-
- /* the function to invoke when plugin is unloaded */
- /* int (*)(void*); */
- STRUCT_FLD(deinit, i_s_common_deinit),
-
- /* plugin version (for SHOW PLUGINS) */
- /* unsigned int */
- STRUCT_FLD(version, INNODB_VERSION_SHORT),
-
- /* struct st_mysql_show_var* */
- STRUCT_FLD(status_vars, NULL),
-
- /* struct st_mysql_sys_var** */
- STRUCT_FLD(system_vars, NULL),
-
- /* reserved for dependency checking */
- /* void* */
- STRUCT_FLD(__reserved1, NULL)
-};
-
-/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLESTATS */
-static ST_FIELD_INFO innodb_sys_tablestats_fields_info[] =
-{
-#define SYS_TABLESTATS_ID 0
- {STRUCT_FLD(field_name, "TABLE_ID"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLESTATS_NAME 1
- {STRUCT_FLD(field_name, "NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLESTATS_INIT 2
- {STRUCT_FLD(field_name, "STATS_INITIALIZED"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLESTATS_NROW 3
- {STRUCT_FLD(field_name, "NUM_ROWS"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLESTATS_CLUST_SIZE 4
- {STRUCT_FLD(field_name, "CLUST_INDEX_SIZE"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLESTATS_INDEX_SIZE 5
- {STRUCT_FLD(field_name, "OTHER_INDEX_SIZE"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLESTATS_MODIFIED 6
- {STRUCT_FLD(field_name, "MODIFIED_COUNTER"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLESTATS_AUTONINC 7
- {STRUCT_FLD(field_name, "AUTOINC"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_TABLESTATS_MYSQL_OPEN_HANDLE 8
- {STRUCT_FLD(field_name, "MYSQL_HANDLES_OPENED"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
- END_OF_ST_FIELD_INFO
-};
-
-/**********************************************************************//**
-Populate information_schema.innodb_sys_tablestats table with information
-from SYS_TABLES.
-@return 0 on success */
-static
-int
-i_s_dict_fill_sys_tablestats(
-/*=========================*/
- THD* thd, /*!< in: thread */
- dict_table_t* table, /*!< in: table */
- TABLE* table_to_fill) /*!< in/out: fill this table */
-{
- Field** fields;
-
- DBUG_ENTER("i_s_dict_fill_sys_tablestats");
-
- fields = table_to_fill->field;
-
- OK(fields[SYS_TABLESTATS_ID]->store(longlong(table->id), TRUE));
-
- OK(field_store_string(fields[SYS_TABLESTATS_NAME], table->name));
-
- if (table->stat_initialized) {
- OK(field_store_string(fields[SYS_TABLESTATS_INIT],
- "Initialized"));
- } else {
- OK(field_store_string(fields[SYS_TABLESTATS_INIT],
- "Uninitialized"));
- }
-
- OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows, TRUE));
-
- OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
- table->stat_clustered_index_size));
-
- OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
- table->stat_sum_of_other_index_sizes));
-
- OK(fields[SYS_TABLESTATS_MODIFIED]->store(
- table->stat_modified_counter));
-
- OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, TRUE));
-
- OK(fields[SYS_TABLESTATS_MYSQL_OPEN_HANDLE]->store(
- table->n_mysql_handles_opened));
-
- OK(schema_table_store_record(thd, table_to_fill));
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Function to go through each record in SYS_TABLES table, and fill the
-information_schema.innodb_sys_tablestats table with table statistics
-related information
-@return 0 on success */
-static
-int
-i_s_sys_tables_fill_table_stats(
-/*============================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- mem_heap_t* heap;
- mtr_t mtr;
-
- DBUG_ENTER("i_s_sys_tables_fill_table_stats");
-
- /* deny access to non-superusers */
- if (check_global_access(thd, PROCESS_ACL)) {
-
- DBUG_RETURN(0);
- }
-
- heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
-
- rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
-
- while (rec) {
- const char* err_msg;
- dict_table_t* table_rec;
-
- /* Fetch the dict_table_t structure corresponding to
- this SYS_TABLES record */
- err_msg = dict_process_sys_tables_rec(
- heap, rec, &table_rec, DICT_TABLE_LOAD_FROM_CACHE);
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
-
- if (!err_msg) {
- i_s_dict_fill_sys_tablestats(thd, table_rec,
- tables->table);
- } else {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_FIND_SYSTEM_REC,
- err_msg);
- }
-
- mem_heap_empty(heap);
-
- /* Get the next record */
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
- rec = dict_getnext_system(&pcur, &mtr);
- }
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- mem_heap_free(heap);
-
- DBUG_RETURN(0);
-}
-
-/*******************************************************************//**
-Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tablestats
-@return 0 on success */
-static
-int
-innodb_sys_tablestats_init(
-/*=======================*/
- void* p) /*!< in/out: table schema object */
-{
- ST_SCHEMA_TABLE* schema;
-
- DBUG_ENTER("innodb_sys_tablestats_init");
-
- schema = (ST_SCHEMA_TABLE*) p;
-
- schema->fields_info = innodb_sys_tablestats_fields_info;
- schema->fill_table = i_s_sys_tables_fill_table_stats;
-
- DBUG_RETURN(0);
-}
-
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablestats =
-{
- /* the plugin type (a MYSQL_XXX_PLUGIN value) */
- /* int */
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-
- /* pointer to type-specific plugin descriptor */
- /* void* */
- STRUCT_FLD(info, &i_s_info),
-
- /* plugin name */
- /* const char* */
- STRUCT_FLD(name, "INNODB_SYS_TABLESTATS"),
-
- /* plugin author (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(author, plugin_author),
-
- /* general descriptive text (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(descr, "InnoDB SYS_TABLESTATS"),
-
- /* the plugin license (PLUGIN_LICENSE_XXX) */
- /* int */
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-
- /* the function to invoke when plugin is loaded */
- /* int (*)(void*); */
- STRUCT_FLD(init, innodb_sys_tablestats_init),
-
- /* the function to invoke when plugin is unloaded */
- /* int (*)(void*); */
- STRUCT_FLD(deinit, i_s_common_deinit),
-
- /* plugin version (for SHOW PLUGINS) */
- /* unsigned int */
- STRUCT_FLD(version, INNODB_VERSION_SHORT),
-
- /* struct st_mysql_show_var* */
- STRUCT_FLD(status_vars, NULL),
-
- /* struct st_mysql_sys_var** */
- STRUCT_FLD(system_vars, NULL),
-
- /* reserved for dependency checking */
- /* void* */
- STRUCT_FLD(__reserved1, NULL)
-};
-
-/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_INDEXES */
-static ST_FIELD_INFO innodb_sysindex_fields_info[] =
-{
-#define SYS_INDEX_ID 0
- {STRUCT_FLD(field_name, "INDEX_ID"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_INDEX_NAME 1
- {STRUCT_FLD(field_name, "NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_INDEX_TABLE_ID 2
- {STRUCT_FLD(field_name, "TABLE_ID"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_INDEX_TYPE 3
- {STRUCT_FLD(field_name, "TYPE"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_INDEX_NUM_FIELDS 4
- {STRUCT_FLD(field_name, "N_FIELDS"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_INDEX_PAGE_NO 5
- {STRUCT_FLD(field_name, "PAGE_NO"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_INDEX_SPACE 6
- {STRUCT_FLD(field_name, "SPACE"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
- END_OF_ST_FIELD_INFO
-};
-
-/**********************************************************************//**
-Function to populate the information_schema.innodb_sys_indexes table with
-collected index information
-@return 0 on success */
-static
-int
-i_s_dict_fill_sys_indexes(
-/*======================*/
- THD* thd, /*!< in: thread */
- table_id_t table_id, /*!< in: table id */
- dict_index_t* index, /*!< in: populated dict_index_t
- struct with index info */
- TABLE* table_to_fill) /*!< in/out: fill this table */
-{
- Field** fields;
-
- DBUG_ENTER("i_s_dict_fill_sys_indexes");
-
- fields = table_to_fill->field;
-
- OK(fields[SYS_INDEX_ID]->store(longlong(index->id), TRUE));
-
- OK(field_store_string(fields[SYS_INDEX_NAME], index->name));
-
- OK(fields[SYS_INDEX_TABLE_ID]->store(longlong(table_id), TRUE));
-
- OK(fields[SYS_INDEX_TYPE]->store(index->type));
-
- OK(fields[SYS_INDEX_NUM_FIELDS]->store(index->n_fields));
-
- OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
-
- OK(fields[SYS_INDEX_SPACE]->store(index->space));
-
- OK(schema_table_store_record(thd, table_to_fill));
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Function to go through each record in SYS_INDEXES table, and fill the
-information_schema.innodb_sys_indexes table with related index information
-@return 0 on success */
-static
-int
-i_s_sys_indexes_fill_table(
-/*=======================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- mem_heap_t* heap;
- mtr_t mtr;
-
- DBUG_ENTER("i_s_sys_indexes_fill_table");
-
- /* deny access to non-superusers */
- if (check_global_access(thd, PROCESS_ACL)) {
-
- DBUG_RETURN(0);
- }
-
- heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
-
- /* Start scan the SYS_INDEXES table */
- rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
-
- /* Process each record in the table */
- while (rec) {
- const char* err_msg;;
- table_id_t table_id;
- dict_index_t index_rec;
-
- /* Populate a dict_index_t structure with information from
- a SYS_INDEXES row */
- err_msg = dict_process_sys_indexes_rec(heap, rec, &index_rec,
- &table_id);
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
-
- if (!err_msg) {
- i_s_dict_fill_sys_indexes(thd, table_id, &index_rec,
- tables->table);
- } else {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_FIND_SYSTEM_REC,
- err_msg);
- }
-
- mem_heap_empty(heap);
-
- /* Get the next record */
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
- rec = dict_getnext_system(&pcur, &mtr);
- }
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- mem_heap_free(heap);
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_indexes
-@return 0 on success */
-static
-int
-innodb_sys_indexes_init(
-/*====================*/
- void* p) /*!< in/out: table schema object */
-{
- ST_SCHEMA_TABLE* schema;
-
- DBUG_ENTER("innodb_sys_index_init");
-
- schema = (ST_SCHEMA_TABLE*) p;
-
- schema->fields_info = innodb_sysindex_fields_info;
- schema->fill_table = i_s_sys_indexes_fill_table;
-
- DBUG_RETURN(0);
-}
-
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes =
-{
- /* the plugin type (a MYSQL_XXX_PLUGIN value) */
- /* int */
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-
- /* pointer to type-specific plugin descriptor */
- /* void* */
- STRUCT_FLD(info, &i_s_info),
-
- /* plugin name */
- /* const char* */
- STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
-
- /* plugin author (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(author, plugin_author),
-
- /* general descriptive text (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(descr, "InnoDB SYS_INDEXES"),
-
- /* the plugin license (PLUGIN_LICENSE_XXX) */
- /* int */
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-
- /* the function to invoke when plugin is loaded */
- /* int (*)(void*); */
- STRUCT_FLD(init, innodb_sys_indexes_init),
-
- /* the function to invoke when plugin is unloaded */
- /* int (*)(void*); */
- STRUCT_FLD(deinit, i_s_common_deinit),
-
- /* plugin version (for SHOW PLUGINS) */
- /* unsigned int */
- STRUCT_FLD(version, INNODB_VERSION_SHORT),
-
- /* struct st_mysql_show_var* */
- STRUCT_FLD(status_vars, NULL),
-
- /* struct st_mysql_sys_var** */
- STRUCT_FLD(system_vars, NULL),
-
- /* reserved for dependency checking */
- /* void* */
- STRUCT_FLD(__reserved1, NULL)
-};
-
-/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_COLUMNS */
-static ST_FIELD_INFO innodb_sys_columns_fields_info[] =
-{
-#define SYS_COLUMN_TABLE_ID 0
- {STRUCT_FLD(field_name, "TABLE_ID"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_COLUMN_NAME 1
- {STRUCT_FLD(field_name, "NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_COLUMN_POSITION 2
- {STRUCT_FLD(field_name, "POS"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_COLUMN_MTYPE 3
- {STRUCT_FLD(field_name, "MTYPE"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_COLUMN__PRTYPE 4
- {STRUCT_FLD(field_name, "PRTYPE"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_COLUMN_COLUMN_LEN 5
- {STRUCT_FLD(field_name, "LEN"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
- END_OF_ST_FIELD_INFO
-};
-
-/**********************************************************************//**
-Function to populate the information_schema.innodb_sys_columns with
-related column information
-@return 0 on success */
-static
-int
-i_s_dict_fill_sys_columns(
-/*======================*/
- THD* thd, /*!< in: thread */
- table_id_t table_id, /*!< in: table ID */
- const char* col_name, /*!< in: column name */
- dict_col_t* column, /*!< in: dict_col_t struct holding
- more column information */
- TABLE* table_to_fill) /*!< in/out: fill this table */
-{
- Field** fields;
-
- DBUG_ENTER("i_s_dict_fill_sys_columns");
-
- fields = table_to_fill->field;
-
- OK(fields[SYS_COLUMN_TABLE_ID]->store(longlong(table_id), TRUE));
-
- OK(field_store_string(fields[SYS_COLUMN_NAME], col_name));
-
- OK(fields[SYS_COLUMN_POSITION]->store(column->ind));
-
- OK(fields[SYS_COLUMN_MTYPE]->store(column->mtype));
-
- OK(fields[SYS_COLUMN__PRTYPE]->store(column->prtype));
-
- OK(fields[SYS_COLUMN_COLUMN_LEN]->store(column->len));
-
- OK(schema_table_store_record(thd, table_to_fill));
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Function to fill information_schema.innodb_sys_columns with information
-collected by scanning SYS_COLUMNS table.
-@return 0 on success */
-static
-int
-i_s_sys_columns_fill_table(
-/*=======================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- const char* col_name;
- mem_heap_t* heap;
- mtr_t mtr;
-
- DBUG_ENTER("i_s_sys_columns_fill_table");
-
- /* deny access to non-superusers */
- if (check_global_access(thd, PROCESS_ACL)) {
-
- DBUG_RETURN(0);
- }
-
- heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
-
- rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
-
- while (rec) {
- const char* err_msg;
- dict_col_t column_rec;
- table_id_t table_id;
-
- /* populate a dict_col_t structure with information from
- a SYS_COLUMNS row */
- err_msg = dict_process_sys_columns_rec(heap, rec, &column_rec,
- &table_id, &col_name);
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
-
- if (!err_msg) {
- i_s_dict_fill_sys_columns(thd, table_id, col_name,
- &column_rec,
- tables->table);
- } else {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_FIND_SYSTEM_REC,
- err_msg);
- }
-
- mem_heap_empty(heap);
-
- /* Get the next record */
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
- rec = dict_getnext_system(&pcur, &mtr);
- }
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- mem_heap_free(heap);
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_columns
-@return 0 on success */
-static
-int
-innodb_sys_columns_init(
-/*====================*/
- void* p) /*!< in/out: table schema object */
-{
- ST_SCHEMA_TABLE* schema;
-
- DBUG_ENTER("innodb_sys_columns_init");
-
- schema = (ST_SCHEMA_TABLE*) p;
-
- schema->fields_info = innodb_sys_columns_fields_info;
- schema->fill_table = i_s_sys_columns_fill_table;
-
- DBUG_RETURN(0);
-}
-
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_columns =
-{
- /* the plugin type (a MYSQL_XXX_PLUGIN value) */
- /* int */
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-
- /* pointer to type-specific plugin descriptor */
- /* void* */
- STRUCT_FLD(info, &i_s_info),
-
- /* plugin name */
- /* const char* */
- STRUCT_FLD(name, "INNODB_SYS_COLUMNS"),
-
- /* plugin author (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(author, plugin_author),
-
- /* general descriptive text (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(descr, "InnoDB SYS_COLUMNS"),
-
- /* the plugin license (PLUGIN_LICENSE_XXX) */
- /* int */
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-
- /* the function to invoke when plugin is loaded */
- /* int (*)(void*); */
- STRUCT_FLD(init, innodb_sys_columns_init),
-
- /* the function to invoke when plugin is unloaded */
- /* int (*)(void*); */
- STRUCT_FLD(deinit, i_s_common_deinit),
-
- /* plugin version (for SHOW PLUGINS) */
- /* unsigned int */
- STRUCT_FLD(version, INNODB_VERSION_SHORT),
-
- /* struct st_mysql_show_var* */
- STRUCT_FLD(status_vars, NULL),
-
- /* struct st_mysql_sys_var** */
- STRUCT_FLD(system_vars, NULL),
-
- /* reserved for dependency checking */
- /* void* */
- STRUCT_FLD(__reserved1, NULL)
-};
-/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_fields */
-static ST_FIELD_INFO innodb_sys_fields_fields_info[] =
-{
-#define SYS_FIELD_INDEX_ID 0
- {STRUCT_FLD(field_name, "INDEX_ID"),
- STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FIELD_NAME 1
- {STRUCT_FLD(field_name, "NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FIELD_POS 2
- {STRUCT_FLD(field_name, "POS"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
- END_OF_ST_FIELD_INFO
-};
-
-/**********************************************************************//**
-Function to fill information_schema.innodb_sys_fields with information
-collected by scanning SYS_FIELDS table.
-@return 0 on success */
-static
-int
-i_s_dict_fill_sys_fields(
-/*=====================*/
- THD* thd, /*!< in: thread */
- index_id_t index_id, /*!< in: index id for the field */
- dict_field_t* field, /*!< in: table */
- ulint pos, /*!< in: Field position */
- TABLE* table_to_fill) /*!< in/out: fill this table */
-{
- Field** fields;
-
- DBUG_ENTER("i_s_dict_fill_sys_fields");
-
- fields = table_to_fill->field;
-
- OK(fields[SYS_FIELD_INDEX_ID]->store(longlong(index_id), TRUE));
-
- OK(field_store_string(fields[SYS_FIELD_NAME], field->name));
-
- OK(fields[SYS_FIELD_POS]->store(pos));
-
- OK(schema_table_store_record(thd, table_to_fill));
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Function to go through each record in SYS_FIELDS table, and fill the
-information_schema.innodb_sys_fields table with related index field
-information
-@return 0 on success */
-static
-int
-i_s_sys_fields_fill_table(
-/*======================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- mem_heap_t* heap;
- index_id_t last_id;
- mtr_t mtr;
-
- DBUG_ENTER("i_s_sys_fields_fill_table");
-
- /* deny access to non-superusers */
- if (check_global_access(thd, PROCESS_ACL)) {
-
- DBUG_RETURN(0);
- }
-
- heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
-
- /* will save last index id so that we know whether we move to
- the next index. This is used to calculate prefix length */
- last_id = 0;
-
- rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
-
- while (rec) {
- ulint pos;
- const char* err_msg;
- index_id_t index_id;
- dict_field_t field_rec;
-
- /* Populate a dict_field_t structure with information from
- a SYS_FIELDS row */
- err_msg = dict_process_sys_fields_rec(heap, rec, &field_rec,
- &pos, &index_id, last_id);
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
-
- if (!err_msg) {
- i_s_dict_fill_sys_fields(thd, index_id, &field_rec,
- pos, tables->table);
- last_id = index_id;
- } else {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_FIND_SYSTEM_REC,
- err_msg);
- }
-
- mem_heap_empty(heap);
-
- /* Get the next record */
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
- rec = dict_getnext_system(&pcur, &mtr);
- }
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- mem_heap_free(heap);
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_fields
-@return 0 on success */
-static
-int
-innodb_sys_fields_init(
-/*===================*/
- void* p) /*!< in/out: table schema object */
-{
- ST_SCHEMA_TABLE* schema;
-
- DBUG_ENTER("innodb_sys_field_init");
-
- schema = (ST_SCHEMA_TABLE*) p;
-
- schema->fields_info = innodb_sys_fields_fields_info;
- schema->fill_table = i_s_sys_fields_fill_table;
-
- DBUG_RETURN(0);
-}
-
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_fields =
-{
- /* the plugin type (a MYSQL_XXX_PLUGIN value) */
- /* int */
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-
- /* pointer to type-specific plugin descriptor */
- /* void* */
- STRUCT_FLD(info, &i_s_info),
-
- /* plugin name */
- /* const char* */
- STRUCT_FLD(name, "INNODB_SYS_FIELDS"),
-
- /* plugin author (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(author, plugin_author),
-
- /* general descriptive text (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(descr, "InnoDB SYS_FIELDS"),
-
- /* the plugin license (PLUGIN_LICENSE_XXX) */
- /* int */
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-
- /* the function to invoke when plugin is loaded */
- /* int (*)(void*); */
- STRUCT_FLD(init, innodb_sys_fields_init),
-
- /* the function to invoke when plugin is unloaded */
- /* int (*)(void*); */
- STRUCT_FLD(deinit, i_s_common_deinit),
-
- /* plugin version (for SHOW PLUGINS) */
- /* unsigned int */
- STRUCT_FLD(version, INNODB_VERSION_SHORT),
-
- /* struct st_mysql_show_var* */
- STRUCT_FLD(status_vars, NULL),
-
- /* struct st_mysql_sys_var** */
- STRUCT_FLD(system_vars, NULL),
-
- /* reserved for dependency checking */
- /* void* */
- STRUCT_FLD(__reserved1, NULL)
-};
-
-/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign */
-static ST_FIELD_INFO innodb_sys_foreign_fields_info[] =
-{
-#define SYS_FOREIGN_ID 0
- {STRUCT_FLD(field_name, "ID"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FOREIGN_FOR_NAME 1
- {STRUCT_FLD(field_name, "FOR_NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FOREIGN_REF_NAME 2
- {STRUCT_FLD(field_name, "REF_NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FOREIGN_NUM_COL 3
- {STRUCT_FLD(field_name, "N_COLS"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FOREIGN_TYPE 4
- {STRUCT_FLD(field_name, "TYPE"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
- END_OF_ST_FIELD_INFO
-};
-
-/**********************************************************************//**
-Function to fill information_schema.innodb_sys_foreign with information
-collected by scanning SYS_FOREIGN table.
-@return 0 on success */
-static
-int
-i_s_dict_fill_sys_foreign(
-/*======================*/
- THD* thd, /*!< in: thread */
- dict_foreign_t* foreign, /*!< in: table */
- TABLE* table_to_fill) /*!< in/out: fill this table */
-{
- Field** fields;
-
- DBUG_ENTER("i_s_dict_fill_sys_foreign");
-
- fields = table_to_fill->field;
-
- OK(field_store_string(fields[SYS_FOREIGN_ID], foreign->id));
-
- OK(field_store_string(fields[SYS_FOREIGN_FOR_NAME],
- foreign->foreign_table_name));
-
- OK(field_store_string(fields[SYS_FOREIGN_REF_NAME],
- foreign->referenced_table_name));
-
- OK(fields[SYS_FOREIGN_NUM_COL]->store(foreign->n_fields));
-
- OK(fields[SYS_FOREIGN_TYPE]->store(foreign->type));
-
- OK(schema_table_store_record(thd, table_to_fill));
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Function to populate INFORMATION_SCHEMA.innodb_sys_foreign table. Loop
-through each record in SYS_FOREIGN, and extract the foreign key
-information.
-@return 0 on success */
-static
-int
-i_s_sys_foreign_fill_table(
-/*=======================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- mem_heap_t* heap;
- mtr_t mtr;
-
- DBUG_ENTER("i_s_sys_foreign_fill_table");
-
- /* deny access to non-superusers */
- if (check_global_access(thd, PROCESS_ACL)) {
-
- DBUG_RETURN(0);
- }
-
- heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
-
- rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
-
- while (rec) {
- const char* err_msg;
- dict_foreign_t foreign_rec;
-
- /* Populate a dict_foreign_t structure with information from
- a SYS_FOREIGN row */
- err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
-
- if (!err_msg) {
- i_s_dict_fill_sys_foreign(thd, &foreign_rec,
- tables->table);
- } else {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_FIND_SYSTEM_REC,
- err_msg);
- }
-
- mem_heap_empty(heap);
-
- /* Get the next record */
- mtr_start(&mtr);
- mutex_enter(&dict_sys->mutex);
- rec = dict_getnext_system(&pcur, &mtr);
- }
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- mem_heap_free(heap);
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign
-@return 0 on success */
-static
-int
-innodb_sys_foreign_init(
-/*====================*/
- void* p) /*!< in/out: table schema object */
-{
- ST_SCHEMA_TABLE* schema;
-
- DBUG_ENTER("innodb_sys_foreign_init");
-
- schema = (ST_SCHEMA_TABLE*) p;
-
- schema->fields_info = innodb_sys_foreign_fields_info;
- schema->fill_table = i_s_sys_foreign_fill_table;
-
- DBUG_RETURN(0);
-}
-
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign =
-{
- /* the plugin type (a MYSQL_XXX_PLUGIN value) */
- /* int */
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-
- /* pointer to type-specific plugin descriptor */
- /* void* */
- STRUCT_FLD(info, &i_s_info),
-
- /* plugin name */
- /* const char* */
- STRUCT_FLD(name, "INNODB_SYS_FOREIGN"),
-
- /* plugin author (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(author, plugin_author),
-
- /* general descriptive text (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
-
- /* the plugin license (PLUGIN_LICENSE_XXX) */
- /* int */
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-
- /* the function to invoke when plugin is loaded */
- /* int (*)(void*); */
- STRUCT_FLD(init, innodb_sys_foreign_init),
-
- /* the function to invoke when plugin is unloaded */
- /* int (*)(void*); */
- STRUCT_FLD(deinit, i_s_common_deinit),
-
- /* plugin version (for SHOW PLUGINS) */
- /* unsigned int */
- STRUCT_FLD(version, INNODB_VERSION_SHORT),
-
- /* struct st_mysql_show_var* */
- STRUCT_FLD(status_vars, NULL),
-
- /* struct st_mysql_sys_var** */
- STRUCT_FLD(system_vars, NULL),
-
- /* reserved for dependency checking */
- /* void* */
- STRUCT_FLD(__reserved1, NULL)
-};
-/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols */
-static ST_FIELD_INFO innodb_sys_foreign_cols_fields_info[] =
-{
-#define SYS_FOREIGN_COL_ID 0
- {STRUCT_FLD(field_name, "ID"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FOREIGN_COL_FOR_NAME 1
- {STRUCT_FLD(field_name, "FOR_COL_NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FOREIGN_COL_REF_NAME 2
- {STRUCT_FLD(field_name, "REF_COL_NAME"),
- STRUCT_FLD(field_length, NAME_LEN + 1),
- STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, 0),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
-#define SYS_FOREIGN_COL_POS 3
- {STRUCT_FLD(field_name, "POS"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
- STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
- STRUCT_FLD(value, 0),
- STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
- STRUCT_FLD(old_name, ""),
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-
- END_OF_ST_FIELD_INFO
-};
-
-/**********************************************************************//**
-Function to fill information_schema.innodb_sys_foreign_cols with information
-collected by scanning SYS_FOREIGN_COLS table.
-@return 0 on success */
-static
-int
-i_s_dict_fill_sys_foreign_cols(
-/*==========================*/
- THD* thd, /*!< in: thread */
- const char* name, /*!< in: foreign key constraint name */
- const char* for_col_name, /*!< in: referencing column name*/
- const char* ref_col_name, /*!< in: referenced column
- name */
- ulint pos, /*!< in: column position */
- TABLE* table_to_fill) /*!< in/out: fill this table */
-{
- Field** fields;
-
- DBUG_ENTER("i_s_dict_fill_sys_foreign_cols");
-
- fields = table_to_fill->field;
-
- OK(field_store_string(fields[SYS_FOREIGN_COL_ID], name));
-
- OK(field_store_string(fields[SYS_FOREIGN_COL_FOR_NAME], for_col_name));
-
- OK(field_store_string(fields[SYS_FOREIGN_COL_REF_NAME], ref_col_name));
-
- OK(fields[SYS_FOREIGN_COL_POS]->store(pos));
-
- OK(schema_table_store_record(thd, table_to_fill));
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Function to populate INFORMATION_SCHEMA.innodb_sys_foreign_cols table. Loop
-through each record in SYS_FOREIGN_COLS, and extract the foreign key column
-information and fill the INFORMATION_SCHEMA.innodb_sys_foreign_cols table.
-@return 0 on success */
-static
-int
-i_s_sys_foreign_cols_fill_table(
-/*============================*/
- THD* thd, /*!< in: thread */
- TABLE_LIST* tables, /*!< in/out: tables to fill */
- COND* cond) /*!< in: condition (not used) */
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- mem_heap_t* heap;
- mtr_t mtr;
-
- DBUG_ENTER("i_s_sys_foreign_cols_fill_table");
-
- /* deny access to non-superusers */
- if (check_global_access(thd, PROCESS_ACL)) {
- DBUG_RETURN(0);
- }
-
- heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
-
- rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
-
- while (rec) {
- const char* err_msg;
- const char* name;
- const char* for_col_name;
- const char* ref_col_name;
- ulint pos;
-
- /* Extract necessary information from a SYS_FOREIGN_COLS row */
- err_msg = dict_process_sys_foreign_col_rec(
- heap, rec, &name, &for_col_name, &ref_col_name, &pos);
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
-
- if (!err_msg) {
- i_s_dict_fill_sys_foreign_cols(
- thd, name, for_col_name, ref_col_name, pos,
- tables->table);
- } else {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_FIND_SYSTEM_REC,
- err_msg);
- }
-
- mem_heap_empty(heap);
-
- /* Get the next record */
- mutex_enter(&dict_sys->mutex);
- mtr_start(&mtr);
- rec = dict_getnext_system(&pcur, &mtr);
- }
-
- mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- mem_heap_free(heap);
-
- DBUG_RETURN(0);
-}
-/*******************************************************************//**
-Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols
-@return 0 on success */
-static
-int
-innodb_sys_foreign_cols_init(
-/*========================*/
- void* p) /*!< in/out: table schema object */
-{
- ST_SCHEMA_TABLE* schema;
-
- DBUG_ENTER("innodb_sys_foreign_cols_init");
-
- schema = (ST_SCHEMA_TABLE*) p;
-
- schema->fields_info = innodb_sys_foreign_cols_fields_info;
- schema->fill_table = i_s_sys_foreign_cols_fill_table;
-
- DBUG_RETURN(0);
-}
-
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign_cols =
-{
- /* the plugin type (a MYSQL_XXX_PLUGIN value) */
- /* int */
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-
- /* pointer to type-specific plugin descriptor */
- /* void* */
- STRUCT_FLD(info, &i_s_info),
-
- /* plugin name */
- /* const char* */
- STRUCT_FLD(name, "INNODB_SYS_FOREIGN_COLS"),
-
- /* plugin author (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(author, plugin_author),
-
- /* general descriptive text (for SHOW PLUGINS) */
- /* const char* */
- STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
-
- /* the plugin license (PLUGIN_LICENSE_XXX) */
- /* int */
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-
- /* the function to invoke when plugin is loaded */
- /* int (*)(void*); */
- STRUCT_FLD(init, innodb_sys_foreign_cols_init),
-
- /* the function to invoke when plugin is unloaded */
- /* int (*)(void*); */
- STRUCT_FLD(deinit, i_s_common_deinit),
-
- /* plugin version (for SHOW PLUGINS) */
- /* unsigned int */
- STRUCT_FLD(version, INNODB_VERSION_SHORT),
-
- /* struct st_mysql_show_var* */
- STRUCT_FLD(status_vars, NULL),
-
- /* struct st_mysql_sys_var** */
- STRUCT_FLD(system_vars, NULL),
-
- /* reserved for dependency checking */
- /* void* */
- STRUCT_FLD(__reserved1, NULL)
-};
-
diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h
index 69f5ed9dad8..dc0deef119b 100644
--- a/storage/innobase/handler/i_s.h
+++ b/storage/innobase/handler/i_s.h
@@ -26,6 +26,8 @@ Created July 18, 2007 Vasil Dimov
#ifndef i_s_h
#define i_s_h
+const char plugin_author[] = "Oracle Corporation";
+
extern struct st_mysql_plugin i_s_innodb_trx;
extern struct st_mysql_plugin i_s_innodb_locks;
extern struct st_mysql_plugin i_s_innodb_lock_waits;
@@ -33,12 +35,5 @@ extern struct st_mysql_plugin i_s_innodb_cmp;
extern struct st_mysql_plugin i_s_innodb_cmp_reset;
extern struct st_mysql_plugin i_s_innodb_cmpmem;
extern struct st_mysql_plugin i_s_innodb_cmpmem_reset;
-extern struct st_mysql_plugin i_s_innodb_sys_tables;
-extern struct st_mysql_plugin i_s_innodb_sys_tablestats;
-extern struct st_mysql_plugin i_s_innodb_sys_indexes;
-extern struct st_mysql_plugin i_s_innodb_sys_columns;
-extern struct st_mysql_plugin i_s_innodb_sys_fields;
-extern struct st_mysql_plugin i_s_innodb_sys_foreign;
-extern struct st_mysql_plugin i_s_innodb_sys_foreign_cols;
#endif /* i_s_h */
diff --git a/storage/innobase/handler/mysql_addons.cc b/storage/innobase/handler/mysql_addons.cc
deleted file mode 100644
index ae6306e5db9..00000000000
--- a/storage/innobase/handler/mysql_addons.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file handler/mysql_addons.cc
-This file contains functions that need to be added to
-MySQL code but have not been added yet.
-
-Whenever you add a function here submit a MySQL bug
-report (feature request) with the implementation. Then
-write the bug number in the comment before the
-function in this file.
-
-When MySQL commits the function it can be deleted from
-here. In a perfect world this file exists but is empty.
-
-Created November 07, 2007 Vasil Dimov
-*******************************************************/
-
-#ifndef MYSQL_SERVER
-#define MYSQL_SERVER
-#endif /* MYSQL_SERVER */
-
-#include <sql_priv.h>
-
-#include "mysql_addons.h"
-#include "univ.i"
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index a048de0e884..7d94ebc6438 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -44,11 +44,11 @@ Created 7/19/1997 Heikki Tuuri
#include "fsp0fsp.h"
#include "trx0sys.h"
#include "fil0fil.h"
-#include "thr0loc.h"
#include "rem0rec.h"
#include "btr0cur.h"
#include "btr0pcur.h"
#include "btr0btr.h"
+#include "row0upd.h"
#include "sync0sync.h"
#include "dict0boot.h"
#include "fut0lst.h"
@@ -192,6 +192,11 @@ access order rules. */
/** Operations that can currently be buffered. */
UNIV_INTERN ibuf_use_t ibuf_use = IBUF_USE_ALL;
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+/** Flag to control insert buffer debugging. */
+UNIV_INTERN uint ibuf_debug;
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
/** The insert buffer control structure */
UNIV_INTERN ibuf_t* ibuf = NULL;
@@ -318,52 +323,43 @@ still physically like the index page even if the index would have been
dropped! So, there seems to be no problem. */
/******************************************************************//**
-Sets the flag in the current OS thread local storage denoting that it is
+Sets the flag in the current mini-transaction record indicating we're
inside an insert buffer routine. */
UNIV_INLINE
void
-ibuf_enter(void)
-/*============*/
+ibuf_enter(
+/*=======*/
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
- ibool* ptr;
-
- ptr = thr_local_get_in_ibuf_field();
-
- ut_ad(*ptr == FALSE);
-
- *ptr = TRUE;
+ ut_ad(!mtr->inside_ibuf);
+ mtr->inside_ibuf = TRUE;
}
/******************************************************************//**
-Sets the flag in the current OS thread local storage denoting that it is
+Sets the flag in the current mini-transaction record indicating we're
exiting an insert buffer routine. */
UNIV_INLINE
void
-ibuf_exit(void)
-/*===========*/
+ibuf_exit(
+/*======*/
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
- ibool* ptr;
-
- ptr = thr_local_get_in_ibuf_field();
-
- ut_ad(*ptr == TRUE);
-
- *ptr = FALSE;
+ ut_ad(mtr->inside_ibuf);
+ mtr->inside_ibuf = FALSE;
}
-/******************************************************************//**
-Returns TRUE if the current OS thread is performing an insert buffer
-routine.
-
-For instance, a read-ahead of non-ibuf pages is forbidden by threads
-that are executing an insert buffer routine.
-@return TRUE if inside an insert buffer routine */
-UNIV_INTERN
-ibool
-ibuf_inside(void)
-/*=============*/
+/**************************************************************//**
+Commits an insert buffer mini-transaction and sets the persistent
+cursor latch mode to BTR_NO_LATCHES, that is, detaches the cursor. */
+UNIV_INLINE
+void
+ibuf_btr_pcur_commit_specify_mtr(
+/*=============================*/
+ btr_pcur_t* pcur, /*!< in/out: persistent cursor */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
- return(*thr_local_get_in_ibuf_field());
+ ut_d(ibuf_exit(mtr));
+ btr_pcur_commit_specify_mtr(pcur, mtr);
}
/******************************************************************//**
@@ -373,11 +369,11 @@ static
page_t*
ibuf_header_page_get(
/*=================*/
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
- ut_ad(!ibuf_inside());
+ ut_ad(!ibuf_inside(mtr));
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr);
@@ -398,7 +394,7 @@ ibuf_tree_root_get(
buf_block_t* block;
page_t* root;
- ut_ad(ibuf_inside());
+ ut_ad(ibuf_inside(mtr));
ut_ad(mutex_own(&ibuf_mutex));
mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
@@ -541,7 +537,7 @@ ibuf_init_at_db_start(void)
fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
&n_used, &mtr);
- ibuf_enter();
+ ibuf_enter(&mtr);
ut_ad(n_used >= 2);
@@ -562,9 +558,7 @@ ibuf_init_at_db_start(void)
mutex_exit(&ibuf_mutex);
ibuf->empty = (page_get_n_recs(root) == 0);
- mtr_commit(&mtr);
-
- ibuf_exit();
+ ibuf_mtr_commit(&mtr);
heap = mem_heap_create(450);
@@ -650,22 +644,49 @@ ibuf_parse_bitmap_init(
return(ptr);
}
#ifndef UNIV_HOTBACKUP
+# ifdef UNIV_DEBUG
+/** Gets the desired bits for a given page from a bitmap page.
+@param page in: bitmap page
+@param offset in: page whose bits to get
+@param zs in: compressed page size in bytes; 0 for uncompressed pages
+@param bit in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
+@param mtr in: mini-transaction holding an x-latch on the bitmap page
+@return value of bits */
+# define ibuf_bitmap_page_get_bits(page, offset, zs, bit, mtr) \
+ ibuf_bitmap_page_get_bits_low(page, offset, zs, \
+ MTR_MEMO_PAGE_X_FIX, mtr, bit)
+# else /* UNIV_DEBUG */
+/** Gets the desired bits for a given page from a bitmap page.
+@param page in: bitmap page
+@param offset in: page whose bits to get
+@param zs in: compressed page size in bytes; 0 for uncompressed pages
+@param bit in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
+@param mtr in: mini-transaction holding an x-latch on the bitmap page
+@return value of bits */
+# define ibuf_bitmap_page_get_bits(page, offset, zs, bit, mtr) \
+ ibuf_bitmap_page_get_bits_low(page, offset, zs, bit)
+# endif /* UNIV_DEBUG */
+
/********************************************************************//**
Gets the desired bits for a given page from a bitmap page.
@return value of bits */
UNIV_INLINE
ulint
-ibuf_bitmap_page_get_bits(
-/*======================*/
+ibuf_bitmap_page_get_bits_low(
+/*==========================*/
const page_t* page, /*!< in: bitmap page */
ulint page_no,/*!< in: page whose bits to get */
ulint zip_size,/*!< in: compressed page size in bytes;
0 for uncompressed pages */
- ulint bit, /*!< in: IBUF_BITMAP_FREE,
+#ifdef UNIV_DEBUG
+ ulint latch_type,
+ /*!< in: MTR_MEMO_PAGE_X_FIX,
+ MTR_MEMO_BUF_FIX, ... */
+ mtr_t* mtr, /*!< in: mini-transaction holding latch_type
+ on the bitmap page */
+#endif /* UNIV_DEBUG */
+ ulint bit) /*!< in: IBUF_BITMAP_FREE,
IBUF_BITMAP_BUFFERED, ... */
- mtr_t* mtr __attribute__((unused)))
- /*!< in: mtr containing an
- x-latch to the bitmap page */
{
ulint byte_offset;
ulint bit_offset;
@@ -677,7 +698,7 @@ ibuf_bitmap_page_get_bits(
# error "IBUF_BITS_PER_PAGE % 2 != 0"
#endif
ut_ad(ut_is_2pow(zip_size));
- ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains_page(mtr, page, latch_type));
if (!zip_size) {
bit_offset = (page_no % UNIV_PAGE_SIZE) * IBUF_BITS_PER_PAGE
@@ -1103,21 +1124,29 @@ Must not be called when recv_no_ibuf_operations==TRUE.
@return TRUE if level 2 or level 3 page */
UNIV_INTERN
ibool
-ibuf_page(
-/*======*/
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
- ulint page_no,/*!< in: page number */
- mtr_t* mtr) /*!< in: mtr which will contain an x-latch to the
- bitmap page if the page is not one of the fixed
- address ibuf pages, or NULL, in which case a new
- transaction is created. */
+ibuf_page_low(
+/*==========*/
+ ulint space, /*!< in: space id */
+ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
+ ulint page_no,/*!< in: page number */
+#ifdef UNIV_DEBUG
+ ibool x_latch,/*!< in: FALSE if relaxed check
+ (avoid latching the bitmap page) */
+#endif /* UNIV_DEBUG */
+ const char* file, /*!< in: file name */
+ ulint line, /*!< in: line where called */
+ mtr_t* mtr) /*!< in: mtr which will contain an
+ x-latch to the bitmap page if the page
+ is not one of the fixed address ibuf
+ pages, or NULL, in which case a new
+ transaction is created. */
{
ibool ret;
mtr_t local_mtr;
page_t* bitmap_page;
ut_ad(!recv_no_ibuf_operations);
+ ut_ad(x_latch || mtr == NULL);
if (ibuf_fixed_addr_page(space, zip_size, page_no)) {
@@ -1129,12 +1158,44 @@ ibuf_page(
ut_ad(fil_space_get_type(IBUF_SPACE_ID) == FIL_TABLESPACE);
+#ifdef UNIV_DEBUG
+ if (!x_latch) {
+ mtr_start(&local_mtr);
+
+ /* Get the bitmap page without a page latch, so that
+ we will not be violating the latching order when
+ another bitmap page has already been latched by this
+ thread. The page will be buffer-fixed, and thus it
+ cannot be removed or relocated while we are looking at
+ it. The contents of the page could change, but the
+ IBUF_BITMAP_IBUF bit that we are interested in should
+ not be modified by any other thread. Nobody should be
+ calling ibuf_add_free_page() or ibuf_remove_free_page()
+ while the page is linked to the insert buffer b-tree. */
+
+ bitmap_page = buf_block_get_frame(
+ buf_page_get_gen(
+ space, zip_size,
+ ibuf_bitmap_page_no_calc(zip_size, page_no),
+ RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
+ file, line, &local_mtr));
+
+ ret = ibuf_bitmap_page_get_bits_low(
+ bitmap_page, page_no, zip_size,
+ MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
+
+ mtr_commit(&local_mtr);
+ return(ret);
+ }
+#endif /* UNIV_DEBUG */
+
if (mtr == NULL) {
mtr = &local_mtr;
mtr_start(mtr);
}
- bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
+ bitmap_page = ibuf_bitmap_get_map_page_func(space, page_no, zip_size,
+ file, line, mtr);
ret = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
IBUF_BITMAP_IBUF, mtr);
@@ -1146,19 +1207,30 @@ ibuf_page(
return(ret);
}
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_page_no(mtr,rec) ibuf_rec_get_page_no_func(mtr,rec)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_page_no(mtr,rec) ibuf_rec_get_page_no_func(rec)
+#endif /* UNIV_DEBUG */
+
/********************************************************************//**
Returns the page number field of an ibuf record.
@return page number */
static
ulint
-ibuf_rec_get_page_no(
-/*=================*/
+ibuf_rec_get_page_no_func(
+/*======================*/
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
const rec_t* rec) /*!< in: ibuf record */
{
const byte* field;
ulint len;
- ut_ad(ibuf_inside());
+ ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+ ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len);
@@ -1180,20 +1252,31 @@ ibuf_rec_get_page_no(
return(mach_read_from_4(field));
}
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_space(mtr,rec) ibuf_rec_get_space_func(mtr,rec)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_space(mtr,rec) ibuf_rec_get_space_func(rec)
+#endif /* UNIV_DEBUG */
+
/********************************************************************//**
Returns the space id field of an ibuf record. For < 4.1.x format records
returns 0.
@return space id */
static
ulint
-ibuf_rec_get_space(
-/*===============*/
+ibuf_rec_get_space_func(
+/*====================*/
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
const rec_t* rec) /*!< in: ibuf record */
{
const byte* field;
ulint len;
- ut_ad(ibuf_inside());
+ ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+ ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len);
@@ -1214,12 +1297,22 @@ ibuf_rec_get_space(
return(0);
}
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_info(mtr,rec,op,comp,info_len,counter) \
+ ibuf_rec_get_info_func(mtr,rec,op,comp,info_len,counter)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_info(mtr,rec,op,comp,info_len,counter) \
+ ibuf_rec_get_info_func(rec,op,comp,info_len,counter)
+#endif
/****************************************************************//**
Get various information about an ibuf record in >= 4.1.x format. */
static
void
-ibuf_rec_get_info(
-/*==============*/
+ibuf_rec_get_info_func(
+/*===================*/
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
const rec_t* rec, /*!< in: ibuf record */
ibuf_op_t* op, /*!< out: operation type, or NULL */
ibool* comp, /*!< out: compact flag, or NULL */
@@ -1238,7 +1331,9 @@ ibuf_rec_get_info(
ulint info_len_local;
ulint counter_local;
- ut_ad(ibuf_inside());
+ ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+ ut_ad(ibuf_inside(mtr));
fields = rec_get_n_fields_old(rec);
ut_a(fields > 4);
@@ -1287,22 +1382,32 @@ ibuf_rec_get_info(
}
}
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_op_type(mtr,rec) ibuf_rec_get_op_type_func(mtr,rec)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_op_type(mtr,rec) ibuf_rec_get_op_type_func(rec)
+#endif
+
/****************************************************************//**
Returns the operation type field of an ibuf record.
@return operation type */
static
ibuf_op_t
-ibuf_rec_get_op_type(
-/*=================*/
+ibuf_rec_get_op_type_func(
+/*======================*/
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
const rec_t* rec) /*!< in: ibuf record */
{
ulint len;
- const byte* field;
- ut_ad(ibuf_inside());
+ ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+ ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
- field = rec_get_nth_field_old(rec, 1, &len);
+ (void) rec_get_nth_field_old(rec, 1, &len);
if (len > 1) {
/* This is a < 4.1.x format record */
@@ -1311,7 +1416,7 @@ ibuf_rec_get_op_type(
} else {
ibuf_op_t op;
- ibuf_rec_get_info(rec, &op, NULL, NULL, NULL);
+ ibuf_rec_get_info(mtr, rec, &op, NULL, NULL, NULL);
return(op);
}
@@ -1358,12 +1463,12 @@ ibuf_add_ops(
const ulint* ops) /*!< in: operation counts */
{
+ ulint i;
+
#ifndef HAVE_ATOMIC_BUILTINS
ut_ad(mutex_own(&ibuf_mutex));
#endif /* !HAVE_ATOMIC_BUILTINS */
- ulint i;
-
for (i = 0; i < IBUF_OP_COUNT; i++) {
#ifdef HAVE_ATOMIC_BUILTINS
os_atomic_increment_ulint(&arr[i], ops[i]);
@@ -1510,6 +1615,14 @@ ibuf_build_entry_pre_4_1_x(
return(tuple);
}
+#ifdef UNIV_DEBUG
+# define ibuf_build_entry_from_ibuf_rec(mtr,ibuf_rec,heap,pindex) \
+ ibuf_build_entry_from_ibuf_rec_func(mtr,ibuf_rec,heap,pindex)
+#else /* UNIV_DEBUG */
+# define ibuf_build_entry_from_ibuf_rec(mtr,ibuf_rec,heap,pindex) \
+ ibuf_build_entry_from_ibuf_rec_func(ibuf_rec,heap,pindex)
+#endif
+
/*********************************************************************//**
Builds the entry used to
@@ -1528,8 +1641,11 @@ hold a latch to the ibuf_rec page as long as the entry is used!
@return own: entry to insert to a non-clustered index */
static
dtuple_t*
-ibuf_build_entry_from_ibuf_rec(
-/*===========================*/
+ibuf_build_entry_from_ibuf_rec_func(
+/*================================*/
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
const rec_t* ibuf_rec, /*!< in: record in an insert buffer */
mem_heap_t* heap, /*!< in: heap where built */
dict_index_t** pindex) /*!< out, own: dummy index that
@@ -1546,6 +1662,10 @@ ibuf_build_entry_from_ibuf_rec(
ulint comp;
dict_index_t* index;
+ ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
+ ut_ad(ibuf_inside(mtr));
+
data = rec_get_nth_field_old(ibuf_rec, 1, &len);
if (len > 1) {
@@ -1566,7 +1686,7 @@ ibuf_build_entry_from_ibuf_rec(
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
- ibuf_rec_get_info(ibuf_rec, NULL, &comp, &info_len, NULL);
+ ibuf_rec_get_info(mtr, ibuf_rec, NULL, &comp, &info_len, NULL);
index = ibuf_dummy_index_create(n_fields, comp);
@@ -1653,6 +1773,12 @@ ibuf_rec_get_size(
return(size);
}
+#ifdef UNIV_DEBUG
+# define ibuf_rec_get_volume(mtr,rec) ibuf_rec_get_volume_func(mtr,rec)
+#else /* UNIV_DEBUG */
+# define ibuf_rec_get_volume(mtr,rec) ibuf_rec_get_volume_func(rec)
+#endif
+
/********************************************************************//**
Returns the space taken by a stored non-clustered index entry if converted to
an index record.
@@ -1660,8 +1786,11 @@ an index record.
taken in the page directory */
static
ulint
-ibuf_rec_get_volume(
-/*================*/
+ibuf_rec_get_volume_func(
+/*=====================*/
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
const rec_t* ibuf_rec)/*!< in: ibuf record */
{
ulint len;
@@ -1672,7 +1801,9 @@ ibuf_rec_get_volume(
ibool pre_4_1;
ulint comp;
- ut_ad(ibuf_inside());
+ ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
+ ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
data = rec_get_nth_field_old(ibuf_rec, 1, &len);
@@ -1700,7 +1831,7 @@ ibuf_rec_get_volume(
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
- ibuf_rec_get_info(ibuf_rec, &op, &comp, &info_len, NULL);
+ ibuf_rec_get_info(mtr, ibuf_rec, &op, &comp, &info_len, NULL);
if (op == IBUF_OP_DELETE_MARK || op == IBUF_OP_DELETE) {
/* Delete-marking a record doesn't take any
@@ -1717,7 +1848,7 @@ ibuf_rec_get_volume(
mem_heap_t* heap = mem_heap_create(500);
entry = ibuf_build_entry_from_ibuf_rec(
- ibuf_rec, heap, &dummy_index);
+ mtr, ibuf_rec, heap, &dummy_index);
volume = rec_get_converted_size(dummy_index, entry, 0);
@@ -2075,21 +2206,15 @@ ibuf_add_free_page(void)
mtr_commit(&mtr);
return(FALSE);
- }
-
- {
- buf_block_t* block;
-
- block = buf_page_get(
+ } else {
+ buf_block_t* block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
-
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
-
page = buf_block_get_frame(block);
}
- ibuf_enter();
+ ibuf_enter(&mtr);
mutex_enter(&ibuf_mutex);
@@ -2117,9 +2242,7 @@ ibuf_add_free_page(void)
ibuf_bitmap_page_set_bits(
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
- mtr_commit(&mtr);
-
- ibuf_exit();
+ ibuf_mtr_commit(&mtr);
return(TRUE);
}
@@ -2151,7 +2274,7 @@ ibuf_remove_free_page(void)
header_page = ibuf_header_page_get(&mtr);
/* Prevent pessimistic inserts to insert buffer trees for a while */
- ibuf_enter();
+ ibuf_enter(&mtr);
mutex_enter(&ibuf_pessimistic_insert_mutex);
mutex_enter(&ibuf_mutex);
@@ -2160,14 +2283,12 @@ ibuf_remove_free_page(void)
mutex_exit(&ibuf_mutex);
mutex_exit(&ibuf_pessimistic_insert_mutex);
- ibuf_exit();
-
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
return;
}
- mtr_start(&mtr2);
+ ibuf_mtr_start(&mtr2);
root = ibuf_tree_root_get(&mtr2);
@@ -2180,9 +2301,8 @@ ibuf_remove_free_page(void)
because in fseg_free_page we access level 1 pages, and the root
is a level 2 page. */
- mtr_commit(&mtr2);
-
- ibuf_exit();
+ ibuf_mtr_commit(&mtr2);
+ ibuf_exit(&mtr);
/* Since pessimistic inserts were prevented, we know that the
page is still in the free list. NOTE that also deletes may take
@@ -2193,11 +2313,11 @@ ibuf_remove_free_page(void)
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
IBUF_SPACE_ID, page_no, &mtr);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
-#endif
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
- ibuf_enter();
+ ibuf_enter(&mtr);
mutex_enter(&ibuf_mutex);
@@ -2239,12 +2359,10 @@ ibuf_remove_free_page(void)
ibuf_bitmap_page_set_bits(
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
-#endif
- mtr_commit(&mtr);
-
- ibuf_exit();
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
+ ibuf_mtr_commit(&mtr);
}
/***********************************************************************//**
@@ -2266,8 +2384,6 @@ ibuf_free_excess_pages(void)
ut_ad(rw_lock_get_x_lock_count(
fil_space_get_latch(IBUF_SPACE_ID, NULL)) == 1);
- ut_ad(!ibuf_inside());
-
/* NOTE: We require that the thread did not own the latch before,
because then we know that we can obey the correct latching order
for ibuf latches */
@@ -2298,20 +2414,30 @@ ibuf_free_excess_pages(void)
}
}
+#ifdef UNIV_DEBUG
+# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,vers,pages,n_stored) \
+ ibuf_get_merge_page_nos_func(contract,rec,mtr,ids,vers,pages,n_stored)
+#else /* UNIV_DEBUG */
+# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,vers,pages,n_stored) \
+ ibuf_get_merge_page_nos_func(contract,rec,ids,vers,pages,n_stored)
+#endif /* UNIV_DEBUG */
+
/*********************************************************************//**
Reads page numbers from a leaf in an ibuf tree.
@return a lower limit for the combined volume of records which will be
merged */
static
ulint
-ibuf_get_merge_page_nos(
-/*====================*/
+ibuf_get_merge_page_nos_func(
+/*=========================*/
ibool contract,/*!< in: TRUE if this function is called to
contract the tree, FALSE if this is called
when a single page becomes full and we look
if it pays to read also nearby pages */
- rec_t* rec, /*!< in: record from which we read up and down
- in the chain of records */
+ const rec_t* rec, /*!< in: insert buffer record */
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction holding rec */
+#endif /* UNIV_DEBUG */
ulint* space_ids,/*!< in/out: space id's of the pages */
ib_int64_t* space_versions,/*!< in/out: tablespace version
timestamps; used to prevent reading in old
@@ -2334,18 +2460,22 @@ ibuf_get_merge_page_nos(
ulint limit;
ulint n_pages;
+ ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+ ut_ad(ibuf_inside(mtr));
+
*n_stored = 0;
limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool_get_curr_size() / 4);
if (page_rec_is_supremum(rec)) {
- rec = page_rec_get_prev(rec);
+ rec = page_rec_get_prev_const(rec);
}
if (page_rec_is_infimum(rec)) {
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
}
if (page_rec_is_supremum(rec)) {
@@ -2353,8 +2483,8 @@ ibuf_get_merge_page_nos(
return(0);
}
- first_page_no = ibuf_rec_get_page_no(rec);
- first_space_id = ibuf_rec_get_space(rec);
+ first_page_no = ibuf_rec_get_page_no(mtr, rec);
+ first_space_id = ibuf_rec_get_space(mtr, rec);
n_pages = 0;
prev_page_no = 0;
prev_space_id = 0;
@@ -2365,8 +2495,8 @@ ibuf_get_merge_page_nos(
while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
- rec_page_no = ibuf_rec_get_page_no(rec);
- rec_space_id = ibuf_rec_get_space(rec);
+ rec_page_no = ibuf_rec_get_page_no(mtr, rec);
+ rec_space_id = ibuf_rec_get_space(mtr, rec);
if (rec_space_id != first_space_id
|| (rec_page_no / IBUF_MERGE_AREA)
@@ -2383,10 +2513,10 @@ ibuf_get_merge_page_nos(
prev_page_no = rec_page_no;
prev_space_id = rec_space_id;
- rec = page_rec_get_prev(rec);
+ rec = page_rec_get_prev_const(rec);
}
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
/* At the loop start there is no prev page; we mark this with a pair
of space id, page no (0, 0) for which there can never be entries in
@@ -2404,8 +2534,8 @@ ibuf_get_merge_page_nos(
rec_page_no = 1;
rec_space_id = 0;
} else {
- rec_page_no = ibuf_rec_get_page_no(rec);
- rec_space_id = ibuf_rec_get_space(rec);
+ rec_page_no = ibuf_rec_get_page_no(mtr, rec);
+ rec_space_id = ibuf_rec_get_space(mtr, rec);
ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
}
@@ -2416,9 +2546,9 @@ ibuf_get_merge_page_nos(
|| rec_page_no != prev_page_no)
&& (prev_space_id != 0 || prev_page_no != 0)) {
- if ((prev_page_no == first_page_no
- && prev_space_id == first_space_id)
- || contract
+ if (contract
+ || (prev_page_no == first_page_no
+ && prev_space_id == first_space_id)
|| (volume_for_page
> ((IBUF_MERGE_THRESHOLD - 1)
* 4 * UNIV_PAGE_SIZE
@@ -2451,14 +2581,14 @@ ibuf_get_merge_page_nos(
break;
}
- rec_volume = ibuf_rec_get_volume(rec);
+ rec_volume = ibuf_rec_get_volume(mtr, rec);
volume_for_page += rec_volume;
prev_page_no = rec_page_no;
prev_space_id = rec_space_id;
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
}
#ifdef UNIV_IBUF_DEBUG
@@ -2493,7 +2623,6 @@ ibuf_contract_ext(
mtr_t mtr;
*n_pages = 0;
- ut_ad(!ibuf_inside());
/* We perform a dirty read of ibuf->empty, without latching
the insert buffer root page. We trust this dirty read except
@@ -2502,29 +2631,10 @@ ibuf_contract_ext(
if (UNIV_UNLIKELY(ibuf->empty)
&& UNIV_LIKELY(!srv_shutdown_state)) {
-ibuf_is_empty:
-
-#if 0 /* TODO */
- if (srv_shutdown_state) {
- /* If the insert buffer becomes empty during
- shutdown, note it in the system tablespace. */
-
- trx_sys_set_ibuf_format(TRX_SYS_IBUF_EMPTY);
- }
-
- /* TO DO: call trx_sys_set_ibuf_format() at startup
- and whenever ibuf_use is changed to allow buffered
- delete-marking or deleting. Never downgrade the
- stamped format except when the insert buffer becomes
- empty. */
-#endif
-
return(0);
}
- mtr_start(&mtr);
-
- ibuf_enter();
+ ibuf_mtr_start(&mtr);
/* Open a cursor to a randomly chosen leaf of the tree, at a random
position within the leaf */
@@ -2543,24 +2653,21 @@ ibuf_is_empty:
ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
== FSP_IBUF_TREE_ROOT_PAGE_NO);
- ibuf_exit();
-
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur);
- goto ibuf_is_empty;
+ return(0);
}
- sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
+ sum_sizes = ibuf_get_merge_page_nos(TRUE,
+ btr_pcur_get_rec(&pcur), &mtr,
space_ids, space_versions,
page_nos, n_pages);
#if 0 /* defined UNIV_IBUF_DEBUG */
fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
sync, *n_pages, sum_sizes);
#endif
- ibuf_exit();
-
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur);
buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos,
@@ -2700,6 +2807,13 @@ ibuf_get_volume_buffered_hash(
return(TRUE);
}
+#ifdef UNIV_DEBUG
+# define ibuf_get_volume_buffered_count(mtr,rec,hash,size,n_recs) \
+ ibuf_get_volume_buffered_count_func(mtr,rec,hash,size,n_recs)
+#else /* UNIV_DEBUG */
+# define ibuf_get_volume_buffered_count(mtr,rec,hash,size,n_recs) \
+ ibuf_get_volume_buffered_count_func(rec,hash,size,n_recs)
+#endif
/*********************************************************************//**
Update the estimate of the number of records on a page, and
get the space taken by merging the buffered record to the index page.
@@ -2707,8 +2821,11 @@ get the space taken by merging the buffered record to the index page.
taken in the page directory */
static
ulint
-ibuf_get_volume_buffered_count(
-/*===========================*/
+ibuf_get_volume_buffered_count_func(
+/*================================*/
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction owning rec */
+#endif /* UNIV_DEBUG */
const rec_t* rec, /*!< in: insert buffer record */
ulint* hash, /*!< in/out: hash array */
ulint size, /*!< in: number of elements in hash array */
@@ -2718,9 +2835,13 @@ ibuf_get_volume_buffered_count(
ulint len;
ibuf_op_t ibuf_op;
const byte* types;
- ulint n_fields = rec_get_n_fields_old(rec);
+ ulint n_fields;
- ut_ad(ibuf_inside());
+ ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
+ ut_ad(ibuf_inside(mtr));
+
+ n_fields = rec_get_n_fields_old(rec);
ut_ad(n_fields > 4);
n_fields -= 4;
@@ -2762,9 +2883,8 @@ ibuf_get_volume_buffered_count(
switch (ibuf_op) {
case IBUF_OP_INSERT:
- /* Inserts can be done by
- btr_cur_set_deleted_flag_for_ibuf(). Because
- delete-mark and insert operations can be pointing to
+ /* Inserts can be done by updating a delete-marked record.
+ Because delete-mark and insert operations can be pointing to
the same records, we must not count duplicates. */
case IBUF_OP_DELETE_MARK:
/* There must be a record to delete-mark.
@@ -2806,7 +2926,7 @@ get_volume_comp:
mem_heap_t* heap = mem_heap_create(500);
entry = ibuf_build_entry_from_ibuf_rec(
- rec, heap, &dummy_index);
+ mtr, rec, heap, &dummy_index);
volume = rec_get_converted_size(dummy_index, entry, 0);
@@ -2827,7 +2947,7 @@ static
ulint
ibuf_get_volume_buffered(
/*=====================*/
- btr_pcur_t* pcur, /*!< in: pcur positioned at a place in an
+ const btr_pcur_t*pcur, /*!< in: pcur positioned at a place in an
insert buffer tree where we would insert an
entry for the index page whose number is
page_no, latch mode has to be BTR_MODIFY_PREV
@@ -2837,16 +2957,17 @@ ibuf_get_volume_buffered(
lint* n_recs, /*!< in/out: minimum number of records on the
page after the buffered changes have been
applied, or NULL to disable the counting */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr) /*!< in: mini-transaction of pcur */
{
- ulint volume;
- rec_t* rec;
- page_t* page;
- ulint prev_page_no;
- page_t* prev_page;
- ulint next_page_no;
- page_t* next_page;
- ulint hash_bitmap[128 / sizeof(ulint)]; /* bitmap of buffered recs */
+ ulint volume;
+ const rec_t* rec;
+ const page_t* page;
+ ulint prev_page_no;
+ const page_t* prev_page;
+ ulint next_page_no;
+ const page_t* next_page;
+ /* bitmap of buffered recs */
+ ulint hash_bitmap[128 / sizeof(ulint)];
ut_a(trx_sys_multiple_tablespace_format);
@@ -2867,26 +2988,22 @@ ibuf_get_volume_buffered(
ut_ad(page_validate(page, ibuf->index));
if (page_rec_is_supremum(rec)) {
- rec = page_rec_get_prev(rec);
+ rec = page_rec_get_prev_const(rec);
}
- for (;;) {
- if (page_rec_is_infimum(rec)) {
-
- break;
- }
+ for (; !page_rec_is_infimum(rec);
+ rec = page_rec_get_prev_const(rec)) {
+ ut_ad(page_align(rec) == page);
- if (page_no != ibuf_rec_get_page_no(rec)
- || space != ibuf_rec_get_space(rec)) {
+ if (page_no != ibuf_rec_get_page_no(mtr, rec)
+ || space != ibuf_rec_get_space(mtr, rec)) {
goto count_later;
}
volume += ibuf_get_volume_buffered_count(
- rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
-
- rec = page_rec_get_prev(rec);
- ut_ad(page_align(rec) == page);
+ mtr, rec,
+ hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
}
/* Look at the previous page */
@@ -2902,7 +3019,8 @@ ibuf_get_volume_buffered(
buf_block_t* block;
block = buf_page_get(
- IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr);
+ IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH,
+ mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
@@ -2912,14 +3030,15 @@ ibuf_get_volume_buffered(
}
#ifdef UNIV_BTR_DEBUG
- ut_a(btr_page_get_next(prev_page, mtr)
- == page_get_page_no(page));
+ ut_a(btr_page_get_next(prev_page, mtr) == page_get_page_no(page));
#endif /* UNIV_BTR_DEBUG */
rec = page_get_supremum_rec(prev_page);
- rec = page_rec_get_prev(rec);
+ rec = page_rec_get_prev_const(rec);
+
+ for (;; rec = page_rec_get_prev_const(rec)) {
+ ut_ad(page_align(rec) == prev_page);
- for (;;) {
if (page_rec_is_infimum(rec)) {
/* We cannot go to yet a previous page, because we
@@ -2929,42 +3048,35 @@ ibuf_get_volume_buffered(
return(UNIV_PAGE_SIZE);
}
- if (page_no != ibuf_rec_get_page_no(rec)
- || space != ibuf_rec_get_space(rec)) {
+ if (page_no != ibuf_rec_get_page_no(mtr, rec)
+ || space != ibuf_rec_get_space(mtr, rec)) {
goto count_later;
}
volume += ibuf_get_volume_buffered_count(
- rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
-
- rec = page_rec_get_prev(rec);
- ut_ad(page_align(rec) == prev_page);
+ mtr, rec,
+ hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
}
count_later:
rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_supremum(rec)) {
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
}
- for (;;) {
- if (page_rec_is_supremum(rec)) {
-
- break;
- }
-
- if (page_no != ibuf_rec_get_page_no(rec)
- || space != ibuf_rec_get_space(rec)) {
+ for (; !page_rec_is_supremum(rec);
+ rec = page_rec_get_next_const(rec)) {
+ if (page_no != ibuf_rec_get_page_no(mtr, rec)
+ || space != ibuf_rec_get_space(mtr, rec)) {
return(volume);
}
volume += ibuf_get_volume_buffered_count(
- rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
-
- rec = page_rec_get_next(rec);
+ mtr, rec,
+ hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
}
/* Look at the next page */
@@ -2980,7 +3092,8 @@ count_later:
buf_block_t* block;
block = buf_page_get(
- IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr);
+ IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH,
+ mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
@@ -2994,9 +3107,11 @@ count_later:
#endif /* UNIV_BTR_DEBUG */
rec = page_get_infimum_rec(next_page);
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
+
+ for (;; rec = page_rec_get_next_const(rec)) {
+ ut_ad(page_align(rec) == next_page);
- for (;;) {
if (page_rec_is_supremum(rec)) {
/* We give up */
@@ -3004,17 +3119,15 @@ count_later:
return(UNIV_PAGE_SIZE);
}
- if (page_no != ibuf_rec_get_page_no(rec)
- || space != ibuf_rec_get_space(rec)) {
+ if (page_no != ibuf_rec_get_page_no(mtr, rec)
+ || space != ibuf_rec_get_space(mtr, rec)) {
return(volume);
}
volume += ibuf_get_volume_buffered_count(
- rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
-
- rec = page_rec_get_next(rec);
- ut_ad(page_align(rec) == next_page);
+ mtr, rec,
+ hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
}
}
@@ -3035,9 +3148,7 @@ ibuf_update_max_tablespace_id(void)
ut_a(!dict_table_is_comp(ibuf->index->table));
- ibuf_enter();
-
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
btr_pcur_open_at_index_side(
FALSE, ibuf->index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
@@ -3060,14 +3171,20 @@ ibuf_update_max_tablespace_id(void)
max_space_id = mach_read_from_4(field);
}
- mtr_commit(&mtr);
- ibuf_exit();
+ ibuf_mtr_commit(&mtr);
/* printf("Maximum space id in insert buffer %lu\n", max_space_id); */
fil_set_max_space_id_if_bigger(max_space_id);
}
+#ifdef UNIV_DEBUG
+# define ibuf_get_entry_counter_low(mtr,rec,space,page_no) \
+ ibuf_get_entry_counter_low_func(mtr,rec,space,page_no)
+#else /* UNIV_DEBUG */
+# define ibuf_get_entry_counter_low(mtr,rec,space,page_no) \
+ ibuf_get_entry_counter_low_func(rec,space,page_no)
+#endif
/****************************************************************//**
Helper function for ibuf_set_entry_counter. Checks if rec is for (space,
page_no), and if so, reads counter value from it and returns that + 1.
@@ -3075,8 +3192,11 @@ Otherwise, returns 0.
@return new counter value, or 0 */
static
ulint
-ibuf_get_entry_counter_low(
-/*=======================*/
+ibuf_get_entry_counter_low_func(
+/*============================*/
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction of rec */
+#endif /* UNIV_DEBUG */
const rec_t* rec, /*!< in: insert buffer record */
ulint space, /*!< in: space id */
ulint page_no) /*!< in: page number */
@@ -3085,7 +3205,9 @@ ibuf_get_entry_counter_low(
const byte* field;
ulint len;
- ut_ad(ibuf_inside());
+ ut_ad(ibuf_inside(mtr));
+ ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
+ || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len);
@@ -3157,12 +3279,15 @@ ibuf_set_entry_counter(
ulint counter = 0;
/* pcur points to either a user rec or to a page's infimum record. */
+ ut_ad(ibuf_inside(mtr));
+ ut_ad(mtr_memo_contains(mtr, btr_pcur_get_block(pcur),
+ MTR_MEMO_PAGE_X_FIX));
ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index));
if (btr_pcur_is_on_user_rec(pcur)) {
counter = ibuf_get_entry_counter_low(
- btr_pcur_get_rec(pcur), space, page_no);
+ mtr, btr_pcur_get_rec(pcur), space, page_no);
if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
/* The record lacks a counter field.
@@ -3218,7 +3343,7 @@ ibuf_set_entry_counter(
ut_ad(page_rec_is_user_rec(rec));
counter = ibuf_get_entry_counter_low(
- rec, space, page_no);
+ mtr, rec, space, page_no);
if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
/* The record lacks a counter field.
@@ -3370,7 +3495,6 @@ ibuf_insert_low(
if (mode == BTR_MODIFY_TREE) {
for (;;) {
- ibuf_enter();
mutex_enter(&ibuf_pessimistic_insert_mutex);
mutex_enter(&ibuf_mutex);
@@ -3381,7 +3505,6 @@ ibuf_insert_low(
mutex_exit(&ibuf_mutex);
mutex_exit(&ibuf_pessimistic_insert_mutex);
- ibuf_exit();
if (UNIV_UNLIKELY(!ibuf_add_free_page())) {
@@ -3389,11 +3512,9 @@ ibuf_insert_low(
return(DB_STRONG_FAIL);
}
}
- } else {
- ibuf_enter();
}
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index));
@@ -3448,7 +3569,7 @@ fail_exit:
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a((buffered == 0) || ibuf_count_get(space, page_no));
#endif
- mtr_start(&bitmap_mtr);
+ ibuf_mtr_start(&bitmap_mtr);
bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
zip_size, &bitmap_mtr);
@@ -3469,15 +3590,15 @@ fail_exit:
if (buffered + entry_size + page_dir_calc_reserved_space(1)
> ibuf_index_page_calc_free_from_bits(zip_size, bits)) {
/* Release the bitmap page latch early. */
- mtr_commit(&bitmap_mtr);
+ ibuf_mtr_commit(&bitmap_mtr);
/* It may not fit */
do_merge = TRUE;
- ibuf_get_merge_page_nos(
- FALSE, btr_pcur_get_rec(&pcur),
- space_ids, space_versions,
- page_nos, &n_stored);
+ ibuf_get_merge_page_nos(FALSE,
+ btr_pcur_get_rec(&pcur), &mtr,
+ space_ids, space_versions,
+ page_nos, &n_stored);
goto fail_exit;
}
@@ -3490,7 +3611,7 @@ fail_exit:
&& !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur,
mode == BTR_MODIFY_PREV, &mtr)) {
bitmap_fail:
- mtr_commit(&bitmap_mtr);
+ ibuf_mtr_commit(&bitmap_mtr);
goto fail_exit;
}
@@ -3508,7 +3629,7 @@ bitmap_fail:
&bitmap_mtr);
}
- mtr_commit(&bitmap_mtr);
+ ibuf_mtr_commit(&bitmap_mtr);
cursor = btr_pcur_get_btr_cur(&pcur);
@@ -3573,9 +3694,8 @@ func_exit:
}
#endif
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur);
- ibuf_exit();
mem_heap_free(heap);
@@ -3749,9 +3869,80 @@ During merge, inserts to an index page a secondary index entry extracted
from the insert buffer. */
static
void
+ibuf_insert_to_index_page_low(
+/*==========================*/
+ const dtuple_t* entry, /*!< in: buffered entry to insert */
+ buf_block_t* block, /*!< in/out: index page where the buffered
+ entry should be placed */
+ dict_index_t* index, /*!< in: record descriptor */
+ mtr_t* mtr, /*!< in/out: mtr */
+ page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
+ after which to insert the buffered entry */
+{
+ const page_t* page;
+ ulint space;
+ ulint page_no;
+ ulint zip_size;
+ const page_t* bitmap_page;
+ ulint old_bits;
+
+ if (UNIV_LIKELY
+ (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
+ return;
+ }
+
+ /* If the record did not fit, reorganize */
+
+ btr_page_reorganize(block, index, mtr);
+ page_cur_search(block, index, entry, PAGE_CUR_LE, page_cur);
+
+ /* This time the record must fit */
+
+ if (UNIV_LIKELY
+ (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
+ return;
+ }
+
+ page = buf_block_get_frame(block);
+
+ ut_print_timestamp(stderr);
+
+ fprintf(stderr,
+ " InnoDB: Error: Insert buffer insert fails;"
+ " page free %lu, dtuple size %lu\n",
+ (ulong) page_get_max_insert_size(page, 1),
+ (ulong) rec_get_converted_size(index, entry, 0));
+ fputs("InnoDB: Cannot insert index record ", stderr);
+ dtuple_print(stderr, entry);
+ fputs("\nInnoDB: The table where this index record belongs\n"
+ "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n"
+ "InnoDB: that table.\n", stderr);
+
+ space = page_get_space_id(page);
+ zip_size = buf_block_get_zip_size(block);
+ page_no = page_get_page_no(page);
+
+ bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
+ old_bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
+ IBUF_BITMAP_FREE, mtr);
+
+ fprintf(stderr,
+ "InnoDB: space %lu, page %lu, zip_size %lu, bitmap bits %lu\n",
+ (ulong) space, (ulong) page_no,
+ (ulong) zip_size, (ulong) old_bits);
+
+ fputs("InnoDB: Submit a detailed bug report"
+ " to http://bugs.mysql.com\n", stderr);
+}
+
+/************************************************************************
+During merge, inserts to an index page a secondary index entry extracted
+from the insert buffer. */
+static
+void
ibuf_insert_to_index_page(
/*======================*/
- dtuple_t* entry, /*!< in: buffered entry to insert */
+ const dtuple_t* entry, /*!< in: buffered entry to insert */
buf_block_t* block, /*!< in/out: index page where the buffered entry
should be placed */
dict_index_t* index, /*!< in: record descriptor */
@@ -3761,11 +3952,10 @@ ibuf_insert_to_index_page(
ulint low_match;
page_t* page = buf_block_get_frame(block);
rec_t* rec;
- page_t* bitmap_page;
- ulint old_bits;
- ut_ad(ibuf_inside());
+ ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry));
+ ut_ad(!buf_block_align(page)->is_hashed);
if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
!= (ibool)!!page_is_comp(page))) {
@@ -3779,17 +3969,11 @@ ibuf_insert_to_index_page(
rec = page_rec_get_next(page_get_infimum_rec(page));
if (page_rec_is_supremum(rec)) {
- /* Empty pages can result from buffered delete operations.
- The first record from the free list can be used to find the
- father node. */
- rec = page_header_get_ptr(page, PAGE_FREE);
- if (UNIV_UNLIKELY(rec == NULL)) {
- fputs("InnoDB: Trying to insert a record from"
- " the insert buffer to an index page\n"
- "InnoDB: but the index page is empty!\n",
- stderr);
- goto dump;
- }
+ fputs("InnoDB: Trying to insert a record from"
+ " the insert buffer to an index page\n"
+ "InnoDB: but the index page is empty!\n",
+ stderr);
+ goto dump;
}
if (UNIV_UNLIKELY(rec_get_n_fields(rec, index)
@@ -3817,71 +4001,87 @@ dump:
low_match = page_cur_search(block, index, entry,
PAGE_CUR_LE, &page_cur);
- if (low_match == dtuple_get_n_fields(entry)) {
+ if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) {
+ mem_heap_t* heap;
+ upd_t* update;
+ ulint* offsets;
page_zip_des_t* page_zip;
rec = page_cur_get_rec(&page_cur);
- page_zip = buf_block_get_page_zip(block);
- btr_cur_set_deleted_flag_for_ibuf(rec, page_zip, FALSE, mtr);
- } else {
- rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr);
+ /* This is based on
+ row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */
+ ut_ad(rec_get_deleted_flag(rec, page_is_comp(page)));
+
+ heap = mem_heap_create(1024);
+
+ offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED,
+ &heap);
+ update = row_upd_build_sec_rec_difference_binary(
+ index, entry, rec, NULL, heap);
+
+ page_zip = buf_block_get_page_zip(block);
- if (UNIV_LIKELY(rec != NULL)) {
+ if (update->n_fields == 0) {
+ /* The records only differ in the delete-mark.
+ Clear the delete-mark, like we did before
+ Bug #56680 was fixed. */
+ btr_cur_set_deleted_flag_for_ibuf(
+ rec, page_zip, FALSE, mtr);
+updated_in_place:
+ mem_heap_free(heap);
return;
}
- /* If the record did not fit, reorganize */
-
- btr_page_reorganize(block, index, mtr);
- page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur);
+ /* Copy the info bits. Clear the delete-mark. */
+ update->info_bits = rec_get_info_bits(rec, page_is_comp(page));
+ update->info_bits &= ~REC_INFO_DELETED_FLAG;
+
+ /* We cannot invoke btr_cur_optimistic_update() here,
+ because we do not have a btr_cur_t or que_thr_t,
+ as the insert buffer merge occurs at a very low level. */
+ if (!row_upd_changes_field_size_or_external(index, offsets,
+ update)
+ && (!page_zip || btr_cur_update_alloc_zip(
+ page_zip, block, index,
+ rec_offs_size(offsets), FALSE, mtr))) {
+ /* This is the easy case. Do something similar
+ to btr_cur_update_in_place(). */
+ row_upd_rec_in_place(rec, index, offsets,
+ update, page_zip);
+ goto updated_in_place;
+ }
- /* This time the record must fit */
- if (UNIV_UNLIKELY
- (!page_cur_tuple_insert(&page_cur, entry, index,
- 0, mtr))) {
- ulint space;
- ulint page_no;
- ulint zip_size;
+ /* A collation may identify values that differ in
+ storage length.
+ Some examples (1 or 2 bytes):
+ utf8_turkish_ci: I = U+0131 LATIN SMALL LETTER DOTLESS I
+ utf8_general_ci: S = U+00DF LATIN SMALL LETTER SHARP S
+ utf8_general_ci: A = U+00E4 LATIN SMALL LETTER A WITH DIAERESIS
- ut_print_timestamp(stderr);
+ latin1_german2_ci: SS = U+00DF LATIN SMALL LETTER SHARP S
- fprintf(stderr,
- " InnoDB: Error: Insert buffer insert"
- " fails; page free %lu,"
- " dtuple size %lu\n",
- (ulong) page_get_max_insert_size(
- page, 1),
- (ulong) rec_get_converted_size(
- index, entry, 0));
- fputs("InnoDB: Cannot insert index record ",
- stderr);
- dtuple_print(stderr, entry);
- fputs("\nInnoDB: The table where"
- " this index record belongs\n"
- "InnoDB: is now probably corrupt."
- " Please run CHECK TABLE on\n"
- "InnoDB: that table.\n", stderr);
+ Examples of a character (3-byte UTF-8 sequence)
+ identified with 2 or 4 characters (1-byte UTF-8 sequences):
- space = page_get_space_id(page);
- zip_size = buf_block_get_zip_size(block);
- page_no = page_get_page_no(page);
+ utf8_unicode_ci: 'II' = U+2171 SMALL ROMAN NUMERAL TWO
+ utf8_unicode_ci: '(10)' = U+247D PARENTHESIZED NUMBER TEN
+ */
- bitmap_page = ibuf_bitmap_get_map_page(
- space, page_no, zip_size, mtr);
- old_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_no, zip_size,
- IBUF_BITMAP_FREE, mtr);
+ /* Delete the different-length record, and insert the
+ buffered one. */
- fprintf(stderr,
- "InnoDB: space %lu, page %lu,"
- " zip_size %lu, bitmap bits %lu\n",
- (ulong) space, (ulong) page_no,
- (ulong) zip_size, (ulong) old_bits);
+ lock_rec_store_on_page_infimum(block, rec);
+ page_cur_delete_rec(&page_cur, index, offsets, mtr);
+ page_cur_move_to_prev(&page_cur);
+ mem_heap_free(heap);
- fputs("InnoDB: Submit a detailed bug report"
- " to http://bugs.mysql.com\n", stderr);
- }
+ ibuf_insert_to_index_page_low(entry, block, index, mtr,
+ &page_cur);
+ lock_rec_restore_from_page_infimum(block, rec, block);
+ } else {
+ ibuf_insert_to_index_page_low(entry, block, index, mtr,
+ &page_cur);
}
}
@@ -3900,7 +4100,7 @@ ibuf_set_del_mark(
page_cur_t page_cur;
ulint low_match;
- ut_ad(ibuf_inside());
+ ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry));
low_match = page_cur_search(
@@ -3913,9 +4113,32 @@ ibuf_set_del_mark(
rec = page_cur_get_rec(&page_cur);
page_zip = page_cur_get_page_zip(&page_cur);
- btr_cur_set_deleted_flag_for_ibuf(rec, page_zip, TRUE, mtr);
+ /* Delete mark the old index record. According to a
+ comment in row_upd_sec_index_entry(), it can already
+ have been delete marked if a lock wait occurred in
+ row_ins_index_entry() in a previous invocation of
+ row_upd_sec_index_entry(). */
+
+ if (UNIV_LIKELY
+ (!rec_get_deleted_flag(
+ rec, dict_table_is_comp(index->table)))) {
+ btr_cur_set_deleted_flag_for_ibuf(rec, page_zip,
+ TRUE, mtr);
+ }
} else {
- /* This can happen benignly in some situations. */
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: unable to find a record to delete-mark\n",
+ stderr);
+ fputs("InnoDB: tuple ", stderr);
+ dtuple_print(stderr, entry);
+ fputs("\n"
+ "InnoDB: record ", stderr);
+ rec_print(stderr, page_cur_get_rec(&page_cur), index);
+ putc('\n', stderr);
+ fputs("\n"
+ "InnoDB: Submit a detailed bug report"
+ " to http://bugs.mysql.com\n", stderr);
+ ut_ad(0);
}
}
@@ -3934,7 +4157,7 @@ ibuf_delete(
page_cur_t page_cur;
ulint low_match;
- ut_ad(ibuf_inside());
+ ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry));
low_match = page_cur_search(
@@ -3990,10 +4213,7 @@ ibuf_delete(
mem_heap_free(heap);
}
} else {
- /* This can happen benignly in some situations: either when
- we crashed at just the right time, or on database startup
- when we redo some old log entries (due to worse stored
- position granularity on disk than in memory). */
+ /* The record must have been purged already. */
}
}
@@ -4025,7 +4245,7 @@ ibuf_restore_pos(
/* The tablespace has been dropped. It is possible
that another thread has deleted the insert buffer
entry. Do not complain. */
- btr_pcur_commit_specify_mtr(pcur, mtr);
+ ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
} else {
fprintf(stderr,
"InnoDB: ERROR: Submit the output to"
@@ -4043,7 +4263,7 @@ ibuf_restore_pos(
page_rec_get_next(btr_pcur_get_rec(pcur)));
fflush(stderr);
- btr_pcur_commit_specify_mtr(pcur, mtr);
+ ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
fputs("InnoDB: Validating insert buffer tree:\n", stderr);
if (!btr_validate_index(ibuf->index, NULL)) {
@@ -4067,8 +4287,8 @@ ibool
ibuf_delete_rec(
/*============*/
ulint space, /*!< in: space id */
- ulint page_no,/*!< in: index page number where the record
- should belong */
+ ulint page_no,/*!< in: index page number that the record
+ should belong to */
btr_pcur_t* pcur, /*!< in: pcur positioned on the record to
delete, having latch mode BTR_MODIFY_LEAF */
const dtuple_t* search_tuple,
@@ -4079,10 +4299,10 @@ ibuf_delete_rec(
page_t* root;
ulint err;
- ut_ad(ibuf_inside());
+ ut_ad(ibuf_inside(mtr));
ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
- ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
- ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
+ ut_ad(ibuf_rec_get_page_no(mtr, btr_pcur_get_rec(pcur)) == page_no);
+ ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur)) == space);
success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
@@ -4115,22 +4335,22 @@ ibuf_delete_rec(
}
ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
- ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
- ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
+ ut_ad(ibuf_rec_get_page_no(mtr, btr_pcur_get_rec(pcur)) == page_no);
+ ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur)) == space);
/* We have to resort to a pessimistic delete from ibuf */
btr_pcur_store_position(pcur, mtr);
+ ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
- btr_pcur_commit_specify_mtr(pcur, mtr);
-
+ ibuf_mtr_start(mtr);
mutex_enter(&ibuf_mutex);
- mtr_start(mtr);
-
if (!ibuf_restore_pos(space, page_no, search_tuple,
BTR_MODIFY_TREE, pcur, mtr)) {
mutex_exit(&ibuf_mutex);
+ ut_ad(!ibuf_inside(mtr));
+ ut_ad(mtr->state == MTR_COMMITTED);
goto func_exit;
}
@@ -4147,9 +4367,11 @@ ibuf_delete_rec(
mutex_exit(&ibuf_mutex);
ibuf->empty = (page_get_n_recs(root) == 0);
- btr_pcur_commit_specify_mtr(pcur, mtr);
+ ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
func_exit:
+ ut_ad(!ibuf_inside(mtr));
+ ut_ad(mtr->state == MTR_COMMITTED);
btr_pcur_close(pcur);
return(TRUE);
@@ -4241,18 +4463,20 @@ ibuf_merge_or_delete_for_page(
update_ibuf_bitmap = FALSE;
} else {
page_t* bitmap_page;
+ ulint bitmap_bits;
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
bitmap_page = ibuf_bitmap_get_map_page(
space, page_no, zip_size, &mtr);
+ bitmap_bits = ibuf_bitmap_page_get_bits(
+ bitmap_page, page_no, zip_size,
+ IBUF_BITMAP_BUFFERED, &mtr);
+
+ ibuf_mtr_commit(&mtr);
- if (!ibuf_bitmap_page_get_bits(bitmap_page, page_no,
- zip_size,
- IBUF_BITMAP_BUFFERED,
- &mtr)) {
+ if (!bitmap_bits) {
/* No inserts buffered for this page */
- mtr_commit(&mtr);
if (!tablespace_being_deleted) {
fil_decr_pending_ibuf_merges(space);
@@ -4260,7 +4484,6 @@ ibuf_merge_or_delete_for_page(
return;
}
- mtr_commit(&mtr);
}
} else if (block
&& (ibuf_fixed_addr_page(space, zip_size, page_no)
@@ -4269,11 +4492,9 @@ ibuf_merge_or_delete_for_page(
return;
}
- ibuf_enter();
-
heap = mem_heap_create(512);
- if (!trx_sys_multiple_tablespace_format) {
+ if (UNIV_UNLIKELY(!trx_sys_multiple_tablespace_format)) {
ut_a(trx_doublewrite_must_reset_space_ids);
search_tuple = ibuf_search_tuple_build(space, page_no, heap);
} else {
@@ -4300,7 +4521,7 @@ ibuf_merge_or_delete_for_page(
ut_print_timestamp(stderr);
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
fputs(" InnoDB: Dump of the ibuf bitmap page:\n",
stderr);
@@ -4308,8 +4529,7 @@ ibuf_merge_or_delete_for_page(
bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
zip_size, &mtr);
buf_page_print(bitmap_page, 0);
-
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
fputs("\nInnoDB: Dump of the page:\n", stderr);
@@ -4340,7 +4560,7 @@ ibuf_merge_or_delete_for_page(
memset(dops, 0, sizeof(dops));
loop:
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
if (block) {
ibool success;
@@ -4374,8 +4594,8 @@ loop:
rec = btr_pcur_get_rec(&pcur);
/* Check if the entry is for this index page */
- if (ibuf_rec_get_page_no(rec) != page_no
- || ibuf_rec_get_space(rec) != space) {
+ if (ibuf_rec_get_page_no(&mtr, rec) != page_no
+ || ibuf_rec_get_space(&mtr, rec) != space) {
if (block) {
page_header_reset_last_insert(
@@ -4398,7 +4618,7 @@ loop:
dtuple_t* entry;
trx_id_t max_trx_id;
dict_index_t* dummy_index;
- ibuf_op_t op = ibuf_rec_get_op_type(rec);
+ ibuf_op_t op = ibuf_rec_get_op_type(&mtr, rec);
max_trx_id = page_get_max_trx_id(page_align(rec));
page_update_max_trx_id(block, page_zip, max_trx_id,
@@ -4407,7 +4627,7 @@ loop:
ut_ad(page_validate(page_align(rec), ibuf->index));
entry = ibuf_build_entry_from_ibuf_rec(
- rec, heap, &dummy_index);
+ &mtr, rec, heap, &dummy_index);
ut_ad(page_validate(block->frame, dummy_index));
@@ -4440,13 +4660,14 @@ loop:
Store and restore the cursor position. */
ut_ad(rec == btr_pcur_get_rec(&pcur));
ut_ad(page_rec_is_user_rec(rec));
- ut_ad(ibuf_rec_get_page_no(rec) == page_no);
- ut_ad(ibuf_rec_get_space(rec) == space);
+ ut_ad(ibuf_rec_get_page_no(&mtr, rec)
+ == page_no);
+ ut_ad(ibuf_rec_get_space(&mtr, rec) == space);
btr_pcur_store_position(&pcur, &mtr);
- btr_pcur_commit_specify_mtr(&pcur, &mtr);
+ ibuf_btr_pcur_commit_specify_mtr(&pcur, &mtr);
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
success = buf_page_get_known_nowait(
RW_X_LATCH, block,
@@ -4461,7 +4682,8 @@ loop:
BTR_MODIFY_LEAF,
&pcur, &mtr)) {
- mtr_commit(&mtr);
+ ut_ad(!ibuf_inside(&mtr));
+ ut_ad(mtr.state == MTR_COMMITTED);
mops[op]++;
ibuf_dummy_index_free(dummy_index);
goto loop;
@@ -4476,7 +4698,7 @@ loop:
ibuf_dummy_index_free(dummy_index);
} else {
- dops[ibuf_rec_get_op_type(rec)]++;
+ dops[ibuf_rec_get_op_type(&mtr, rec)]++;
}
/* Delete the record from ibuf */
@@ -4487,7 +4709,7 @@ loop:
goto loop;
} else if (btr_pcur_is_after_last_on_page(&pcur)) {
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur);
goto loop;
@@ -4521,7 +4743,7 @@ reset_bit:
}
}
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur);
mem_heap_free(heap);
@@ -4545,8 +4767,6 @@ reset_bit:
fil_decr_pending_ibuf_merges(space);
}
- ibuf_exit();
-
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(space, page_no) == 0);
#endif
@@ -4566,9 +4786,8 @@ ibuf_delete_for_discarded_space(
mem_heap_t* heap;
btr_pcur_t pcur;
dtuple_t* search_tuple;
- rec_t* ibuf_rec;
+ const rec_t* ibuf_rec;
ulint page_no;
- ibool closed;
mtr_t mtr;
/* Counts for discarded operations. */
@@ -4583,9 +4802,7 @@ ibuf_delete_for_discarded_space(
memset(dops, 0, sizeof(dops));
loop:
- ibuf_enter();
-
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for the
space */
@@ -4605,39 +4822,34 @@ loop:
ibuf_rec = btr_pcur_get_rec(&pcur);
/* Check if the entry is for this space */
- if (ibuf_rec_get_space(ibuf_rec) != space) {
+ if (ibuf_rec_get_space(&mtr, ibuf_rec) != space) {
goto leave_loop;
}
- page_no = ibuf_rec_get_page_no(ibuf_rec);
+ page_no = ibuf_rec_get_page_no(&mtr, ibuf_rec);
- dops[ibuf_rec_get_op_type(ibuf_rec)]++;
+ dops[ibuf_rec_get_op_type(&mtr, ibuf_rec)]++;
/* Delete the record from ibuf */
- closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple,
- &mtr);
- if (closed) {
+ if (ibuf_delete_rec(space, page_no, &pcur, search_tuple,
+ &mtr)) {
/* Deletion was pessimistic and mtr was committed:
we start from the beginning again */
- ibuf_exit();
-
goto loop;
}
if (btr_pcur_is_after_last_on_page(&pcur)) {
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur);
- ibuf_exit();
-
goto loop;
}
}
leave_loop:
- mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
btr_pcur_close(&pcur);
#ifdef HAVE_ATOMIC_BUILTINS
@@ -4649,8 +4861,6 @@ leave_loop:
mutex_exit(&ibuf_mutex);
#endif /* HAVE_ATOMIC_BUILTINS */
- ibuf_exit();
-
mem_heap_free(heap);
}
@@ -4666,18 +4876,15 @@ ibuf_is_empty(void)
const page_t* root;
mtr_t mtr;
- ibuf_enter();
- mtr_start(&mtr);
+ ibuf_mtr_start(&mtr);
mutex_enter(&ibuf_mutex);
root = ibuf_tree_root_get(&mtr);
mutex_exit(&ibuf_mutex);
is_empty = (page_get_n_recs(root) == 0);
- mtr_commit(&mtr);
- ibuf_exit();
-
ut_a(is_empty == ibuf->empty);
+ ibuf_mtr_commit(&mtr);
return(is_empty);
}
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 3912f315f2a..5b3e166371d 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -92,6 +92,91 @@ insert/delete buffer when the record is not in the buffer pool. */
buffer when the record is not in the buffer pool. */
#define BTR_DELETE 8192
+#ifdef UNIV_BLOB_DEBUG
+# include "ut0rbt.h"
+/** An index->blobs entry for keeping track of off-page column references */
+struct btr_blob_dbg_struct
+{
+ unsigned blob_page_no:32; /*!< first BLOB page number */
+ unsigned ref_page_no:32; /*!< referring page number */
+ unsigned ref_heap_no:16; /*!< referring heap number */
+ unsigned ref_field_no:10; /*!< referring field number */
+ unsigned owner:1; /*!< TRUE if BLOB owner */
+ unsigned always_owner:1; /*!< TRUE if always
+ has been the BLOB owner;
+ reset to TRUE on B-tree
+ page splits and merges */
+ unsigned del:1; /*!< TRUE if currently
+ delete-marked */
+};
+
+/**************************************************************//**
+Add a reference to an off-page column to the index->blobs map. */
+UNIV_INTERN
+void
+btr_blob_dbg_add_blob(
+/*==================*/
+ const rec_t* rec, /*!< in: clustered index record */
+ ulint field_no, /*!< in: number of off-page column */
+ ulint page_no, /*!< in: start page of the column */
+ dict_index_t* index, /*!< in/out: index tree */
+ const char* ctx) /*!< in: context (for logging) */
+ __attribute__((nonnull));
+/**************************************************************//**
+Display the references to off-page columns.
+This function is to be called from a debugger,
+for example when a breakpoint on ut_dbg_assertion_failed is hit. */
+UNIV_INTERN
+void
+btr_blob_dbg_print(
+/*===============*/
+ const dict_index_t* index) /*!< in: index tree */
+ __attribute__((nonnull));
+/**************************************************************//**
+Check that there are no references to off-page columns from or to
+the given page. Invoked when freeing or clearing a page.
+@return TRUE when no orphan references exist */
+UNIV_INTERN
+ibool
+btr_blob_dbg_is_empty(
+/*==================*/
+ dict_index_t* index, /*!< in: index */
+ ulint page_no) /*!< in: page number */
+ __attribute__((nonnull, warn_unused_result));
+
+/**************************************************************//**
+Modify the 'deleted' flag of a record. */
+UNIV_INTERN
+void
+btr_blob_dbg_set_deleted_flag(
+/*==========================*/
+ const rec_t* rec, /*!< in: record */
+ dict_index_t* index, /*!< in/out: index */
+ const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
+ ibool del) /*!< in: TRUE=deleted, FALSE=exists */
+ __attribute__((nonnull));
+/**************************************************************//**
+Change the ownership of an off-page column. */
+UNIV_INTERN
+void
+btr_blob_dbg_owner(
+/*===============*/
+ const rec_t* rec, /*!< in: record */
+ dict_index_t* index, /*!< in/out: index */
+ const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
+ ulint i, /*!< in: ith field in rec */
+ ibool own) /*!< in: TRUE=owned, FALSE=disowned */
+ __attribute__((nonnull));
+/** Assert that there are no BLOB references to or from the given page. */
+# define btr_blob_dbg_assert_empty(index, page_no) \
+ ut_a(btr_blob_dbg_is_empty(index, page_no))
+#else /* UNIV_BLOB_DEBUG */
+# define btr_blob_dbg_add_blob(rec, field_no, page, index, ctx) ((void) 0)
+# define btr_blob_dbg_set_deleted_flag(rec, index, offsets, del)((void) 0)
+# define btr_blob_dbg_owner(rec, index, offsets, i, val) ((void) 0)
+# define btr_blob_dbg_assert_empty(index, page_no) ((void) 0)
+#endif /* UNIV_BLOB_DEBUG */
+
/**************************************************************//**
Gets the root node of a tree and x-latches it.
@return root page, x-latched */
@@ -105,26 +190,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/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
index 6c580a0bd6e..ccf41904fd0 100644
--- a/storage/innobase/include/btr0btr.ic
+++ b/storage/innobase/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/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index 16a557850a3..be918439f59 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -243,6 +243,22 @@ btr_cur_pessimistic_insert(
que_thr_t* thr, /*!< in: query thread or NULL */
mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
+See if there is enough place in the page modification log to log
+an update-in-place.
+@return TRUE if enough place */
+UNIV_INTERN
+ibool
+btr_cur_update_alloc_zip(
+/*=====================*/
+ page_zip_des_t* page_zip,/*!< in/out: compressed page */
+ buf_block_t* block, /*!< in/out: buffer page */
+ dict_index_t* index, /*!< in: the index corresponding to the block */
+ ulint length, /*!< in: size needed */
+ ibool create, /*!< in: TRUE=delete-and-insert,
+ FALSE=update-in-place */
+ mtr_t* mtr) /*!< in: mini-transaction */
+ __attribute__((nonnull, warn_unused_result));
+/*************************************************************//**
Updates a record when the update causes no size changes in its fields.
@return DB_SUCCESS or error number */
UNIV_INTERN
@@ -317,10 +333,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 */
@@ -446,57 +466,42 @@ btr_estimate_n_rows_in_range(
/*******************************************************************//**
Estimates the number of different key values in a given index, for
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
-The estimates are stored in the array index->stat_n_diff_key_vals. */
+The estimates are stored in the array index->stat_n_diff_key_vals.
+If innodb_stats_method is nulls_ignored, we also record the number of
+non-null values for each prefix and stored the estimates in
+array index->stat_n_non_null_key_vals. */
UNIV_INTERN
void
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(
-/*============================*/
+btr_store_big_rec_extern_fields_func(
+/*=================================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
@@ -505,10 +510,42 @@ btr_store_big_rec_extern_fields(
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
- big_rec_t* big_rec_vec, /*!< in: vector containing fields
+#ifdef UNIV_DEBUG
+ mtr_t* local_mtr, /*!< in: mtr containing the
+ latch to rec and to the tree */
+#endif /* UNIV_DEBUG */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ibool update_in_place,/*! in: TRUE if the record is updated
+ in place (not delete+insert) */
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+ const big_rec_t*big_rec_vec) /*!< in: vector containing fields
to be stored externally */
- mtr_t* local_mtr); /*!< in: mtr containing the latch to
- rec and to the tree */
+ __attribute__((nonnull));
+
+/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
+them in rec. The extern flags in rec will have to be set beforehand.
+The fields are stored on pages allocated from leaf node
+file segment of the index tree.
+@param index in: clustered index; MUST be X-latched by mtr
+@param b in/out: block containing rec; MUST be X-latched by mtr
+@param rec in/out: clustered index record
+@param offsets in: rec_get_offsets(rec, index);
+ the "external storage" flags in offsets will not be adjusted
+@param mtr in: mini-transaction that holds x-latch on index and b
+@param upd in: TRUE if the record is updated in place (not delete+insert)
+@param big in: vector containing fields to be stored externally
+@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
+#ifdef UNIV_DEBUG
+# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
+ btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
+#elif defined UNIV_BLOB_LIGHT_DEBUG
+# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
+ btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
+#else
+# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
+ btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
+#endif
+
/*******************************************************************//**
Frees the space in an externally stored field to the file space
management if the field in data is owned the externally stored field,
diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h
index 2334a266280..6c11c973fc9 100644
--- a/storage/innobase/include/btr0pcur.h
+++ b/storage/innobase/include/btr0pcur.h
@@ -150,7 +150,7 @@ UNIV_INLINE
ulint
btr_pcur_get_up_match(
/*==================*/
- btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
+ const btr_pcur_t* cursor); /*!< in: persistent cursor */
/**************************************************************//**
Gets the low_match value for a pcur after a search.
@return number of matched fields at the cursor or to the right if
@@ -159,7 +159,7 @@ UNIV_INLINE
ulint
btr_pcur_get_low_match(
/*===================*/
- btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
+ const btr_pcur_t* cursor); /*!< in: persistent cursor */
/**************************************************************//**
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
user record satisfying the search condition, in the case PAGE_CUR_L or
@@ -264,22 +264,6 @@ ulint
btr_pcur_get_rel_pos(
/*=================*/
const btr_pcur_t* cursor);/*!< in: persistent cursor */
-/*********************************************************//**
-Sets the mtr field for a pcur. */
-UNIV_INLINE
-void
-btr_pcur_set_mtr(
-/*=============*/
- btr_pcur_t* cursor, /*!< in: persistent cursor */
- mtr_t* mtr); /*!< in, own: mtr */
-/*********************************************************//**
-Gets the mtr field for a pcur.
-@return mtr */
-UNIV_INLINE
-mtr_t*
-btr_pcur_get_mtr(
-/*=============*/
- btr_pcur_t* cursor); /*!< in: persistent cursor */
/**************************************************************//**
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
that is, the cursor becomes detached. If there have been modifications
@@ -387,10 +371,6 @@ page_cur_t*
btr_pcur_get_page_cur(
/*==================*/
const btr_pcur_t* cursor); /*!< in: persistent cursor */
-#else /* UNIV_DEBUG */
-# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
-# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
-#endif /* UNIV_DEBUG */
/*********************************************************//**
Returns the page of a persistent cursor.
@return pointer to the page */
@@ -398,7 +378,7 @@ UNIV_INLINE
page_t*
btr_pcur_get_page(
/*==============*/
- btr_pcur_t* cursor);/*!< in: persistent cursor */
+ const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Returns the buffer block of a persistent cursor.
@return pointer to the block */
@@ -406,7 +386,7 @@ UNIV_INLINE
buf_block_t*
btr_pcur_get_block(
/*===============*/
- btr_pcur_t* cursor);/*!< in: persistent cursor */
+ const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Returns the record of a persistent cursor.
@return pointer to the record */
@@ -414,7 +394,14 @@ UNIV_INLINE
rec_t*
btr_pcur_get_rec(
/*=============*/
- btr_pcur_t* cursor);/*!< in: persistent cursor */
+ const btr_pcur_t* cursor);/*!< in: persistent cursor */
+#else /* UNIV_DEBUG */
+# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
+# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
+# define btr_pcur_get_page(cursor) ((cursor)->btr_cur.page_cur.block->frame)
+# define btr_pcur_get_block(cursor) ((cursor)->btr_cur.page_cur.block)
+# define btr_pcur_get_rec(cursor) ((cursor)->btr_cur.page_cur.rec)
+#endif /* UNIV_DEBUG */
/*********************************************************//**
Checks if the persistent cursor is on a user record. */
UNIV_INLINE
@@ -517,9 +504,6 @@ struct btr_pcur_struct{
/* NOTE that the following fields may possess dynamically allocated
memory which should be freed if not needed anymore! */
- mtr_t* mtr; /*!< NULL, or this field may contain
- a mini-transaction which holds the
- latch on the cursor page */
byte* old_rec_buf; /*!< NULL, or a dynamically allocated
buffer for old_rec */
ulint buf_size; /*!< old_rec_buf size if old_rec_buf
diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic
index 0c38797e6c5..59fdb21824b 100644
--- a/storage/innobase/include/btr0pcur.ic
+++ b/storage/innobase/include/btr0pcur.ic
@@ -42,34 +42,6 @@ btr_pcur_get_rel_pos(
return(cursor->rel_pos);
}
-/*********************************************************//**
-Sets the mtr field for a pcur. */
-UNIV_INLINE
-void
-btr_pcur_set_mtr(
-/*=============*/
- btr_pcur_t* cursor, /*!< in: persistent cursor */
- mtr_t* mtr) /*!< in, own: mtr */
-{
- ut_ad(cursor);
-
- cursor->mtr = mtr;
-}
-
-/*********************************************************//**
-Gets the mtr field for a pcur.
-@return mtr */
-UNIV_INLINE
-mtr_t*
-btr_pcur_get_mtr(
-/*=============*/
- btr_pcur_t* cursor) /*!< in: persistent cursor */
-{
- ut_ad(cursor);
-
- return(cursor->mtr);
-}
-
#ifdef UNIV_DEBUG
/*********************************************************//**
Returns the btr cursor component of a persistent cursor.
@@ -95,7 +67,7 @@ btr_pcur_get_page_cur(
{
return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor)));
}
-#endif /* UNIV_DEBUG */
+
/*********************************************************//**
Returns the page of a persistent cursor.
@return pointer to the page */
@@ -103,7 +75,7 @@ UNIV_INLINE
page_t*
btr_pcur_get_page(
/*==============*/
- btr_pcur_t* cursor) /*!< in: persistent cursor */
+ const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
@@ -117,7 +89,7 @@ UNIV_INLINE
buf_block_t*
btr_pcur_get_block(
/*===============*/
- btr_pcur_t* cursor) /*!< in: persistent cursor */
+ const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
@@ -131,13 +103,14 @@ UNIV_INLINE
rec_t*
btr_pcur_get_rec(
/*=============*/
- btr_pcur_t* cursor) /*!< in: persistent cursor */
+ const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor)));
}
+#endif /* UNIV_DEBUG */
/**************************************************************//**
Gets the up_match value for a pcur after a search.
@@ -147,9 +120,9 @@ UNIV_INLINE
ulint
btr_pcur_get_up_match(
/*==================*/
- btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
+ const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
- btr_cur_t* btr_cursor;
+ const btr_cur_t* btr_cursor;
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
@@ -169,9 +142,9 @@ UNIV_INLINE
ulint
btr_pcur_get_low_match(
/*===================*/
- btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
+ const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
- btr_cur_t* btr_cursor;
+ const btr_cur_t* btr_cursor;
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h
index ef4a6b04b34..07c06fb18d7 100644
--- a/storage/innobase/include/btr0types.h
+++ b/storage/innobase/include/btr0types.h
@@ -38,6 +38,131 @@ typedef struct btr_cur_struct btr_cur_t;
/** B-tree search information for the adaptive hash index */
typedef struct btr_search_struct btr_search_t;
+#ifdef UNIV_BLOB_DEBUG
+# include "buf0types.h"
+/** An index->blobs entry for keeping track of off-page column references */
+typedef struct btr_blob_dbg_struct btr_blob_dbg_t;
+
+/** Insert to index->blobs a reference to an off-page column.
+@param index the index tree
+@param b the reference
+@param ctx context (for logging) */
+UNIV_INTERN
+void
+btr_blob_dbg_rbt_insert(
+/*====================*/
+ dict_index_t* index, /*!< in/out: index tree */
+ const btr_blob_dbg_t* b, /*!< in: the reference */
+ const char* ctx) /*!< in: context (for logging) */
+ __attribute__((nonnull));
+
+/** Remove from index->blobs a reference to an off-page column.
+@param index the index tree
+@param b the reference
+@param ctx context (for logging) */
+UNIV_INTERN
+void
+btr_blob_dbg_rbt_delete(
+/*====================*/
+ dict_index_t* index, /*!< in/out: index tree */
+ const btr_blob_dbg_t* b, /*!< in: the reference */
+ const char* ctx) /*!< in: context (for logging) */
+ __attribute__((nonnull));
+
+/**************************************************************//**
+Add to index->blobs any references to off-page columns from a record.
+@return number of references added */
+UNIV_INTERN
+ulint
+btr_blob_dbg_add_rec(
+/*=================*/
+ const rec_t* rec, /*!< in: record */
+ dict_index_t* index, /*!< in/out: index */
+ const ulint* offsets,/*!< in: offsets */
+ const char* ctx) /*!< in: context (for logging) */
+ __attribute__((nonnull));
+/**************************************************************//**
+Remove from index->blobs any references to off-page columns from a record.
+@return number of references removed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_remove_rec(
+/*====================*/
+ const rec_t* rec, /*!< in: record */
+ dict_index_t* index, /*!< in/out: index */
+ const ulint* offsets,/*!< in: offsets */
+ const char* ctx) /*!< in: context (for logging) */
+ __attribute__((nonnull));
+/**************************************************************//**
+Count and add to index->blobs any references to off-page columns
+from records on a page.
+@return number of references added */
+UNIV_INTERN
+ulint
+btr_blob_dbg_add(
+/*=============*/
+ const page_t* page, /*!< in: rewritten page */
+ dict_index_t* index, /*!< in/out: index */
+ const char* ctx) /*!< in: context (for logging) */
+ __attribute__((nonnull));
+/**************************************************************//**
+Count and remove from index->blobs any references to off-page columns
+from records on a page.
+Used when reorganizing a page, before copying the records.
+@return number of references removed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_remove(
+/*================*/
+ const page_t* page, /*!< in: b-tree page */
+ dict_index_t* index, /*!< in/out: index */
+ const char* ctx) /*!< in: context (for logging) */
+ __attribute__((nonnull));
+/**************************************************************//**
+Restore in index->blobs any references to off-page columns
+Used when page reorganize fails due to compressed page overflow. */
+UNIV_INTERN
+void
+btr_blob_dbg_restore(
+/*=================*/
+ const page_t* npage, /*!< in: page that failed to compress */
+ const page_t* page, /*!< in: copy of original page */
+ dict_index_t* index, /*!< in/out: index */
+ const char* ctx) /*!< in: context (for logging) */
+ __attribute__((nonnull));
+
+/** Operation that processes the BLOB references of an index record
+@param[in] rec record on index page
+@param[in/out] index the index tree of the record
+@param[in] offsets rec_get_offsets(rec,index)
+@param[in] ctx context (for logging)
+@return number of BLOB references processed */
+typedef ulint (*btr_blob_dbg_op_f)
+(const rec_t* rec,dict_index_t* index,const ulint* offsets,const char* ctx);
+
+/**************************************************************//**
+Count and process all references to off-page columns on a page.
+@return number of references processed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_op(
+/*============*/
+ const page_t* page, /*!< in: B-tree leaf page */
+ const rec_t* rec, /*!< in: record to start from
+ (NULL to process the whole page) */
+ dict_index_t* index, /*!< in/out: index */
+ const char* ctx, /*!< in: context (for logging) */
+ const btr_blob_dbg_op_f op) /*!< in: operation on records */
+ __attribute__((nonnull(1,3,4,5)));
+#else /* UNIV_BLOB_DEBUG */
+# define btr_blob_dbg_add_rec(rec, index, offsets, ctx) ((void) 0)
+# define btr_blob_dbg_add(page, index, ctx) ((void) 0)
+# define btr_blob_dbg_remove_rec(rec, index, offsets, ctx) ((void) 0)
+# define btr_blob_dbg_remove(page, index, ctx) ((void) 0)
+# define btr_blob_dbg_restore(npage, page, index, ctx) ((void) 0)
+# define btr_blob_dbg_op(page, rec, index, ctx, op) ((void) 0)
+#endif /* UNIV_BLOB_DEBUG */
+
/** The size of a reference to data stored on a different page.
The reference is stored at the end of the prefix of the field
in the index record. */
diff --git a/storage/innobase/include/buf0buddy.h b/storage/innobase/include/buf0buddy.h
index 03588d18197..b255d8c9351 100644
--- a/storage/innobase/include/buf0buddy.h
+++ b/storage/innobase/include/buf0buddy.h
@@ -36,7 +36,7 @@ Created December 2006 by Marko Makela
/**********************************************************************//**
Allocate a block. The thread calling this function must hold
-buf_pool->mutex and must not hold buf_pool_zip_mutex or any
+buf_pool->mutex and must not hold buf_pool->zip_mutex or any
block->mutex. The buf_pool->mutex may only be released and reacquired
if lru != NULL. This function should only be used for allocating
compressed page frames or control blocks (buf_page_t). Allocated
diff --git a/storage/innobase/include/buf0buddy.ic b/storage/innobase/include/buf0buddy.ic
index 387eacc754a..e50c33ea15a 100644
--- a/storage/innobase/include/buf0buddy.ic
+++ b/storage/innobase/include/buf0buddy.ic
@@ -35,7 +35,7 @@ Created December 2006 by Marko Makela
/**********************************************************************//**
Allocate a block. The thread calling this function must hold
-buf_pool->mutex and must not hold buf_pool_zip_mutex or any block->mutex.
+buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex.
The buf_pool->mutex may only be released and reacquired if lru != NULL.
@return allocated block, possibly NULL if lru==NULL */
UNIV_INTERN
@@ -86,7 +86,7 @@ buf_buddy_get_slot(
/**********************************************************************//**
Allocate a block. The thread calling this function must hold
-buf_pool->mutex and must not hold buf_pool_zip_mutex or any
+buf_pool->mutex and must not hold buf_pool->zip_mutex or any
block->mutex. The buf_pool->mutex may only be released and reacquired
if lru != NULL. This function should only be used for allocating
compressed page frames or control blocks (buf_page_t). Allocated
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index f33ef65ddf2..d83d484bace 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -41,6 +41,8 @@ Created 11/5/1995 Heikki Tuuri
/* @{ */
#define BUF_GET 10 /*!< get always */
#define BUF_GET_IF_IN_POOL 11 /*!< get if in pool */
+#define BUF_PEEK_IF_IN_POOL 12 /*!< get if in pool, do not make
+ the block young in the LRU list */
#define BUF_GET_NO_LATCH 14 /*!< get and bufferfix, but
set no latch; we have
separated this case, because
@@ -51,6 +53,9 @@ Created 11/5/1995 Heikki Tuuri
/*!< Get the page only if it's in the
buffer pool, if not then set a watch
on the page. */
+#define BUF_GET_POSSIBLY_FREED 16
+ /*!< Like BUF_GET, but do not mind
+ if the file page has been freed. */
/* @} */
/** @name Modes for buf_page_get_known_nowait */
/* @{ */
@@ -69,7 +74,7 @@ Created 11/5/1995 Heikki Tuuri
#define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent
buffer pool watches */
-extern buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS]; /*!< The buffer pools
+extern buf_pool_t* buf_pool_ptr; /*!< The buffer pools
of the database */
#ifdef UNIV_DEBUG
extern ibool buf_debug_prints;/*!< If this is set TRUE, the program
@@ -96,7 +101,7 @@ enum buf_page_state {
BUF_BLOCK_ZIP_FREE = 0, /*!< contains a free
compressed page */
BUF_BLOCK_POOL_WATCH = 0, /*!< a sentinel for the buffer pool
- watch, element of buf_pool_watch[] */
+ watch, element of buf_pool->watch[] */
BUF_BLOCK_ZIP_PAGE, /*!< contains a clean
compressed page */
BUF_BLOCK_ZIP_DIRTY, /*!< contains a compressed
@@ -116,6 +121,76 @@ enum buf_page_state {
before putting to the free list */
};
+
+/** This structure defines information we will fetch from each buffer pool. It
+will be used to print table IO stats */
+struct buf_pool_info_struct{
+ /* General buffer pool info */
+ ulint pool_unique_id; /*!< Buffer Pool ID */
+ ulint pool_size; /*!< Buffer Pool size in pages */
+ ulint lru_len; /*!< Length of buf_pool->LRU */
+ ulint old_lru_len; /*!< buf_pool->LRU_old_len */
+ ulint free_list_len; /*!< Length of buf_pool->free list */
+ ulint flush_list_len; /*!< Length of buf_pool->flush_list */
+ ulint n_pend_unzip; /*!< buf_pool->n_pend_unzip, pages
+ pending decompress */
+ ulint n_pend_reads; /*!< buf_pool->n_pend_reads, pages
+ pending read */
+ ulint n_pending_flush_lru; /*!< Pages pending flush in LRU */
+ ulint n_pending_flush_list; /*!< Pages pending flush in FLUSH
+ LIST */
+ ulint n_pending_flush_single_page;/*!< Pages pending flush in
+ BUF_FLUSH_SINGLE_PAGE list */
+ ulint n_pages_made_young; /*!< number of pages made young */
+ ulint n_pages_not_made_young; /*!< number of pages not made young */
+ ulint n_pages_read; /*!< buf_pool->n_pages_read */
+ ulint n_pages_created; /*!< buf_pool->n_pages_created */
+ ulint n_pages_written; /*!< buf_pool->n_pages_written */
+ ulint n_page_gets; /*!< buf_pool->n_page_gets */
+ ulint n_ra_pages_read; /*!< buf_pool->n_ra_pages_read, number
+ of pages readahead */
+ ulint n_ra_pages_evicted; /*!< buf_pool->n_ra_pages_evicted,
+ number of readahead pages evicted
+ without access */
+ ulint n_page_get_delta; /*!< num of buffer pool page gets since
+ last printout */
+
+ /* Buffer pool access stats */
+ double page_made_young_rate; /*!< page made young rate in pages
+ per second */
+ double page_not_made_young_rate;/*!< page not made young rate
+ in pages per second */
+ double pages_read_rate; /*!< num of pages read per second */
+ double pages_created_rate; /*!< num of pages create per second */
+ double pages_written_rate; /*!< num of pages written per second */
+ ulint page_read_delta; /*!< num of pages read since last
+ printout */
+ ulint young_making_delta; /*!< num of pages made young since
+ last printout */
+ ulint not_young_making_delta; /*!< num of pages not make young since
+ last printout */
+
+ /* Statistics about read ahead algorithm. */
+ double pages_readahead_rate; /*!< readahead rate in pages per
+ second */
+ double pages_evicted_rate; /*!< rate of readahead page evicted
+ without access, in pages per second */
+
+ /* Stats about LRU eviction */
+ ulint unzip_lru_len; /*!< length of buf_pool->unzip_LRU
+ list */
+ /* Counters for LRU policy */
+ ulint io_sum; /*!< buf_LRU_stat_sum.io */
+ ulint io_cur; /*!< buf_LRU_stat_cur.io, num of IO
+ for current interval */
+ ulint unzip_sum; /*!< buf_LRU_stat_sum.unzip */
+ ulint unzip_cur; /*!< buf_LRU_stat_cur.unzip, num
+ pages decompressed in current
+ interval */
+};
+
+typedef struct buf_pool_info_struct buf_pool_info_t;
+
#ifndef UNIV_HOTBACKUP
/********************************************************************//**
Acquire mutex on all buffer pool instances */
@@ -206,9 +281,9 @@ UNIV_INTERN
buf_block_t*
buf_block_alloc(
/*============*/
- buf_pool_t* buf_pool, /*!< buffer pool instance */
- ulint zip_size); /*!< in: compressed page size in bytes,
- or 0 if uncompressed tablespace */
+ buf_pool_t* buf_pool); /*!< in: buffer pool instance,
+ or NULL for round-robin selection
+ of the buffer pool */
/********************************************************************//**
Frees a buffer block which does not contain a file page. */
UNIV_INLINE
@@ -326,7 +401,7 @@ buf_page_get_gen(
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
buf_block_t* guess, /*!< in: guessed block or NULL */
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
- BUF_GET_NO_LATCH or
+ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH or
BUF_GET_IF_IN_POOL_OR_WATCH */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
@@ -410,7 +485,7 @@ buf_reset_check_index_page_at_flush(
/*================================*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */
-#ifdef UNIV_DEBUG_FILE_ACCESSES
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
This function should be called when we free a file page and want the
@@ -435,7 +510,7 @@ buf_page_reset_file_page_was_freed(
/*===============================*/
ulint space, /*!< in: space id */
ulint offset); /*!< in: page number */
-#endif /* UNIV_DEBUG_FILE_ACCESSES */
+#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/********************************************************************//**
Reads the freed_page_clock of a buffer block.
@return freed_page_clock */
@@ -1034,6 +1109,15 @@ buf_page_address_fold(
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page within space */
__attribute__((const));
+/********************************************************************//**
+Calculates the index of a buffer pool to the buf_pool[] array.
+@return the position of the buffer pool in buf_pool[] */
+UNIV_INLINE
+ulint
+buf_pool_index(
+/*===========*/
+ const buf_pool_t* buf_pool) /*!< in: buffer pool */
+ __attribute__((nonnull, const));
/******************************************************************//**
Returns the buffer pool instance given a page instance
@return buf_pool */
@@ -1065,8 +1149,9 @@ Returns the buffer pool instance given its array index
UNIV_INLINE
buf_pool_t*
buf_pool_from_array(
-/*====================*/
- ulint index); /*!< in: array index to get buffer pool instance from */
+/*================*/
+ ulint index); /*!< in: array index to get
+ buffer pool instance from */
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
@return block, NULL if not found */
@@ -1204,16 +1289,21 @@ struct buf_page_struct{
unsigned io_fix:2; /*!< type of pending I/O operation;
also protected by buf_pool->mutex
@see enum buf_io_fix */
- unsigned buf_fix_count:25;/*!< count of how manyfold this block
+ unsigned buf_fix_count:19;/*!< count of how manyfold this block
is currently bufferfixed */
+ unsigned buf_pool_index:6;/*!< index number of the buffer pool
+ that this block belongs to */
+# if MAX_BUFFER_POOLS > 64
+# error "MAX_BUFFER_POOLS > 64; redefine buf_pool_index:6"
+# endif
/* @} */
#endif /* !UNIV_HOTBACKUP */
page_zip_des_t zip; /*!< compressed page; zip.data
(but not the data it points to) is
- also protected by buf_pool_mutex;
+ also protected by buf_pool->mutex;
state == BUF_BLOCK_ZIP_PAGE and
zip.data == NULL means an active
- buf_pool_watch */
+ buf_pool->watch */
#ifndef UNIV_HOTBACKUP
buf_page_t* hash; /*!< node used in chaining to
buf_pool->page_hash or
@@ -1224,15 +1314,16 @@ struct buf_page_struct{
#endif /* UNIV_DEBUG */
/** @name Page flushing fields
- All these are protected by buf_pool_mutex. */
+ All these are protected by buf_pool->mutex. */
/* @{ */
UT_LIST_NODE_T(buf_page_t) list;
/*!< based on state, this is a
list node, protected either by
- buf_pool_mutex or by
- flush_list_mutex, in one of the
- following lists in buf_pool:
+ buf_pool->mutex or by
+ buf_pool->flush_list_mutex,
+ in one of the following lists in
+ buf_pool:
- BUF_BLOCK_NOT_USED: free
- BUF_BLOCK_FILE_PAGE: flush_list
@@ -1242,9 +1333,9 @@ struct buf_page_struct{
If bpage is part of flush_list
then the node pointers are
- covered by flush_list_mutex.
+ covered by buf_pool->flush_list_mutex.
Otherwise these pointers are
- protected by buf_pool_mutex.
+ protected by buf_pool->mutex.
The contents of the list node
is undefined if !in_flush_list
@@ -1256,17 +1347,18 @@ struct buf_page_struct{
#ifdef UNIV_DEBUG
ibool in_flush_list; /*!< TRUE if in buf_pool->flush_list;
- when flush_list_mutex is free, the
- following should hold: in_flush_list
+ when buf_pool->flush_list_mutex is
+ free, the following should hold:
+ in_flush_list
== (state == BUF_BLOCK_FILE_PAGE
|| state == BUF_BLOCK_ZIP_DIRTY)
Writes to this field must be
covered by both block->mutex
- and flush_list_mutex. Hence
+ and buf_pool->flush_list_mutex. Hence
reads can happen while holding
any one of the two mutexes */
ibool in_free_list; /*!< TRUE if in buf_pool->free; when
- buf_pool_mutex is free, the following
+ buf_pool->mutex is free, the following
should hold: in_free_list
== (state == BUF_BLOCK_NOT_USED) */
#endif /* UNIV_DEBUG */
@@ -1286,7 +1378,7 @@ struct buf_page_struct{
modifications are on disk.
Writes to this field must be
covered by both block->mutex
- and flush_list_mutex. Hence
+ and buf_pool->flush_list_mutex. Hence
reads can happen while holding
any one of the two mutexes */
/* @} */
@@ -1316,14 +1408,12 @@ struct buf_page_struct{
0 if the block was never accessed
in the buffer pool */
/* @} */
-# ifdef UNIV_DEBUG_FILE_ACCESSES
+# if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ibool file_page_was_freed;
/*!< this is set to TRUE when fsp
frees a page in buffer pool */
-# endif /* UNIV_DEBUG_FILE_ACCESSES */
+# endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */
- buf_pool_t* buf_pool; /*!< buffer pool instance this
- page belongs to */
};
/** The buffer control block structure */
@@ -1661,20 +1751,13 @@ struct buf_pool_struct{
/* @} */
};
-/** mutex protecting the buffer pool struct and control blocks, except the
-read-write lock in them */
-extern mutex_t buf_pool_mutex;
-/** mutex protecting the control blocks of compressed-only pages
-(of type buf_page_t, not buf_block_t) */
-extern mutex_t buf_pool_zip_mutex;
-
-/** @name Accessors for buf_pool_mutex.
-Use these instead of accessing buf_pool_mutex directly. */
+/** @name Accessors for buf_pool->mutex.
+Use these instead of accessing buf_pool->mutex directly. */
/* @{ */
-/** Test if buf_pool_mutex is owned. */
+/** Test if a buffer pool mutex is owned. */
#define buf_pool_mutex_own(b) mutex_own(&b->mutex)
-/** Acquire the buffer pool mutex. */
+/** Acquire a buffer pool mutex. */
#define buf_pool_mutex_enter(b) do { \
ut_ad(!mutex_own(&b->zip_mutex)); \
mutex_enter(&b->mutex); \
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 713b7cb990d..e2e83de0a78 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -46,6 +46,48 @@ buf_pool_get_curr_size(void)
return(srv_buf_pool_curr_size);
}
+/********************************************************************//**
+Calculates the index of a buffer pool to the buf_pool[] array.
+@return the position of the buffer pool in buf_pool[] */
+UNIV_INLINE
+ulint
+buf_pool_index(
+/*===========*/
+ const buf_pool_t* buf_pool) /*!< in: buffer pool */
+{
+ ulint i = buf_pool - buf_pool_ptr;
+ ut_ad(i < MAX_BUFFER_POOLS);
+ ut_ad(i < srv_buf_pool_instances);
+ return(i);
+}
+
+/******************************************************************//**
+Returns the buffer pool instance given a page instance
+@return buf_pool */
+UNIV_INLINE
+buf_pool_t*
+buf_pool_from_bpage(
+/*================*/
+ const buf_page_t* bpage) /*!< in: buffer pool page */
+{
+ ulint i;
+ i = bpage->buf_pool_index;
+ ut_ad(i < srv_buf_pool_instances);
+ return(&buf_pool_ptr[i]);
+}
+
+/******************************************************************//**
+Returns the buffer pool instance given a block instance
+@return buf_pool */
+UNIV_INLINE
+buf_pool_t*
+buf_pool_from_block(
+/*================*/
+ const buf_block_t* block) /*!< in: block */
+{
+ return(buf_pool_from_bpage(&block->page));
+}
+
/*********************************************************************//**
Gets the current size of buffer buf_pool in pages.
@return size in pages*/
@@ -886,33 +928,6 @@ buf_block_buf_fix_dec(
}
/******************************************************************//**
-Returns the buffer pool instance given a page instance
-@return buf_pool */
-UNIV_INLINE
-buf_pool_t*
-buf_pool_from_bpage(
-/*================*/
- const buf_page_t* bpage) /*!< in: buffer pool page */
-{
- /* Every page must be in some buffer pool. */
- ut_ad(bpage->buf_pool != NULL);
-
- return(bpage->buf_pool);
-}
-
-/******************************************************************//**
-Returns the buffer pool instance given a block instance
-@return buf_pool */
-UNIV_INLINE
-buf_pool_t*
-buf_pool_from_block(
-/*================*/
- const buf_block_t* block) /*!< in: block */
-{
- return(buf_pool_from_bpage(&block->page));
-}
-
-/******************************************************************//**
Returns the buffer pool instance given space and offset of page
@return buffer pool */
UNIV_INLINE
@@ -929,7 +944,7 @@ buf_pool_get(
ignored_offset = offset >> 6; /* 2log of BUF_READ_AHEAD_AREA (64)*/
fold = buf_page_address_fold(space, ignored_offset);
index = fold % srv_buf_pool_instances;
- return buf_pool_ptr[index];
+ return(&buf_pool_ptr[index]);
}
/******************************************************************//**
@@ -939,10 +954,12 @@ UNIV_INLINE
buf_pool_t*
buf_pool_from_array(
/*================*/
- ulint index) /*!< in: array index to get
+ ulint index) /*!< in: array index to get
buffer pool instance from */
{
- return buf_pool_ptr[index];
+ ut_ad(index < MAX_BUFFER_POOLS);
+ ut_ad(index < srv_buf_pool_instances);
+ return(&buf_pool_ptr[index]);
}
/******************************************************************//**
diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h
index 55814b6bf86..ae27f5dab0e 100644
--- a/storage/innobase/include/buf0flu.h
+++ b/storage/innobase/include/buf0flu.h
@@ -84,6 +84,21 @@ buf_flush_init_for_writing(
ib_uint64_t newest_lsn); /*!< in: newest modification lsn
to the page */
#ifndef UNIV_HOTBACKUP
+# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+/********************************************************************//**
+Writes a flushable page asynchronously from the buffer pool to a file.
+NOTE: buf_pool->mutex and block->mutex must be held upon entering this
+function, and they will be released by this function after flushing.
+This is loosely based on buf_flush_batch() and buf_flush_page().
+@return TRUE if the page was flushed and the mutexes released */
+UNIV_INTERN
+ibool
+buf_flush_page_try(
+/*===============*/
+ buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
+ buf_block_t* block) /*!< in/out: buffer control block */
+ __attribute__((nonnull, warn_unused_result));
+# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/*******************************************************************//**
This utility flushes dirty blocks from the end of the LRU list.
NOTE: The calling thread may own latches to pages: to avoid deadlocks,
@@ -123,7 +138,18 @@ UNIV_INTERN
void
buf_flush_wait_batch_end(
/*=====================*/
- buf_pool_t* buf_pool, /*!< buffer pool instance */
+ buf_pool_t* buf_pool, /*!< in: buffer pool instance */
+ enum buf_flush type); /*!< in: BUF_FLUSH_LRU
+ or BUF_FLUSH_LIST */
+/******************************************************************//**
+Waits until a flush batch of the given type ends. This is called by
+a thread that only wants to wait for a flush to end but doesn't do
+any flushing itself. */
+UNIV_INTERN
+void
+buf_flush_wait_batch_end_wait_only(
+/*===============================*/
+ buf_pool_t* buf_pool, /*!< in: buffer pool instance */
enum buf_flush type); /*!< in: BUF_FLUSH_LRU
or BUF_FLUSH_LIST */
/********************************************************************//**
@@ -228,8 +254,8 @@ make sure that a read-ahead batch can be read efficiently in a single
sweep). */
#define BUF_FLUSH_FREE_BLOCK_MARGIN(b) (5 + BUF_READ_AHEAD_AREA(b))
/** Extra margin to apply above BUF_FLUSH_FREE_BLOCK_MARGIN */
-#define BUF_FLUSH_EXTRA_MARGIN(b) (BUF_FLUSH_FREE_BLOCK_MARGIN(b) / 4 \
- + 100)
+#define BUF_FLUSH_EXTRA_MARGIN(b) ((BUF_FLUSH_FREE_BLOCK_MARGIN(b) / 4 \
+ + 100) / srv_buf_pool_instances)
#endif /* !UNIV_HOTBACKUP */
#ifndef UNIV_NONINL
diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h
index 7bcec633d9c..9b150188b03 100644
--- a/storage/innobase/include/buf0lru.h
+++ b/storage/innobase/include/buf0lru.h
@@ -111,12 +111,9 @@ enum buf_lru_free_block_status
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
- ibool zip, /*!< in: TRUE if should remove also the
+ ibool zip) /*!< in: TRUE if should remove also the
compressed page of an uncompressed page */
- ibool* buf_pool_mutex_released);
- /*!< in: pointer to a variable that will
- be assigned TRUE if buf_pool->mutex
- was temporarily released, or NULL */
+ __attribute__((nonnull));
/******************************************************************//**
Try to free a replaceable block.
@return TRUE if found and freed */
@@ -153,9 +150,8 @@ UNIV_INTERN
buf_block_t*
buf_LRU_get_free_block(
/*===================*/
- buf_pool_t* buf_pool, /*!< in: preferred buffer pool */
- ulint zip_size); /*!< in: compressed page size in bytes,
- or 0 if uncompressed tablespace */
+ buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */
+ __attribute__((nonnull,warn_unused_result));
/******************************************************************//**
Puts a block back to the free list. */
diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h
index 4a52f9dcd8d..cdf6cdba3d1 100644
--- a/storage/innobase/include/buf0rea.h
+++ b/storage/innobase/include/buf0rea.h
@@ -70,10 +70,10 @@ UNIV_INTERN
ulint
buf_read_ahead_linear(
/*==================*/
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
- ulint offset);/*!< in: page number of a page; NOTE: the current thread
- must want access to this page (see NOTE 3 above) */
+ ulint space, /*!< in: space id */
+ ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
+ ulint offset, /*!< in: page number; see NOTE 3 above */
+ ibool inside_ibuf); /*!< in: TRUE if we are inside ibuf routine */
/********************************************************************//**
Issues read requests for pages which the ibuf module wants to read in, in
order to contract the insert buffer tree. Technically, this function is like
diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h
index 11e4027777a..f7bdd29ed90 100644
--- a/storage/innobase/include/data0data.h
+++ b/storage/innobase/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/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic
index 2e3adf4b707..5c0f8039c80 100644
--- a/storage/innobase/include/data0data.ic
+++ b/storage/innobase/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/innobase/include/data0type.h b/storage/innobase/include/data0type.h
index 850cf2e2975..d7fa0b9cd44 100644
--- a/storage/innobase/include/data0type.h
+++ b/storage/innobase/include/data0type.h
@@ -174,10 +174,13 @@ store the charset-collation number; one byte is left unused, though */
/* Pack mbminlen, mbmaxlen to mbminmaxlen. */
#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \
((mbmaxlen) * DATA_MBMAX + (mbminlen))
-/* Get mbminlen from mbminmaxlen. */
-#define DATA_MBMINLEN(mbminmaxlen) UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), 1)
+/* Get mbminlen from mbminmaxlen. Cast the result of UNIV_EXPECT to ulint
+because in GCC it returns a long. */
+#define DATA_MBMINLEN(mbminmaxlen) ((ulint) \
+ UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), \
+ 1))
/* Get mbmaxlen from mbminmaxlen. */
-#define DATA_MBMAXLEN(mbminmaxlen) ((mbminmaxlen) / DATA_MBMAX)
+#define DATA_MBMAXLEN(mbminmaxlen) ((ulint) ((mbminmaxlen) / DATA_MBMAX))
#ifndef UNIV_HOTBACKUP
/*********************************************************************//**
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index 010ab32fd31..74a2354bce3 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -94,9 +94,6 @@ enum db_err {
DB_PRIMARY_KEY_IS_NULL, /* a column in the PRIMARY KEY
was found to be NULL */
- DB_FOREIGN_EXCEED_MAX_CASCADE, /* Foreign key constraint related
- cascading delete/update exceeds
- maximum allowed depth */
DB_STATS_DO_NOT_EXIST, /* an operation that requires the
persistent storage, used for recording
@@ -104,6 +101,17 @@ enum db_err {
requested but this storage does not
exist itself or the stats for a given
table do not exist */
+ DB_FOREIGN_EXCEED_MAX_CASCADE, /* Foreign key constraint related
+ cascading delete/update exceeds
+ maximum allowed depth */
+ DB_CHILD_NO_INDEX, /* the child (foreign) table does not
+ have an index that contains the
+ foreign keys as its prefix columns */
+ DB_PARENT_NO_INDEX, /* the parent table does not
+ have an index that contains the
+ foreign keys as its prefix columns */
+ DB_TOO_BIG_INDEX_COL, /* index column size exceeds maximum
+ limit */
/* The following are partial failure codes */
DB_FAIL = 1000,
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 029cf408141..f979d0fcc96 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -136,6 +136,19 @@ dict_col_copy_type(
/*===============*/
const dict_col_t* col, /*!< in: column */
dtype_t* type); /*!< out: data type */
+/**********************************************************************//**
+Determine bytes of column prefix to be stored in the undo log. Please
+note if the table format is UNIV_FORMAT_A (< DICT_TF_FORMAT_ZIP), no prefix
+needs to be stored in the undo log.
+@return bytes of column prefix to be stored in the undo log */
+UNIV_INLINE
+ulint
+dict_max_field_len_store_undo(
+/*==========================*/
+ dict_table_t* table, /*!< in: table */
+ const dict_col_t* col); /*!< in: column which index prefix
+ is based on */
+
#endif /* !UNIV_HOTBACKUP */
#ifdef UNIV_DEBUG
/*********************************************************************//**
@@ -345,7 +358,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
@@ -440,6 +454,18 @@ function.
@return table, NULL if not found */
UNIV_INLINE
dict_table_t*
+dict_table_get_low_ignore_err(
+/*===========================*/
+ const char* table_name, /*!< in: table name */
+ dict_err_ignore_t
+ ignore_err); /*!< in: error to be ignored when
+ loading a table definition */
+/**********************************************************************//**
+Gets a table; loads it to the dictionary cache if necessary. A low-level
+function.
+@return table, NULL if not found */
+UNIV_INLINE
+dict_table_t*
dict_table_get_low(
/*===============*/
const char* table_name); /*!< in: table name */
@@ -1080,19 +1106,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
@@ -1106,21 +1126,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/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index 42f124dedfc..59811568556 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -828,6 +828,34 @@ dict_table_check_if_in_cache_low(
}
/**********************************************************************//**
+load a table into dictionary cache, ignore any error specified during load;
+@return table, NULL if not found */
+UNIV_INLINE
+dict_table_t*
+dict_table_get_low_ignore_err(
+/*==========================*/
+ const char* table_name, /*!< in: table name */
+ dict_err_ignore_t
+ ignore_err) /*!< in: error to be ignored when
+ loading a table definition */
+{
+ dict_table_t* table;
+
+ ut_ad(table_name);
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+
+ table = dict_table_check_if_in_cache_low(table_name);
+
+ if (table == NULL) {
+ table = dict_load_table(table_name, TRUE, ignore_err);
+ }
+
+ ut_ad(!table || table->cached);
+
+ return(table);
+}
+
+/**********************************************************************//**
Gets a table; loads it to the dictionary cache if necessary. A low-level
function.
@return table, NULL if not found */
@@ -845,7 +873,7 @@ dict_table_get_low(
table = dict_table_check_if_in_cache_low(table_name);
if (table == NULL) {
- table = dict_load_table(table_name, TRUE);
+ table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
}
ut_ad(!table || table->cached);
@@ -883,4 +911,30 @@ dict_table_get_on_id_low(
return(table);
}
+
+/**********************************************************************//**
+Determine bytes of column prefix to be stored in the undo log. Please
+note if the table format is UNIV_FORMAT_A (< DICT_TF_FORMAT_ZIP), no prefix
+needs to be stored in the undo log.
+@return bytes of column prefix to be stored in the undo log */
+UNIV_INLINE
+ulint
+dict_max_field_len_store_undo(
+/*==========================*/
+ dict_table_t* table, /*!< in: table */
+ const dict_col_t* col) /*!< in: column which index prefix
+ is based on */
+{
+ ulint prefix_len = 0;
+
+ if (dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP)
+ {
+ prefix_len = col->max_prefix
+ ? col->max_prefix
+ : DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+ }
+
+ return(prefix_len);
+}
+
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h
index f009f221f32..16177ade713 100644
--- a/storage/innobase/include/dict0load.h
+++ b/storage/innobase/include/dict0load.h
@@ -155,7 +155,12 @@ dict_load_field_low(
byte* last_index_id, /*!< in: last index id */
mem_heap_t* heap, /*!< in/out: memory heap
for temporary storage */
- const rec_t* rec); /*!< in: SYS_FIELDS record */
+ const rec_t* rec, /*!< in: SYS_FIELDS record */
+ char* addition_err_str,/*!< out: additional error message
+ that requires information to be
+ filled, or NULL */
+ ulint err_str_len); /*!< in: length of addition_err_str
+ in bytes */
/********************************************************************//**
Loads a table definition and also all its index definitions, and also
the cluster definition if the table is a member in a cluster. Also loads
@@ -170,7 +175,10 @@ dict_load_table(
/*============*/
const char* name, /*!< in: table name in the
databasename/tablename format */
- ibool cached);/*!< in: TRUE=add to cache, FALSE=do not */
+ ibool cached, /*!< in: TRUE=add to cache, FALSE=do not */
+ dict_err_ignore_t ignore_err);
+ /*!< in: error to be ignored when loading
+ table and its indexes' definition */
/***********************************************************************//**
Loads a table object based on the table id.
@return table; NULL if table does not exist */
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index ecc401066f1..3a475fa85fc 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -122,7 +122,7 @@ This could result in rescursive calls and out of stack error eventually.
DICT_FK_MAX_RECURSIVE_LOAD defines the maximum number of recursive loads,
when exceeded, the child table will not be loaded. It will be loaded when
the foreign constraint check needs to be run. */
-#define DICT_FK_MAX_RECURSIVE_LOAD 250
+#define DICT_FK_MAX_RECURSIVE_LOAD 255
/** Similarly, when tables are chained together with foreign key constraints
with on cascading delete/update clause, delete from parent table could
@@ -130,7 +130,7 @@ result in recursive cascading calls. This defines the maximum number of
such cascading deletes/updates allowed. When exceeded, the delete from
parent table will fail, and user has to drop excessive foreign constraint
before proceeds. */
-#define FK_MAX_CASCADE_DEL 300
+#define FK_MAX_CASCADE_DEL 255
/**********************************************************************//**
Creates a table memory object.
@@ -238,6 +238,30 @@ dict_foreign_t*
dict_mem_foreign_create(void);
/*=========================*/
+/**********************************************************************//**
+Sets the foreign_table_name_lookup pointer based on the value of
+lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup
+will point to foreign_table_name. If 2, then another string is
+allocated from the heap and set to lower case. */
+UNIV_INTERN
+void
+dict_mem_foreign_table_name_lookup_set(
+/*===================================*/
+ dict_foreign_t* foreign, /*!< in/out: foreign struct */
+ ibool do_alloc); /*!< in: is an alloc needed */
+
+/**********************************************************************//**
+Sets the referenced_table_name_lookup pointer based on the value of
+lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup
+will point to referenced_table_name. If 2, then another string is
+allocated from the heap and set to lower case. */
+UNIV_INTERN
+void
+dict_mem_referenced_table_name_lookup_set(
+/*======================================*/
+ dict_foreign_t* foreign, /*!< in/out: foreign struct */
+ ibool do_alloc); /*!< in: is an alloc needed */
+
/** Data structure for a column in a table */
struct dict_col_struct{
/*----------------------*/
@@ -278,32 +302,58 @@ struct dict_col_struct{
unsigned ord_part:1; /*!< nonzero if this column
appears in the ordering fields
of an index */
+ unsigned max_prefix:12; /*!< maximum index prefix length on
+ this column. Our current max limit is
+ 3072 for Barracuda table */
};
-/** @brief DICT_MAX_INDEX_COL_LEN is measured in bytes and is the maximum
-indexed column length (or indexed prefix length).
+/** @brief DICT_ANTELOPE_MAX_INDEX_COL_LEN is measured in bytes and
+is the maximum indexed column length (or indexed prefix length) in
+ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT. Also, in any format,
+any fixed-length field that is longer than this will be encoded as
+a variable-length field.
It is set to 3*256, so that one can create a column prefix index on
256 characters of a TEXT or VARCHAR column also in the UTF-8
charset. In that charset, a character may take at most 3 bytes. This
constant MUST NOT BE CHANGED, or the compatibility of InnoDB data
files would be at risk! */
-#define DICT_MAX_INDEX_COL_LEN REC_MAX_INDEX_COL_LEN
+#define DICT_ANTELOPE_MAX_INDEX_COL_LEN REC_ANTELOPE_MAX_INDEX_COL_LEN
+
+/** Find out maximum indexed column length by its table format.
+For ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT, the maximum
+field length is REC_ANTELOPE_MAX_INDEX_COL_LEN - 1 (767). For new
+barracuda format, the length could be REC_VERSION_56_MAX_INDEX_COL_LEN
+(3072) bytes */
+#define DICT_MAX_FIELD_LEN_BY_FORMAT(table) \
+ ((dict_table_get_format(table) < DICT_TF_FORMAT_ZIP) \
+ ? (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1) \
+ : REC_VERSION_56_MAX_INDEX_COL_LEN)
+
+#define DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags) \
+ ((((flags & DICT_TF_FORMAT_MASK) >> DICT_TF_FORMAT_SHIFT)\
+ < DICT_TF_FORMAT_ZIP) \
+ ? (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1) \
+ : REC_VERSION_56_MAX_INDEX_COL_LEN)
+
+/** Defines the maximum fixed length column size */
+#define DICT_MAX_FIXED_COL_LEN DICT_ANTELOPE_MAX_INDEX_COL_LEN
/** Data structure for a field in an index */
struct dict_field_struct{
dict_col_t* col; /*!< pointer to the table column */
const char* name; /*!< name of the column */
- unsigned prefix_len:10; /*!< 0 or the length of the column
+ unsigned prefix_len:12; /*!< 0 or the length of the column
prefix in bytes in a MySQL index of
type, e.g., INDEX (textcol(25));
must be smaller than
- DICT_MAX_INDEX_COL_LEN; NOTE that
- in the UTF-8 charset, MySQL sets this
- to 3 * the prefix len in UTF-8 chars */
+ DICT_MAX_FIELD_LEN_BY_FORMAT;
+ NOTE that in the UTF-8 charset, MySQL
+ sets this to (mbmaxlen * the prefix len)
+ in UTF-8 chars */
unsigned fixed_len:10; /*!< 0 or the fixed length of the
column if smaller than
- DICT_MAX_INDEX_COL_LEN */
+ DICT_ANTELOPE_MAX_INDEX_COL_LEN */
};
/** Data structure for an index. Most fields will be
@@ -341,6 +391,8 @@ struct dict_index_struct{
/*!< TRUE if this index is marked to be
dropped in ha_innobase::prepare_drop_index(),
otherwise FALSE */
+ unsigned corrupted:1;
+ /*!< TRUE if the index object is corrupted */
dict_field_t* fields; /*!< array of field descriptions */
#ifndef UNIV_HOTBACKUP
UT_LIST_NODE_T(dict_index_t)
@@ -356,6 +408,12 @@ struct dict_index_struct{
dict_get_n_unique(index); we
periodically calculate new
estimates */
+ ib_int64_t* stat_n_non_null_key_vals;
+ /* approximate number of non-null key values
+ for this index, for each column where
+ n < dict_get_n_unique(index); This
+ is used when innodb_stats_method is
+ "nulls_ignored". */
ulint stat_index_size;
/*!< approximate index size in
database pages */
@@ -369,6 +427,13 @@ struct dict_index_struct{
index, or 0 if the index existed
when InnoDB was started up */
#endif /* !UNIV_HOTBACKUP */
+#ifdef UNIV_BLOB_DEBUG
+ mutex_t blobs_mutex;
+ /*!< mutex protecting blobs */
+ void* blobs; /*!< map of (page_no,heap_no,field_no)
+ to first_blob_page_no; protected by
+ blobs_mutex; @see btr_blob_dbg_t */
+#endif /* UNIV_BLOB_DEBUG */
#ifdef UNIV_DEBUG
ulint magic_n;/*!< magic number */
/** Value of dict_index_struct::magic_n */
@@ -393,10 +458,14 @@ struct dict_foreign_struct{
unsigned type:6; /*!< 0 or DICT_FOREIGN_ON_DELETE_CASCADE
or DICT_FOREIGN_ON_DELETE_SET_NULL */
char* foreign_table_name;/*!< foreign table name */
+ char* foreign_table_name_lookup;
+ /*!< foreign table name used for dict lookup */
dict_table_t* foreign_table; /*!< table where the foreign key is */
const char** foreign_col_names;/*!< names of the columns in the
foreign key */
char* referenced_table_name;/*!< referenced table name */
+ char* referenced_table_name_lookup;
+ /*!< referenced table name for dict lookup*/
dict_table_t* referenced_table;/*!< table where the referenced key
is */
const char** referenced_col_names;/*!< names of the referenced
@@ -457,6 +526,8 @@ struct dict_table_struct{
to the dictionary cache */
unsigned n_def:10;/*!< number of columns defined so far */
unsigned n_cols:10;/*!< number of columns */
+ unsigned corrupted:1;
+ /*!< TRUE if table is corrupted */
dict_col_t* cols; /*!< array of column descriptions */
const char* col_names;
/*!< Column names packed in a character string
diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
index 0a9edfbfe70..8cbd7cd5783 100644
--- a/storage/innobase/include/dict0types.h
+++ b/storage/innobase/include/dict0types.h
@@ -33,11 +33,6 @@ typedef struct dict_index_struct dict_index_t;
typedef struct dict_table_struct dict_table_t;
typedef struct dict_foreign_struct dict_foreign_t;
-/* A cluster object is a table object with the type field set to
-DICT_CLUSTERED */
-
-typedef dict_table_t dict_cluster_t;
-
typedef struct ind_node_struct ind_node_t;
typedef struct tab_node_struct tab_node_t;
@@ -48,4 +43,18 @@ typedef struct tab_node_struct tab_node_t;
typedef ib_id_t table_id_t;
typedef ib_id_t index_id_t;
+/** Error to ignore when we load table dictionary into memory. However,
+the table and index will be marked as "corrupted", and caller will
+be responsible to deal with corrupted table or index.
+Note: please define the IGNORE_ERR_* as bits, so their value can
+be or-ed together */
+enum dict_err_ignore {
+ DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */
+ DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
+ page is FIL_NUL or incorrect value */
+ DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */
+};
+
+typedef enum dict_err_ignore dict_err_ignore_t;
+
#endif
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index d7d98787bcf..3a6336f1a01 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -717,6 +717,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/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index b75002944bd..edf7a1a28c1 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -174,6 +174,15 @@ innobase_strcasecmp(
const char* b); /*!< in: second string to compare */
/******************************************************************//**
+Strip dir name from a full path name and return only its file name.
+@return file name or "null" if no file name */
+UNIV_INTERN
+const char*
+innobase_basename(
+/*==============*/
+ const char* path_name); /*!< in: full path name */
+
+/******************************************************************//**
Returns true if the thread is executing a SELECT statement.
@return true if thd is executing SELECT */
@@ -276,4 +285,15 @@ thd_set_lock_wait_time(
void* thd, /*!< in: thread handle (THD*) */
ulint value); /*!< in: time waited for the lock */
+/**********************************************************************//**
+Get the current setting of the lower_case_table_names global parameter from
+mysqld.cc. We do a dirty read because for one there is no synchronization
+object and secondly there is little harm in doing so even if we get a torn
+read.
+@return value of lower_case_table_names */
+UNIV_INTERN
+ulint
+innobase_get_lower_case_table_names(void);
+/*=====================================*/
+
#endif
diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h
index 0f1631fde77..28c97fd609f 100644
--- a/storage/innobase/include/ibuf0ibuf.h
+++ b/storage/innobase/include/ibuf0ibuf.h
@@ -43,7 +43,7 @@ typedef enum {
IBUF_OP_DELETE = 2,
/* Number of different operation types. */
- IBUF_OP_COUNT = 3,
+ IBUF_OP_COUNT = 3
} ibuf_op_t;
/** Combinations of operations that can be buffered. Because the enum
@@ -63,6 +63,11 @@ typedef enum {
/** Operations that can currently be buffered. */
extern ibuf_use_t ibuf_use;
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+/** Flag to control insert buffer debugging. */
+extern uint ibuf_debug;
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
/** The insert buffer control structure */
extern ibuf_t* ibuf;
@@ -99,6 +104,22 @@ UNIV_INTERN
void
ibuf_update_max_tablespace_id(void);
/*===============================*/
+/***************************************************************//**
+Starts an insert buffer mini-transaction. */
+UNIV_INLINE
+void
+ibuf_mtr_start(
+/*===========*/
+ mtr_t* mtr) /*!< out: mini-transaction */
+ __attribute__((nonnull));
+/***************************************************************//**
+Commits an insert buffer mini-transaction. */
+UNIV_INLINE
+void
+ibuf_mtr_commit(
+/*============*/
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/*********************************************************************//**
Initializes an ibuf bitmap page. */
UNIV_INTERN
@@ -219,10 +240,12 @@ routine.
For instance, a read-ahead of non-ibuf pages is forbidden by threads
that are executing an insert buffer routine.
@return TRUE if inside an insert buffer routine */
-UNIV_INTERN
+UNIV_INLINE
ibool
-ibuf_inside(void);
-/*=============*/
+ibuf_inside(
+/*========*/
+ const mtr_t* mtr) /*!< in: mini-transaction */
+ __attribute__((nonnull, pure));
/***********************************************************************//**
Checks if a page address is an ibuf bitmap page (level 3 page) address.
@return TRUE if a bitmap page */
@@ -239,15 +262,44 @@ Must not be called when recv_no_ibuf_operations==TRUE.
@return TRUE if level 2 or level 3 page */
UNIV_INTERN
ibool
-ibuf_page(
-/*======*/
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
- ulint page_no,/*!< in: page number */
- mtr_t* mtr); /*!< in: mtr which will contain an x-latch to the
- bitmap page if the page is not one of the fixed
- address ibuf pages, or NULL, in which case a new
- transaction is created. */
+ibuf_page_low(
+/*==========*/
+ ulint space, /*!< in: space id */
+ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
+ ulint page_no,/*!< in: page number */
+#ifdef UNIV_DEBUG
+ ibool x_latch,/*!< in: FALSE if relaxed check
+ (avoid latching the bitmap page) */
+#endif /* UNIV_DEBUG */
+ const char* file, /*!< in: file name */
+ ulint line, /*!< in: line where called */
+ mtr_t* mtr) /*!< in: mtr which will contain an
+ x-latch to the bitmap page if the page
+ is not one of the fixed address ibuf
+ pages, or NULL, in which case a new
+ transaction is created. */
+ __attribute__((warn_unused_result));
+#ifdef UNIV_DEBUG
+/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
+pages. Must not be called when recv_no_ibuf_operations==TRUE.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes, or 0
+@param page_no page number
+@param mtr mini-transaction or NULL
+@return TRUE if level 2 or level 3 page */
+# define ibuf_page(space, zip_size, page_no, mtr) \
+ ibuf_page_low(space, zip_size, page_no, TRUE, __FILE__, __LINE__, mtr)
+#else /* UVIV_DEBUG */
+/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
+pages. Must not be called when recv_no_ibuf_operations==TRUE.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes, or 0
+@param page_no page number
+@param mtr mini-transaction or NULL
+@return TRUE if level 2 or level 3 page */
+# define ibuf_page(space, zip_size, page_no, mtr) \
+ ibuf_page_low(space, zip_size, page_no, __FILE__, __LINE__, mtr)
+#endif /* UVIV_DEBUG */
/***********************************************************************//**
Frees excess pages from the ibuf free list. This function is called when an OS
thread calls fsp services to allocate a new file segment, or a new page to a
diff --git a/storage/innobase/include/ibuf0ibuf.ic b/storage/innobase/include/ibuf0ibuf.ic
index e3fa6e3e929..0a22667a260 100644
--- a/storage/innobase/include/ibuf0ibuf.ic
+++ b/storage/innobase/include/ibuf0ibuf.ic
@@ -37,6 +37,30 @@ buffer inserts to this page. If there is this much of free space, the
corresponding bits are set in the ibuf bitmap. */
#define IBUF_PAGE_SIZE_PER_FREE_SPACE 32
+/***************************************************************//**
+Starts an insert buffer mini-transaction. */
+UNIV_INLINE
+void
+ibuf_mtr_start(
+/*===========*/
+ mtr_t* mtr) /*!< out: mini-transaction */
+{
+ mtr_start(mtr);
+ mtr->inside_ibuf = TRUE;
+}
+/***************************************************************//**
+Commits an insert buffer mini-transaction. */
+UNIV_INLINE
+void
+ibuf_mtr_commit(
+/*============*/
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+{
+ ut_ad(mtr->inside_ibuf);
+ ut_d(mtr->inside_ibuf = FALSE);
+ mtr_commit(mtr);
+}
+
/** Insert buffer struct */
struct ibuf_struct{
ulint size; /*!< current size of the ibuf index
@@ -120,6 +144,22 @@ ibuf_should_try(
return(FALSE);
}
+/******************************************************************//**
+Returns TRUE if the current OS thread is performing an insert buffer
+routine.
+
+For instance, a read-ahead of non-ibuf pages is forbidden by threads
+that are executing an insert buffer routine.
+@return TRUE if inside an insert buffer routine */
+UNIV_INLINE
+ibool
+ibuf_inside(
+/*========*/
+ const mtr_t* mtr) /*!< in: mini-transaction */
+{
+ return(mtr->inside_ibuf);
+}
+
/***********************************************************************//**
Checks if a page address is an ibuf bitmap page address.
@return TRUE if a bitmap page */
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index 3eca80beda4..29fdc3bbe97 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -72,9 +72,10 @@ UNIV_INLINE
trx_t*
lock_clust_rec_some_has_impl(
/*=========================*/
- const rec_t* rec, /*!< in: user record */
- dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets);/*!< in: rec_get_offsets(rec, index) */
+ const rec_t* rec, /*!< in: user record */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ __attribute__((nonnull, warn_unused_result));
/*********************************************************************//**
Gets the heap_no of the smallest user record on a page.
@return heap_no of smallest user record, or PAGE_HEAP_NO_SUPREMUM */
diff --git a/storage/innobase/include/lock0lock.ic b/storage/innobase/include/lock0lock.ic
index 014722f51c4..1d740a5fa43 100644
--- a/storage/innobase/include/lock0lock.ic
+++ b/storage/innobase/include/lock0lock.ic
@@ -75,9 +75,9 @@ UNIV_INLINE
trx_t*
lock_clust_rec_some_has_impl(
/*=========================*/
- const rec_t* rec, /*!< in: user record */
- dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ const rec_t* rec, /*!< in: user record */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
{
trx_id_t trx_id;
diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic
index 1ce00fd7313..67db6695cab 100644
--- a/storage/innobase/include/log0log.ic
+++ b/storage/innobase/include/log0log.ic
@@ -435,7 +435,7 @@ log_free_check(void)
{
#ifdef UNIV_SYNC_DEBUG
- ut_ad(sync_thread_levels_empty_gen(TRUE));
+ ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */
if (log_sys->check_flush_or_checkpoint) {
diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic
index cbce2edc661..d214c3fe6c9 100644
--- a/storage/innobase/include/mem0mem.ic
+++ b/storage/innobase/include/mem0mem.ic
@@ -350,27 +350,27 @@ mem_heap_get_top(
ulint n) /*!< in: size of the topmost element */
{
mem_block_t* block;
- void* buf;
+ byte* buf;
ut_ad(mem_heap_check(heap));
block = UT_LIST_GET_LAST(heap->base);
- buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
+ buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
#ifdef UNIV_MEM_DEBUG
- ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
+ ut_ad(mem_block_get_start(block) <= (ulint) (buf - (byte*) block));
/* In the debug version, advance buf to point at the storage which
was given to the caller in the allocation*/
- buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
+ buf += MEM_FIELD_HEADER_SIZE;
/* Check that the field lengths agree */
- ut_ad(n == (ulint)mem_field_header_get_len(buf));
+ ut_ad(n == mem_field_header_get_len(buf));
#endif
- return(buf);
+ return((void*) buf);
}
/*****************************************************************//**
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 8abca093548..5582ad63039 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -190,21 +190,21 @@ functions). The page number parameter was originally written as 0. @{ */
/* @} */
/***************************************************************//**
-Starts a mini-transaction and creates a mini-transaction handle
-and buffer in the memory buffer given by the caller.
-@return mtr buffer which also acts as the mtr handle */
+Starts a mini-transaction. */
UNIV_INLINE
-mtr_t*
+void
mtr_start(
/*======*/
- mtr_t* mtr); /*!< in: memory buffer for the mtr buffer */
+ mtr_t* mtr) /*!< out: mini-transaction */
+ __attribute__((nonnull));
/***************************************************************//**
Commits a mini-transaction. */
UNIV_INTERN
void
mtr_commit(
/*=======*/
- mtr_t* mtr); /*!< in: mini-transaction */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/**********************************************************//**
Sets and returns a savepoint in mtr.
@return savepoint */
@@ -378,6 +378,8 @@ struct mtr_struct{
#endif
dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */
+ ibool inside_ibuf;
+ /*!< TRUE if inside ibuf changes */
ibool modifications;
/* TRUE if the mtr made modifications to
buffer pool pages */
diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic
index 18f8e87b3cf..1db4a4bd735 100644
--- a/storage/innobase/include/mtr0mtr.ic
+++ b/storage/innobase/include/mtr0mtr.ic
@@ -30,26 +30,25 @@ Created 11/26/1995 Heikki Tuuri
#include "mach0data.h"
/***************************************************************//**
-Starts a mini-transaction and creates a mini-transaction handle
-and a buffer in the memory buffer given by the caller.
-@return mtr buffer which also acts as the mtr handle */
+Starts a mini-transaction. */
UNIV_INLINE
-mtr_t*
+void
mtr_start(
/*======*/
- mtr_t* mtr) /*!< in: memory buffer for the mtr buffer */
+ mtr_t* mtr) /*!< out: mini-transaction */
{
+ UNIV_MEM_INVALID(mtr, sizeof *mtr);
+
dyn_array_create(&(mtr->memo));
dyn_array_create(&(mtr->log));
mtr->log_mode = MTR_LOG_ALL;
mtr->modifications = FALSE;
+ mtr->inside_ibuf = FALSE;
mtr->n_log_recs = 0;
ut_d(mtr->state = MTR_ACTIVE);
ut_d(mtr->magic_n = MTR_MAGIC_N);
-
- return(mtr);
}
/***************************************************//**
@@ -160,7 +159,7 @@ mtr_memo_contains(
while (offset > 0) {
offset -= sizeof(mtr_memo_slot_t);
- slot = dyn_array_get_element(memo, offset);
+ slot = (mtr_memo_slot_t*) dyn_array_get_element(memo, offset);
if ((object == slot->object) && (type == slot->type)) {
diff --git a/storage/innobase/include/mysql_addons.h b/storage/innobase/include/mysql_addons.h
deleted file mode 100644
index 17660c18710..00000000000
--- a/storage/innobase/include/mysql_addons.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/mysql_addons.h
-This file contains functions that need to be added to
-MySQL code but have not been added yet.
-
-Whenever you add a function here submit a MySQL bug
-report (feature request) with the implementation. Then
-write the bug number in the comment before the
-function in this file.
-
-When MySQL commits the function it can be deleted from
-here. In a perfect world this file exists but is empty.
-
-Created November 07, 2007 Vasil Dimov
-*******************************************************/
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index 6d95b280330..fb13120a481 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -373,6 +373,7 @@ typedef HANDLE os_file_dir_t; /*!< directory stream */
typedef DIR* os_file_dir_t; /*!< directory stream */
#endif
+#ifdef __WIN__
/***********************************************************************//**
Gets the operating system version. Currently works only on Windows.
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA,
@@ -381,6 +382,7 @@ UNIV_INTERN
ulint
os_get_os_version(void);
/*===================*/
+#endif /* __WIN__ */
#ifndef UNIV_HOTBACKUP
/****************************************************************//**
Creates the seek mutexes used in positioned reads and writes. */
diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h
index ec5ccee3e27..1b98f94f641 100644
--- a/storage/innobase/include/os0sync.h
+++ b/storage/innobase/include/os0sync.h
@@ -76,6 +76,12 @@ struct os_event_struct {
/*!< list of all created events */
};
+/** Denotes an infinite delay for os_event_wait_time() */
+#define OS_SYNC_INFINITE_TIME ULINT_UNDEFINED
+
+/** Return value of os_event_wait_time() when the time is exceeded */
+#define OS_SYNC_TIME_EXCEEDED 1
+
/** Operating system mutex */
typedef struct os_mutex_struct os_mutex_str_t;
/** Operating system mutex handle */
@@ -144,10 +150,7 @@ os_event_free(
os_event_t event); /*!< in: event to free */
/**********************************************************//**
-Waits for an event object until it is in the signaled state. If
-srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
-waiting thread when the event becomes signaled (or immediately if the
-event is already in the signaled state).
+Waits for an event object until it is in the signaled state.
Typically, if the event has been signalled after the os_event_reset()
we'll return immediately because event->is_set == TRUE.
@@ -173,7 +176,23 @@ os_event_wait_low(
os_event_reset(). */
#define os_event_wait(event) os_event_wait_low(event, 0)
+#define os_event_wait_time(e, t) os_event_wait_time_low(event, t, 0)
+/**********************************************************//**
+Waits for an event object until it is in the signaled state or
+a timeout is exceeded. In Unix the timeout is always infinite.
+@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
+UNIV_INTERN
+ulint
+os_event_wait_time_low(
+/*===================*/
+ os_event_t event, /*!< in: event to wait */
+ ulint time_in_usec, /*!< in: timeout in
+ microseconds, or
+ OS_SYNC_INFINITE_TIME */
+ ib_int64_t reset_sig_count); /*!< in: zero or the value
+ returned by previous call of
+ os_event_reset(). */
/*********************************************************//**
Creates an operating system mutex semaphore. Because these are slow, the
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
diff --git a/storage/innobase/include/os0thread.h b/storage/innobase/include/os0thread.h
index cc56e2158ee..df3cdb7728e 100644
--- a/storage/innobase/include/os0thread.h
+++ b/storage/innobase/include/os0thread.h
@@ -107,8 +107,9 @@ UNIV_INTERN
void
os_thread_exit(
/*===========*/
- void* exit_value); /*!< in: exit value; in Windows this void*
+ void* exit_value) /*!< in: exit value; in Windows this void*
is cast as a DWORD */
+ UNIV_COLD __attribute__((noreturn));
/*****************************************************************//**
Returns the thread identifier of current thread.
@return current thread identifier */
@@ -117,13 +118,6 @@ os_thread_id_t
os_thread_get_curr_id(void);
/*========================*/
/*****************************************************************//**
-Returns handle to the current thread.
-@return current thread handle */
-UNIV_INTERN
-os_thread_t
-os_thread_get_curr(void);
-/*====================*/
-/*****************************************************************//**
Advises the os to give up remainder of the thread's time slice. */
UNIV_INTERN
void
@@ -136,29 +130,6 @@ void
os_thread_sleep(
/*============*/
ulint tm); /*!< in: time in microseconds */
-/******************************************************************//**
-Gets a thread priority.
-@return priority */
-UNIV_INTERN
-ulint
-os_thread_get_priority(
-/*===================*/
- os_thread_t handle);/*!< in: OS handle to the thread */
-/******************************************************************//**
-Sets a thread priority. */
-UNIV_INTERN
-void
-os_thread_set_priority(
-/*===================*/
- os_thread_t handle, /*!< in: OS handle to the thread */
- ulint pri); /*!< in: priority: one of OS_PRIORITY_... */
-/******************************************************************//**
-Gets the last operating system error code for the calling thread.
-@return last error on Windows, 0 otherwise */
-UNIV_INTERN
-ulint
-os_thread_get_last_error(void);
-/*==========================*/
#ifndef UNIV_NONINL
#include "os0thread.ic"
diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h
index 826fd13125d..7091d8c2707 100644
--- a/storage/innobase/include/page0page.h
+++ b/storage/innobase/include/page0page.h
@@ -618,18 +618,19 @@ rec_t*
page_rec_find_owner_rec(
/*====================*/
rec_t* rec); /*!< in: the physical record */
+#ifndef UNIV_HOTBACKUP
/***********************************************************************//**
-This is a low-level operation which is used in a database index creation
-to update the page number of a created B-tree to a data dictionary
-record. */
-UNIV_INTERN
+Write a 32-bit field in a data dictionary record. */
+UNIV_INLINE
void
-page_rec_write_index_page_no(
-/*=========================*/
- rec_t* rec, /*!< in: record to update */
+page_rec_write_field(
+/*=================*/
+ rec_t* rec, /*!< in/out: record to update */
ulint i, /*!< in: index of the field to update */
- ulint page_no,/*!< in: value to write */
- mtr_t* mtr); /*!< in: mtr */
+ ulint val, /*!< in: value to write */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
+#endif /* !UNIV_HOTBACKUP */
/************************************************************//**
Returns the maximum combined size of records which can be inserted on top
of record heap.
@@ -952,7 +953,7 @@ UNIV_INTERN
ibool
page_rec_validate(
/*==============*/
- rec_t* rec, /*!< in: physical record */
+ const rec_t* rec, /*!< in: physical record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
/***************************************************************//**
Checks that the first directory slot points to the infimum record and
@@ -972,7 +973,7 @@ UNIV_INTERN
ibool
page_simple_validate_old(
/*=====================*/
- page_t* page); /*!< in: old-style index page */
+ const page_t* page); /*!< in: index page in ROW_FORMAT=REDUNDANT */
/***************************************************************//**
This function checks the consistency of an index page when we do not
know the index. This is also resilient so that this should never crash
@@ -982,7 +983,7 @@ UNIV_INTERN
ibool
page_simple_validate_new(
/*=====================*/
- page_t* block); /*!< in: new-style index page */
+ const page_t* page); /*!< in: index page in ROW_FORMAT!=REDUNDANT */
/***************************************************************//**
This function checks the consistency of an index page.
@return TRUE if ok */
@@ -990,7 +991,7 @@ UNIV_INTERN
ibool
page_validate(
/*==========*/
- page_t* page, /*!< in: index page */
+ const page_t* page, /*!< in: index page */
dict_index_t* index); /*!< in: data dictionary index containing
the page record type definition */
/***************************************************************//**
diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic
index e9624c2360f..115cee64f8b 100644
--- a/storage/innobase/include/page0page.ic
+++ b/storage/innobase/include/page0page.ic
@@ -959,6 +959,29 @@ page_get_free_space_of_empty(
- 2 * PAGE_DIR_SLOT_SIZE));
}
+#ifndef UNIV_HOTBACKUP
+/***********************************************************************//**
+Write a 32-bit field in a data dictionary record. */
+UNIV_INLINE
+void
+page_rec_write_field(
+/*=================*/
+ rec_t* rec, /*!< in/out: record to update */
+ ulint i, /*!< in: index of the field to update */
+ ulint val, /*!< in: value to write */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+{
+ byte* data;
+ ulint len;
+
+ data = rec_get_nth_field_old(rec, i, &len);
+
+ ut_ad(len == 4);
+
+ mlog_write_ulint(data, val, MLOG_4BYTES, mtr);
+}
+#endif /* !UNIV_HOTBACKUP */
+
/************************************************************//**
Each user record on a page, and also the deleted user records in the heap
takes its size plus the fraction of the dir cell size /
diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h
index 574809e5227..00c1d0516e6 100644
--- a/storage/innobase/include/page0zip.h
+++ b/storage/innobase/include/page0zip.h
@@ -420,7 +420,7 @@ page_zip_copy_recs(
const page_t* src, /*!< in: page */
dict_index_t* index, /*!< in: index of the B-tree */
mtr_t* mtr) /*!< in: mini-transaction */
- __attribute__((nonnull(1,2,3,4)));
+ __attribute__((nonnull));
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
diff --git a/storage/innobase/include/rem0cmp.h b/storage/innobase/include/rem0cmp.h
index 2f751a38864..a908521c9f7 100644
--- a/storage/innobase/include/rem0cmp.h
+++ b/storage/innobase/include/rem0cmp.h
@@ -165,6 +165,10 @@ cmp_rec_rec_with_match(
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */
dict_index_t* index, /*!< in: data dictionary index */
+ ibool nulls_unequal,
+ /* in: TRUE if this is for index statistics
+ cardinality estimation, and innodb_stats_method
+ is "nulls_unequal" or "nulls_ignored" */
ulint* matched_fields, /*!< in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
diff --git a/storage/innobase/include/rem0cmp.ic b/storage/innobase/include/rem0cmp.ic
index 39ef5f4fba3..63415fe7837 100644
--- a/storage/innobase/include/rem0cmp.ic
+++ b/storage/innobase/include/rem0cmp.ic
@@ -87,5 +87,5 @@ cmp_rec_rec(
ulint match_b = 0;
return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index,
- &match_f, &match_b));
+ FALSE, &match_f, &match_b));
}
diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h
index 53402e8d3a9..10b74d18c13 100644
--- a/storage/innobase/include/rem0rec.h
+++ b/storage/innobase/include/rem0rec.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -480,6 +480,18 @@ ulint
rec_offs_any_extern(
/*================*/
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
+#ifdef UNIV_BLOB_NULL_DEBUG
+/******************************************************//**
+Determine if the offsets are for a record containing null BLOB pointers.
+@return first field containing a null BLOB pointer, or NULL if none found */
+UNIV_INLINE
+const byte*
+rec_offs_any_null_extern(
+/*=====================*/
+ const rec_t* rec, /*!< in: record */
+ const ulint* offsets) /*!< in: rec_get_offsets(rec) */
+ __attribute__((nonnull, warn_unused_result));
+#endif /* UNIV_BLOB_NULL_DEBUG */
/******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec.
@return nonzero if externally stored */
@@ -600,6 +612,7 @@ ulint
rec_offs_size(
/*==========*/
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
+#ifdef UNIV_DEBUG
/**********************************************************//**
Returns a pointer to the start of the record.
@return pointer to start */
@@ -607,7 +620,7 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
- rec_t* rec, /*!< in: pointer to record */
+ const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
/**********************************************************//**
Returns a pointer to the end of the record.
@@ -616,8 +629,12 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
- rec_t* rec, /*!< in: pointer to record */
+ const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
+#else /* UNIV_DEBUG */
+# define rec_get_start(rec, offsets) ((rec) - rec_offs_extra_size(offsets))
+# define rec_get_end(rec, offsets) ((rec) + rec_offs_data_size(offsets))
+#endif /* UNIV_DEBUG */
/***************************************************************//**
Copies a physical record to a buffer.
@return pointer to the origin of the copy */
@@ -801,13 +818,11 @@ UNIV_INTERN
void
rec_print(
/*======*/
- FILE* file, /*!< in: file where to print */
- const rec_t* rec, /*!< in: physical record */
- dict_index_t* index); /*!< in: record descriptor */
+ FILE* file, /*!< in: file where to print */
+ const rec_t* rec, /*!< in: physical record */
+ const dict_index_t* index); /*!< in: record descriptor */
#endif /* UNIV_HOTBACKUP */
-#define REC_INFO_BITS 6 /* This is single byte bit-field */
-
/* Maximum lengths for the data in a physical record if the offsets
are given in one byte (resp. two byte) format. */
#define REC_1BYTE_OFFS_LIMIT 0x7FUL
diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic
index ba306eaf27f..dc8ed515c30 100644
--- a/storage/innobase/include/rem0rec.ic
+++ b/storage/innobase/include/rem0rec.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -26,6 +26,7 @@ Created 5/30/1994 Heikki Tuuri
#include "mach0data.h"
#include "ut0byte.h"
#include "dict0dict.h"
+#include "btr0types.h"
/* Compact flag ORed to the extra size returned by rec_get_offsets() */
#define REC_OFFS_COMPACT ((ulint) 1 << 31)
@@ -1087,6 +1088,44 @@ rec_offs_any_extern(
return(UNIV_UNLIKELY(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL));
}
+#ifdef UNIV_BLOB_NULL_DEBUG
+/******************************************************//**
+Determine if the offsets are for a record containing null BLOB pointers.
+@return first field containing a null BLOB pointer, or NULL if none found */
+UNIV_INLINE
+const byte*
+rec_offs_any_null_extern(
+/*=====================*/
+ const rec_t* rec, /*!< in: record */
+ const ulint* offsets) /*!< in: rec_get_offsets(rec) */
+{
+ ulint i;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
+ if (!rec_offs_any_extern(offsets)) {
+ return(NULL);
+ }
+
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (rec_offs_nth_extern(offsets, i)) {
+ ulint len;
+ const byte* field
+ = rec_get_nth_field(rec, offsets, i, &len);
+
+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+ if (!memcmp(field + len
+ - BTR_EXTERN_FIELD_REF_SIZE,
+ field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE)) {
+ return(field);
+ }
+ }
+ }
+
+ return(NULL);
+}
+#endif /* UNIV_BLOB_NULL_DEBUG */
+
/******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec.
@return nonzero if externally stored */
@@ -1462,6 +1501,7 @@ rec_offs_size(
return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets));
}
+#ifdef UNIV_DEBUG
/**********************************************************//**
Returns a pointer to the end of the record.
@return pointer to end */
@@ -1469,11 +1509,11 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
- rec_t* rec, /*!< in: pointer to record */
+ const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ut_ad(rec_offs_validate(rec, NULL, offsets));
- return(rec + rec_offs_data_size(offsets));
+ return((rec_t*) rec + rec_offs_data_size(offsets));
}
/**********************************************************//**
@@ -1483,12 +1523,13 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
- rec_t* rec, /*!< in: pointer to record */
+ const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ut_ad(rec_offs_validate(rec, NULL, offsets));
- return(rec - rec_offs_extra_size(offsets));
+ return((rec_t*) rec - rec_offs_extra_size(offsets));
}
+#endif /* UNIV_DEBUG */
/***************************************************************//**
Copies a physical record to a buffer.
diff --git a/storage/innobase/include/rem0types.h b/storage/innobase/include/rem0types.h
index 8b84d4af233..7afd595be90 100644
--- a/storage/innobase/include/rem0types.h
+++ b/storage/innobase/include/rem0types.h
@@ -34,13 +34,21 @@ typedef byte rec_t;
#define REC_MAX_HEAP_NO (2 * 8192 - 1)
#define REC_MAX_N_OWNED (16 - 1)
-/* REC_MAX_INDEX_COL_LEN is measured in bytes and is the maximum
-indexed column length (or indexed prefix length). It is set to 3*256,
-so that one can create a column prefix index on 256 characters of a
-TEXT or VARCHAR column also in the UTF-8 charset. In that charset,
-a character may take at most 3 bytes.
+/* REC_ANTELOPE_MAX_INDEX_COL_LEN is measured in bytes and is the maximum
+indexed field length (or indexed prefix length) for indexes on tables of
+ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT format.
+Before we support UTF-8 encodings with mbmaxlen = 4, a UTF-8 character
+may take at most 3 bytes. So the limit was set to 3*256, so that one
+can create a column prefix index on 256 characters of a TEXT or VARCHAR
+column also in the UTF-8 charset.
This constant MUST NOT BE CHANGED, or the compatibility of InnoDB data
files would be at risk! */
-#define REC_MAX_INDEX_COL_LEN 768
+#define REC_ANTELOPE_MAX_INDEX_COL_LEN 768
+
+/** Maximum indexed field length for table format DICT_TF_FORMAT_ZIP and
+beyond.
+This (3072) is the maximum index row length allowed, so we cannot create index
+prefix column longer than that. */
+#define REC_VERSION_56_MAX_INDEX_COL_LEN 3072
#endif
diff --git a/storage/innobase/include/row0ext.h b/storage/innobase/include/row0ext.h
index 43d82d644e6..557da2c4a82 100644
--- a/storage/innobase/include/row0ext.h
+++ b/storage/innobase/include/row0ext.h
@@ -30,6 +30,7 @@ Created September 2006 Marko Makela
#include "row0types.h"
#include "data0types.h"
#include "mem0mem.h"
+#include "dict0types.h"
/********************************************************************//**
Creates a cache of column prefixes of externally stored columns.
@@ -43,13 +44,13 @@ row_ext_create(
in the InnoDB table object, as reported by
dict_col_get_no(); NOT relative to the records
in the clustered index */
+ ulint flags, /*!< in: table->flags */
const dtuple_t* tuple, /*!< in: data tuple containing the field
references of the externally stored
columns; must be indexed by col_no;
the clustered index record must be
covered by a lock or a page latch
to prevent deletion (rollback or purge). */
- ulint zip_size,/*!< compressed page size in bytes, or 0 */
mem_heap_t* heap); /*!< in: heap where created */
/********************************************************************//**
@@ -63,7 +64,8 @@ row_ext_lookup_ith(
const row_ext_t* ext, /*!< in/out: column prefix cache */
ulint i, /*!< in: index of ext->ext[] */
ulint* len); /*!< out: length of prefix, in bytes,
- at most REC_MAX_INDEX_COL_LEN */
+ at most the length determined by
+ DICT_MAX_FIELD_LEN_BY_FORMAT() */
/********************************************************************//**
Looks up a column prefix of an externally stored column.
@return column prefix, or NULL if the column is not stored externally,
@@ -78,13 +80,18 @@ row_ext_lookup(
dict_col_get_no(); NOT relative to the
records in the clustered index */
ulint* len); /*!< out: length of prefix, in bytes,
- at most REC_MAX_INDEX_COL_LEN */
+ at most the length determined by
+ DICT_MAX_FIELD_LEN_BY_FORMAT() */
/** Prefixes of externally stored columns */
struct row_ext_struct{
ulint n_ext; /*!< number of externally stored columns */
const ulint* ext; /*!< col_no's of externally stored columns */
byte* buf; /*!< backing store of the column prefix cache */
+ ulint max_len;/*!< maximum prefix length, it could be
+ REC_ANTELOPE_MAX_INDEX_COL_LEN or
+ REC_VERSION_56_MAX_INDEX_COL_LEN depending
+ on row format */
ulint len[1]; /*!< prefix lengths; 0 if not cached */
};
diff --git a/storage/innobase/include/row0ext.ic b/storage/innobase/include/row0ext.ic
index 82771a9312a..466046b2821 100644
--- a/storage/innobase/include/row0ext.ic
+++ b/storage/innobase/include/row0ext.ic
@@ -37,7 +37,7 @@ row_ext_lookup_ith(
const row_ext_t* ext, /*!< in/out: column prefix cache */
ulint i, /*!< in: index of ext->ext[] */
ulint* len) /*!< out: length of prefix, in bytes,
- at most REC_MAX_INDEX_COL_LEN */
+ at most ext->max_len */
{
ut_ad(ext);
ut_ad(len);
@@ -45,11 +45,14 @@ row_ext_lookup_ith(
*len = ext->len[i];
+ ut_ad(*len <= ext->max_len);
+ ut_ad(ext->max_len > 0);
+
if (UNIV_UNLIKELY(*len == 0)) {
/* The BLOB could not be fetched to the cache. */
return(field_ref_zero);
} else {
- return(ext->buf + i * REC_MAX_INDEX_COL_LEN);
+ return(ext->buf + i * ext->max_len);
}
}
@@ -67,7 +70,7 @@ row_ext_lookup(
dict_col_get_no(); NOT relative to the
records in the clustered index */
ulint* len) /*!< out: length of prefix, in bytes,
- at most REC_MAX_INDEX_COL_LEN */
+ at most ext->max_len */
{
ulint i;
diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h
index 9f93565ddb7..810973e61a7 100644
--- a/storage/innobase/include/row0ins.h
+++ b/storage/innobase/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/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index d9c26a2ee3b..dd619406ab9 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -538,6 +538,10 @@ struct mysql_row_templ_struct {
Innobase record in the current index;
not defined if template_type is
ROW_MYSQL_WHOLE_ROW */
+ ulint clust_rec_field_no; /*!< field number of the column in an
+ Innobase record in the clustered index;
+ not defined if template_type is
+ ROW_MYSQL_WHOLE_ROW */
ulint mysql_col_offset; /*!< offset of the column in the MySQL
row format */
ulint mysql_col_len; /*!< length of the column in the MySQL
diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h
index 195691a420b..75e15d67246 100644
--- a/storage/innobase/include/row0row.h
+++ b/storage/innobase/include/row0row.h
@@ -41,13 +41,24 @@ Created 4/20/1996 Heikki Tuuri
Gets the offset of the trx id field, in bytes relative to the origin of
a clustered index record.
@return offset of DATA_TRX_ID */
-UNIV_INTERN
+UNIV_INLINE
ulint
-row_get_trx_id_offset(
-/*==================*/
- const rec_t* rec, /*!< in: record */
- dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets);/*!< in: rec_get_offsets(rec, index) */
+row_get_trx_id_offset_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const rec_t* rec, /*!< in: record */
+#endif /* UNIV_DEBUG */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ __attribute__((nonnull, warn_unused_result));
+#ifdef UNIV_DEBUG
+# define row_get_trx_id_offset(rec, index, offsets) \
+ row_get_trx_id_offset_func(rec, index, offsets)
+#else /* UNIV_DEBUG */
+# define row_get_trx_id_offset(rec, index, offsets) \
+ row_get_trx_id_offset_func(index, offsets)
+#endif /* UNIV_DEBUG */
+
/*********************************************************************//**
Reads the trx id field from a clustered index record.
@return value of the field */
@@ -55,9 +66,10 @@ UNIV_INLINE
trx_id_t
row_get_rec_trx_id(
/*===============*/
- const rec_t* rec, /*!< in: record */
- dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets);/*!< in: rec_get_offsets(rec, index) */
+ const rec_t* rec, /*!< in: record */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ __attribute__((nonnull, warn_unused_result));
/*********************************************************************//**
Reads the roll pointer field from a clustered index record.
@return value of the field */
@@ -267,7 +279,7 @@ enum row_search_result {
secondary index leaf page was not in
the buffer pool, and the operation was
enqueued in the insert/delete buffer */
- ROW_NOT_DELETED_REF, /*!< BTR_DELETE was specified, and
+ ROW_NOT_DELETED_REF /*!< BTR_DELETE was specified, and
row_purge_poss_sec() failed */
};
diff --git a/storage/innobase/include/row0row.ic b/storage/innobase/include/row0row.ic
index 05c007641af..9d19e430e16 100644
--- a/storage/innobase/include/row0row.ic
+++ b/storage/innobase/include/row0row.ic
@@ -28,15 +28,45 @@ Created 4/20/1996 Heikki Tuuri
#include "trx0undo.h"
/*********************************************************************//**
+Gets the offset of trx id field, in bytes relative to the origin of
+a clustered index record.
+@return offset of DATA_TRX_ID */
+UNIV_INLINE
+ulint
+row_get_trx_id_offset_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const rec_t* rec, /*!< in: record */
+#endif /* UNIV_DEBUG */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+{
+ ulint pos;
+ ulint offset;
+ ulint len;
+
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
+ pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
+
+ offset = rec_get_nth_field_offs(offsets, pos, &len);
+
+ ut_ad(len == DATA_TRX_ID_LEN);
+
+ return(offset);
+}
+
+/*********************************************************************//**
Reads the trx id field from a clustered index record.
@return value of the field */
UNIV_INLINE
trx_id_t
row_get_rec_trx_id(
/*===============*/
- const rec_t* rec, /*!< in: record */
- dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ const rec_t* rec, /*!< in: record */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
{
ulint offset;
diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h
index f7bec6f7561..c275c1da78e 100644
--- a/storage/innobase/include/row0upd.h
+++ b/storage/innobase/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 */
@@ -167,8 +167,11 @@ row_upd_changes_field_size_or_external(
const upd_t* update);/*!< in: update vector */
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
-Replaces the new column values stored in the update vector to the record
-given. No field size changes are allowed. */
+Replaces the new column values stored in the update vector to the
+record given. No field size changes are allowed. This function is
+usually invoked on a clustered index. The only use case for a
+secondary index is row_ins_sec_index_entry_by_modify() or its
+counterpart in ibuf_insert_to_index_page(). */
UNIV_INTERN
void
row_upd_rec_in_place(
@@ -277,16 +280,29 @@ NOTE: we compare the fields as binary strings!
@return TRUE if update vector changes an ordering field in the index record */
UNIV_INTERN
ibool
-row_upd_changes_ord_field_binary(
-/*=============================*/
+row_upd_changes_ord_field_binary_func(
+/*==================================*/
+ 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! */
+#ifdef UNIV_DEBUG
+ const que_thr_t*thr, /*!< in: query thread */
+#endif /* UNIV_DEBUG */
const dtuple_t* row, /*!< in: old value of row, or NULL if the
row and the data values in update are not
known when this function is called, e.g., at
compile time */
- 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! */
+ const row_ext_t*ext) /*!< NULL, or prefixes of the externally
+ stored columns in the old row */
+ __attribute__((nonnull(1,2), warn_unused_result));
+#ifdef UNIV_DEBUG
+# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
+ row_upd_changes_ord_field_binary_func(index,update,thr,row,ext)
+#else /* UNIV_DEBUG */
+# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
+ row_upd_changes_ord_field_binary_func(index,update,row,ext)
+#endif /* UNIV_DEBUG */
/***********************************************************//**
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
@@ -459,11 +475,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/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index d78c8113aee..fc9401a12f5 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -57,14 +57,20 @@ extern const char srv_mysql50_table_name_prefix[9];
thread starts running */
extern os_event_t srv_lock_timeout_thread_event;
+/* The monitor thread waits on this event. */
+extern os_event_t srv_monitor_event;
+
+/* The lock timeout thread waits on this event. */
+extern os_event_t srv_timeout_event;
+
+/* The error monitor thread waits on this event. */
+extern os_event_t srv_error_event;
+
/* If the last data file is auto-extended, we add this many pages to it
at a time */
#define SRV_AUTO_EXTEND_INCREMENT \
(srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE))
-/* This is set to TRUE if the MySQL user has set it in MySQL */
-extern ibool srv_lower_case_table_names;
-
/* Mutex for locking srv_monitor_file */
extern mutex_t srv_monitor_file_mutex;
/* Temporary file for innodb monitor output */
@@ -163,6 +169,11 @@ capacity. PCT_IO(5) -> returns the number of IO operations that
is 5% of the max where max is srv_io_capacity. */
#define PCT_IO(p) ((ulong) (srv_io_capacity * ((double) p / 100.0)))
+/* The "innodb_stats_method" setting, decides how InnoDB is going
+to treat NULL value when collecting statistics. It is not defined
+as enum type because the configure option takes unsigned integer type. */
+extern ulong srv_innodb_stats_method;
+
#ifdef UNIV_LOG_ARCHIVE
extern ibool srv_log_archive_on;
extern ibool srv_archive_recovery;
@@ -225,6 +236,8 @@ extern ulong srv_thread_sleep_delay;
extern ulong srv_spin_wait_delay;
extern ibool srv_priority_boost;
+extern ulint srv_truncated_status_writes;
+
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
@@ -278,9 +291,12 @@ extern ulint srv_log_waits;
/* the number of purge threads to use from the worker pool (currently 0 or 1) */
extern ulong srv_n_purge_threads;
-/* the number of records to purge in one batch */
+/* the number of pages to purge in one batch */
extern ulong srv_purge_batch_size;
+/* the number of rollback segments to use */
+extern ulong srv_rollback_segments;
+
/* variable that counts amount of data read in total (in bytes) */
extern ulint srv_data_read;
@@ -407,19 +423,24 @@ enum {
in connection with recovery */
};
+/* Alternatives for srv_innodb_stats_method, which could be changed by
+setting innodb_stats_method */
+enum srv_stats_method_name_enum {
+ SRV_STATS_NULLS_EQUAL, /* All NULL values are treated as
+ equal. This is the default setting
+ for innodb_stats_method */
+ SRV_STATS_NULLS_UNEQUAL, /* All NULL values are treated as
+ NOT equal. */
+ SRV_STATS_NULLS_IGNORED /* NULL values are ignored */
+};
+
+typedef enum srv_stats_method_name_enum srv_stats_method_name_t;
+
#ifndef UNIV_HOTBACKUP
/** Types of threads existing in the system. */
enum srv_thread_type {
- SRV_COM = 1, /**< threads serving communication and queries */
- SRV_CONSOLE, /**< thread serving console */
- SRV_WORKER, /**< threads serving parallelized queries and
+ SRV_WORKER = 0, /**< threads serving parallelized queries and
queries released from lock wait */
-#if 0
- /* Utility threads */
- SRV_BUFFER, /**< thread flushing dirty buffer blocks */
- SRV_RECOVERY, /**< threads finishing a recovery */
- SRV_INSERT, /**< thread flushing the insert buffer to disk */
-#endif
SRV_MASTER /**< the master thread, (whose type number must
be biggest) */
};
@@ -458,12 +479,13 @@ ulint
srv_get_n_threads(void);
/*===================*/
/*********************************************************************//**
-Returns the calling thread type.
-@return SRV_COM, ... */
-
-enum srv_thread_type
-srv_get_thread_type(void);
-/*=====================*/
+Check whether thread type has reserved a slot.
+@return slot number or UNDEFINED if not found*/
+UNIV_INTERN
+ulint
+srv_thread_has_reserved_slot(
+/*=========================*/
+ enum srv_thread_type type); /*!< in: thread type to check */
/*********************************************************************//**
Sets the info describing an i/o thread current state. */
UNIV_INTERN
@@ -710,11 +732,12 @@ struct export_var_struct{
ulint innodb_rows_inserted; /*!< srv_n_rows_inserted */
ulint innodb_rows_updated; /*!< srv_n_rows_updated */
ulint innodb_rows_deleted; /*!< srv_n_rows_deleted */
+ ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */
};
/** Thread slot in the thread table */
typedef struct srv_slot_struct srv_slot_t;
-
+
/** Thread table is an array of slots */
typedef srv_slot_t srv_table_t;
diff --git a/storage/innobase/include/sync0arr.h b/storage/innobase/include/sync0arr.h
index 5f1280f5e28..6e931346238 100644
--- a/storage/innobase/include/sync0arr.h
+++ b/storage/innobase/include/sync0arr.h
@@ -115,8 +115,11 @@ Prints warnings of long semaphore waits to stderr.
@return TRUE if fatal semaphore wait threshold was exceeded */
UNIV_INTERN
ibool
-sync_array_print_long_waits(void);
-/*=============================*/
+sync_array_print_long_waits(
+/*========================*/
+ os_thread_id_t* waiter, /*!< out: longest waiting thread */
+ const void** sema) /*!< out: longest-waited-for semaphore */
+ __attribute__((nonnull));
/********************************************************************//**
Validates the integrity of the wait array. Checks
that the number of reserved cells equals the count variable. */
diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
index 70471186f6d..9e5c96fa323 100644
--- a/storage/innobase/include/sync0rw.h
+++ b/storage/innobase/include/sync0rw.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -122,6 +122,7 @@ extern mysql_pfs_key_t checkpoint_lock_key;
extern mysql_pfs_key_t trx_i_s_cache_lock_key;
extern mysql_pfs_key_t trx_purge_latch_key;
extern mysql_pfs_key_t index_tree_rw_lock_key;
+extern mysql_pfs_key_t dict_table_stats_latch_key;
#endif /* UNIV_PFS_RWLOCK */
@@ -554,6 +555,7 @@ UNIV_INTERN
void
rw_lock_debug_print(
/*================*/
+ FILE* f, /*!< in: output stream */
rw_lock_debug_t* info); /*!< in: debug struct */
#endif /* UNIV_SYNC_DEBUG */
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index 940e583350a..b823c9d5259 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -85,7 +85,6 @@ extern mysql_pfs_key_t hash_table_mutex_key;
extern mysql_pfs_key_t ibuf_bitmap_mutex_key;
extern mysql_pfs_key_t ibuf_mutex_key;
extern mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key;
-extern mysql_pfs_key_t ios_mutex_key;
extern mysql_pfs_key_t log_sys_mutex_key;
extern mysql_pfs_key_t log_flush_order_mutex_key;
extern mysql_pfs_key_t kernel_mutex_key;
@@ -94,7 +93,7 @@ extern mysql_pfs_key_t mem_hash_mutex_key;
# endif /* UNIV_MEM_DEBUG */
extern mysql_pfs_key_t mem_pool_mutex_key;
extern mysql_pfs_key_t mutex_list_mutex_key;
-extern mysql_pfs_key_t purge_sys_mutex_key;
+extern mysql_pfs_key_t purge_sys_bh_mutex_key;
extern mysql_pfs_key_t recv_sys_mutex_key;
extern mysql_pfs_key_t rseg_mutex_key;
# ifdef UNIV_SYNC_DEBUG
@@ -111,7 +110,6 @@ extern mysql_pfs_key_t syn_arr_mutex_key;
extern mysql_pfs_key_t sync_thread_mutex_key;
# endif /* UNIV_SYNC_DEBUG */
extern mysql_pfs_key_t trx_doublewrite_mutex_key;
-extern mysql_pfs_key_t thr_local_mutex_key;
extern mysql_pfs_key_t trx_undo_mutex_key;
#endif /* UNIV_PFS_MUTEX */
@@ -415,13 +413,6 @@ sync_thread_reset_level(
/*====================*/
void* latch); /*!< in: pointer to a mutex or an rw-lock */
/******************************************************************//**
-Checks that the level array for the current thread is empty.
-@return TRUE if empty */
-UNIV_INTERN
-ibool
-sync_thread_levels_empty(void);
-/*==========================*/
-/******************************************************************//**
Checks if the level array for the current thread contains a
mutex or rw-latch at the specified level.
@return a matching latch, or NULL if not found */
@@ -432,17 +423,33 @@ sync_thread_levels_contains(
ulint level); /*!< in: latching order level
(SYNC_DICT, ...)*/
/******************************************************************//**
-Checks if the level array for the current thread is empty.
+Checks that the level array for the current thread is empty.
@return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN
void*
sync_thread_levels_nonempty_gen(
/*============================*/
- ibool dict_mutex_allowed); /*!< in: TRUE if dictionary mutex is
- allowed to be owned by the thread,
- also purge_is_running mutex is
- allowed */
-#define sync_thread_levels_empty_gen(d) (!sync_thread_levels_nonempty_gen(d))
+ ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is
+ allowed to be owned by the thread */
+ __attribute__((warn_unused_result));
+/******************************************************************//**
+Checks if the level array for the current thread is empty,
+except for data dictionary latches. */
+#define sync_thread_levels_empty_except_dict() \
+ (!sync_thread_levels_nonempty_gen(TRUE))
+/******************************************************************//**
+Checks if the level array for the current thread is empty,
+except for the btr_search_latch.
+@return a latch, or NULL if empty except the exceptions specified below */
+UNIV_INTERN
+void*
+sync_thread_levels_nonempty_trx(
+/*============================*/
+ ibool has_search_latch)
+ /*!< in: TRUE if and only if the thread
+ is supposed to hold btr_search_latch */
+ __attribute__((warn_unused_result));
+
/******************************************************************//**
Gets the debug information for a reserved mutex. */
UNIV_INTERN
@@ -638,7 +645,6 @@ or row lock! */
#define SYNC_TREE_NODE_NEW 892
#define SYNC_TREE_NODE_FROM_HASH 891
#define SYNC_TREE_NODE 890
-#define SYNC_PURGE_SYS 810
#define SYNC_PURGE_LATCH 800
#define SYNC_TRX_UNDO 700
#define SYNC_RSEG 600
@@ -660,6 +666,7 @@ or row lock! */
#define SYNC_REC_LOCK 299
#define SYNC_TRX_LOCK_HEAP 298
#define SYNC_TRX_SYS_HEADER 290
+#define SYNC_PURGE_QUEUE 200
#define SYNC_LOG 170
#define SYNC_LOG_FLUSH_ORDER 147
#define SYNC_RECV 168
diff --git a/storage/innobase/include/thr0loc.h b/storage/innobase/include/thr0loc.h
deleted file mode 100644
index b7eb29f2ed0..00000000000
--- a/storage/innobase/include/thr0loc.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/thr0loc.h
-The thread local storage
-
-Created 10/5/1995 Heikki Tuuri
-*******************************************************/
-
-/* This module implements storage private to each thread,
-a capability useful in some situations like storing the
-OS handle to the current thread, or its priority. */
-
-#ifndef thr0loc_h
-#define thr0loc_h
-
-#include "univ.i"
-#include "os0thread.h"
-
-/****************************************************************//**
-Initializes the thread local storage module. */
-UNIV_INTERN
-void
-thr_local_init(void);
-/*================*/
- /****************************************************************//**
-Close the thread local storage module. */
-UNIV_INTERN
-void
-thr_local_close(void);
-/*=================*/
-/*******************************************************************//**
-Creates a local storage struct for the calling new thread. */
-UNIV_INTERN
-void
-thr_local_create(void);
-/*==================*/
-/*******************************************************************//**
-Frees the local storage struct for the specified thread. */
-UNIV_INTERN
-void
-thr_local_free(
-/*===========*/
- os_thread_id_t id); /*!< in: thread id */
-/*******************************************************************//**
-Gets the slot number in the thread table of a thread.
-@return slot number */
-UNIV_INTERN
-ulint
-thr_local_get_slot_no(
-/*==================*/
- os_thread_id_t id); /*!< in: thread id of the thread */
-/*******************************************************************//**
-Sets in the local storage the slot number in the thread table of a thread. */
-UNIV_INTERN
-void
-thr_local_set_slot_no(
-/*==================*/
- os_thread_id_t id, /*!< in: thread id of the thread */
- ulint slot_no);/*!< in: slot number */
-/*******************************************************************//**
-Returns pointer to the 'in_ibuf' field within the current thread local
-storage.
-@return pointer to the in_ibuf field */
-UNIV_INTERN
-ibool*
-thr_local_get_in_ibuf_field(void);
-/*=============================*/
-
-#ifndef UNIV_NONINL
-#include "thr0loc.ic"
-#endif
-
-#endif
diff --git a/storage/innobase/include/thr0loc.ic b/storage/innobase/include/thr0loc.ic
deleted file mode 100644
index ce44e512320..00000000000
--- a/storage/innobase/include/thr0loc.ic
+++ /dev/null
@@ -1,24 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/thr0loc.ic
-Thread local storage
-
-Created 10/4/1995 Heikki Tuuri
-*******************************************************/
diff --git a/storage/innobase/include/trx0i_s.h b/storage/innobase/include/trx0i_s.h
index 8f8b7367fb0..73896a3cb76 100644
--- a/storage/innobase/include/trx0i_s.h
+++ b/storage/innobase/include/trx0i_s.h
@@ -140,6 +140,9 @@ struct i_s_trx_row_struct {
ulint trx_mysql_thread_id; /*!< 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 */
const char* trx_operation_state; /*!< trx_struct::op_info */
ulint trx_tables_in_use;/*!< n_mysql_tables_in_use in
trx_struct */
diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h
index d2730a68a78..0b83a76cab7 100644
--- a/storage/innobase/include/trx0purge.h
+++ b/storage/innobase/include/trx0purge.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -68,8 +68,9 @@ Creates the global purge system control structure and inits the history
mutex. */
UNIV_INTERN
void
-trx_purge_sys_create(void);
-/*======================*/
+trx_purge_sys_create(
+/*=================*/
+ ib_bh_t* ib_bh); /*!< in/own: UNDO log min binary heap*/
/********************************************************************//**
Frees the global purge system control structure. */
UNIV_INTERN
@@ -128,20 +129,20 @@ struct trx_purge_struct{
ulint state; /*!< Purge system state */
sess_t* sess; /*!< System session running the purge
query */
- trx_t* trx; /*!< System transaction running the purge
+ trx_t* trx; /*!< System transaction running the
+ purge
query: this trx is not in the trx list
of the trx system and it never ends */
que_t* query; /*!< The query graph which will do the
parallelized purge operation */
- rw_lock_t latch; /*!< The latch protecting the purge view.
- A purge operation must acquire an
- x-latch here for the instant at which
+ rw_lock_t latch; /*!< The latch protecting the purge
+ view. A purge operation must acquire
+ an x-latch here for the instant at which
it changes the purge view: an undo
log operation can prevent this by
obtaining an s-latch here. */
read_view_t* view; /*!< The purge will not remove undo logs
which are >= this view (purge view) */
- mutex_t mutex; /*!< Mutex protecting the fields below */
ulint n_pages_handled;/*!< Approximate number of undo log
pages processed in purge */
ulint handle_limit; /*!< Target of how many pages to get
@@ -179,6 +180,11 @@ struct trx_purge_struct{
mem_heap_t* heap; /*!< Temporary storage used during a
purge: can be emptied after purge
completes */
+ /*-----------------------------*/
+ ib_bh_t* ib_bh; /*!< Binary min-heap, ordered on
+ rseg_queue_t::trx_no. It is protected
+ by the bh_mutex */
+ mutex_t bh_mutex; /*!< Mutex protecting ib_bh */
};
#define TRX_PURGE_ON 1 /* purge operation is running */
diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h
index 78a7a8c4bb0..5acde05de3d 100644
--- a/storage/innobase/include/trx0rseg.h
+++ b/storage/innobase/include/trx0rseg.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -113,7 +113,9 @@ void
trx_rseg_list_and_array_init(
/*=========================*/
trx_sysf_t* sys_header, /*!< in: trx system header */
+ ib_bh_t* ib_bh, /*!< in: rseg queue */
mtr_t* mtr); /*!< in: mtr */
+
/***************************************************************************
Free's an instance of the rollback segment in memory. */
UNIV_INTERN
@@ -141,9 +143,7 @@ struct trx_rseg_struct{
ulint id; /*!< rollback segment id == the index of
its slot in the trx system file copy */
mutex_t mutex; /*!< mutex protecting the fields in this
- struct except id; NOTE that the latching
- order must always be kernel mutex ->
- rseg mutex */
+ struct except id, which is constant */
ulint space; /*!< space where the rollback segment is
header is placed */
ulint zip_size;/* compressed page size of space
@@ -182,6 +182,14 @@ struct trx_rseg_struct{
memory objects */
};
+/** For prioritising the rollback segments for purge. */
+struct rseg_queue_struct {
+ trx_id_t trx_no; /*!< trx_rseg_t::last_trx_no */
+ trx_rseg_t* rseg; /*!< Rollback segment */
+};
+
+typedef struct rseg_queue_struct rseg_queue_t;
+
/* Undo log segment slot in a rollback segment header */
/*-------------------------------------------------------------*/
#define TRX_RSEG_SLOT_PAGE_NO 0 /* Page number of the header page of
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index 63e3f6be934..dc0ca2285b9 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -38,6 +38,7 @@ Created 3/26/1996 Heikki Tuuri
#include "mem0mem.h"
#include "sync0sync.h"
#include "ut0lst.h"
+#include "ut0bh.h"
#include "read0types.h"
#include "page0types.h"
@@ -221,13 +222,6 @@ UNIV_INLINE
trx_id_t
trx_sys_get_new_trx_id(void);
/*========================*/
-/*****************************************************************//**
-Allocates a new transaction number.
-@return new, allocated trx number */
-UNIV_INLINE
-trx_id_t
-trx_sys_get_new_trx_no(void);
-/*========================*/
#endif /* !UNIV_HOTBACKUP */
/*****************************************************************//**
Writes a trx id to an index page. In case that the id size changes in
diff --git a/storage/innobase/include/trx0sys.ic b/storage/innobase/include/trx0sys.ic
index 385c7f4f0cc..355f118a1ec 100644
--- a/storage/innobase/include/trx0sys.ic
+++ b/storage/innobase/include/trx0sys.ic
@@ -369,16 +369,4 @@ trx_sys_get_new_trx_id(void)
return(id);
}
-/*****************************************************************//**
-Allocates a new transaction number.
-@return new, allocated trx number */
-UNIV_INLINE
-trx_id_t
-trx_sys_get_new_trx_no(void)
-/*========================*/
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- return(trx_sys_get_new_trx_id());
-}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 6a817ccdc8e..588ddd65e88 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -44,6 +44,9 @@ extern sess_t* trx_dummy_sess;
/** Number of transactions currently allocated for MySQL: protected by
the kernel mutex */
extern ulint trx_n_mysql_transactions;
+/** Number of transactions currently in the XA PREPARED state: protected by
+the kernel mutex */
+extern ulint trx_n_prepared;
/********************************************************************//**
Releases the search latch if trx has reserved it. */
@@ -108,6 +111,14 @@ trx_free(
/*=====*/
trx_t* trx); /*!< in, own: trx object */
/********************************************************************//**
+At shutdown, frees a transaction object that is in the PREPARED state. */
+UNIV_INTERN
+void
+trx_free_prepared(
+/*==============*/
+ trx_t* trx) /*!< in, own: trx object */
+ UNIV_COLD __attribute__((nonnull));
+/********************************************************************//**
Frees a transaction object for MySQL. */
UNIV_INTERN
void
@@ -214,12 +225,12 @@ trx_recover_for_mysql(
/*******************************************************************//**
This function is used to find one X/Open XA distributed transaction
which is in the prepared state
-@return trx or NULL */
+@return trx or NULL; on match, the trx->xid will be invalidated */
UNIV_INTERN
trx_t *
trx_get_trx_by_xid(
/*===============*/
- XID* xid); /*!< in: X/Open XA transaction identification */
+ const XID* xid); /*!< in: X/Open XA transaction identifier */
/**********************************************************************//**
If required, flushes the log to disk if we called trx_commit_for_mysql()
with trx->flush_log_later == TRUE.
@@ -470,6 +481,20 @@ struct trx_struct{
of view of concurrency control:
TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY,
... */
+ /*------------------------------*/
+ /* MySQL has a transaction coordinator to coordinate two phase
+ commit between multiple storage engines and the binary log. When
+ an engine participates in a transaction, it's responsible for
+ registering itself using the trans_register_ha() API. */
+ unsigned is_registered:1;/* This flag is set to 1 after the
+ transaction has been registered with
+ the coordinator using the XA API, and
+ is set to 0 after commit or rollback. */
+ unsigned owns_prepare_mutex:1;/* 1 if owns prepare mutex, if
+ this is set to 1 then registered should
+ also be set to 1. This is used in the
+ XA code */
+ /*------------------------------*/
ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
ulint check_foreigns; /* normally TRUE, but if the user
wants to suppress foreign key checks,
@@ -500,9 +525,6 @@ struct trx_struct{
in that case we must flush the log
in trx_commit_complete_for_mysql() */
ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
- ulint active_trans; /*!< 1 - if a transaction in MySQL
- is active. 2 - if prepare_commit_mutex
- was taken */
ulint has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
@@ -558,11 +580,6 @@ struct trx_struct{
ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field
contains the end offset of the binlog
entry */
- os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
- with this transaction object */
- ulint mysql_process_no;/* since in Linux, 'top' reports
- process id's and not thread id's, we
- store the process number too */
/*------------------------------*/
ulint n_mysql_tables_in_use; /* number of Innobase tables
used in the processing of the current
diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h
index 54809f9c2d5..df16c939070 100644
--- a/storage/innobase/include/trx0undo.h
+++ b/storage/innobase/include/trx0undo.h
@@ -262,8 +262,6 @@ UNIV_INTERN
page_t*
trx_undo_set_state_at_finish(
/*=========================*/
- trx_rseg_t* rseg, /*!< in: rollback segment memory object */
- trx_t* trx, /*!< in: transaction */
trx_undo_t* undo, /*!< in: undo log memory copy */
mtr_t* mtr); /*!< in: mtr */
/******************************************************************//**
@@ -298,6 +296,15 @@ void
trx_undo_insert_cleanup(
/*====================*/
trx_t* trx); /*!< in: transaction handle */
+
+/********************************************************************//**
+At shutdown, frees the undo logs of a PREPARED transaction. */
+UNIV_INTERN
+void
+trx_undo_free_prepared(
+/*===================*/
+ trx_t* trx) /*!< in/out: PREPARED transaction */
+ UNIV_COLD __attribute__((nonnull));
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
Parses the redo log entry of an undo log page initialization.
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index 548eb446fab..21d1eb03b99 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -44,9 +44,14 @@ Created 1/20/1994 Heikki Tuuri
#include "hb_univ.i"
#endif /* UNIV_HOTBACKUP */
+/* aux macros to convert M into "123" (string) if M is defined like
+#define M 123 */
+#define _IB_TO_STR(s) #s
+#define IB_TO_STR(s) _IB_TO_STR(s)
+
#define INNODB_VERSION_MAJOR 1
#define INNODB_VERSION_MINOR 1
-#define INNODB_VERSION_BUGFIX 2
+#define INNODB_VERSION_BUGFIX 8
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
@@ -57,16 +62,14 @@ component, i.e. we show M.N.P as M.N */
#define INNODB_VERSION_SHORT \
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
-/* auxiliary macros to help creating the version as string */
-#define __INNODB_VERSION(a, b, c) (#a "." #b "." #c)
-#define _INNODB_VERSION(a, b, c) __INNODB_VERSION(a, b, c)
-
#define INNODB_VERSION_STR \
- _INNODB_VERSION(INNODB_VERSION_MAJOR, \
- INNODB_VERSION_MINOR, \
- INNODB_VERSION_BUGFIX)
+ IB_TO_STR(INNODB_VERSION_MAJOR) "." \
+ IB_TO_STR(INNODB_VERSION_MINOR) "." \
+ IB_TO_STR(INNODB_VERSION_BUGFIX)
-#define REFMAN "http://dev.mysql.com/doc/refman/5.1/en/"
+#define REFMAN "http://dev.mysql.com/doc/refman/" \
+ IB_TO_STR(MYSQL_MAJOR_VERSION) "." \
+ IB_TO_STR(MYSQL_MINOR_VERSION) "/en/"
#ifdef MYSQL_DYNAMIC_PLUGIN
/* In the dynamic plugin, redefine some externally visible symbols
@@ -78,19 +81,6 @@ the virtual method table (vtable) in GCC 3. */
# define ha_innobase ha_innodb
#endif /* MYSQL_DYNAMIC_PLUGIN */
-/* if any of the following macros is defined at this point this means
-that the code from the "right" plug.in was executed and we do not
-need to include ut0auxconf.h which would either define the same macros
-or will be empty */
-#if !defined(HAVE_IB_GCC_ATOMIC_BUILTINS) \
- && !defined(HAVE_IB_ATOMIC_PTHREAD_T_GCC) \
- && !defined(HAVE_IB_SOLARIS_ATOMICS) \
- && !defined(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) \
- && !defined(SIZEOF_PTHREAD_T) \
- && !defined(HAVE_IB_PAUSE_INSTRUCTION)
-# include "ut0auxconf.h"
-#endif
-
#if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)) && !defined(MYSQL_SERVER) && !defined(__WIN__)
# undef __WIN__
# define __WIN__
@@ -194,14 +184,17 @@ command. Not tested on Windows. */
debugging without UNIV_DEBUG */
#define UNIV_BUF_DEBUG /* Enable buffer pool
debugging without UNIV_DEBUG */
+#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column
+ debugging without UNIV_DEBUG */
+#define UNIV_BLOB_NULL_DEBUG /* Enable deep off-page
+ column debugging */
#define UNIV_DEBUG /* Enable ut_ad() assertions
and disable UNIV_INLINE */
#define UNIV_DEBUG_LOCK_VALIDATE /* Enable
ut_ad(lock_rec_validate_page())
assertions. */
-#define UNIV_DEBUG_FILE_ACCESSES /* Debug .ibd file access
- (field file_page_was_freed
- in buf_page_t) */
+#define UNIV_DEBUG_FILE_ACCESSES /* Enable freed block access
+ debugging without UNIV_DEBUG */
#define UNIV_LRU_DEBUG /* debug the buffer pool LRU */
#define UNIV_HASH_DEBUG /* debug HASH_ macros */
#define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */
@@ -210,6 +203,8 @@ this will break redo log file compatibility, but it may be useful when
debugging redo log application problems. */
#define UNIV_MEM_DEBUG /* detect memory leaks etc */
#define UNIV_IBUF_DEBUG /* debug the insert buffer */
+#define UNIV_BLOB_DEBUG /* track BLOB ownership;
+assumes that no BLOBs survive server restart */
#define UNIV_IBUF_COUNT_DEBUG /* debug the insert buffer;
this limits the database to IBUF_COUNT_N_SPACES and IBUF_COUNT_N_PAGES,
and the insert buffer must be empty when the database is started */
@@ -262,8 +257,21 @@ easy way to get it to work. See http://bugs.mysql.com/bug.php?id=52263. */
#else
# define UNIV_INTERN
#endif
+#if defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3)
+/** Starting with GCC 4.3, the "cold" attribute is used to inform the
+compiler that a function is unlikely executed. The function is
+optimized for size rather than speed and on many targets it is placed
+into special subsection of the text section so all cold functions
+appears close together improving code locality of non-cold parts of
+program. The paths leading to call of cold functions within code are
+marked as unlikely by the branch prediction mechanism. optimize a
+rarely invoked function for size instead for speed. */
+# define UNIV_COLD __attribute__((cold))
+#else
+# define UNIV_COLD /* empty */
+#endif
-#if (!defined(UNIV_DEBUG) && !defined(UNIV_MUST_NOT_INLINE))
+#ifndef UNIV_MUST_NOT_INLINE
/* Definition for inline version */
#ifdef __WIN__
@@ -318,6 +326,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
==========================
@@ -387,6 +407,9 @@ typedef unsigned long long int ullint;
/** The generic InnoDB system object identifier data type */
typedef ib_uint64_t ib_id_t;
+/* The 'undefined' value for a 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
@@ -436,7 +459,7 @@ it is read or written. */
/* Use sun_prefetch when compile with Sun Studio */
# define UNIV_EXPECT(expr,value) (expr)
# define UNIV_LIKELY_NULL(expr) (expr)
-# define UNIV_PREFETCH_R(addr) sun_prefetch_read_many(addr)
+# define UNIV_PREFETCH_R(addr) sun_prefetch_read_many((void*) addr)
# define UNIV_PREFETCH_RW(addr) sun_prefetch_write_many(addr)
#else
/* Dummy versions of the macros */
diff --git a/storage/innobase/include/ut0auxconf.h b/storage/innobase/include/ut0auxconf.h
deleted file mode 100644
index 16bcc308392..00000000000
--- a/storage/innobase/include/ut0auxconf.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* Do not remove this file even though it is empty.
-This file is included in univ.i and will cause compilation failure
-if not present.
-A custom checks have been added in the generated
-storage/innobase/Makefile.in that is shipped with the InnoDB Plugin
-source archive. These checks eventually define some macros and put
-them in this file.
-This is a hack that has been developed in order to deploy new compile
-time checks without the need to regenerate the ./configure script that is
-distributed in the MySQL 5.1 official source archives.
-If by any chance Makefile.in and ./configure are regenerated and thus
-the hack from Makefile.in wiped away then the "real" checks from plug.in
-will take over.
-*/
diff --git a/storage/innobase/include/ut0bh.h b/storage/innobase/include/ut0bh.h
new file mode 100644
index 00000000000..1b211390283
--- /dev/null
+++ b/storage/innobase/include/ut0bh.h
@@ -0,0 +1,152 @@
+/***************************************************************************//**
+
+Copyright (c) 2011, Oracle Corpn. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/******************************************************************//**
+@file include/ut0bh.h
+Binary min-heap interface.
+
+Created 2010-05-28 by Sunny Bains
+*******************************************************/
+
+#ifndef INNOBASE_UT0BH_H
+#define INNOBASE_UT0BH_H
+
+#include "univ.i"
+
+/** Comparison function for objects in the binary heap. */
+typedef int (*ib_bh_cmp_t)(const void* p1, const void* p2);
+
+typedef struct ib_bh_struct ib_bh_t;
+
+/**********************************************************************//**
+Get the number of elements in the binary heap.
+@return number of elements */
+UNIV_INLINE
+ulint
+ib_bh_size(
+/*=======*/
+ const ib_bh_t* ib_bh); /*!< in: instance */
+
+/**********************************************************************//**
+Test if binary heap is empty.
+@return TRUE if empty. */
+UNIV_INLINE
+ibool
+ib_bh_is_empty(
+/*===========*/
+ const ib_bh_t* ib_bh); /*!< in: instance */
+
+/**********************************************************************//**
+Test if binary heap is full.
+@return TRUE if full. */
+UNIV_INLINE
+ibool
+ib_bh_is_full(
+/*===========*/
+ const ib_bh_t* ib_bh); /*!< in: instance */
+
+/**********************************************************************//**
+Get a pointer to the element.
+@return pointer to element */
+UNIV_INLINE
+void*
+ib_bh_get(
+/*=======*/
+ ib_bh_t* ib_bh, /*!< in: instance */
+ ulint i); /*!< in: index */
+
+/**********************************************************************//**
+Copy an element to the binary heap.
+@return pointer to copied element */
+UNIV_INLINE
+void*
+ib_bh_set(
+/*======*/
+ ib_bh_t* ib_bh, /*!< in/out: instance */
+ ulint i, /*!< in: index */
+ const void* elem); /*!< in: element to add */
+
+/**********************************************************************//**
+Return the first element from the binary heap.
+@return pointer to first element or NULL if empty. */
+UNIV_INLINE
+void*
+ib_bh_first(
+/*========*/
+ ib_bh_t* ib_bh); /*!< in: instance */
+
+/**********************************************************************//**
+Return the last element from the binary heap.
+@return pointer to last element or NULL if empty. */
+UNIV_INLINE
+void*
+ib_bh_last(
+/*========*/
+ ib_bh_t* ib_bh); /*!< in/out: instance */
+
+/**********************************************************************//**
+Create a binary heap.
+@return a new binary heap */
+UNIV_INTERN
+ib_bh_t*
+ib_bh_create(
+/*=========*/
+ ib_bh_cmp_t compare, /*!< in: comparator */
+ ulint sizeof_elem, /*!< in: size of one element */
+ ulint max_elems); /*!< in: max elements allowed */
+
+/**********************************************************************//**
+Free a binary heap.
+@return a new binary heap */
+UNIV_INTERN
+void
+ib_bh_free(
+/*=======*/
+ ib_bh_t* ib_bh); /*!< in,own: instance */
+
+/**********************************************************************//**
+Add an element to the binary heap. Note: The element is copied.
+@return pointer to added element or NULL if full. */
+UNIV_INTERN
+void*
+ib_bh_push(
+/*=======*/
+ ib_bh_t* ib_bh, /*!< in/out: instance */
+ const void* elem); /*!< in: element to add */
+
+/**********************************************************************//**
+Remove the first element from the binary heap. */
+UNIV_INTERN
+void
+ib_bh_pop(
+/*======*/
+ ib_bh_t* ib_bh); /*!< in/out: instance */
+
+/** Binary heap data structure */
+struct ib_bh_struct {
+ ulint max_elems; /*!< max elements allowed */
+ ulint n_elems; /*!< current size */
+ ulint sizeof_elem; /*!< sizeof element */
+ ib_bh_cmp_t compare; /*!< comparator */
+};
+
+#ifndef UNIV_NONINL
+#include "ut0bh.ic"
+#endif
+
+#endif /* INNOBASE_UT0BH_H */
diff --git a/storage/innobase/include/ut0bh.ic b/storage/innobase/include/ut0bh.ic
new file mode 100644
index 00000000000..afbe58e7e3b
--- /dev/null
+++ b/storage/innobase/include/ut0bh.ic
@@ -0,0 +1,125 @@
+/***************************************************************************//**
+Copyright (c) 2011, Oracle Corpn. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/******************************************************************//**
+@file include/ut0bh.ic
+Binary min-heap implementation.
+
+Created 2011-01-15 by Sunny Bains
+*******************************************************/
+
+#include "ut0bh.h"
+#include "ut0mem.h" /* For ut_memcpy() */
+
+/**********************************************************************//**
+Get the number of elements in the binary heap.
+@return number of elements */
+UNIV_INLINE
+ulint
+ib_bh_size(
+/*=======*/
+ const ib_bh_t* ib_bh) /*!< in: instance */
+{
+ return(ib_bh->n_elems);
+}
+
+/**********************************************************************//**
+Test if binary heap is empty.
+@return TRUE if empty. */
+UNIV_INLINE
+ibool
+ib_bh_is_empty(
+/*===========*/
+ const ib_bh_t* ib_bh) /*!< in: instance */
+{
+ return(ib_bh_size(ib_bh) == 0);
+}
+
+/**********************************************************************//**
+Test if binary heap is full.
+@return TRUE if full. */
+UNIV_INLINE
+ibool
+ib_bh_is_full(
+/*===========*/
+ const ib_bh_t* ib_bh) /*!< in: instance */
+{
+ return(ib_bh_size(ib_bh) >= ib_bh->max_elems);
+}
+
+/**********************************************************************//**
+Get a pointer to the element.
+@return pointer to element */
+UNIV_INLINE
+void*
+ib_bh_get(
+/*=======*/
+ ib_bh_t* ib_bh, /*!< in: instance */
+ ulint i) /*!< in: index */
+{
+ byte* ptr = (byte*) (ib_bh + 1);
+
+ ut_a(i < ib_bh_size(ib_bh));
+
+ return(ptr + (ib_bh->sizeof_elem * i));
+}
+
+/**********************************************************************//**
+Copy an element to the binary heap.
+@return pointer to copied element */
+UNIV_INLINE
+void*
+ib_bh_set(
+/*======*/
+ ib_bh_t* ib_bh, /*!< in/out: instance */
+ ulint i, /*!< in: index */
+ const void* elem) /*!< in: element to add */
+{
+ void* ptr = ib_bh_get(ib_bh, i);
+
+ ut_memcpy(ptr, elem, ib_bh->sizeof_elem);
+
+ return(ptr);
+}
+
+/**********************************************************************//**
+Return the first element from the binary heap.
+@return pointer to first element or NULL if empty. */
+UNIV_INLINE
+void*
+ib_bh_first(
+/*========*/
+ ib_bh_t* ib_bh) /*!< in: instance */
+{
+ return(ib_bh_is_empty(ib_bh) ? NULL : ib_bh_get(ib_bh, 0));
+}
+
+/**********************************************************************//**
+Return the last element from the binary heap.
+@return pointer to last element or NULL if empty. */
+UNIV_INLINE
+void*
+ib_bh_last(
+/*========*/
+ ib_bh_t* ib_bh) /*!< in/out: instance */
+{
+ return(ib_bh_is_empty(ib_bh)
+ ? NULL
+ : ib_bh_get(ib_bh, ib_bh_size(ib_bh) - 1));
+}
+
+
diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h
index d7ec90db0fb..07730176d81 100644
--- a/storage/innobase/include/ut0dbg.h
+++ b/storage/innobase/include/ut0dbg.h
@@ -50,9 +50,10 @@ UNIV_INTERN
void
ut_dbg_assertion_failed(
/*====================*/
- const char* expr, /*!< in: the failed assertion */
- const char* file, /*!< in: source file containing the assertion */
- ulint line); /*!< in: line number of the assertion */
+ const char* expr, /*!< in: the failed assertion */
+ const char* file, /*!< in: source file containing the assertion */
+ ulint line) /*!< in: line number of the assertion */
+ UNIV_COLD __attribute__((nonnull(2)));
#if defined(__WIN__) || defined(__INTEL_COMPILER)
# undef UT_DBG_USE_ABORT
diff --git a/storage/innobase/include/ut0rbt.h b/storage/innobase/include/ut0rbt.h
index 7902dc91f09..e26b637ae13 100644
--- a/storage/innobase/include/ut0rbt.h
+++ b/storage/innobase/include/ut0rbt.h
@@ -53,7 +53,7 @@ Created 2007-03-20 Sunny Bains
/* Red black tree typedefs */
typedef struct ib_rbt_struct ib_rbt_t;
typedef struct ib_rbt_node_struct ib_rbt_node_t;
-// FIXME: Iterator is a better name than _bound_
+/* FIXME: Iterator is a better name than _bound_ */
typedef struct ib_rbt_bound_struct ib_rbt_bound_t;
typedef void (*ib_rbt_print_node)(const ib_rbt_node_t* node);
typedef int (*ib_rbt_compare)(const void* p1, const void* p2);
diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h
index dd59b3eba46..cad39e9a34f 100644
--- a/storage/innobase/include/ut0ut.h
+++ b/storage/innobase/include/ut0ut.h
@@ -55,24 +55,24 @@ Created 1/20/1994 Heikki Tuuri
typedef time_t ib_time_t;
#ifndef UNIV_HOTBACKUP
-#if defined(HAVE_IB_PAUSE_INSTRUCTION)
-# ifdef WIN32
- /* In the Win32 API, the x86 PAUSE instruction is executed by calling
- the YieldProcessor macro defined in WinNT.h. It is a CPU architecture-
- independent way by using YieldProcessor.*/
-# define UT_RELAX_CPU() YieldProcessor()
-# else
- /* According to the gcc info page, asm volatile means that the
- instruction has important side-effects and must not be removed.
- Also asm volatile may trigger a memory barrier (spilling all registers
- to memory). */
-# define UT_RELAX_CPU() __asm__ __volatile__ ("pause")
-# endif
+#if defined(HAVE_PAUSE_INSTRUCTION)
+ /* According to the gcc info page, asm volatile means that the
+ instruction has important side-effects and must not be removed.
+ Also asm volatile may trigger a memory barrier (spilling all registers
+ to memory). */
+# define UT_RELAX_CPU() __asm__ __volatile__ ("pause")
+#elif defined(HAVE_FAKE_PAUSE_INSTRUCTION)
+# define UT_RELAX_CPU() __asm__ __volatile__ ("rep; nop")
#elif defined(HAVE_ATOMIC_BUILTINS)
# define UT_RELAX_CPU() do { \
volatile lint volatile_var; \
os_compare_and_swap_lint(&volatile_var, 0, 1); \
} while (0)
+#elif defined(HAVE_WINDOWS_ATOMICS)
+ /* In the Win32 API, the x86 PAUSE instruction is executed by calling
+ the YieldProcessor macro defined in WinNT.h. It is a CPU architecture-
+ independent way by using YieldProcessor. */
+# define UT_RELAX_CPU() YieldProcessor()
#else
# define UT_RELAX_CPU() ((void)0) /* avoid warning for an empty statement */
#endif
@@ -275,7 +275,8 @@ UNIV_INTERN
void
ut_print_timestamp(
/*===============*/
- FILE* file); /*!< in: file where to print */
+ FILE* file) /*!< in: file where to print */
+ UNIV_COLD __attribute__((nonnull));
/**********************************************************//**
Sprintfs a timestamp to a buffer, 13..14 chars plus terminating NUL. */
UNIV_INTERN
diff --git a/storage/innobase/include/ut0vec.h b/storage/innobase/include/ut0vec.h
index a770f671cfc..0f8b955b098 100644
--- a/storage/innobase/include/ut0vec.h
+++ b/storage/innobase/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/innobase/include/ut0vec.ic b/storage/innobase/include/ut0vec.ic
index 02e881f9bca..34c858868ce 100644
--- a/storage/innobase/include/ut0vec.ic
+++ b/storage/innobase/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/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c
index dcfca1b6315..714107304f7 100644
--- a/storage/innobase/lock/lock0lock.c
+++ b/storage/innobase/lock/lock0lock.c
@@ -359,10 +359,8 @@ static
ibool
lock_rec_validate_page(
/*===================*/
- 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 */
+ const buf_block_t* block) /*!< in: buffer block */
+ __attribute__((nonnull, warn_unused_result));
#endif /* UNIV_DEBUG */
/* The lock system */
@@ -1100,10 +1098,10 @@ lock_rec_reset_nth_bit(
Gets the first or next record lock on a page.
@return next lock, NULL if none exists */
UNIV_INLINE
-lock_t*
-lock_rec_get_next_on_page(
-/*======================*/
- lock_t* lock) /*!< in: a record lock */
+const lock_t*
+lock_rec_get_next_on_page_const(
+/*============================*/
+ const lock_t* lock) /*!< in: a record lock */
{
ulint space;
ulint page_no;
@@ -1133,6 +1131,18 @@ lock_rec_get_next_on_page(
}
/*********************************************************************//**
+Gets the first or next record lock on a page.
+@return next lock, NULL if none exists */
+UNIV_INLINE
+lock_t*
+lock_rec_get_next_on_page(
+/*======================*/
+ lock_t* lock) /*!< in: a record lock */
+{
+ return((lock_t*) lock_rec_get_next_on_page_const(lock));
+}
+
+/*********************************************************************//**
Gets the first record lock on a page, where the page is identified by its
file address.
@return first lock, NULL if none exists */
@@ -2645,9 +2655,7 @@ lock_move_reorganize_page(
mem_heap_free(heap);
#ifdef UNIV_DEBUG_LOCK_VALIDATE
- ut_ad(lock_rec_validate_page(buf_block_get_space(block),
- buf_block_get_zip_size(block),
- buf_block_get_page_no(block)));
+ ut_ad(lock_rec_validate_page(block));
#endif
}
@@ -2735,12 +2743,8 @@ lock_move_rec_list_end(
lock_mutex_exit_kernel();
#ifdef UNIV_DEBUG_LOCK_VALIDATE
- ut_ad(lock_rec_validate_page(buf_block_get_space(block),
- buf_block_get_zip_size(block),
- buf_block_get_page_no(block)));
- ut_ad(lock_rec_validate_page(buf_block_get_space(new_block),
- buf_block_get_zip_size(block),
- buf_block_get_page_no(new_block)));
+ ut_ad(lock_rec_validate_page(block));
+ ut_ad(lock_rec_validate_page(new_block));
#endif
}
@@ -2848,9 +2852,7 @@ lock_move_rec_list_start(
lock_mutex_exit_kernel();
#ifdef UNIV_DEBUG_LOCK_VALIDATE
- ut_ad(lock_rec_validate_page(buf_block_get_space(block),
- buf_block_get_zip_size(block),
- buf_block_get_page_no(block)));
+ ut_ad(lock_rec_validate_page(block));
#endif
}
@@ -3622,6 +3624,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. */
@@ -3660,10 +3736,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);
@@ -3761,17 +3835,18 @@ Checks if other transactions have an incompatible mode lock request in
the lock queue.
@return lock or NULL */
UNIV_INLINE
-lock_t*
+const lock_t*
lock_table_other_has_incompatible(
/*==============================*/
- trx_t* trx, /*!< in: transaction, or NULL if all
- transactions should be included */
- ulint wait, /*!< in: LOCK_WAIT if also waiting locks are
- taken into account, or 0 if not */
- dict_table_t* table, /*!< in: table */
- enum lock_mode mode) /*!< in: lock mode */
+ const trx_t* trx, /*!< in: transaction, or NULL if all
+ transactions should be included */
+ ulint wait, /*!< in: LOCK_WAIT if also
+ waiting locks are taken into
+ account, or 0 if not */
+ const dict_table_t* table, /*!< in: table */
+ enum lock_mode mode) /*!< in: lock mode */
{
- lock_t* lock;
+ const lock_t* lock;
ut_ad(mutex_own(&kernel_mutex));
@@ -3862,10 +3937,10 @@ static
ibool
lock_table_has_to_wait_in_queue(
/*============================*/
- lock_t* wait_lock) /*!< in: waiting table lock */
+ const lock_t* wait_lock) /*!< in: waiting table lock */
{
- dict_table_t* table;
- lock_t* lock;
+ const dict_table_t* table;
+ const lock_t* lock;
ut_ad(mutex_own(&kernel_mutex));
ut_ad(lock_get_wait(wait_lock));
@@ -4605,9 +4680,9 @@ static
ibool
lock_table_queue_validate(
/*======================*/
- dict_table_t* table) /*!< in: table */
+ const dict_table_t* table) /*!< in: table */
{
- lock_t* lock;
+ const lock_t* lock;
ut_ad(mutex_own(&kernel_mutex));
@@ -4643,7 +4718,7 @@ lock_rec_queue_validate(
/*====================*/
const buf_block_t* block, /*!< in: buffer block containing rec */
const rec_t* rec, /*!< in: record to look at */
- dict_index_t* index, /*!< in: index, or NULL if not known */
+ const dict_index_t* index, /*!< in: index, or NULL if not known */
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
{
trx_t* impl_trx;
@@ -4792,46 +4867,37 @@ static
ibool
lock_rec_validate_page(
/*===================*/
- 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 */
+ const buf_block_t* block) /*!< in: buffer block */
{
- dict_index_t* index;
- buf_block_t* block;
- const page_t* page;
- lock_t* lock;
+ const lock_t* lock;
const rec_t* rec;
ulint nth_lock = 0;
ulint nth_bit = 0;
ulint i;
- mtr_t mtr;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
rec_offs_init(offsets_);
ut_ad(!mutex_own(&kernel_mutex));
-
- mtr_start(&mtr);
-
- ut_ad(zip_size != ULINT_UNDEFINED);
- block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
-
- page = block->frame;
+ ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
lock_mutex_enter_kernel();
loop:
- lock = lock_rec_get_first_on_page_addr(space, page_no);
+ lock = lock_rec_get_first_on_page_addr(buf_block_get_space(block),
+ buf_block_get_page_no(block));
if (!lock) {
goto function_exit;
}
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
+ ut_a(!block->page.file_page_was_freed);
+#endif
+
for (i = 0; i < nth_lock; i++) {
- lock = lock_rec_get_next_on_page(lock);
+ lock = lock_rec_get_next_on_page_const(lock);
if (!lock) {
goto function_exit;
@@ -4854,16 +4920,15 @@ loop:
if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
- index = lock->index;
- rec = page_find_rec_with_heap_no(page, i);
+ rec = page_find_rec_with_heap_no(block->frame, i);
ut_a(rec);
- offsets = rec_get_offsets(rec, index, offsets,
+ offsets = rec_get_offsets(rec, lock->index, offsets,
ULINT_UNDEFINED, &heap);
-
+#if 0
fprintf(stderr,
- "Validating %lu %lu\n",
- (ulong) space, (ulong) page_no);
-
+ "Validating %u %u\n",
+ block->page.space, block->page.offset);
+#endif
lock_mutex_exit_kernel();
/* If this thread is holding the file space
@@ -4871,7 +4936,8 @@ loop:
check WILL break the latching order and may
cause a deadlock of threads. */
- lock_rec_queue_validate(block, rec, index, offsets);
+ lock_rec_queue_validate(block, rec, lock->index,
+ offsets);
lock_mutex_enter_kernel();
@@ -4889,8 +4955,6 @@ loop:
function_exit:
lock_mutex_exit_kernel();
- mtr_commit(&mtr);
-
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -4905,11 +4969,8 @@ ibool
lock_validate(void)
/*===============*/
{
- lock_t* lock;
- trx_t* trx;
- ib_uint64_t limit;
- ulint space;
- ulint page_no;
+ const lock_t* lock;
+ const trx_t* trx;
ulint i;
lock_mutex_enter_kernel();
@@ -4934,9 +4995,14 @@ lock_validate(void)
for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
- limit = 0;
+ ulint space;
+ ulint page_no;
+ ib_uint64_t limit = 0;
for (;;) {
+ mtr_t mtr;
+ buf_block_t* block;
+
lock = HASH_GET_FIRST(lock_sys->rec_hash, i);
while (lock) {
@@ -4962,13 +5028,26 @@ lock_validate(void)
lock_mutex_exit_kernel();
- lock_rec_validate_page(space,
- fil_space_get_zip_size(space),
- page_no);
+ /* The lock and the block that it is referring
+ to may be freed at this point. We pass
+ BUF_GET_POSSIBLY_FREED to skip a debug check.
+ If the lock exists in lock_rec_validate_page()
+ we assert !block->page.file_page_was_freed. */
- lock_mutex_enter_kernel();
+ mtr_start(&mtr);
+ block = buf_page_get_gen(
+ space, fil_space_get_zip_size(space),
+ page_no, RW_X_LATCH, NULL,
+ BUF_GET_POSSIBLY_FREED,
+ __FILE__, __LINE__, &mtr);
+ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
+
+ ut_ad(lock_rec_validate_page(block));
+ mtr_commit(&mtr);
+
+ limit++;
- limit = ut_ull_create(space, page_no + 1);
+ lock_mutex_enter_kernel();
}
}
diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c
index 401cede1d8f..fd2258945b6 100644
--- a/storage/innobase/log/log0log.c
+++ b/storage/innobase/log/log0log.c
@@ -3078,6 +3078,7 @@ logs_empty_and_mark_files_at_shutdown(void)
{
ib_uint64_t lsn;
ulint arch_log_no;
+ ibool server_busy;
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
@@ -3092,80 +3093,86 @@ loop:
mutex_enter(&kernel_mutex);
- /* We need the monitor threads to stop before we proceed with a
- normal shutdown. In case of very fast shutdown, however, we can
- proceed without waiting for monitor threads. */
+ /* We need the monitor threads to stop before we proceed with
+ a shutdown. */
- if (srv_fast_shutdown < 2
- && (srv_error_monitor_active
- || srv_lock_timeout_active || srv_monitor_active)) {
+ if (srv_error_monitor_active
+ || srv_lock_timeout_active
+ || srv_monitor_active) {
mutex_exit(&kernel_mutex);
- goto loop;
- }
-
- /* Check that there are no longer transactions. We need this wait even
- for the 'very fast' shutdown, because the InnoDB layer may have
- committed or prepared transactions and we don't want to lose them. */
-
- if (trx_n_mysql_transactions > 0
- || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
-
- mutex_exit(&kernel_mutex);
+ os_event_set(srv_error_event);
+ os_event_set(srv_monitor_event);
+ os_event_set(srv_timeout_event);
goto loop;
}
- if (srv_fast_shutdown == 2) {
- /* In this fastest shutdown we do not flush the buffer pool:
- it is essentially a 'crash' of the InnoDB server. Make sure
- that the log is all flushed to disk, so that we can recover
- all committed transactions in a crash recovery. We must not
- write the lsn stamps to the data files, since at a startup
- InnoDB deduces from the stamps if the previous shutdown was
- clean. */
-
- log_buffer_flush_to_disk();
-
- return; /* We SKIP ALL THE REST !! */
- }
+ /* Check that there are no longer transactions, except for
+ PREPARED ones. We need this wait even for the 'very fast'
+ shutdown, because the InnoDB layer may have committed or
+ prepared transactions and we don't want to lose them. */
+ server_busy = trx_n_mysql_transactions > 0
+ || UT_LIST_GET_LEN(trx_sys->trx_list) > trx_n_prepared;
mutex_exit(&kernel_mutex);
- /* Check that the background threads are suspended */
-
- if (srv_is_any_background_thread_active()) {
+ if (server_busy || srv_is_any_background_thread_active()) {
goto loop;
}
- mutex_enter(&(log_sys->mutex));
-
- if (log_sys->n_pending_checkpoint_writes
+ mutex_enter(&log_sys->mutex);
+ server_busy = log_sys->n_pending_checkpoint_writes
#ifdef UNIV_LOG_ARCHIVE
- || log_sys->n_pending_archive_ios
+ || log_sys->n_pending_archive_ios
#endif /* UNIV_LOG_ARCHIVE */
- || log_sys->n_pending_writes) {
-
- mutex_exit(&(log_sys->mutex));
-
- goto loop;
- }
-
- mutex_exit(&(log_sys->mutex));
-
- if (!buf_pool_check_no_pending_io()) {
+ || log_sys->n_pending_writes;
+ mutex_exit(&log_sys->mutex);
+ if (server_busy || !buf_pool_check_no_pending_io()) {
goto loop;
}
#ifdef UNIV_LOG_ARCHIVE
log_archive_all();
#endif /* UNIV_LOG_ARCHIVE */
+ if (srv_fast_shutdown == 2) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: MySQL has requested a very fast shutdown"
+ " without flushing "
+ "the InnoDB buffer pool to data files."
+ " At the next mysqld startup "
+ "InnoDB will do a crash recovery!\n");
+
+ /* In this fastest shutdown we do not flush the buffer
+ pool: it is essentially a 'crash' of the InnoDB
+ server. Make sure that the log is all flushed to disk,
+ so that we can recover all committed transactions in a
+ crash recovery. We must not write the lsn stamps to
+ the data files, since at a startup InnoDB deduces from
+ the stamps if the previous shutdown was clean. */
+
+ log_buffer_flush_to_disk();
+
+ /* Check that the background threads stay suspended */
+ if (srv_is_any_background_thread_active()) {
+ fprintf(stderr,
+ "InnoDB: Warning: some background thread"
+ " woke up during shutdown\n");
+ goto loop;
+ }
+
+ srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
+ fil_close_all_files();
+ ut_a(!srv_is_any_background_thread_active());
+ return;
+ }
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
- mutex_enter(&(log_sys->mutex));
+ mutex_enter(&log_sys->mutex);
lsn = log_sys->lsn;
@@ -3176,7 +3183,7 @@ loop:
#endif /* UNIV_LOG_ARCHIVE */
) {
- mutex_exit(&(log_sys->mutex));
+ mutex_exit(&log_sys->mutex);
goto loop;
}
@@ -3194,7 +3201,7 @@ loop:
log_archive_close_groups(TRUE);
#endif /* UNIV_LOG_ARCHIVE */
- mutex_exit(&(log_sys->mutex));
+ mutex_exit(&log_sys->mutex);
/* Check that the background threads stay suspended */
if (srv_is_any_background_thread_active()) {
diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c
index e5b2de14f74..f9e0fecb6c6 100644
--- a/storage/innobase/log/log0recv.c
+++ b/storage/innobase/log/log0recv.c
@@ -1657,12 +1657,8 @@ recv_recover_page_func(
#ifndef UNIV_HOTBACKUP
if (modification_to_page) {
- buf_pool_t* buf_pool;
-
ut_a(block);
- buf_pool = buf_pool_from_block(block);
-
log_flush_order_mutex_enter();
buf_flush_recv_note_modification(block, start_lsn, end_lsn);
log_flush_order_mutex_exit();
@@ -2203,7 +2199,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/innobase/mem/mem0dbg.c b/storage/innobase/mem/mem0dbg.c
index d91e610a08a..ae43d6097a6 100644
--- a/storage/innobase/mem/mem0dbg.c
+++ b/storage/innobase/mem/mem0dbg.c
@@ -24,6 +24,8 @@ but is included in mem0mem.* !
Created 6/9/1994 Heikki Tuuri
*************************************************************************/
+#include "ha_prototypes.h"
+
#ifdef UNIV_MEM_DEBUG
# ifndef UNIV_HOTBACKUP
/* The mutex which protects in the debug version the hash table
@@ -400,7 +402,7 @@ mem_hash_remove(
fprintf(stderr,
"Memory heap or buffer freed in %s line %lu"
" did not exist.\n",
- file_name, (ulong) line);
+ innobase_basename(file_name), (ulong) line);
ut_error;
}
@@ -419,8 +421,9 @@ mem_hash_remove(
"in %s line %lu and tried to free in %s line %lu.\n"
"Hex dump of 400 bytes around memory heap"
" first block start:\n",
- node->nth_heap, node->file_name, (ulong) node->line,
- file_name, (ulong) line);
+ node->nth_heap,
+ innobase_basename(node->file_name), (ulong) node->line,
+ innobase_basename(file_name), (ulong) line);
ut_print_buf(stderr, (byte*)node->heap - 200, 400);
fputs("\nDump of the mem heap:\n", stderr);
mem_heap_validate_or_print(node->heap, NULL, TRUE, &error,
@@ -763,7 +766,8 @@ mem_validate_no_assert(void)
"Inconsistency in memory heap"
" or buffer created\n"
"in %s line %lu.\n",
- node->file_name, node->line);
+ innobase_basename(node->file_name),
+ node->line);
mutex_exit(&mem_hash_mutex);
@@ -989,7 +993,8 @@ mem_print_info_low(
fprintf(outfile,
"%lu: file %s line %lu of size %lu phys.size %lu"
" with %lu blocks, type %lu\n",
- node->nth_heap, node->file_name, node->line,
+ node->nth_heap,
+ innobase_basename(node->file_name), node->line,
allocated_mem, ph_size, n_blocks,
(node->heap)->type);
next_heap:
diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c
index b5a7ddbd7b2..7727760f1cd 100644
--- a/storage/innobase/mem/mem0mem.c
+++ b/storage/innobase/mem/mem0mem.c
@@ -347,7 +347,7 @@ mem_heap_create_block(
return(NULL);
}
} else {
- buf_block = buf_block_alloc(NULL, 0);
+ buf_block = buf_block_alloc(NULL);
}
block = (mem_block_t*) buf_block->frame;
diff --git a/storage/innobase/mtr/mtr0log.c b/storage/innobase/mtr/mtr0log.c
index 04eeb4391cd..864970cef40 100644
--- a/storage/innobase/mtr/mtr0log.c
+++ b/storage/innobase/mtr/mtr0log.c
@@ -408,7 +408,7 @@ mlog_parse_string(
ptr += 2;
if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
- || UNIV_UNLIKELY(len + offset) > UNIV_PAGE_SIZE) {
+ || UNIV_UNLIKELY(len + offset > UNIV_PAGE_SIZE)) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c
index 74d04a22b86..439b429db43 100644
--- a/storage/innobase/mtr/mtr0mtr.c
+++ b/storage/innobase/mtr/mtr0mtr.c
@@ -251,6 +251,7 @@ mtr_commit(
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE);
+ ut_ad(!mtr->inside_ibuf);
ut_d(mtr->state = MTR_COMMITTING);
#ifndef UNIV_HOTBACKUP
@@ -264,9 +265,20 @@ mtr_commit(
mtr_memo_pop_all(mtr);
#endif /* !UNIV_HOTBACKUP */
- ut_d(mtr->state = MTR_COMMITTED);
dyn_array_free(&(mtr->memo));
dyn_array_free(&(mtr->log));
+#ifdef UNIV_DEBUG_VALGRIND
+ /* Declare everything uninitialized except
+ mtr->start_lsn, mtr->end_lsn and mtr->state. */
+ {
+ ib_uint64_t start_lsn = mtr->start_lsn;
+ ib_uint64_t end_lsn = mtr->end_lsn;
+ UNIV_MEM_INVALID(mtr, sizeof *mtr);
+ mtr->start_lsn = start_lsn;
+ mtr->end_lsn = end_lsn;
+ }
+#endif /* UNIV_DEBUG_VALGRIND */
+ ut_d(mtr->state = MTR_COMMITTED);
}
#ifndef UNIV_HOTBACKUP
diff --git a/storage/innobase/mysql-test/patches/README b/storage/innobase/mysql-test/patches/README
deleted file mode 100644
index 122d756e9e3..00000000000
--- a/storage/innobase/mysql-test/patches/README
+++ /dev/null
@@ -1,30 +0,0 @@
-This directory contains patches that need to be applied to the MySQL
-source tree in order to get the mysql-test suite to succeed (when
-storage/innobase is replaced with this InnoDB branch). Things to keep
-in mind when adding new patches here:
-
-* The patch must be appliable from the mysql top-level source directory.
-
-* The patch filename must end in ".diff".
-
-* All patches here are expected to apply cleanly to the latest MySQL 5.1
- tree when storage/innobase is replaced with this InnoDB branch. If
- changes to either of those cause the patch to fail, then please check
- whether the patch is still needed and, if yes, adjust it so it applies
- cleanly.
-
-* If applicable, always submit the patch at http://bugs.mysql.com and
- name the file here like bug%d.diff. Once the patch is committed to
- MySQL remove the file from here.
-
-* If the patch cannot be proposed for inclusion in the MySQL source tree
- (via http://bugs.mysql.com) then add a comment at the beginning of the
- patch, explaining the problem it is solving, how it does solve it and
- why it is not applicable for inclusion in the MySQL source tree.
- Obviously this is a very bad situation and should be avoided at all
- costs, especially for files that are in the MySQL source repository
- (not in storage/innobase).
-
-* If you ever need to add a patch here that is not related to mysql-test
- suite, then please move this directory from ./mysql-test/patches to
- ./patches and remove this text.
diff --git a/storage/innobase/mysql-test/patches/index_merge_innodb-explain.diff b/storage/innobase/mysql-test/patches/index_merge_innodb-explain.diff
deleted file mode 100644
index d1ed8afc778..00000000000
--- a/storage/innobase/mysql-test/patches/index_merge_innodb-explain.diff
+++ /dev/null
@@ -1,31 +0,0 @@
-InnoDB's estimate for the index cardinality depends on a pseudo random
-number generator (it picks up random pages to sample). After an
-optimization that was made in r2625 the following EXPLAINs started
-returning a different number of rows (3 instead of 4).
-
-This patch adjusts the result file.
-
-This patch cannot be proposed to MySQL because the failures occur only
-in this tree and do not occur in the standard InnoDB 5.1. Furthermore,
-the file index_merge2.inc is used by other engines too.
-
---- mysql-test/r/index_merge_innodb.result.orig 2008-09-30 18:32:13.000000000 +0300
-+++ mysql-test/r/index_merge_innodb.result 2008-09-30 18:33:01.000000000 +0300
-@@ -111,7 +111,7 @@
- explain select count(*) from t1 where
- key1a = 2 and key1b is null and key2a = 2 and key2b is null;
- id select_type table type possible_keys key key_len ref rows Extra
--1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 4 Using intersect(i1,i2); Using where; Using index
-+1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 3 Using intersect(i1,i2); Using where; Using index
- select count(*) from t1 where
- key1a = 2 and key1b is null and key2a = 2 and key2b is null;
- count(*)
-@@ -119,7 +119,7 @@
- explain select count(*) from t1 where
- key1a = 2 and key1b is null and key3a = 2 and key3b is null;
- id select_type table type possible_keys key key_len ref rows Extra
--1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 4 Using intersect(i1,i3); Using where; Using index
-+1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 3 Using intersect(i1,i3); Using where; Using index
- select count(*) from t1 where
- key1a = 2 and key1b is null and key3a = 2 and key3b is null;
- count(*)
diff --git a/storage/innobase/mysql-test/patches/information_schema.diff b/storage/innobase/mysql-test/patches/information_schema.diff
deleted file mode 100644
index a3a21f7a08d..00000000000
--- a/storage/innobase/mysql-test/patches/information_schema.diff
+++ /dev/null
@@ -1,124 +0,0 @@
---- mysql-test/r/information_schema.result.orig 2009-01-31 03:38:50.000000000 +0200
-+++ mysql-test/r/information_schema.result 2009-01-31 07:51:58.000000000 +0200
-@@ -71,6 +71,13 @@
- TRIGGERS
- USER_PRIVILEGES
- VIEWS
-+INNODB_CMP_RESET
-+INNODB_TRX
-+INNODB_CMPMEM_RESET
-+INNODB_LOCK_WAITS
-+INNODB_CMPMEM
-+INNODB_CMP
-+INNODB_LOCKS
- columns_priv
- db
- event
-@@ -799,6 +806,8 @@
- TABLES UPDATE_TIME datetime
- TABLES CHECK_TIME datetime
- TRIGGERS CREATED datetime
-+INNODB_TRX trx_started datetime
-+INNODB_TRX trx_wait_started datetime
- event execute_at datetime
- event last_executed datetime
- event starts datetime
-@@ -852,7 +861,7 @@
- flush privileges;
- SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
- table_schema count(*)
--information_schema 28
-+information_schema 35
- mysql 22
- create table t1 (i int, j int);
- create trigger trg1 before insert on t1 for each row
-@@ -1267,6 +1276,13 @@
- TRIGGERS TRIGGER_SCHEMA
- USER_PRIVILEGES GRANTEE
- VIEWS TABLE_SCHEMA
-+INNODB_CMP_RESET page_size
-+INNODB_TRX trx_id
-+INNODB_CMPMEM_RESET page_size
-+INNODB_LOCK_WAITS requesting_trx_id
-+INNODB_CMPMEM page_size
-+INNODB_CMP page_size
-+INNODB_LOCKS lock_id
- SELECT t.table_name, c1.column_name
- FROM information_schema.tables t
- INNER JOIN
-@@ -1310,6 +1326,13 @@
- TRIGGERS TRIGGER_SCHEMA
- USER_PRIVILEGES GRANTEE
- VIEWS TABLE_SCHEMA
-+INNODB_CMP_RESET page_size
-+INNODB_TRX trx_id
-+INNODB_CMPMEM_RESET page_size
-+INNODB_LOCK_WAITS requesting_trx_id
-+INNODB_CMPMEM page_size
-+INNODB_CMP page_size
-+INNODB_LOCKS lock_id
- SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test');
- MAX(table_name)
- VIEWS
-@@ -1386,6 +1409,13 @@
- FILES information_schema.FILES 1
- GLOBAL_STATUS information_schema.GLOBAL_STATUS 1
- GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1
-+INNODB_CMP information_schema.INNODB_CMP 1
-+INNODB_CMPMEM information_schema.INNODB_CMPMEM 1
-+INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1
-+INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1
-+INNODB_LOCKS information_schema.INNODB_LOCKS 1
-+INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
-+INNODB_TRX information_schema.INNODB_TRX 1
- KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
- PARTITIONS information_schema.PARTITIONS 1
- PLUGINS information_schema.PLUGINS 1
-diff mysql-test/r/information_schema_db.result.orig mysql-test/r/information_schema_db.result
---- mysql-test/r/information_schema_db.result.orig 2008-08-04 09:27:49.000000000 +0300
-+++ mysql-test/r/information_schema_db.result 2008-10-07 12:26:31.000000000 +0300
-@@ -33,6 +33,13 @@
- TRIGGERS
- USER_PRIVILEGES
- VIEWS
-+INNODB_CMP_RESET
-+INNODB_TRX
-+INNODB_CMPMEM_RESET
-+INNODB_LOCK_WAITS
-+INNODB_CMPMEM
-+INNODB_CMP
-+INNODB_LOCKS
- show tables from INFORMATION_SCHEMA like 'T%';
- Tables_in_information_schema (T%)
- TABLES
-diff mysql-test/r/mysqlshow.result.orig mysql-test/r/mysqlshow.result
---- mysql-test/r/mysqlshow.result.orig 2008-08-04 09:27:51.000000000 +0300
-+++ mysql-test/r/mysqlshow.result 2008-10-07 12:35:39.000000000 +0300
-@@ -107,6 +107,13 @@
- | TRIGGERS |
- | USER_PRIVILEGES |
- | VIEWS |
-+| INNODB_CMP_RESET |
-+| INNODB_TRX |
-+| INNODB_CMPMEM_RESET |
-+| INNODB_LOCK_WAITS |
-+| INNODB_CMPMEM |
-+| INNODB_CMP |
-+| INNODB_LOCKS |
- +---------------------------------------+
- Database: INFORMATION_SCHEMA
- +---------------------------------------+
-@@ -140,6 +147,13 @@
- | TRIGGERS |
- | USER_PRIVILEGES |
- | VIEWS |
-+| INNODB_CMP_RESET |
-+| INNODB_TRX |
-+| INNODB_CMPMEM_RESET |
-+| INNODB_LOCK_WAITS |
-+| INNODB_CMPMEM |
-+| INNODB_CMP |
-+| INNODB_LOCKS |
- +---------------------------------------+
- Wildcard: inf_rmation_schema
- +--------------------+
diff --git a/storage/innobase/mysql-test/patches/innodb_change_buffering_basic.diff b/storage/innobase/mysql-test/patches/innodb_change_buffering_basic.diff
deleted file mode 100644
index bfa1609a97c..00000000000
--- a/storage/innobase/mysql-test/patches/innodb_change_buffering_basic.diff
+++ /dev/null
@@ -1,60 +0,0 @@
---- mysql-test/suite/sys_vars/t/innodb_change_buffering_basic.test.orig Mon Mar 15 16:15:22 2010
-+++ mysql-test/suite/sys_vars/t/innodb_change_buffering_basic.test Fri Mar 19 01:19:09 2010
-@@ -11,8 +11,8 @@
- #
- # exists as global only
- #
----echo Valid values are 'inserts' and 'none'
--select @@global.innodb_change_buffering in ('inserts', 'none');
-+--echo Valid values are 'inserts', 'deletes', 'changes', 'purges', 'all', and 'none'
-+select @@global.innodb_change_buffering in ('inserts', 'deletes', 'changes', 'purges', 'all', 'none');
- select @@global.innodb_change_buffering;
- --error ER_INCORRECT_GLOBAL_LOCAL_VAR
- select @@session.innodb_change_buffering;
-
---- mysql-test/suite/sys_vars/r/innodb_change_buffering_basic.result.orig Mon Mar 15 16:15:22 2010
-+++ mysql-test/suite/sys_vars/r/innodb_change_buffering_basic.result Fri Mar 19 01:23:58 2010
-@@ -1,28 +1,28 @@
- SET @start_global_value = @@global.innodb_change_buffering;
- SELECT @start_global_value;
- @start_global_value
--inserts
--Valid values are 'inserts' and 'none'
--select @@global.innodb_change_buffering in ('inserts', 'none');
--@@global.innodb_change_buffering in ('inserts', 'none')
-+all
-+Valid values are 'inserts', 'deletes', 'changes', 'purges', 'all', and 'none'
-+select @@global.innodb_change_buffering in ('inserts', 'deletes', 'changes', 'purges', 'all', 'none');
-+@@global.innodb_change_buffering in ('inserts', 'deletes', 'changes', 'purges', 'all', 'none')
- 1
- select @@global.innodb_change_buffering;
- @@global.innodb_change_buffering
--inserts
-+all
- select @@session.innodb_change_buffering;
- ERROR HY000: Variable 'innodb_change_buffering' is a GLOBAL variable
- show global variables like 'innodb_change_buffering';
- Variable_name Value
--innodb_change_buffering inserts
-+innodb_change_buffering all
- show session variables like 'innodb_change_buffering';
- Variable_name Value
--innodb_change_buffering inserts
-+innodb_change_buffering all
- select * from information_schema.global_variables where variable_name='innodb_change_buffering';
- VARIABLE_NAME VARIABLE_VALUE
--INNODB_CHANGE_BUFFERING inserts
-+INNODB_CHANGE_BUFFERING all
- select * from information_schema.session_variables where variable_name='innodb_change_buffering';
- VARIABLE_NAME VARIABLE_VALUE
--INNODB_CHANGE_BUFFERING inserts
-+INNODB_CHANGE_BUFFERING all
- set global innodb_change_buffering='none';
- select @@global.innodb_change_buffering;
- @@global.innodb_change_buffering
-@@ -60,4 +60,4 @@
- SET @@global.innodb_change_buffering = @start_global_value;
- SELECT @@global.innodb_change_buffering;
- @@global.innodb_change_buffering
--inserts
-+all
diff --git a/storage/innobase/mysql-test/patches/innodb_file_per_table.diff b/storage/innobase/mysql-test/patches/innodb_file_per_table.diff
deleted file mode 100644
index 8b7ae2036c9..00000000000
--- a/storage/innobase/mysql-test/patches/innodb_file_per_table.diff
+++ /dev/null
@@ -1,47 +0,0 @@
-diff mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test.orig mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test
---- mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test.orig 2008-10-07 11:32:30.000000000 +0300
-+++ mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test 2008-10-07 11:52:14.000000000 +0300
-@@ -37,10 +37,6 @@
- # Check if Value can set #
- ####################################################################
-
----error ER_INCORRECT_GLOBAL_LOCAL_VAR
--SET @@GLOBAL.innodb_file_per_table=1;
----echo Expected error 'Read only variable'
--
- SELECT COUNT(@@GLOBAL.innodb_file_per_table);
- --echo 1 Expected
-
-@@ -52,7 +48,7 @@
- # Check if the value in GLOBAL Table matches value in variable #
- #################################################################
-
--SELECT @@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
-+SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
- FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
- WHERE VARIABLE_NAME='innodb_file_per_table';
- --echo 1 Expected
-diff mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result.orig mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result
---- mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result.orig 2008-10-07 11:32:02.000000000 +0300
-+++ mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result 2008-10-07 11:52:47.000000000 +0300
-@@ -4,18 +4,15 @@
- 1
- 1 Expected
- '#---------------------BS_STVARS_028_02----------------------#'
--SET @@GLOBAL.innodb_file_per_table=1;
--ERROR HY000: Variable 'innodb_file_per_table' is a read only variable
--Expected error 'Read only variable'
- SELECT COUNT(@@GLOBAL.innodb_file_per_table);
- COUNT(@@GLOBAL.innodb_file_per_table)
- 1
- 1 Expected
- '#---------------------BS_STVARS_028_03----------------------#'
--SELECT @@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
-+SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
- FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
- WHERE VARIABLE_NAME='innodb_file_per_table';
--@@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
-+IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
- 1
- 1 Expected
- SELECT COUNT(@@GLOBAL.innodb_file_per_table);
diff --git a/storage/innobase/mysql-test/patches/innodb_lock_wait_timeout.diff b/storage/innobase/mysql-test/patches/innodb_lock_wait_timeout.diff
deleted file mode 100644
index bc61a0f5841..00000000000
--- a/storage/innobase/mysql-test/patches/innodb_lock_wait_timeout.diff
+++ /dev/null
@@ -1,55 +0,0 @@
---- mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test.orig 2008-08-04 09:28:16.000000000 +0300
-+++ mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test 2008-10-07 11:14:15.000000000 +0300
-@@ -37,10 +37,6 @@
- # Check if Value can set #
- ####################################################################
-
----error ER_INCORRECT_GLOBAL_LOCAL_VAR
--SET @@GLOBAL.innodb_lock_wait_timeout=1;
----echo Expected error 'Read only variable'
--
- SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
- --echo 1 Expected
-
-@@ -84,13 +80,9 @@
- SELECT COUNT(@@innodb_lock_wait_timeout);
- --echo 1 Expected
-
----Error ER_INCORRECT_GLOBAL_LOCAL_VAR
- SELECT COUNT(@@local.innodb_lock_wait_timeout);
----echo Expected error 'Variable is a GLOBAL variable'
-
----Error ER_INCORRECT_GLOBAL_LOCAL_VAR
- SELECT COUNT(@@SESSION.innodb_lock_wait_timeout);
----echo Expected error 'Variable is a GLOBAL variable'
-
- SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
- --echo 1 Expected
---- mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result.orig 2008-08-04 09:27:50.000000000 +0300
-+++ mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result 2008-10-07 11:15:14.000000000 +0300
-@@ -4,9 +4,6 @@
- 1
- 1 Expected
- '#---------------------BS_STVARS_032_02----------------------#'
--SET @@GLOBAL.innodb_lock_wait_timeout=1;
--ERROR HY000: Variable 'innodb_lock_wait_timeout' is a read only variable
--Expected error 'Read only variable'
- SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
- COUNT(@@GLOBAL.innodb_lock_wait_timeout)
- 1
-@@ -39,11 +36,11 @@
- 1
- 1 Expected
- SELECT COUNT(@@local.innodb_lock_wait_timeout);
--ERROR HY000: Variable 'innodb_lock_wait_timeout' is a GLOBAL variable
--Expected error 'Variable is a GLOBAL variable'
-+COUNT(@@local.innodb_lock_wait_timeout)
-+1
- SELECT COUNT(@@SESSION.innodb_lock_wait_timeout);
--ERROR HY000: Variable 'innodb_lock_wait_timeout' is a GLOBAL variable
--Expected error 'Variable is a GLOBAL variable'
-+COUNT(@@SESSION.innodb_lock_wait_timeout)
-+1
- SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
- COUNT(@@GLOBAL.innodb_lock_wait_timeout)
- 1
diff --git a/storage/innobase/mysql-test/patches/innodb_thread_concurrency_basic.diff b/storage/innobase/mysql-test/patches/innodb_thread_concurrency_basic.diff
deleted file mode 100644
index 72e5457905f..00000000000
--- a/storage/innobase/mysql-test/patches/innodb_thread_concurrency_basic.diff
+++ /dev/null
@@ -1,31 +0,0 @@
---- mysql-test/suite/sys_vars/r/innodb_thread_concurrency_basic.result.orig 2008-12-04 18:45:52 -06:00
-+++ mysql-test/suite/sys_vars/r/innodb_thread_concurrency_basic.result 2009-02-12 02:05:48 -06:00
-@@ -1,19 +1,19 @@
- SET @global_start_value = @@global.innodb_thread_concurrency;
- SELECT @global_start_value;
- @global_start_value
--8
-+0
- '#--------------------FN_DYNVARS_046_01------------------------#'
- SET @@global.innodb_thread_concurrency = 0;
- SET @@global.innodb_thread_concurrency = DEFAULT;
- SELECT @@global.innodb_thread_concurrency;
- @@global.innodb_thread_concurrency
--8
-+0
- '#---------------------FN_DYNVARS_046_02-------------------------#'
- SET innodb_thread_concurrency = 1;
- ERROR HY000: Variable 'innodb_thread_concurrency' is a GLOBAL variable and should be set with SET GLOBAL
- SELECT @@innodb_thread_concurrency;
- @@innodb_thread_concurrency
--8
-+0
- SELECT local.innodb_thread_concurrency;
- ERROR 42S02: Unknown table 'local' in field list
- SET global innodb_thread_concurrency = 0;
-@@ -93,4 +93,4 @@
- SET @@global.innodb_thread_concurrency = @global_start_value;
- SELECT @@global.innodb_thread_concurrency;
- @@global.innodb_thread_concurrency
--8
-+0
diff --git a/storage/innobase/mysql-test/patches/partition_innodb.diff b/storage/innobase/mysql-test/patches/partition_innodb.diff
deleted file mode 100644
index 01bc073008e..00000000000
--- a/storage/innobase/mysql-test/patches/partition_innodb.diff
+++ /dev/null
@@ -1,59 +0,0 @@
-The partition_innodb test only fails if run immediately after innodb_trx_weight.
-The reason for this failure is that innodb_trx_weight creates deadlocks and
-leaves something like this in the SHOW ENGINE INNODB STATUS output:
-
- ------------------------
- LATEST DETECTED DEADLOCK
- ------------------------
- 090213 10:26:25
- *** (1) TRANSACTION:
- TRANSACTION 313, ACTIVE 0 sec, OS thread id 13644672 inserting
- mysql tables in use 1, locked 1
- LOCK WAIT 4 lock struct(s), heap size 488, 3 row lock(s)
- MySQL thread id 3, query id 36 localhost root update
-
-The regular expressions that partition_innodb is using are intended to extract
-the lock structs and row locks numbers from another part of the output:
-
- ------------
- TRANSACTIONS
- ------------
- Trx id counter 31D
- Purge done for trx's n:o < 0 undo n:o < 0
- History list length 4
- LIST OF TRANSACTIONS FOR EACH SESSION:
- ---TRANSACTION 0, not started, OS thread id 13645056
- 0 lock struct(s), heap size 488, 0 row lock(s)
- MySQL thread id 8, query id 81 localhost root
-
-In the InnoDB Plugin a transaction id is not printed as 2 consecutive
-decimal integers (as it is in InnoDB 5.1) but rather as a single
-hexadecimal integer. Thus the regular expressions somehow pick the wrong
-part of the SHOW ENGINE INNODB STATUS output.
-
-So after the regular expressions are adjusted to the InnoDB Plugin's variant
-of trx_id prinout, then they pick the expected part of the output.
-
-This patch cannot be proposed to MySQL because the failures occur only
-in this tree and do not occur in the standard InnoDB 5.1.
-
---- mysql-test/t/partition_innodb.test 2008-11-14 22:51:17 +0000
-+++ mysql-test/t/partition_innodb.test 2009-02-13 07:36:07 +0000
-@@ -27,14 +27,14 @@
-
- # grouping/referencing in replace_regex is very slow on long strings,
- # removing all before/after the interesting row before grouping/referencing
----replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
-+--replace_regex /.*---TRANSACTION [0-9A-F]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
- SHOW ENGINE InnoDB STATUS;
-
- UPDATE t1 SET data = data*2 WHERE data = 2;
-
- # grouping/referencing in replace_regex is very slow on long strings,
- # removing all before/after the interesting row before grouping/referencing
----replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
-+--replace_regex /.*---TRANSACTION [0-9A-F]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
- SHOW ENGINE InnoDB STATUS;
-
- SET @@session.tx_isolation = @old_tx_isolation;
-
diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c
index 6c17ded0073..bd48d0e4b6e 100644
--- a/storage/innobase/os/os0file.c
+++ b/storage/innobase/os/os0file.c
@@ -302,6 +302,36 @@ UNIV_INTERN ulint os_n_pending_writes = 0;
/** Number of pending read operations */
UNIV_INTERN ulint os_n_pending_reads = 0;
+#ifdef UNIV_DEBUG
+/**********************************************************************//**
+Validates the consistency the aio system some of the time.
+@return TRUE if ok or the check was skipped */
+UNIV_INTERN
+ibool
+os_aio_validate_skip(void)
+/*======================*/
+{
+/** Try os_aio_validate() every this many times */
+# define OS_AIO_VALIDATE_SKIP 13
+
+ /** The os_aio_validate() call skip counter.
+ Use a signed type because of the race condition below. */
+ static int os_aio_validate_count = OS_AIO_VALIDATE_SKIP;
+
+ /* There is a race condition below, but it does not matter,
+ because this call is only for heuristic purposes. We want to
+ reduce the call frequency of the costly os_aio_validate()
+ check in debug builds. */
+ if (--os_aio_validate_count > 0) {
+ return(TRUE);
+ }
+
+ os_aio_validate_count = OS_AIO_VALIDATE_SKIP;
+ return(os_aio_validate());
+}
+#endif /* UNIV_DEBUG */
+
+#ifdef __WIN__
/***********************************************************************//**
Gets the operating system version. Currently works only on Windows.
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA,
@@ -311,7 +341,6 @@ ulint
os_get_os_version(void)
/*===================*/
{
-#ifdef __WIN__
OSVERSIONINFO os_info;
os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@@ -340,12 +369,8 @@ os_get_os_version(void)
ut_error;
return(0);
}
-#else
- ut_error;
-
- return(0);
-#endif
}
+#endif /* __WIN__ */
/***********************************************************************//**
Retrieves the last error number if an error occurs in a file io function.
@@ -1295,10 +1320,12 @@ UNIV_INTERN
void
os_file_set_nocache(
/*================*/
- int fd, /*!< in: file descriptor to alter */
- const char* file_name, /*!< in: file name, used in the
- diagnostic message */
- const char* operation_name) /*!< in: "open" or "create"; used in the
+ int fd /*!< in: file descriptor to alter */
+ __attribute__((unused)),
+ const char* file_name /*!< in: used in the diagnostic message */
+ __attribute__((unused)),
+ const char* operation_name __attribute__((unused)))
+ /*!< in: "open" or "create"; used in the
diagnostic message */
{
/* some versions of Solaris may not have DIRECTIO_ON */
@@ -2398,7 +2425,10 @@ os_file_read_func(
ulint i;
#endif /* !UNIV_HOTBACKUP */
+ /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
+ no more than 32 bits. */
ut_a((offset & 0xFFFFFFFFUL) == offset);
+ ut_a((n & 0xFFFFFFFFUL) == n);
os_n_file_reads++;
os_bytes_read_since_printout += n;
@@ -2524,7 +2554,10 @@ os_file_read_no_error_handling_func(
ulint i;
#endif /* !UNIV_HOTBACKUP */
+ /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
+ no more than 32 bits. */
ut_a((offset & 0xFFFFFFFFUL) == offset);
+ ut_a((n & 0xFFFFFFFFUL) == n);
os_n_file_reads++;
os_bytes_read_since_printout += n;
@@ -2656,7 +2689,10 @@ os_file_write_func(
ulint i;
#endif /* !UNIV_HOTBACKUP */
- ut_a((offset & 0xFFFFFFFF) == offset);
+ /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
+ no more than 32 bits. */
+ ut_a((offset & 0xFFFFFFFFUL) == offset);
+ ut_a((n & 0xFFFFFFFFUL) == n);
os_n_file_writes++;
@@ -3619,6 +3655,10 @@ os_aio_array_reserve_slot(
ulint slots_per_seg;
ulint local_seg;
+#ifdef WIN_ASYNC_IO
+ ut_a((len & 0xFFFFFFFFUL) == len);
+#endif
+
/* No need of a mutex. Only reading constant fields */
slots_per_seg = array->n_slots / array->n_segments;
@@ -3993,7 +4033,10 @@ os_aio_func(
ut_ad(n > 0);
ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
- ut_ad(os_aio_validate());
+ ut_ad(os_aio_validate_skip());
+#ifdef WIN_ASYNC_IO
+ ut_ad((n & 0xFFFFFFFFUL) == n);
+#endif
wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
@@ -4008,26 +4051,33 @@ os_aio_func(
Windows async i/o, Windows does not allow us to use
ordinary synchronous os_file_read etc. on the same file,
therefore we have built a special mechanism for synchronous
- wait in the Windows case. */
+ wait in the Windows case.
+ Also note that the Performance Schema instrumentation has
+ been performed by current os_aio_func()'s wrapper function
+ pfs_os_aio_func(). So we would no longer need to call
+ Performance Schema instrumented os_file_read() and
+ os_file_write(). Instead, we should use os_file_read_func()
+ and os_file_write_func() */
if (type == OS_FILE_READ) {
- return(os_file_read(file, buf, offset,
+ return(os_file_read_func(file, buf, offset,
offset_high, n));
}
ut_a(type == OS_FILE_WRITE);
- return(os_file_write(name, file, buf, offset, offset_high, n));
+ return(os_file_write_func(name, file, buf, offset,
+ offset_high, n));
}
try_again:
- if (mode == OS_AIO_NORMAL) {
- if (type == OS_FILE_READ) {
- array = os_aio_read_array;
- } else {
- array = os_aio_write_array;
- }
- } else if (mode == OS_AIO_IBUF) {
+ switch (mode) {
+ case OS_AIO_NORMAL:
+ array = (type == OS_FILE_READ)
+ ? os_aio_read_array
+ : os_aio_write_array;
+ break;
+ case OS_AIO_IBUF:
ut_ad(type == OS_FILE_READ);
/* Reduce probability of deadlock bugs in connection with ibuf:
do not let the ibuf i/o handler sleep */
@@ -4035,19 +4085,21 @@ try_again:
wake_later = FALSE;
array = os_aio_ibuf_array;
- } else if (mode == OS_AIO_LOG) {
-
+ break;
+ case OS_AIO_LOG:
array = os_aio_log_array;
- } else if (mode == OS_AIO_SYNC) {
+ break;
+ case OS_AIO_SYNC:
array = os_aio_sync_array;
#if defined(LINUX_NATIVE_AIO)
/* In Linux native AIO we don't use sync IO array. */
ut_a(!srv_use_native_aio);
#endif /* LINUX_NATIVE_AIO */
- } else {
- array = NULL; /* Eliminate compiler warning */
+ break;
+ default:
ut_error;
+ array = NULL; /* Eliminate compiler warning */
}
slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
@@ -4192,7 +4244,7 @@ os_aio_windows_handle(
/* NOTE! We only access constant fields in os_aio_array. Therefore
we do not have to acquire the protecting mutex yet */
- ut_ad(os_aio_validate());
+ ut_ad(os_aio_validate_skip());
ut_ad(segment < array->n_segments);
n = array->n_slots / array->n_segments;
@@ -4210,11 +4262,17 @@ os_aio_windows_handle(
INFINITE);
}
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
+ os_mutex_enter(array->mutex);
+
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS
+ && array->n_reserved == 0) {
+ *message1 = NULL;
+ *message2 = NULL;
+ os_mutex_exit(array->mutex);
+ return(TRUE);
}
- os_mutex_enter(array->mutex);
+ ut_a(i >= WAIT_OBJECT_0 && i <= WAIT_OBJECT_0 + n);
slot = os_aio_array_get_nth_slot(array, i + segment * n);
@@ -4269,16 +4327,18 @@ os_aio_windows_handle(
__FILE__, __LINE__);
#endif
+ ut_a((slot->len & 0xFFFFFFFFUL) == slot->len);
+
switch (slot->type) {
case OS_FILE_WRITE:
ret = WriteFile(slot->file, slot->buf,
- slot->len, &len,
+ (DWORD) slot->len, &len,
&(slot->control));
break;
case OS_FILE_READ:
ret = ReadFile(slot->file, slot->buf,
- slot->len, &len,
+ (DWORD) slot->len, &len,
&(slot->control));
break;
@@ -4358,14 +4418,6 @@ os_aio_linux_collect(
retry:
- /* Go down if we are in shutdown mode.
- In case of srv_fast_shutdown == 2, there may be pending
- IO requests but that should be OK as we essentially treat
- that as a crash of InnoDB. */
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
- }
-
/* Initialize the events. The timeout value is arbitrary.
We probably need to experiment with it a little. */
memset(events, 0, sizeof(*events) * seg_size);
@@ -4374,76 +4426,72 @@ retry:
ret = io_getevents(io_ctx, 1, seg_size, events, &timeout);
- /* This error handling is for any error in collecting the
- IO requests. The errors, if any, for any particular IO
- request are simply passed on to the calling routine. */
+ if (ret > 0) {
+ for (i = 0; i < ret; i++) {
+ os_aio_slot_t* slot;
+ struct iocb* control;
- /* Not enough resources! Try again. */
- if (ret == -EAGAIN) {
- goto retry;
- }
+ control = (struct iocb *)events[i].obj;
+ ut_a(control != NULL);
- /* Interrupted! I have tested the behaviour in case of an
- interrupt. If we have some completed IOs available then
- the return code will be the number of IOs. We get EINTR only
- if there are no completed IOs and we have been interrupted. */
- if (ret == -EINTR) {
- goto retry;
- }
-
- /* No pending request! Go back and check again. */
- if (ret == 0) {
- goto retry;
- }
-
- /* All other errors! should cause a trap for now. */
- if (UNIV_UNLIKELY(ret < 0)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: unexpected ret_code[%d] from"
- " io_getevents()!\n", ret);
- ut_error;
- }
+ slot = (os_aio_slot_t *) control->data;
- ut_a(ret > 0);
+ /* Some sanity checks. */
+ ut_a(slot != NULL);
+ ut_a(slot->reserved);
- for (i = 0; i < ret; i++) {
- os_aio_slot_t* slot;
- struct iocb* control;
-
- control = (struct iocb *)events[i].obj;
- ut_a(control != NULL);
+#if defined(UNIV_AIO_DEBUG)
+ fprintf(stderr,
+ "io_getevents[%c]: slot[%p] ctx[%p]"
+ " seg[%lu]\n",
+ (slot->type == OS_FILE_WRITE) ? 'w' : 'r',
+ slot, io_ctx, segment);
+#endif
- slot = (os_aio_slot_t *) control->data;
+ /* We are not scribbling previous segment. */
+ ut_a(slot->pos >= start_pos);
- /* Some sanity checks. */
- ut_a(slot != NULL);
- ut_a(slot->reserved);
+ /* We have not overstepped to next segment. */
+ ut_a(slot->pos < end_pos);
-#if defined(UNIV_AIO_DEBUG)
- fprintf(stderr,
- "io_getevents[%c]: slot[%p] ctx[%p]"
- " seg[%lu]\n",
- (slot->type == OS_FILE_WRITE) ? 'w' : 'r',
- slot, io_ctx, segment);
-#endif
+ /* Mark this request as completed. The error handling
+ will be done in the calling function. */
+ os_mutex_enter(array->mutex);
+ slot->n_bytes = events[i].res;
+ slot->ret = events[i].res2;
+ slot->io_already_done = TRUE;
+ os_mutex_exit(array->mutex);
+ }
+ return;
+ }
- /* We are not scribbling previous segment. */
- ut_a(slot->pos >= start_pos);
+ if (UNIV_UNLIKELY(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS)) {
+ return;
+ }
- /* We have not overstepped to next segment. */
- ut_a(slot->pos < end_pos);
+ /* This error handling is for any error in collecting the
+ IO requests. The errors, if any, for any particular IO
+ request are simply passed on to the calling routine. */
- /* Mark this request as completed. The error handling
- will be done in the calling function. */
- os_mutex_enter(array->mutex);
- slot->n_bytes = events[i].res;
- slot->ret = events[i].res2;
- slot->io_already_done = TRUE;
- os_mutex_exit(array->mutex);
+ switch (ret) {
+ case -EAGAIN:
+ /* Not enough resources! Try again. */
+ case -EINTR:
+ /* Interrupted! I have tested the behaviour in case of an
+ interrupt. If we have some completed IOs available then
+ the return code will be the number of IOs. We get EINTR only
+ if there are no completed IOs and we have been interrupted. */
+ case 0:
+ /* No pending request! Go back and check again. */
+ goto retry;
}
- return;
+ /* All other errors should cause a trap for now. */
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: unexpected ret_code[%d] from io_getevents()!\n",
+ ret);
+ ut_error;
}
/**********************************************************************//**
@@ -4487,20 +4535,35 @@ os_aio_linux_handle(
/* Loop until we have found a completed request. */
for (;;) {
+ ibool any_reserved = FALSE;
os_mutex_enter(array->mutex);
for (i = 0; i < n; ++i) {
slot = os_aio_array_get_nth_slot(
- array, i + segment * n);
- if (slot->reserved && slot->io_already_done) {
+ array, i + segment * n);
+ if (!slot->reserved) {
+ continue;
+ } else if (slot->io_already_done) {
/* Something for us to work on. */
goto found;
+ } else {
+ any_reserved = TRUE;
}
}
os_mutex_exit(array->mutex);
- /* We don't have any completed request.
- Wait for some request. Note that we return
+ /* There is no completed request.
+ If there is no pending request at all,
+ and the system is being shut down, exit. */
+ if (UNIV_UNLIKELY
+ (!any_reserved
+ && srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS)) {
+ *message1 = NULL;
+ *message2 = NULL;
+ return(TRUE);
+ }
+
+ /* Wait for some request. Note that we return
from wait iff we have found a request. */
srv_set_io_thread_op_info(global_seg,
@@ -4596,6 +4659,7 @@ os_aio_simulated_handle(
byte* combined_buf;
byte* combined_buf2;
ibool ret;
+ ibool any_reserved;
ulint n;
ulint i;
@@ -4610,7 +4674,7 @@ restart:
srv_set_io_thread_op_info(global_segment,
"looking for i/o requests (a)");
- ut_ad(os_aio_validate());
+ ut_ad(os_aio_validate_skip());
ut_ad(segment < array->n_segments);
n = array->n_slots / array->n_segments;
@@ -4626,18 +4690,21 @@ restart:
goto recommended_sleep;
}
- os_mutex_enter(array->mutex);
-
srv_set_io_thread_op_info(global_segment,
"looking for i/o requests (b)");
/* Check if there is a slot for which the i/o has already been
done */
+ any_reserved = FALSE;
+
+ os_mutex_enter(array->mutex);
for (i = 0; i < n; i++) {
slot = os_aio_array_get_nth_slot(array, i + segment * n);
- if (slot->reserved && slot->io_already_done) {
+ if (!slot->reserved) {
+ continue;
+ } else if (slot->io_already_done) {
if (os_aio_print_debug) {
fprintf(stderr,
@@ -4649,9 +4716,23 @@ restart:
ret = TRUE;
goto slot_io_done;
+ } else {
+ any_reserved = TRUE;
}
}
+ /* There is no completed request.
+ If there is no pending request at all,
+ and the system is being shut down, exit. */
+ if (UNIV_UNLIKELY
+ (!any_reserved
+ && srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS)) {
+ os_mutex_exit(array->mutex);
+ *message1 = NULL;
+ *message2 = NULL;
+ return(TRUE);
+ }
+
n_consecutive = 0;
/* If there are at least 2 seconds old requests, then pick the oldest
diff --git a/storage/innobase/os/os0sync.c b/storage/innobase/os/os0sync.c
index 3c70e93aae0..41a19843812 100644
--- a/storage/innobase/os/os0sync.c
+++ b/storage/innobase/os/os0sync.c
@@ -72,6 +72,9 @@ UNIV_INTERN ulint os_event_count = 0;
UNIV_INTERN ulint os_mutex_count = 0;
UNIV_INTERN ulint os_fast_mutex_count = 0;
+/* The number of microsecnds in a second. */
+static const ulint MICROSECS_IN_A_SECOND = 1000000;
+
/* Because a mutex is embedded inside an event and there is an
event embedded inside a mutex, on free, this generates a recursive call.
This version of the free event function doesn't acquire the global lock */
@@ -122,6 +125,70 @@ os_cond_init(
}
/*********************************************************//**
+Do a timed wait on condition variable.
+@return TRUE if timed out, FALSE otherwise */
+UNIV_INLINE
+ibool
+os_cond_wait_timed(
+/*===============*/
+ os_cond_t* cond, /*!< in: condition variable. */
+ os_fast_mutex_t* mutex, /*!< in: fast mutex */
+#ifndef __WIN__
+ const struct timespec* abstime /*!< in: timeout */
+#else
+ DWORD time_in_ms /*!< in: timeout in
+ milliseconds*/
+#endif /* !__WIN__ */
+)
+{
+#ifdef __WIN__
+ BOOL ret;
+ DWORD err;
+
+ ut_a(sleep_condition_variable != NULL);
+
+ ret = sleep_condition_variable(cond, mutex, time_in_ms);
+
+ if (!ret) {
+ err = GetLastError();
+ /* From http://msdn.microsoft.com/en-us/library/ms686301%28VS.85%29.aspx,
+ "Condition variables are subject to spurious wakeups
+ (those not associated with an explicit wake) and stolen wakeups
+ (another thread manages to run before the woken thread)."
+ Check for both types of timeouts.
+ Conditions are checked by the caller.*/
+ if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
+ return(TRUE);
+ }
+ }
+
+ ut_a(ret);
+
+ return(FALSE);
+#else
+ int ret;
+
+ ret = pthread_cond_timedwait(cond, mutex, abstime);
+
+ switch (ret) {
+ case 0:
+ case ETIMEDOUT:
+ /* We play it safe by checking for EINTR even though
+ according to the POSIX documentation it can't return EINTR. */
+ case EINTR:
+ break;
+
+ default:
+ fprintf(stderr, " InnoDB: pthread_cond_timedwait() returned: "
+ "%d: abstime={%lu,%lu}\n",
+ ret, (ulong) abstime->tv_sec, (ulong) abstime->tv_nsec);
+ ut_error;
+ }
+
+ return(ret == ETIMEDOUT);
+#endif
+}
+/*********************************************************//**
Wait on condition variable */
UNIV_INLINE
void
@@ -491,10 +558,7 @@ os_event_free(
}
/**********************************************************//**
-Waits for an event object until it is in the signaled state. If
-srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
-waiting thread when the event becomes signaled (or immediately if the
-event is already in the signaled state).
+Waits for an event object until it is in the signaled state.
Typically, if the event has been signalled after the os_event_reset()
we'll return immediately because event->is_set == TRUE.
@@ -519,8 +583,6 @@ os_event_wait_low(
returned by previous call of
os_event_reset(). */
{
- ib_int64_t old_signal_count;
-
#ifdef __WIN__
if(!srv_use_native_conditions) {
DWORD err;
@@ -533,43 +595,138 @@ os_event_wait_low(
err = WaitForSingleObject(event->handle, INFINITE);
ut_a(err == WAIT_OBJECT_0);
-
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
- }
return;
}
#endif
- os_fast_mutex_lock(&(event->os_mutex));
+ os_fast_mutex_lock(&event->os_mutex);
+
+ if (!reset_sig_count) {
+ reset_sig_count = event->signal_count;
+ }
+
+ while (!event->is_set && event->signal_count == reset_sig_count) {
+ os_cond_wait(&(event->cond_var), &(event->os_mutex));
- if (reset_sig_count) {
- old_signal_count = reset_sig_count;
+ /* Solaris manual said that spurious wakeups may occur: we
+ have to check if the event really has been signaled after
+ we came here to wait */
+ }
+
+ os_fast_mutex_unlock(&event->os_mutex);
+}
+
+/**********************************************************//**
+Waits for an event object until it is in the signaled state or
+a timeout is exceeded.
+@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
+UNIV_INTERN
+ulint
+os_event_wait_time_low(
+/*===================*/
+ os_event_t event, /*!< in: event to wait */
+ ulint time_in_usec, /*!< in: timeout in
+ microseconds, or
+ OS_SYNC_INFINITE_TIME */
+ ib_int64_t reset_sig_count) /*!< in: zero or the value
+ returned by previous call of
+ os_event_reset(). */
+
+{
+ ibool timed_out = FALSE;
+
+#ifdef __WIN__
+ DWORD time_in_ms;
+
+ if (!srv_use_native_conditions) {
+ DWORD err;
+
+ ut_a(event);
+
+ if (time_in_usec != OS_SYNC_INFINITE_TIME) {
+ time_in_ms = time_in_usec / 1000;
+ err = WaitForSingleObject(event->handle, time_in_ms);
+ } else {
+ err = WaitForSingleObject(event->handle, INFINITE);
+ }
+
+ if (err == WAIT_OBJECT_0) {
+ return(0);
+ } else if ((err == WAIT_TIMEOUT) || (err == ERROR_TIMEOUT)) {
+ return(OS_SYNC_TIME_EXCEEDED);
+ }
+
+ ut_error;
+ /* Dummy value to eliminate compiler warning. */
+ return(42);
} else {
- old_signal_count = event->signal_count;
+ ut_a(sleep_condition_variable != NULL);
+
+ if (time_in_usec != OS_SYNC_INFINITE_TIME) {
+ time_in_ms = time_in_usec / 1000;
+ } else {
+ time_in_ms = INFINITE;
+ }
}
+#else
+ struct timespec abstime;
- for (;;) {
- if (event->is_set == TRUE
- || event->signal_count != old_signal_count) {
+ if (time_in_usec != OS_SYNC_INFINITE_TIME) {
+ struct timeval tv;
+ int ret;
+ ulint sec;
+ ulint usec;
- os_fast_mutex_unlock(&(event->os_mutex));
+ ret = ut_usectime(&sec, &usec);
+ ut_a(ret == 0);
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ tv.tv_sec = sec;
+ tv.tv_usec = usec;
- os_thread_exit(NULL);
- }
- /* Ok, we may return */
+ tv.tv_usec += time_in_usec;
- return;
+ if ((ulint) tv.tv_usec >= MICROSECS_IN_A_SECOND) {
+ tv.tv_sec += time_in_usec / MICROSECS_IN_A_SECOND;
+ tv.tv_usec %= MICROSECS_IN_A_SECOND;
}
- os_cond_wait(&(event->cond_var), &(event->os_mutex));
+ abstime.tv_sec = tv.tv_sec;
+ abstime.tv_nsec = tv.tv_usec * 1000;
+ } else {
+ abstime.tv_nsec = 999999999;
+ abstime.tv_sec = (time_t) ULINT_MAX;
+ }
- /* Solaris manual said that spurious wakeups may occur: we
- have to check if the event really has been signaled after
- we came here to wait */
+ ut_a(abstime.tv_nsec <= 999999999);
+
+#endif /* __WIN__ */
+
+ os_fast_mutex_lock(&event->os_mutex);
+
+ if (!reset_sig_count) {
+ reset_sig_count = event->signal_count;
}
+
+ do {
+ if (event->is_set || event->signal_count != reset_sig_count) {
+
+ break;
+ }
+
+ timed_out = os_cond_wait_timed(
+ &event->cond_var, &event->os_mutex,
+#ifndef __WIN__
+ &abstime
+#else
+ time_in_ms
+#endif /* !__WIN__ */
+ );
+
+ } while (!timed_out);
+
+ os_fast_mutex_unlock(&event->os_mutex);
+
+ return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
}
/*********************************************************//**
diff --git a/storage/innobase/os/os0thread.c b/storage/innobase/os/os0thread.c
index adc876be5d5..12b6805d98e 100644
--- a/storage/innobase/os/os0thread.c
+++ b/storage/innobase/os/os0thread.c
@@ -220,21 +220,6 @@ os_thread_exit(
}
/*****************************************************************//**
-Returns handle to the current thread.
-@return current thread handle */
-UNIV_INTERN
-os_thread_t
-os_thread_get_curr(void)
-/*====================*/
-{
-#ifdef __WIN__
- return(GetCurrentThread());
-#else
- return(pthread_self());
-#endif
-}
-
-/*****************************************************************//**
Advises the os to give up remainder of the thread's time slice. */
UNIV_INTERN
void
@@ -274,81 +259,3 @@ os_thread_sleep(
select(0, NULL, NULL, NULL, &t);
#endif
}
-
-#ifndef UNIV_HOTBACKUP
-/******************************************************************//**
-Sets a thread priority. */
-UNIV_INTERN
-void
-os_thread_set_priority(
-/*===================*/
- os_thread_t handle, /*!< in: OS handle to the thread */
- ulint pri) /*!< in: priority */
-{
-#ifdef __WIN__
- int os_pri;
-
- if (pri == OS_THREAD_PRIORITY_BACKGROUND) {
- os_pri = THREAD_PRIORITY_BELOW_NORMAL;
- } else if (pri == OS_THREAD_PRIORITY_NORMAL) {
- os_pri = THREAD_PRIORITY_NORMAL;
- } else if (pri == OS_THREAD_PRIORITY_ABOVE_NORMAL) {
- os_pri = THREAD_PRIORITY_HIGHEST;
- } else {
- ut_error;
- }
-
- ut_a(SetThreadPriority(handle, os_pri));
-#else
- UT_NOT_USED(handle);
- UT_NOT_USED(pri);
-#endif
-}
-
-/******************************************************************//**
-Gets a thread priority.
-@return priority */
-UNIV_INTERN
-ulint
-os_thread_get_priority(
-/*===================*/
- os_thread_t handle __attribute__((unused)))
- /*!< in: OS handle to the thread */
-{
-#ifdef __WIN__
- int os_pri;
- ulint pri;
-
- os_pri = GetThreadPriority(handle);
-
- if (os_pri == THREAD_PRIORITY_BELOW_NORMAL) {
- pri = OS_THREAD_PRIORITY_BACKGROUND;
- } else if (os_pri == THREAD_PRIORITY_NORMAL) {
- pri = OS_THREAD_PRIORITY_NORMAL;
- } else if (os_pri == THREAD_PRIORITY_HIGHEST) {
- pri = OS_THREAD_PRIORITY_ABOVE_NORMAL;
- } else {
- ut_error;
- }
-
- return(pri);
-#else
- return(0);
-#endif
-}
-
-/******************************************************************//**
-Gets the last operating system error code for the calling thread.
-@return last error on Windows, 0 otherwise */
-UNIV_INTERN
-ulint
-os_thread_get_last_error(void)
-/*==========================*/
-{
-#ifdef __WIN__
- return(GetLastError());
-#else
- return(0);
-#endif
-}
-#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innobase/page/page0cur.c b/storage/innobase/page/page0cur.c
index f10f16a7dd9..936762b986a 100644
--- a/storage/innobase/page/page0cur.c
+++ b/storage/innobase/page/page0cur.c
@@ -1149,6 +1149,8 @@ use_heap:
current_rec, index, mtr);
}
+ btr_blob_dbg_add_rec(insert_rec, index, offsets, "insert");
+
return(insert_rec);
}
@@ -1195,10 +1197,12 @@ page_cur_insert_rec_zip_reorg(
}
/* Out of space: restore the page */
+ btr_blob_dbg_remove(page, index, "insert_zip_fail");
if (!page_zip_decompress(page_zip, page, FALSE)) {
ut_error; /* Memory corrupted? */
}
ut_ad(page_validate(page, index));
+ btr_blob_dbg_add(page, index, "insert_zip_fail");
return(NULL);
}
@@ -1490,6 +1494,8 @@ use_heap:
page_zip_write_rec(page_zip, insert_rec, index, offsets, 1);
+ btr_blob_dbg_add_rec(insert_rec, index, offsets, "insert_zip_ok");
+
/* 9. Write log record of the insert */
if (UNIV_LIKELY(mtr != NULL)) {
page_cur_insert_rec_write_log(insert_rec, rec_size,
@@ -1697,6 +1703,9 @@ page_copy_rec_list_end_to_created_page(
heap_top += rec_size;
+ rec_offs_make_valid(insert_rec, index, offsets);
+ btr_blob_dbg_add_rec(insert_rec, index, offsets, "copy_end");
+
page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
index, mtr);
prev_rec = insert_rec;
@@ -1944,6 +1953,7 @@ page_cur_delete_rec(
page_dir_slot_set_n_owned(cur_dir_slot, page_zip, cur_n_owned - 1);
/* 6. Free the memory occupied by the record */
+ btr_blob_dbg_remove_rec(current_rec, index, offsets, "delete");
page_mem_free(page, page_zip, current_rec, index, offsets);
/* 7. Now we have decremented the number of owned records of the slot.
diff --git a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c
index 2e785412ac9..6064d028ae1 100644
--- a/storage/innobase/page/page0page.c
+++ b/storage/innobase/page/page0page.c
@@ -166,11 +166,11 @@ static
ibool
page_dir_slot_check(
/*================*/
- page_dir_slot_t* slot) /*!< in: slot */
+ const page_dir_slot_t* slot) /*!< in: slot */
{
- page_t* page;
- ulint n_slots;
- ulint n_owned;
+ const page_t* page;
+ ulint n_slots;
+ ulint n_owned;
ut_a(slot);
@@ -685,12 +685,16 @@ page_copy_rec_list_end(
if (UNIV_UNLIKELY
(!page_zip_reorganize(new_block, index, mtr))) {
+ btr_blob_dbg_remove(new_page, index,
+ "copy_end_reorg_fail");
if (UNIV_UNLIKELY
(!page_zip_decompress(new_page_zip,
new_page, FALSE))) {
ut_error;
}
ut_ad(page_validate(new_page, index));
+ btr_blob_dbg_add(new_page, index,
+ "copy_end_reorg_fail");
return(NULL);
} else {
/* The page was reorganized:
@@ -803,12 +807,16 @@ page_copy_rec_list_start(
if (UNIV_UNLIKELY
(!page_zip_reorganize(new_block, index, mtr))) {
+ btr_blob_dbg_remove(new_page, index,
+ "copy_start_reorg_fail");
if (UNIV_UNLIKELY
(!page_zip_decompress(new_page_zip,
new_page, FALSE))) {
ut_error;
}
ut_ad(page_validate(new_page, index));
+ btr_blob_dbg_add(new_page, index,
+ "copy_start_reorg_fail");
return(NULL);
} else {
/* The page was reorganized:
@@ -1080,6 +1088,9 @@ page_delete_rec_list_end(
/* Remove the record chain segment from the record chain */
page_rec_set_next(prev_rec, page_get_supremum_rec(page));
+ btr_blob_dbg_op(page, rec, index, "delete_end",
+ btr_blob_dbg_remove_rec);
+
/* Catenate the deleted chain segment to the page free list */
page_rec_set_next(last_rec, page_header_get_ptr(page, PAGE_FREE));
@@ -1242,28 +1253,6 @@ page_move_rec_list_start(
return(TRUE);
}
-
-/***********************************************************************//**
-This is a low-level operation which is used in a database index creation
-to update the page number of a created B-tree to a data dictionary record. */
-UNIV_INTERN
-void
-page_rec_write_index_page_no(
-/*=========================*/
- rec_t* rec, /*!< in: record to update */
- ulint i, /*!< in: index of the field to update */
- ulint page_no,/*!< in: value to write */
- mtr_t* mtr) /*!< in: mtr */
-{
- byte* data;
- ulint len;
-
- data = rec_get_nth_field_old(rec, i, &len);
-
- ut_ad(len == 4);
-
- mlog_write_ulint(data, page_no, MLOG_4BYTES, mtr);
-}
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
@@ -1792,12 +1781,12 @@ UNIV_INTERN
ibool
page_rec_validate(
/*==============*/
- rec_t* rec, /*!< in: physical record */
+ const rec_t* rec, /*!< in: physical record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
- ulint n_owned;
- ulint heap_no;
- page_t* page;
+ ulint n_owned;
+ ulint heap_no;
+ const page_t* page;
page = page_align(rec);
ut_a(!page_is_comp(page) == !rec_offs_comp(offsets));
@@ -1878,16 +1867,16 @@ UNIV_INTERN
ibool
page_simple_validate_old(
/*=====================*/
- page_t* page) /*!< in: old-style index page */
+ const page_t* page) /*!< in: index page in ROW_FORMAT=REDUNDANT */
{
- page_dir_slot_t* slot;
- ulint slot_no;
- ulint n_slots;
- rec_t* rec;
- byte* rec_heap_top;
- ulint count;
- ulint own_count;
- ibool ret = FALSE;
+ const page_dir_slot_t* slot;
+ ulint slot_no;
+ ulint n_slots;
+ const rec_t* rec;
+ const byte* rec_heap_top;
+ ulint count;
+ ulint own_count;
+ ibool ret = FALSE;
ut_a(!page_is_comp(page));
@@ -2000,7 +1989,7 @@ page_simple_validate_old(
goto func_exit;
}
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
own_count++;
}
@@ -2061,7 +2050,7 @@ page_simple_validate_old(
goto func_exit;
}
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
}
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
@@ -2088,16 +2077,16 @@ UNIV_INTERN
ibool
page_simple_validate_new(
/*=====================*/
- page_t* page) /*!< in: new-style index page */
+ const page_t* page) /*!< in: index page in ROW_FORMAT!=REDUNDANT */
{
- page_dir_slot_t* slot;
- ulint slot_no;
- ulint n_slots;
- rec_t* rec;
- byte* rec_heap_top;
- ulint count;
- ulint own_count;
- ibool ret = FALSE;
+ const page_dir_slot_t* slot;
+ ulint slot_no;
+ ulint n_slots;
+ const rec_t* rec;
+ const byte* rec_heap_top;
+ ulint count;
+ ulint own_count;
+ ibool ret = FALSE;
ut_a(page_is_comp(page));
@@ -2210,7 +2199,7 @@ page_simple_validate_new(
goto func_exit;
}
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
own_count++;
}
@@ -2272,7 +2261,7 @@ page_simple_validate_new(
goto func_exit;
}
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
}
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
@@ -2297,26 +2286,26 @@ UNIV_INTERN
ibool
page_validate(
/*==========*/
- page_t* page, /*!< in: index page */
+ const page_t* page, /*!< in: index page */
dict_index_t* index) /*!< in: data dictionary index containing
the page record type definition */
{
- page_dir_slot_t*slot;
- mem_heap_t* heap;
- byte* buf;
- ulint count;
- ulint own_count;
- ulint rec_own_count;
- ulint slot_no;
- ulint data_size;
- rec_t* rec;
- rec_t* old_rec = NULL;
- ulint offs;
- ulint n_slots;
- ibool ret = FALSE;
- ulint i;
- ulint* offsets = NULL;
- ulint* old_offsets = NULL;
+ const page_dir_slot_t* slot;
+ mem_heap_t* heap;
+ byte* buf;
+ ulint count;
+ ulint own_count;
+ ulint rec_own_count;
+ ulint slot_no;
+ ulint data_size;
+ const rec_t* rec;
+ const rec_t* old_rec = NULL;
+ ulint offs;
+ ulint n_slots;
+ ibool ret = FALSE;
+ ulint i;
+ ulint* offsets = NULL;
+ ulint* old_offsets = NULL;
if (UNIV_UNLIKELY((ibool) !!page_is_comp(page)
!= dict_table_is_comp(index->table))) {
@@ -2471,7 +2460,7 @@ page_validate(
count++;
own_count++;
old_rec = rec;
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
/* set old_offsets to offsets; recycle offsets */
{
@@ -2545,7 +2534,7 @@ n_owned_zero:
buf[offs + i] = 1;
}
- rec = page_rec_get_next(rec);
+ rec = page_rec_get_next_const(rec);
}
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
diff --git a/storage/innobase/page/page0zip.c b/storage/innobase/page/page0zip.c
index 98640a8e6fb..c92ad9dc25b 100644
--- a/storage/innobase/page/page0zip.c
+++ b/storage/innobase/page/page0zip.c
@@ -464,7 +464,7 @@ page_zip_fields_encode(
if (fixed_sum && UNIV_UNLIKELY
(fixed_sum + field->fixed_len
- > DICT_MAX_INDEX_COL_LEN)) {
+ > DICT_MAX_FIXED_COL_LEN)) {
/* Write out the length of the
preceding non-nullable fields,
to avoid exceeding the maximum
@@ -653,13 +653,13 @@ page_zip_dir_encode(
Allocate memory for zlib. */
static
void*
-page_zip_malloc(
+page_zip_zalloc(
/*============*/
void* opaque, /*!< in/out: memory heap */
uInt items, /*!< in: number of items to allocate */
uInt size) /*!< in: size of an item in bytes */
{
- return(mem_heap_alloc(opaque, items * size));
+ return(mem_heap_zalloc(opaque, items * size));
}
/**********************************************************************//**
@@ -684,7 +684,7 @@ page_zip_set_alloc(
{
z_stream* strm = stream;
- strm->zalloc = page_zip_malloc;
+ strm->zalloc = page_zip_zalloc;
strm->zfree = page_zip_free;
strm->opaque = heap;
}
@@ -2912,19 +2912,18 @@ zlib_error:
page_zip_set_alloc(&d_stream, heap);
- if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
- != Z_OK)) {
- ut_error;
- }
-
d_stream.next_in = page_zip->data + PAGE_DATA;
/* Subtract the space reserved for
the page header and the end marker of the modification log. */
d_stream.avail_in = page_zip_get_size(page_zip) - (PAGE_DATA + 1);
-
d_stream.next_out = page + PAGE_ZIP_START;
d_stream.avail_out = UNIV_PAGE_SIZE - PAGE_ZIP_START;
+ if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
+ != Z_OK)) {
+ ut_error;
+ }
+
/* Decode the zlib header and the index information. */
if (UNIV_UNLIKELY(inflate(&d_stream, Z_BLOCK) != Z_OK)) {
@@ -4440,7 +4439,7 @@ page_zip_reorganize(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
#ifndef UNIV_HOTBACKUP
- temp_block = buf_block_alloc(buf_pool, 0);
+ temp_block = buf_block_alloc(buf_pool);
btr_search_drop_page_hash_index(block);
block->check_index_page_at_flush = TRUE;
#else /* !UNIV_HOTBACKUP */
@@ -4452,6 +4451,8 @@ page_zip_reorganize(
/* Copy the old page to temporary space */
buf_frame_copy(temp_page, page);
+ btr_blob_dbg_remove(page, index, "zip_reorg");
+
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
@@ -4510,7 +4511,7 @@ page_zip_copy_recs(
mtr_t* mtr) /*!< in: mini-transaction */
{
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
- ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains_page(mtr, src, MTR_MEMO_PAGE_X_FIX));
ut_ad(!dict_index_is_ibuf(index));
#ifdef UNIV_ZIP_DEBUG
/* The B-tree operations that call this function may set
@@ -4580,6 +4581,7 @@ page_zip_copy_recs(
#ifdef UNIV_ZIP_DEBUG
ut_a(page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
+ btr_blob_dbg_add(page, index, "page_zip_copy_recs");
page_zip_compress_write_log(page_zip, page, index, mtr);
}
diff --git a/storage/innobase/plug.in b/storage/innobase/plug.in
deleted file mode 100644
index 76d18cd8dd0..00000000000
--- a/storage/innobase/plug.in
+++ /dev/null
@@ -1,233 +0,0 @@
-#
-# Copyright (c) 2006, 2010, Innobase Oy. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-# Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine],
- [Transactional Tables using InnoDB], [])
-MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase])
-MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a])
-MYSQL_PLUGIN_DYNAMIC(innobase, [ha_innodb.la])
-MYSQL_PLUGIN_ACTIONS(innobase, [
- AC_CHECK_HEADERS(sched.h)
- AC_CHECK_SIZEOF(int, 4)
- AC_CHECK_SIZEOF(long, 4)
- AC_CHECK_SIZEOF(void*, 4)
- AC_CHECK_FUNCS(sched_yield fdatasync localtime_r)
- AC_C_BIGENDIAN
- case "$target_os" in
- lin*)
- AC_CHECK_HEADER(libaio.h,
- AC_CHECK_LIB(aio, io_setup,
- LIBS="$LIBS -laio"
- AC_DEFINE(LINUX_NATIVE_AIO, [1],
- [Linux native async I/O support]),
- AC_MSG_WARN([No Linux native async I/O])),
- AC_MSG_WARN([No Linux native async I/O]))
-
- CFLAGS="$CFLAGS -DUNIV_LINUX";;
- hpux10*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
- hp*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
- aix*)
- CFLAGS="$CFLAGS -DUNIV_AIX";;
- irix*|osf*|sysv5uw7*|openbsd*)
- CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
- *solaris*|*SunOS*)
- CFLAGS="$CFLAGS -DUNIV_SOLARIS";;
- esac
-
- INNODB_DYNAMIC_CFLAGS="-DMYSQL_DYNAMIC_PLUGIN"
-
- case "$target_cpu" in
- x86_64)
- # The AMD64 ABI forbids absolute addresses in shared libraries
- ;;
- *86)
- # Use absolute addresses on IA-32
- INNODB_DYNAMIC_CFLAGS="$INNODB_DYNAMIC_CFLAGS -prefer-non-pic"
- ;;
- esac
- AC_SUBST(INNODB_DYNAMIC_CFLAGS)
-
- AC_MSG_CHECKING(whether GCC atomic builtins are available)
- # either define HAVE_IB_GCC_ATOMIC_BUILTINS or not
- AC_TRY_RUN(
- [
- int main()
- {
- long x;
- long y;
- long res;
- char c;
-
- x = 10;
- y = 123;
- res = __sync_bool_compare_and_swap(&x, x, y);
- if (!res || x != y) {
- return(1);
- }
-
- x = 10;
- y = 123;
- res = __sync_bool_compare_and_swap(&x, x + 1, y);
- if (res || x != 10) {
- return(1);
- }
-
- x = 10;
- y = 123;
- res = __sync_add_and_fetch(&x, y);
- if (res != 123 + 10 || x != 123 + 10) {
- return(1);
- }
-
- c = 10;
- res = __sync_lock_test_and_set(&c, 123);
- if (res != 10 || c != 123) {
- return(1);
- }
-
- return(0);
- }
- ],
- [
- AC_DEFINE([HAVE_IB_GCC_ATOMIC_BUILTINS], [1],
- [GCC atomic builtins are available])
- AC_MSG_RESULT(yes)
- ],
- [
- AC_MSG_RESULT(no)
- ]
- )
-
- AC_MSG_CHECKING(whether pthread_t can be used by GCC atomic builtins)
- # either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not
- AC_TRY_RUN(
- [
- #include <pthread.h>
- #include <string.h>
-
- int main(int argc, char** argv) {
- pthread_t x1;
- pthread_t x2;
- pthread_t x3;
-
- memset(&x1, 0x0, sizeof(x1));
- memset(&x2, 0x0, sizeof(x2));
- memset(&x3, 0x0, sizeof(x3));
-
- __sync_bool_compare_and_swap(&x1, x2, x3);
-
- return(0);
- }
- ],
- [
- AC_DEFINE([HAVE_IB_ATOMIC_PTHREAD_T_GCC], [1],
- [pthread_t can be used by GCC atomic builtins])
- AC_MSG_RESULT(yes)
- ],
- [
- AC_MSG_RESULT(no)
- ]
- )
-
- AC_MSG_CHECKING(whether Solaris libc atomic functions are available)
- # either define HAVE_IB_SOLARIS_ATOMICS or not
- AC_CHECK_FUNCS(atomic_add_long \
- atomic_cas_32 \
- atomic_cas_64 \
- atomic_cas_ulong,
-
- AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1],
- [Define to 1 if Solaris libc atomic functions \
- are available])
- )
-
- AC_MSG_CHECKING(whether pthread_t can be used by Solaris libc atomic functions)
- # either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not
- AC_TRY_RUN(
- [
- #include <pthread.h>
- #include <string.h>
-
- int main(int argc, char** argv) {
- pthread_t x1;
- pthread_t x2;
- pthread_t x3;
-
- memset(&x1, 0x0, sizeof(x1));
- memset(&x2, 0x0, sizeof(x2));
- memset(&x3, 0x0, sizeof(x3));
-
- if (sizeof(pthread_t) == 4) {
-
- atomic_cas_32(&x1, x2, x3);
-
- } else if (sizeof(pthread_t) == 8) {
-
- atomic_cas_64(&x1, x2, x3);
-
- } else {
-
- return(1);
- }
-
- return(0);
- }
- ],
- [
- AC_DEFINE([HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS], [1],
- [pthread_t can be used by solaris atomics])
- AC_MSG_RESULT(yes)
- ],
- [
- AC_MSG_RESULT(no)
- ]
- )
-
- # this is needed to know which one of atomic_cas_32() or atomic_cas_64()
- # to use in the source
- AC_CHECK_SIZEOF([pthread_t], [], [#include <pthread.h>])
-
- # Check for x86 PAUSE instruction
- AC_MSG_CHECKING(for x86 PAUSE instruction)
- # We have to actually try running the test program, because of a bug
- # in Solaris on x86_64, where it wrongly reports that PAUSE is not
- # supported when trying to run an application. See
- # http://bugs.opensolaris.org/bugdatabase/printableBug.do?bug_id=6478684
- # We use ib_ prefix to avoid collisoins if this code is added to
- # mysql's configure.in.
- AC_TRY_RUN(
- [
- int main() {
- __asm__ __volatile__ ("pause");
- return(0);
- }
- ],
- [
- AC_DEFINE([HAVE_IB_PAUSE_INSTRUCTION], [1], [Does x86 PAUSE instruction exist])
- AC_MSG_RESULT(yes)
- ],
- [
- AC_MSG_RESULT(no)
- ],
- [
- AC_MSG_RESULT(no)
- ]
- )
- ])
-
-# vim: set ft=config:
diff --git a/storage/innobase/rem/rem0cmp.c b/storage/innobase/rem/rem0cmp.c
index 35b67992558..04d2c15437b 100644
--- a/storage/innobase/rem/rem0cmp.c
+++ b/storage/innobase/rem/rem0cmp.c
@@ -862,6 +862,10 @@ cmp_rec_rec_with_match(
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */
dict_index_t* index, /*!< in: data dictionary index */
+ ibool nulls_unequal,
+ /* in: TRUE if this is for index statistics
+ cardinality estimation, and innodb_stats_method
+ is "nulls_unequal" or "nulls_ignored" */
ulint* matched_fields, /*!< in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
@@ -961,9 +965,13 @@ cmp_rec_rec_with_match(
|| rec2_f_len == UNIV_SQL_NULL) {
if (rec1_f_len == rec2_f_len) {
-
- goto next_field;
-
+ /* This is limited to stats collection,
+ cannot use it for regular search */
+ if (nulls_unequal) {
+ ret = -1;
+ } else {
+ goto next_field;
+ }
} else if (rec2_f_len == UNIV_SQL_NULL) {
/* We define the SQL null to be the
diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c
index 37ba8ca2ffe..5a96e608ab5 100644
--- a/storage/innobase/rem/rem0rec.c
+++ b/storage/innobase/rem/rem0rec.c
@@ -1174,7 +1174,7 @@ rec_convert_dtuple_to_rec_comp(
} else if (dfield_is_ext(field)) {
ut_ad(ifield->col->len >= 256
|| ifield->col->mtype == DATA_BLOB);
- ut_ad(len <= REC_MAX_INDEX_COL_LEN
+ ut_ad(len <= REC_ANTELOPE_MAX_INDEX_COL_LEN
+ BTR_EXTERN_FIELD_REF_SIZE);
*lens-- = (byte) (len >> 8) | 0xc0;
*lens-- = (byte) len;
@@ -1749,9 +1749,9 @@ UNIV_INTERN
void
rec_print(
/*======*/
- FILE* file, /*!< in: file where to print */
- const rec_t* rec, /*!< in: physical record */
- dict_index_t* index) /*!< in: record descriptor */
+ FILE* file, /*!< in: file where to print */
+ const rec_t* rec, /*!< in: physical record */
+ const dict_index_t* index) /*!< in: record descriptor */
{
ut_ad(index);
diff --git a/storage/innobase/row/row0ext.c b/storage/innobase/row/row0ext.c
index 7320f5b1dca..07e970cf485 100644
--- a/storage/innobase/row/row0ext.c
+++ b/storage/innobase/row/row0ext.c
@@ -44,8 +44,9 @@ row_ext_cache_fill(
{
const byte* field = dfield_get_data(dfield);
ulint f_len = dfield_get_len(dfield);
- byte* buf = ext->buf + i * REC_MAX_INDEX_COL_LEN;
+ byte* buf = ext->buf + i * ext->max_len;
+ ut_ad(ext->max_len > 0);
ut_ad(i < ext->n_ext);
ut_ad(dfield_is_ext(dfield));
ut_a(f_len >= BTR_EXTERN_FIELD_REF_SIZE);
@@ -56,14 +57,14 @@ row_ext_cache_fill(
/* The BLOB pointer is not set: we cannot fetch it */
ext->len[i] = 0;
} else {
- /* Fetch at most REC_MAX_INDEX_COL_LEN of the column.
+ /* Fetch at most ext->max_len of the column.
The column should be non-empty. However,
trx_rollback_or_clean_all_recovered() may try to
access a half-deleted BLOB if the server previously
crashed during the execution of
btr_free_externally_stored_field(). */
ext->len[i] = btr_copy_externally_stored_field_prefix(
- buf, REC_MAX_INDEX_COL_LEN, zip_size, field, f_len);
+ buf, ext->max_len, zip_size, field, f_len);
}
}
@@ -79,16 +80,18 @@ row_ext_create(
in the InnoDB table object, as reported by
dict_col_get_no(); NOT relative to the records
in the clustered index */
+ ulint flags, /*!< in: table->flags */
const dtuple_t* tuple, /*!< in: data tuple containing the field
references of the externally stored
columns; must be indexed by col_no;
the clustered index record must be
covered by a lock or a page latch
to prevent deletion (rollback or purge). */
- ulint zip_size,/*!< compressed page size in bytes, or 0 */
mem_heap_t* heap) /*!< in: heap where created */
{
ulint i;
+ ulint zip_size = dict_table_flags_to_zip_size(flags);
+
row_ext_t* ret = mem_heap_alloc(heap, (sizeof *ret)
+ (n_ext - 1) * sizeof ret->len);
@@ -97,10 +100,12 @@ row_ext_create(
ret->n_ext = n_ext;
ret->ext = ext;
- ret->buf = mem_heap_alloc(heap, n_ext * REC_MAX_INDEX_COL_LEN);
+ ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags);
+
+ ret->buf = mem_heap_alloc(heap, n_ext * ret->max_len);
#ifdef UNIV_DEBUG
- memset(ret->buf, 0xaa, n_ext * REC_MAX_INDEX_COL_LEN);
- UNIV_MEM_ALLOC(ret->buf, n_ext * REC_MAX_INDEX_COL_LEN);
+ memset(ret->buf, 0xaa, n_ext * ret->max_len);
+ UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len);
#endif
/* Fetch the BLOB prefixes */
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index 8fd8c4f8532..e0414cde80d 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -1525,7 +1525,7 @@ row_ins_check_foreign_constraints(
if (foreign->foreign_index == index) {
if (foreign->referenced_table == NULL) {
- dict_table_get(foreign->referenced_table_name,
+ dict_table_get(foreign->referenced_table_name_lookup,
FALSE);
}
@@ -1768,7 +1768,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 */
{
@@ -1964,7 +1964,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 */
{
@@ -2122,7 +2122,7 @@ function_exit:
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor),
- rec, offsets, big_rec, &mtr);
+ rec, offsets, &mtr, FALSE, big_rec);
if (modify) {
dtuple_big_rec_free(big_rec);
@@ -2150,9 +2150,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/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c
index 1b96ff50e66..5be437add5a 100644
--- a/storage/innobase/row/row0merge.c
+++ b/storage/innobase/row/row0merge.c
@@ -1929,7 +1929,6 @@ row_merge_lock_table(
sel_node_t* node;
ut_ad(trx);
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(mode == LOCK_X || mode == LOCK_S);
heap = mem_heap_create(512);
@@ -2042,7 +2041,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 = "";
@@ -2158,13 +2157,15 @@ row_merge_drop_temp_indexes(void)
}
/*********************************************************************//**
-Create a merge file. */
-static
-void
-row_merge_file_create(
-/*==================*/
- merge_file_t* merge_file) /*!< out: merge file structure */
+Creates temperary merge files, and if UNIV_PFS_IO defined, register
+the file descriptor with Performance Schema.
+@return File descriptor */
+UNIV_INLINE
+int
+row_merge_file_create_low(void)
+/*===========================*/
{
+ int fd;
#ifdef UNIV_PFS_IO
/* This temp file open does not go through normal
file APIs, add instrumentation to register with
@@ -2176,37 +2177,59 @@ row_merge_file_create(
"Innodb Merge Temp File",
__FILE__, __LINE__);
#endif
- merge_file->fd = innobase_mysql_tmpfile();
- merge_file->offset = 0;
- merge_file->n_rec = 0;
+ fd = innobase_mysql_tmpfile();
#ifdef UNIV_PFS_IO
- register_pfs_file_open_end(locker, merge_file->fd);
+ register_pfs_file_open_end(locker, fd);
#endif
+ return(fd);
}
-
/*********************************************************************//**
-Destroy a merge file. */
+Create a merge file. */
static
void
-row_merge_file_destroy(
-/*===================*/
+row_merge_file_create(
+/*==================*/
merge_file_t* merge_file) /*!< out: merge file structure */
{
+ merge_file->fd = row_merge_file_create_low();
+ merge_file->offset = 0;
+ merge_file->n_rec = 0;
+}
+
+/*********************************************************************//**
+Destroy a merge file. And de-register the file from Performance Schema
+if UNIV_PFS_IO is defined. */
+UNIV_INLINE
+void
+row_merge_file_destroy_low(
+/*=======================*/
+ int fd) /*!< in: merge file descriptor */
+{
#ifdef UNIV_PFS_IO
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_io_begin(&state, locker, merge_file->fd, 0, PSI_FILE_CLOSE,
+ register_pfs_file_io_begin(&state, locker,
+ fd, 0, PSI_FILE_CLOSE,
__FILE__, __LINE__);
#endif
- if (merge_file->fd != -1) {
- close(merge_file->fd);
- merge_file->fd = -1;
- }
-
+ close(fd);
#ifdef UNIV_PFS_IO
register_pfs_file_io_end(locker, 0);
#endif
}
+/*********************************************************************//**
+Destroy a merge file. */
+static
+void
+row_merge_file_destroy(
+/*===================*/
+ merge_file_t* merge_file) /*!< out: merge file structure */
+{
+ if (merge_file->fd != -1) {
+ row_merge_file_destroy_low(merge_file->fd);
+ merge_file->fd = -1;
+ }
+}
/*********************************************************************//**
Determine the precise type of a column that is added to a tem
@@ -2364,9 +2387,8 @@ 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);
ut_ad(mutex_own(&dict_sys->mutex));
@@ -2379,7 +2401,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;
}
@@ -2600,7 +2622,7 @@ row_merge_build_indexes(
row_merge_file_create(&merge_files[i]);
}
- tmpfd = innobase_mysql_tmpfile();
+ tmpfd = row_merge_file_create_low();
/* Reset the MySQL row buffer that is used when reporting
duplicate keys. */
@@ -2642,7 +2664,7 @@ row_merge_build_indexes(
}
func_exit:
- close(tmpfd);
+ row_merge_file_destroy_low(tmpfd);
for (i = 0; i < n_indexes; i++) {
row_merge_file_destroy(&merge_files[i]);
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 3e155fd14e6..e1ada387729 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -503,7 +503,7 @@ row_mysql_convert_row_to_innobase(
row is used, as row may contain
pointers to this record! */
{
- mysql_row_templ_t* templ;
+ const mysql_row_templ_t*templ;
dfield_t* dfield;
ulint i;
@@ -632,7 +632,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:
@@ -930,7 +930,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 */);
}
}
@@ -975,7 +976,6 @@ row_lock_table_autoinc_for_mysql(
ibool was_lock_wait;
ut_ad(trx);
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
/* If we already hold an AUTOINC lock on the table then do nothing.
Note: We peek at the value of the current owner without acquiring
@@ -1055,7 +1055,6 @@ row_lock_table_for_mysql(
ibool was_lock_wait;
ut_ad(trx);
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx->op_info = "setting table lock";
@@ -1129,7 +1128,6 @@ row_insert_for_mysql(
ins_node_t* node = prebuilt->ins_node;
ut_ad(trx);
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
if (prebuilt->table->ibd_file_missing) {
ut_print_timestamp(stderr);
@@ -1363,7 +1361,6 @@ row_update_for_mysql(
trx_t* trx = prebuilt->trx;
ut_ad(prebuilt && trx);
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
UT_NOT_USED(mysql_rec);
if (prebuilt->table->ibd_file_missing) {
@@ -1531,7 +1528,6 @@ row_unlock_for_mysql(
trx_t* trx = prebuilt->trx;
ut_ad(prebuilt && trx);
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
if (UNIV_UNLIKELY
(!srv_locks_unsafe_for_binlog
@@ -1833,7 +1829,6 @@ row_create_table_for_mysql(
ulint table_name_len;
ulint err;
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
@@ -1938,15 +1933,13 @@ err_exit:
err = trx->error_state;
- if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+ switch (err) {
+ case DB_SUCCESS:
+ break;
+ case DB_OUT_OF_FILE_SPACE:
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, NULL);
- /* TO DO: free table? The code below will dereference
- table->name, though. */
- }
- switch (err) {
- case DB_OUT_OF_FILE_SPACE:
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: cannot create table ",
stderr);
@@ -1961,9 +1954,13 @@ err_exit:
break;
case DB_DUPLICATE_KEY:
+ default:
/* We may also get err == DB_ERROR if the .ibd file for the
table already exists */
+ trx->error_state = DB_SUCCESS;
+ trx_general_rollback_for_mysql(trx, NULL);
+ dict_mem_table_free(table);
break;
}
@@ -2000,12 +1997,12 @@ row_create_index_for_mysql(
ulint i;
ulint len;
char* table_name;
+ dict_table_t* table;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(mutex_own(&(dict_sys->mutex)));
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx->op_info = "creating index";
@@ -2014,6 +2011,8 @@ row_create_index_for_mysql(
que_run_threads()) and thus index->table_name is not available. */
table_name = mem_strdup(index->table_name);
+ table = dict_table_get_low(table_name);
+
trx_start_if_not_started(trx);
/* Check that the same column does not appear twice in the index.
@@ -2046,7 +2045,7 @@ row_create_index_for_mysql(
}
/* Check also that prefix_len and actual length
- < DICT_MAX_INDEX_COL_LEN */
+ is less than that from DICT_MAX_FIELD_LEN_BY_FORMAT() */
len = dict_index_get_nth_field(index, i)->prefix_len;
@@ -2054,8 +2053,9 @@ row_create_index_for_mysql(
len = ut_max(len, field_lengths[i]);
}
- if (len >= DICT_MAX_INDEX_COL_LEN) {
- err = DB_TOO_BIG_RECORD;
+ /* Column or prefix length exceeds maximum column length */
+ if (len > (ulint) DICT_MAX_FIELD_LEN_BY_FORMAT(table)) {
+ err = DB_TOO_BIG_INDEX_COL;
goto error_handling;
}
@@ -2080,6 +2080,7 @@ row_create_index_for_mysql(
que_graph_free((que_t*) que_node_get_parent(thr));
error_handling:
+
if (err != DB_SUCCESS) {
/* We have special error handling here */
@@ -2408,8 +2409,6 @@ row_discard_tablespace_for_mysql(
table->n_foreign_key_checks_running > 0, we do not allow the
discard. We also reserve the data dictionary latch. */
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
-
trx->op_info = "discarding tablespace";
trx_start_if_not_started(trx);
@@ -2568,8 +2567,6 @@ row_import_tablespace_for_mysql(
ib_uint64_t current_lsn;
ulint err = DB_SUCCESS;
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
-
trx_start_if_not_started(trx);
trx->op_info = "importing tablespace";
@@ -2753,7 +2750,6 @@ row_truncate_table_for_mysql(
redo log records on the truncated tablespace, we will assign
a new tablespace identifier to the truncated tablespace. */
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(table);
if (srv_created_new_raw) {
@@ -2839,15 +2835,6 @@ row_truncate_table_for_mysql(
trx->table_id = table->id;
- /* Lock all index trees for this table, as we will
- truncate the table/index and possibly change their metadata.
- All DML/DDL are blocked by table level lock, with
- a few exceptions such as queries into information schema
- about the table, MySQL could try to access index stats
- for this kind of query, we need to use index locks to
- sync up */
- dict_table_x_lock_indexes(table);
-
if (table->space && !table->dir_path_of_temp_table) {
/* Discard and create the single-table tablespace. */
ulint space = table->space;
@@ -2860,6 +2847,11 @@ row_truncate_table_for_mysql(
dict_hdr_get_new_id(NULL, NULL, &space);
+ /* Lock all index trees for this table. We must
+ do so after dict_hdr_get_new_id() to preserve
+ the latch order */
+ dict_table_x_lock_indexes(table);
+
if (space == ULINT_UNDEFINED
|| fil_create_new_single_table_tablespace(
space, table->name, FALSE, flags,
@@ -2893,6 +2885,15 @@ row_truncate_table_for_mysql(
FIL_IBD_FILE_INITIAL_SIZE, &mtr);
mtr_commit(&mtr);
}
+ } else {
+ /* Lock all index trees for this table, as we will
+ truncate the table/index and possibly change their metadata.
+ All DML/DDL are blocked by table level lock, with
+ a few exceptions such as queries into information schema
+ about the table, MySQL could try to access index stats
+ for this kind of query, we need to use index locks to
+ sync up */
+ dict_table_x_lock_indexes(table);
}
/* scan SYS_INDEXES for all indexes of the table */
@@ -2945,7 +2946,7 @@ row_truncate_table_for_mysql(
rec = btr_pcur_get_rec(&pcur);
if (root_page_no != FIL_NULL) {
- page_rec_write_index_page_no(
+ page_rec_write_field(
rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
root_page_no, &mtr);
/* We will need to commit and restart the
@@ -3011,12 +3012,12 @@ next_rec:
dict_table_change_id_in_cache(table, new_id);
}
- /* MySQL calls ha_innobase::reset_auto_increment() which does
- the same thing. */
+ /* Reset auto-increment. */
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);
@@ -3124,7 +3125,7 @@ row_drop_table_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- table = dict_table_get_low(name);
+ table = dict_table_get_low_ignore_err(name, DICT_ERR_IGNORE_INDEX_ROOT);
if (!table) {
err = DB_TABLE_NOT_FOUND;
@@ -3157,7 +3158,7 @@ check_next_foreign:
if (foreign && trx->check_foreigns
&& !(drop_db && dict_tables_have_same_db(
- name, foreign->foreign_table_name))) {
+ name, foreign->foreign_table_name_lookup))) {
FILE* ef = dict_foreign_err_file;
/* We only allow dropping a referenced table if
@@ -3359,7 +3360,7 @@ check_next_foreign:
dict_table_remove_from_cache(table);
- if (dict_load_table(name, TRUE) != NULL) {
+ if (dict_load_table(name, TRUE, DICT_ERR_IGNORE_NONE) != NULL) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: not able to remove table ",
stderr);
@@ -3505,7 +3506,7 @@ row_mysql_drop_temp_tables(void)
btr_pcur_store_position(&pcur, &mtr);
btr_pcur_commit_specify_mtr(&pcur, &mtr);
- table = dict_load_table(table_name, TRUE);
+ table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
if (table) {
row_drop_table_for_mysql(table_name, trx, FALSE);
@@ -3599,7 +3600,6 @@ row_drop_database_for_mysql(
int err = DB_SUCCESS;
ulint namelen = strlen(name);
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(name != NULL);
ut_a(name[namelen - 1] == '/');
@@ -3769,7 +3769,6 @@ row_rename_table_for_mysql(
ibool old_is_tmp, new_is_tmp;
pars_info_t* info = NULL;
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
ut_a(new_name != NULL);
diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c
index 031b5258e98..83e7c9e4857 100644
--- a/storage/innobase/row/row0purge.c
+++ b/storage/innobase/row/row0purge.c
@@ -489,8 +489,11 @@ Purges an update of an existing record. Also purges an update of a delete
marked record if that record contained an externally stored field. */
static
void
-row_purge_upd_exist_or_extern(
-/*==========================*/
+row_purge_upd_exist_or_extern_func(
+/*===============================*/
+#ifdef UNIV_DEBUG
+ const que_thr_t*thr, /*!< in: query thread */
+#endif /* UNIV_DEBUG */
purge_node_t* node) /*!< in: row purge node */
{
mem_heap_t* heap;
@@ -515,8 +518,8 @@ row_purge_upd_exist_or_extern(
while (node->index != NULL) {
index = node->index;
- if (row_upd_changes_ord_field_binary(NULL, node->index,
- node->update)) {
+ if (row_upd_changes_ord_field_binary(node->index, node->update,
+ thr, NULL, NULL)) {
/* Build the older version of the index entry */
entry = row_build_index_entry(node->row, NULL,
index, heap);
@@ -598,6 +601,14 @@ skip_secondaries:
}
}
+#ifdef UNIV_DEBUG
+# define row_purge_upd_exist_or_extern(thr,node) \
+ row_purge_upd_exist_or_extern_func(thr,node)
+#else /* UNIV_DEBUG */
+# define row_purge_upd_exist_or_extern(thr,node) \
+ row_purge_upd_exist_or_extern_func(node)
+#endif /* UNIV_DEBUG */
+
/***********************************************************//**
Parses the row reference and other info in a modify undo log record.
@return TRUE if purge operation required: NOTE that then the CALLER
@@ -704,47 +715,32 @@ err_exit:
/***********************************************************//**
Fetches an undo log record and does the purge for the recorded operation.
If none left, or the current purge completed, returns the control to the
-parent node, which is always a query thread node.
-@return DB_SUCCESS if operation successfully completed, else error code */
-static
-ulint
+parent node, which is always a query thread node. */
+static __attribute__((nonnull))
+void
row_purge(
/*======*/
purge_node_t* node, /*!< in: row purge node */
que_thr_t* thr) /*!< in: query thread */
{
- roll_ptr_t roll_ptr;
- ibool purge_needed;
ibool updated_extern;
- trx_t* trx;
- ut_ad(node && thr);
-
- trx = thr_get_trx(thr);
+ ut_ad(node);
+ ut_ad(thr);
- node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
- &(node->reservation),
+ node->undo_rec = trx_purge_fetch_next_rec(&node->roll_ptr,
+ &node->reservation,
node->heap);
if (!node->undo_rec) {
/* Purge completed for this query thread */
thr->run_node = que_node_get_parent(node);
- return(DB_SUCCESS);
- }
-
- node->roll_ptr = roll_ptr;
-
- if (node->undo_rec == &trx_purge_dummy_rec) {
- purge_needed = FALSE;
- } else {
- purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
- thr);
- /* If purge_needed == TRUE, we must also remember to unfreeze
- data dictionary! */
+ return;
}
- if (purge_needed) {
+ if (node->undo_rec != &trx_purge_dummy_rec
+ && row_purge_parse_undo_rec(node, &updated_extern, thr)) {
node->found_clust = FALSE;
node->index = dict_table_get_next_index(
@@ -756,14 +752,14 @@ row_purge(
} else if (updated_extern
|| node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
- row_purge_upd_exist_or_extern(node);
+ row_purge_upd_exist_or_extern(thr, node);
}
if (node->found_clust) {
btr_pcur_close(&(node->pcur));
}
- row_mysql_unfreeze_data_dictionary(trx);
+ row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
}
/* Do some cleanup */
@@ -771,8 +767,6 @@ row_purge(
mem_heap_empty(node->heap);
thr->run_node = node;
-
- return(DB_SUCCESS);
}
/***********************************************************//**
@@ -786,9 +780,6 @@ row_purge_step(
que_thr_t* thr) /*!< in: query thread */
{
purge_node_t* node;
-#ifdef UNIV_DEBUG
- ulint err;
-#endif /* UNIV_DEBUG */
ut_ad(thr);
@@ -796,12 +787,7 @@ row_purge_step(
ut_ad(que_node_get_type(node) == QUE_NODE_PURGE);
-#ifdef UNIV_DEBUG
- err =
-#endif /* UNIV_DEBUG */
row_purge(node, thr);
- ut_ad(err == DB_SUCCESS);
-
return(thr);
}
diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c
index 050b8522fa3..3bd0323ddbe 100644
--- a/storage/innobase/row/row0row.c
+++ b/storage/innobase/row/row0row.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -47,35 +47,6 @@ Created 4/20/1996 Heikki Tuuri
#include "read0read.h"
#include "ut0mem.h"
-/*********************************************************************//**
-Gets the offset of trx id field, in bytes relative to the origin of
-a clustered index record.
-@return offset of DATA_TRX_ID */
-UNIV_INTERN
-ulint
-row_get_trx_id_offset(
-/*==================*/
- const rec_t* rec __attribute__((unused)),
- /*!< in: record */
- dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
-{
- ulint pos;
- ulint offset;
- ulint len;
-
- ut_ad(dict_index_is_clust(index));
- ut_ad(rec_offs_validate(rec, index, offsets));
-
- pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
-
- offset = rec_get_nth_field_offs(offsets, pos, &len);
-
- ut_ad(len == DATA_TRX_ID_LEN);
-
- return(offset);
-}
-
/*****************************************************************//**
When an insert or purge to a table is performed, this function builds
the entry to be inserted into or purged from an index on the table.
@@ -151,8 +122,6 @@ row_build_index_entry(
} else if (dfield_is_ext(dfield)) {
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
len -= BTR_EXTERN_FIELD_REF_SIZE;
- ut_a(ind_field->prefix_len <= len
- || dict_index_is_clust(index));
}
len = dtype_get_at_most_n_mbchars(
@@ -231,6 +200,14 @@ row_build(
ut_ad(rec_offs_validate(rec, index, offsets));
}
+#if 0 && defined UNIV_BLOB_NULL_DEBUG
+ /* This one can fail in trx_rollback_active() if
+ the server crashed during an insert before the
+ btr_store_big_rec_extern_fields() did mtr_commit()
+ all BLOB pointers to the clustered index record. */
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+#endif /* 0 && UNIV_BLOB_NULL_DEBUG */
+
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
@@ -301,8 +278,7 @@ row_build(
ut_ad(dict_table_get_format(index->table)
< DICT_TF_FORMAT_ZIP);
} else if (j) {
- *ext = row_ext_create(j, ext_cols, row,
- dict_table_zip_size(index->table),
+ *ext = row_ext_create(j, ext_cols, index->table->flags, row,
heap);
} else {
*ext = NULL;
@@ -415,6 +391,10 @@ row_rec_to_index_entry(
rec = rec_copy(buf, rec, offsets);
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(rec, index, offsets);
+#ifdef UNIV_BLOB_NULL_DEBUG
+ } else {
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+#endif /* UNIV_BLOB_NULL_DEBUG */
}
entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index 4d874ab3940..53d0c2ec232 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -99,12 +99,26 @@ row_sel_sec_rec_is_for_blob(
ulint clust_len, /*!< in: length of clust_field */
const byte* sec_field, /*!< in: column in secondary index */
ulint sec_len, /*!< in: length of sec_field */
- ulint zip_size) /*!< in: compressed page size, or 0 */
+ dict_table_t* table) /*!< in: table */
{
ulint len;
- byte buf[DICT_MAX_INDEX_COL_LEN];
+ byte buf[REC_VERSION_56_MAX_INDEX_COL_LEN];
+ ulint zip_size = dict_table_flags_to_zip_size(table->flags);
+ ulint max_prefix_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+
+ 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,
+ len = btr_copy_externally_stored_field_prefix(buf, max_prefix_len,
zip_size,
clust_field, clust_len);
@@ -210,8 +224,7 @@ row_sel_sec_rec_is_for_clust_rec(
col->mbminmaxlen,
clust_field, clust_len,
sec_field, sec_len,
- dict_table_zip_size(
- clust_index->table))) {
+ clust_index->table)) {
goto inequal;
}
@@ -1939,7 +1952,7 @@ stop_for_a_while:
mtr_commit(&mtr);
#ifdef UNIV_SYNC_DEBUG
- ut_ad(sync_thread_levels_empty_gen(TRUE));
+ ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */
err = DB_SUCCESS;
goto func_exit;
@@ -1959,7 +1972,7 @@ commit_mtr_for_a_while:
mtr_has_extra_clust_latch = FALSE;
#ifdef UNIV_SYNC_DEBUG
- ut_ad(sync_thread_levels_empty_gen(TRUE));
+ ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */
goto table_loop;
@@ -1976,7 +1989,7 @@ lock_wait_or_error:
mtr_commit(&mtr);
#ifdef UNIV_SYNC_DEBUG
- ut_ad(sync_thread_levels_empty_gen(TRUE));
+ ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */
func_exit:
@@ -2667,17 +2680,17 @@ row_sel_store_mysql_rec(
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
const rec_t* rec, /*!< in: Innobase record in the index
which was described in prebuilt's
- template; must be protected by
- a page latch */
+ template, or in the clustered index;
+ must be protected by a page latch */
+ ibool rec_clust, /*!< in: TRUE if rec is in the
+ clustered index instead of
+ prebuilt->index */
const ulint* offsets) /*!< in: array returned by
- rec_get_offsets() */
+ rec_get_offsets(rec) */
{
- mysql_row_templ_t* templ;
- mem_heap_t* extern_field_heap = NULL;
- mem_heap_t* heap;
- const byte* data;
- ulint len;
- ulint i;
+ mem_heap_t* extern_field_heap = NULL;
+ mem_heap_t* heap;
+ ulint i;
ut_ad(prebuilt->mysql_template);
ut_ad(prebuilt->default_rec);
@@ -2689,18 +2702,17 @@ row_sel_store_mysql_rec(
prebuilt->blob_heap = NULL;
}
- /* init null bytes with default values as they might be
- left uninitialized in some cases and these uninited bytes
- might be copied into mysql record buffer that leads to
- valgrind warnings */
- memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len);
-
for (i = 0; i < prebuilt->n_template; i++) {
- templ = prebuilt->mysql_template + i;
+ const mysql_row_templ_t*templ = prebuilt->mysql_template + i;
+ const byte* data;
+ ulint len;
+ ulint field_no;
+
+ field_no = rec_clust
+ ? templ->clust_rec_field_no : templ->rec_field_no;
- if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
- templ->rec_field_no))) {
+ if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) {
/* Copy an externally stored field to the temporary
heap */
@@ -2728,7 +2740,7 @@ row_sel_store_mysql_rec(
data = btr_rec_copy_externally_stored_field(
rec, offsets,
dict_table_zip_size(prebuilt->table),
- templ->rec_field_no, &len, heap);
+ field_no, &len, heap);
if (UNIV_UNLIKELY(!data)) {
/* The externally stored field
@@ -2749,8 +2761,7 @@ row_sel_store_mysql_rec(
} else {
/* Field is stored in the row. */
- data = rec_get_nth_field(rec, offsets,
- templ->rec_field_no, &len);
+ data = rec_get_nth_field(rec, offsets, field_no, &len);
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
&& len != UNIV_SQL_NULL) {
@@ -3112,7 +3123,7 @@ row_sel_pop_cached_row_for_mysql(
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct */
{
ulint i;
- mysql_row_templ_t* templ;
+ const mysql_row_templ_t*templ;
byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
@@ -3169,15 +3180,21 @@ ibool
row_sel_push_cache_row_for_mysql(
/*=============================*/
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
- const rec_t* rec, /*!< in: record to push; must
- be protected by a page latch */
- const ulint* offsets) /*!< in: rec_get_offsets() */
+ const rec_t* rec, /*!< in: record to push, in the index
+ which was described in prebuilt's
+ template, or in the clustered index;
+ must be protected by a page latch */
+ ibool rec_clust, /*!< in: TRUE if rec is in the
+ clustered index instead of
+ prebuilt->index */
+ const ulint* offsets) /*!< in: rec_get_offsets(rec) */
{
byte* buf;
ulint i;
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
ut_a(!prebuilt->templ_contains_blob);
if (prebuilt->fetch_cache[0] == NULL) {
@@ -3206,7 +3223,7 @@ row_sel_push_cache_row_for_mysql(
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
prebuilt->fetch_cache[
prebuilt->n_fetch_cached],
- prebuilt, rec, offsets))) {
+ prebuilt, rec, rec_clust, offsets))) {
return(FALSE);
}
@@ -3354,7 +3371,6 @@ row_search_for_mysql(
rec_offs_init(offsets_);
ut_ad(index && pcur && search_tuple);
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) {
ut_print_timestamp(stderr);
@@ -3371,11 +3387,17 @@ row_search_for_mysql(
"InnoDB: how you can resolve the problem.\n",
prebuilt->table->name);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
return(DB_ERROR);
}
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
return(DB_MISSING_HISTORY);
}
@@ -3604,9 +3626,11 @@ row_search_for_mysql(
row_sel_try_search_shortcut_for_mysql().
The latch will not be released until
mtr_commit(&mtr). */
+ ut_ad(!rec_get_deleted_flag(rec, comp));
if (!row_sel_store_mysql_rec(buf, prebuilt,
- rec, offsets)) {
+ rec, FALSE,
+ offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such
@@ -4233,16 +4257,19 @@ no_gap_lock:
rec = old_vers;
}
- } else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
+ } else {
/* We are looking into a non-clustered index,
and to get the right version of the record we
have to look also into the clustered index: this
is necessary, because we can only get the undo
information via the clustered index record. */
- ut_ad(index != clust_index);
+ ut_ad(!dict_index_is_clust(index));
- goto requires_clust_rec;
+ if (!lock_sec_rec_cons_read_sees(
+ rec, trx->read_view)) {
+ goto requires_clust_rec;
+ }
}
}
@@ -4352,19 +4379,8 @@ requires_clust_rec:
goto next_rec;
}
- if (prebuilt->need_to_access_clustered) {
-
- result_rec = clust_rec;
-
- ut_ad(rec_offs_validate(result_rec, clust_index,
- offsets));
- } else {
- /* We used 'offsets' for the clust rec, recalculate
- them for 'rec' */
- offsets = rec_get_offsets(rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- result_rec = rec;
- }
+ result_rec = clust_rec;
+ ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
} else {
result_rec = rec;
}
@@ -4375,6 +4391,7 @@ requires_clust_rec:
ut_ad(rec_offs_validate(result_rec,
result_rec != rec ? clust_index : index,
offsets));
+ ut_ad(!rec_get_deleted_flag(result_rec, comp));
/* At this point, the clustered index record is protected
by a page latch that was acquired when pcur was positioned.
@@ -4399,6 +4416,7 @@ requires_clust_rec:
cursor. */
if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
+ result_rec != rec,
offsets)) {
/* Only fresh inserts may contain incomplete
externally stored columns. Pretend that such
@@ -4416,15 +4434,31 @@ requires_clust_rec:
goto next_rec;
} else {
- if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
+ if (UNIV_UNLIKELY
+ (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) {
+ /* CHECK TABLE: fetch the row */
+
+ if (result_rec != rec
+ && !prebuilt->need_to_access_clustered) {
+ /* We used 'offsets' for the clust
+ rec, recalculate them for 'rec' */
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED,
+ &heap);
+ result_rec = rec;
+ }
+
memcpy(buf + 4, result_rec
- rec_offs_extra_size(offsets),
rec_offs_size(offsets));
mach_write_to_4(buf,
rec_offs_extra_size(offsets) + 4);
} else {
- if (!row_sel_store_mysql_rec(buf, prebuilt,
- result_rec, offsets)) {
+ /* Returning a row to MySQL */
+
+ if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec,
+ result_rec != rec,
+ offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such records do
@@ -4652,6 +4686,10 @@ func_exit:
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
}
}
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
return(err);
}
diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c
index aef653b3150..2188fdeff49 100644
--- a/storage/innobase/row/row0umod.c
+++ b/storage/innobase/row/row0umod.c
@@ -173,40 +173,26 @@ row_undo_mod_remove_clust_low(
mtr_t* mtr, /*!< in: mtr */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
- btr_pcur_t* pcur;
btr_cur_t* btr_cur;
ulint err;
- ibool success;
ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
- pcur = &(node->pcur);
- btr_cur = btr_pcur_get_btr_cur(pcur);
- success = btr_pcur_restore_position(mode, pcur, mtr);
+ /* Find out if the record has been purged already
+ or if we can remove it. */
- if (!success) {
+ if (!btr_pcur_restore_position(mode, &node->pcur, mtr)
+ || row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
return(DB_SUCCESS);
}
- /* Find out if we can remove the whole clustered index record */
-
- if (node->rec_type == TRX_UNDO_UPD_DEL_REC
- && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
-
- /* Ok, we can remove */
- } else {
- return(DB_SUCCESS);
- }
+ btr_cur = btr_pcur_get_btr_cur(&node->pcur);
if (mode == BTR_MODIFY_LEAF) {
- success = btr_cur_optimistic_delete(btr_cur, mtr);
-
- if (success) {
- err = DB_SUCCESS;
- } else {
- err = DB_FAIL;
- }
+ err = btr_cur_optimistic_delete(btr_cur, mtr)
+ ? DB_SUCCESS
+ : DB_FAIL;
} else {
ut_ad(mode == BTR_MODIFY_TREE);
@@ -693,19 +679,19 @@ 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->index, node->update,
+ thr,
+ node->row, node->ext)) {
/* 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/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c
index 9243521cf05..04b3dcb3a4a 100644
--- a/storage/innobase/row/row0upd.c
+++ b/storage/innobase/row/row0upd.c
@@ -238,7 +238,7 @@ row_upd_check_references_constraints(
foreign->n_fields))) {
if (foreign->foreign_table == NULL) {
- dict_table_get(foreign->foreign_table_name,
+ dict_table_get(foreign->foreign_table_name_lookup,
FALSE);
}
@@ -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 */
@@ -466,8 +466,11 @@ row_upd_changes_field_size_or_external(
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
-Replaces the new column values stored in the update vector to the record
-given. No field size changes are allowed. */
+Replaces the new column values stored in the update vector to the
+record given. No field size changes are allowed. This function is
+usually invoked on a clustered index. The only use case for a
+secondary index is row_ins_sec_index_entry_by_modify() or its
+counterpart in ibuf_insert_to_index_page(). */
UNIV_INTERN
void
row_upd_rec_in_place(
@@ -495,14 +498,49 @@ row_upd_rec_in_place(
n_fields = upd_get_n_fields(update);
for (i = 0; i < n_fields; i++) {
+#ifdef UNIV_BLOB_DEBUG
+ btr_blob_dbg_t b;
+ const byte* field_ref = NULL;
+#endif /* UNIV_BLOB_DEBUG */
+
upd_field = upd_get_nth_field(update, i);
new_val = &(upd_field->new_val);
ut_ad(!dfield_is_ext(new_val) ==
!rec_offs_nth_extern(offsets, upd_field->field_no));
+#ifdef UNIV_BLOB_DEBUG
+ if (dfield_is_ext(new_val)) {
+ ulint len;
+ field_ref = rec_get_nth_field(rec, offsets, i, &len);
+ ut_a(len != UNIV_SQL_NULL);
+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+ field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+ b.ref_page_no = page_get_page_no(page_align(rec));
+ b.ref_heap_no = page_rec_get_heap_no(rec);
+ b.ref_field_no = i;
+ b.blob_page_no = mach_read_from_4(
+ field_ref + BTR_EXTERN_PAGE_NO);
+ ut_a(b.ref_field_no >= index->n_uniq);
+ btr_blob_dbg_rbt_delete(index, &b, "upd_in_place");
+ }
+#endif /* UNIV_BLOB_DEBUG */
rec_set_nth_field(rec, offsets, upd_field->field_no,
dfield_get_data(new_val),
dfield_get_len(new_val));
+
+#ifdef UNIV_BLOB_DEBUG
+ if (dfield_is_ext(new_val)) {
+ b.blob_page_no = mach_read_from_4(
+ field_ref + BTR_EXTERN_PAGE_NO);
+ b.always_owner = b.owner = !(field_ref[BTR_EXTERN_LEN]
+ & BTR_EXTERN_OWNER_FLAG);
+ b.del = rec_get_deleted_flag(
+ rec, rec_offs_comp(offsets));
+
+ btr_blob_dbg_rbt_insert(index, &b, "upd_in_place");
+ }
+#endif /* UNIV_BLOB_DEBUG */
}
if (UNIV_LIKELY_NULL(page_zip)) {
@@ -1173,8 +1211,8 @@ row_upd_replace(
}
if (n_ext_cols) {
- *ext = row_ext_create(n_ext_cols, ext_cols, row,
- dict_table_zip_size(table), heap);
+ *ext = row_ext_create(n_ext_cols, ext_cols, table->flags, row,
+ heap);
} else {
*ext = NULL;
}
@@ -1189,26 +1227,33 @@ NOTE: we compare the fields as binary strings!
@return TRUE if update vector changes an ordering field in the index record */
UNIV_INTERN
ibool
-row_upd_changes_ord_field_binary(
-/*=============================*/
+row_upd_changes_ord_field_binary_func(
+/*==================================*/
+ 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! */
+#ifdef UNIV_DEBUG
+ const que_thr_t*thr, /*!< in: query thread */
+#endif /* UNIV_DEBUG */
const dtuple_t* row, /*!< in: old value of row, or NULL if the
row and the data values in update are not
known when this function is called, e.g., at
compile time */
- 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! */
+ const row_ext_t*ext) /*!< NULL, or prefixes of the externally
+ stored columns in the old row */
{
- 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(index);
+ ut_ad(update);
+ ut_ad(thr);
+ ut_ad(thr->graph);
+ ut_ad(thr->graph->trx);
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);
@@ -1216,33 +1261,81 @@ 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;
+ 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;
+ }
- /* 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 */
+ if (row == NULL) {
+ ut_ad(ext == NULL);
+ return(TRUE);
+ }
- 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)))) {
+ dfield = dtuple_get_nth_field(row, col_no);
- return(TRUE);
+ /* This treatment of column prefix indexes is loosely
+ based on row_build_index_entry(). */
+
+ if (UNIV_LIKELY(ind_field->prefix_len == 0)
+ || dfield_is_null(dfield)) {
+ /* do nothing special */
+ } else if (UNIV_LIKELY_NULL(ext)) {
+ /* Silence a compiler warning without
+ silencing a Valgrind error. */
+ dfield_len = 0;
+ UNIV_MEM_INVALID(&dfield_len, sizeof dfield_len);
+ /* 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)) {
+ /* The externally stored field
+ was not written yet. This
+ record should only be seen by
+ recv_recovery_rollback_active(),
+ when the server had crashed before
+ storing the field. */
+ ut_ad(thr->graph->trx->is_recovered);
+ ut_ad(trx_is_recv(thr->graph->trx));
+ 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);
}
}
@@ -1326,7 +1419,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);
}
@@ -1593,14 +1686,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->index, node->update,
+ thr, node->row, node->ext)) {
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
@@ -1612,21 +1790,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 referenced,/*!< 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));
@@ -1636,32 +1816,63 @@ 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);
- err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
- btr_cur, TRUE, thr, mtr);
+ entry = row_build_index_entry(node->upd_row, node->upd_ext,
+ index, heap);
+ ut_a(entry);
+
+ 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 (referenced) {
/* NOTE that the following call loses
the position of pcur ! */
@@ -1670,48 +1881,49 @@ row_upd_clust_rec_by_insert(
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_disown_inherited_fields(
+ btr_cur_get_page_zip(btr_cur),
+ rec, index, offsets, node->update, mtr);
- btr_cur_mark_dtuple_inherited_extern(entry, node->update);
+ 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);
@@ -1805,7 +2017,7 @@ row_upd_clust_rec(
index, btr_cur_get_block(btr_cur), rec,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- big_rec, mtr);
+ mtr, TRUE, big_rec);
mtr_commit(mtr);
}
@@ -1856,8 +2068,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 && referenced) {
/* NOTE that the following call loses the position of pcur ! */
@@ -2002,7 +2215,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(index, node->update, thr,
+ node->row, node->ext)) {
/* Update causes an ordering field (ordering fields within
the B-tree) of the clustered index record to change: perform
@@ -2072,7 +2286,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/innobase/row/row0vers.c b/storage/innobase/row/row0vers.c
index 2e12361312c..5fd7d082194 100644
--- a/storage/innobase/row/row0vers.c
+++ b/storage/innobase/row/row0vers.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -550,6 +550,11 @@ row_vers_build_for_consistent_read(
/* The view already sees this version: we can
copy it to in_heap and return */
+#ifdef UNIV_BLOB_NULL_DEBUG
+ ut_a(!rec_offs_any_null_extern(
+ version, *offsets));
+#endif /* UNIV_BLOB_NULL_DEBUG */
+
buf = mem_heap_alloc(in_heap,
rec_offs_size(*offsets));
*old_vers = rec_copy(buf, version, *offsets);
@@ -583,6 +588,10 @@ row_vers_build_for_consistent_read(
*offsets = rec_get_offsets(prev_version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
+#ifdef UNIV_BLOB_NULL_DEBUG
+ ut_a(!rec_offs_any_null_extern(prev_version, *offsets));
+#endif /* UNIV_BLOB_NULL_DEBUG */
+
trx_id = row_get_rec_trx_id(prev_version, index, *offsets);
if (read_view_sees_trx_id(view, trx_id)) {
@@ -669,15 +678,23 @@ row_vers_build_for_semi_consistent_read(
mutex_enter(&kernel_mutex);
version_trx = trx_get_on_id(version_trx_id);
+ if (version_trx
+ && (version_trx->conc_state == TRX_COMMITTED_IN_MEMORY
+ || version_trx->conc_state == TRX_NOT_STARTED)) {
+
+ version_trx = NULL;
+ }
mutex_exit(&kernel_mutex);
- if (!version_trx
- || version_trx->conc_state == TRX_NOT_STARTED
- || version_trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
+ if (!version_trx) {
/* We found a version that belongs to a
committed transaction: return it. */
+#ifdef UNIV_BLOB_NULL_DEBUG
+ ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_BLOB_NULL_DEBUG */
+
if (rec == version) {
*old_vers = rec;
err = DB_SUCCESS;
@@ -735,6 +752,9 @@ row_vers_build_for_semi_consistent_read(
version = prev_version;
*offsets = rec_get_offsets(version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
+#ifdef UNIV_BLOB_NULL_DEBUG
+ ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_BLOB_NULL_DEBUG */
}/* for (;;) */
if (heap) {
diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
index b2da43c188b..04503d25cd4 100644
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -66,7 +66,6 @@ Created 10/8/1995 Heikki Tuuri
#include "mem0mem.h"
#include "mem0pool.h"
#include "sync0sync.h"
-#include "thr0loc.h"
#include "que0que.h"
#include "log0recv.h"
#include "pars0pars.h"
@@ -87,10 +86,6 @@ Created 10/8/1995 Heikki Tuuri
#include "mysql/plugin.h"
#include "mysql/service_thd_wait.h"
-/* This is set to TRUE if the MySQL user has set it in MySQL; currently
-affects only FOREIGN KEY definition parsing */
-UNIV_INTERN ibool srv_lower_case_table_names = FALSE;
-
/* The following counter is incremented whenever there is some user activity
in the server */
UNIV_INTERN ulint srv_activity_count = 0;
@@ -267,12 +262,20 @@ UNIV_INTERN ulong srv_max_buf_pool_modified_pct = 75;
/* the number of purge threads to use from the worker pool (currently 0 or 1).*/
UNIV_INTERN ulong srv_n_purge_threads = 0;
-/* the number of records to purge in one batch */
+/* the number of pages to purge in one batch */
UNIV_INTERN ulong srv_purge_batch_size = 20;
+/* the number of rollback segments to use */
+UNIV_INTERN ulong srv_rollback_segments = TRX_SYS_N_RSEGS;
+
/* variable counts amount of data read in total (in bytes) */
UNIV_INTERN ulint srv_data_read = 0;
+/* Internal setting for "innodb_stats_method". Decides how InnoDB treats
+NULL value when collecting statistics. By default, it is set to
+SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */
+ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL;
+
/* here we count the amount of data written in total (in bytes) */
UNIV_INTERN ulint srv_data_written = 0;
@@ -424,6 +427,7 @@ UNIV_INTERN ulint srv_n_lock_wait_current_count = 0;
UNIV_INTERN ib_int64_t srv_n_lock_wait_time = 0;
UNIV_INTERN ulint srv_n_lock_max_wait_time = 0;
+UNIV_INTERN ulint srv_truncated_status_writes = 0;
/*
Set the following to 0 if you want InnoDB to write messages on
@@ -677,9 +681,7 @@ Unix.*/
/* Thread slot in the thread table */
struct srv_slot_struct{
- os_thread_id_t id; /*!< thread id */
- os_thread_t handle; /*!< thread handle */
- unsigned type:3; /*!< thread type: user, utility etc. */
+ unsigned type:1; /*!< thread type: user, utility etc. */
unsigned in_use:1; /*!< TRUE if this slot is in use */
unsigned suspended:1; /*!< TRUE if the thread is waiting
for the event of this slot */
@@ -694,6 +696,12 @@ struct srv_slot_struct{
/* Table for MySQL threads where they will be suspended to wait for locks */
UNIV_INTERN srv_slot_t* srv_mysql_table = NULL;
+UNIV_INTERN os_event_t srv_timeout_event;
+
+UNIV_INTERN os_event_t srv_monitor_event;
+
+UNIV_INTERN os_event_t srv_error_event;
+
UNIV_INTERN os_event_t srv_lock_timeout_thread_event;
UNIV_INTERN srv_sys_t* srv_sys = NULL;
@@ -780,6 +788,7 @@ srv_table_get_nth_slot(
/*===================*/
ulint index) /*!< in: index of the slot */
{
+ ut_ad(mutex_own(&kernel_mutex));
ut_a(index < OS_THREAD_MAX_N);
return(srv_sys->threads + index);
@@ -798,7 +807,7 @@ srv_get_n_threads(void)
mutex_enter(&kernel_mutex);
- for (i = SRV_COM; i < SRV_MASTER + 1; i++) {
+ for (i = 0; i < SRV_MASTER + 1; i++) {
n_threads += srv_n_threads[i];
}
@@ -808,13 +817,46 @@ srv_get_n_threads(void)
return(n_threads);
}
+#ifdef UNIV_DEBUG
/*********************************************************************//**
-Reserves a slot in the thread table for the current thread. Also creates the
-thread local storage struct for the current thread. NOTE! The server mutex
-has to be reserved by the caller!
-@return reserved slot index */
+Validates the type of a thread table slot.
+@return TRUE if ok */
static
-ulint
+ibool
+srv_thread_type_validate(
+/*=====================*/
+ enum srv_thread_type type) /*!< in: thread type */
+{
+ switch (type) {
+ case SRV_WORKER:
+ case SRV_MASTER:
+ return(TRUE);
+ }
+ ut_error;
+ return(FALSE);
+}
+#endif /* UNIV_DEBUG */
+
+/*********************************************************************//**
+Gets the type of a thread table slot.
+@return thread type */
+static
+enum srv_thread_type
+srv_slot_get_type(
+/*==============*/
+ const srv_slot_t* slot) /*!< in: thread slot */
+{
+ enum srv_thread_type type = (enum srv_thread_type) slot->type;
+ ut_ad(srv_thread_type_validate(type));
+ return(type);
+}
+
+/*********************************************************************//**
+Reserves a slot in the thread table for the current thread.
+NOTE! The server mutex has to be reserved by the caller!
+@return reserved slot */
+static
+srv_slot_t*
srv_table_reserve_slot(
/*===================*/
enum srv_thread_type type) /*!< in: type of the thread */
@@ -822,8 +864,8 @@ srv_table_reserve_slot(
srv_slot_t* slot;
ulint i;
- ut_a(type > 0);
- ut_a(type <= SRV_MASTER);
+ ut_ad(srv_thread_type_validate(type));
+ ut_ad(mutex_own(&kernel_mutex));
i = 0;
slot = srv_table_get_nth_slot(i);
@@ -833,53 +875,37 @@ srv_table_reserve_slot(
slot = srv_table_get_nth_slot(i);
}
- ut_a(slot->in_use == FALSE);
-
slot->in_use = TRUE;
slot->suspended = FALSE;
slot->type = type;
- slot->id = os_thread_get_curr_id();
- slot->handle = os_thread_get_curr();
-
- thr_local_create();
+ ut_ad(srv_slot_get_type(slot) == type);
- thr_local_set_slot_no(os_thread_get_curr_id(), i);
-
- return(i);
+ return(slot);
}
/*********************************************************************//**
Suspends the calling thread to wait for the event in its thread slot.
-NOTE! The server mutex has to be reserved by the caller!
-@return event for the calling thread to wait */
+NOTE! The server mutex has to be reserved by the caller! */
static
-os_event_t
-srv_suspend_thread(void)
-/*====================*/
+void
+srv_suspend_thread(
+/*===============*/
+ srv_slot_t* slot) /*!< in/out: thread slot */
{
- srv_slot_t* slot;
- os_event_t event;
- ulint slot_no;
enum srv_thread_type type;
ut_ad(mutex_own(&kernel_mutex));
-
- slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
+ ut_ad(slot->in_use);
+ ut_ad(!slot->suspended);
if (srv_print_thread_releases) {
fprintf(stderr,
"Suspending thread %lu to slot %lu\n",
- (ulong) os_thread_get_curr_id(), (ulong) slot_no);
+ (ulong) os_thread_get_curr_id(),
+ (ulong) (slot - srv_sys->threads));
}
- slot = srv_table_get_nth_slot(slot_no);
-
- type = slot->type;
-
- ut_ad(type >= SRV_WORKER);
- ut_ad(type <= SRV_MASTER);
-
- event = slot->event;
+ type = srv_slot_get_type(slot);
slot->suspended = TRUE;
@@ -887,9 +913,7 @@ srv_suspend_thread(void)
srv_n_threads_active[type]--;
- os_event_reset(event);
-
- return(event);
+ os_event_reset(slot->event);
}
/*********************************************************************//**
@@ -908,8 +932,7 @@ srv_release_threads(
ulint i;
ulint count = 0;
- ut_ad(type >= SRV_WORKER);
- ut_ad(type <= SRV_MASTER);
+ ut_ad(srv_thread_type_validate(type));
ut_ad(n > 0);
ut_ad(mutex_own(&kernel_mutex));
@@ -917,7 +940,8 @@ srv_release_threads(
slot = srv_table_get_nth_slot(i);
- if (slot->in_use && slot->type == type && slot->suspended) {
+ if (slot->in_use && slot->suspended
+ && srv_slot_get_type(slot) == type) {
slot->suspended = FALSE;
@@ -927,10 +951,9 @@ srv_release_threads(
if (srv_print_thread_releases) {
fprintf(stderr,
- "Releasing thread %lu type %lu"
+ "Releasing thread type %lu"
" from slot %lu\n",
- (ulong) slot->id, (ulong) type,
- (ulong) i);
+ (ulong) type, (ulong) i);
}
count++;
@@ -945,31 +968,35 @@ srv_release_threads(
}
/*********************************************************************//**
-Returns the calling thread type.
-@return SRV_COM, ... */
+Check whether thread type has reserved a slot. Return the first slot that
+is found. This works because we currently have only 1 thread of each type.
+@return slot number or ULINT_UNDEFINED if not found*/
UNIV_INTERN
-enum srv_thread_type
-srv_get_thread_type(void)
-/*=====================*/
+ulint
+srv_thread_has_reserved_slot(
+/*=========================*/
+ enum srv_thread_type type) /*!< in: thread type to check */
{
- ulint slot_no;
- srv_slot_t* slot;
- enum srv_thread_type type;
+ ulint i;
+ ulint slot_no = ULINT_UNDEFINED;
+ ut_ad(srv_thread_type_validate(type));
mutex_enter(&kernel_mutex);
- slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
-
- slot = srv_table_get_nth_slot(slot_no);
+ for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ srv_slot_t* slot;
- type = slot->type;
+ slot = srv_table_get_nth_slot(i);
- ut_ad(type >= SRV_WORKER);
- ut_ad(type <= SRV_MASTER);
+ if (slot->in_use && slot->type == type) {
+ slot_no = i;
+ break;
+ }
+ }
mutex_exit(&kernel_mutex);
- return(type);
+ return(slot_no);
}
/*********************************************************************//**
@@ -991,26 +1018,28 @@ srv_init(void)
mutex_create(srv_innodb_monitor_mutex_key,
&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
- srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
+ srv_sys->threads = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
for (i = 0; i < OS_THREAD_MAX_N; i++) {
- slot = srv_table_get_nth_slot(i);
- slot->in_use = FALSE;
- slot->type=0; /* Avoid purify errors */
+ slot = srv_sys->threads + i;
slot->event = os_event_create(NULL);
ut_a(slot->event);
}
- srv_mysql_table = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
+ srv_mysql_table = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
for (i = 0; i < OS_THREAD_MAX_N; i++) {
slot = srv_mysql_table + i;
- slot->in_use = FALSE;
- slot->type = 0;
slot->event = os_event_create(NULL);
ut_a(slot->event);
}
+ srv_error_event = os_event_create(NULL);
+
+ srv_timeout_event = os_event_create(NULL);
+
+ srv_monitor_event = os_event_create(NULL);
+
srv_lock_timeout_thread_event = os_event_create(NULL);
for (i = 0; i < SRV_MASTER + 1; i++) {
@@ -1087,7 +1116,6 @@ srv_general_init(void)
os_sync_init();
sync_init();
mem_init(srv_mem_pool_size);
- thr_local_init();
}
/*======================= InnoDB Server FIFO queue =======================*/
@@ -1109,6 +1137,10 @@ srv_conc_enter_innodb(
srv_conc_slot_t* slot = NULL;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+
if (trx->mysql_thd != NULL
&& thd_is_replication_slave_thread(trx->mysql_thd)) {
@@ -1232,9 +1264,13 @@ retry:
/* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */
+ ut_ad(!trx->has_search_latch);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
trx->op_info = "waiting in InnoDB queue";
- thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK);
+ thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK);
os_event_wait(slot->event);
thd_wait_end(trx->mysql_thd);
@@ -1267,6 +1303,10 @@ srv_conc_force_enter_innodb(
trx_t* trx) /*!< in: transaction object associated with the
thread */
{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+
if (UNIV_LIKELY(!srv_thread_concurrency)) {
return;
@@ -1338,6 +1378,10 @@ srv_conc_force_exit_innodb(
if (slot != NULL) {
os_event_set(slot->event);
}
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
}
/*********************************************************************//**
@@ -1349,6 +1393,10 @@ srv_conc_exit_innodb(
trx_t* trx) /*!< in: transaction object associated with the
thread */
{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+
if (trx->n_tickets_to_enter_innodb > 0) {
/* We will pretend the thread is still inside InnoDB though it
now leaves the InnoDB engine. In this way we save
@@ -1446,7 +1494,7 @@ srv_table_reserve_slot_for_mysql(void)
while (slot->in_use) {
i++;
- if (i >= OS_THREAD_MAX_N) {
+ if (UNIV_UNLIKELY(i >= OS_THREAD_MAX_N)) {
ut_print_timestamp(stderr);
@@ -1465,10 +1513,9 @@ srv_table_reserve_slot_for_mysql(void)
slot = srv_mysql_table + i;
fprintf(stderr,
- "Slot %lu: thread id %lu, type %lu,"
+ "Slot %lu: thread type %lu,"
" in use %lu, susp %lu, time %lu\n",
(ulong) i,
- (ulong) os_thread_pf(slot->id),
(ulong) slot->type,
(ulong) slot->in_use,
(ulong) slot->suspended,
@@ -1485,8 +1532,6 @@ srv_table_reserve_slot_for_mysql(void)
ut_a(slot->in_use == FALSE);
slot->in_use = TRUE;
- slot->id = os_thread_get_curr_id();
- slot->handle = os_thread_get_curr();
return(slot);
}
@@ -1573,17 +1618,6 @@ srv_suspend_mysql_thread(
mutex_exit(&kernel_mutex);
- if (trx->declared_to_be_inside_innodb) {
-
- was_declared_inside_innodb = TRUE;
-
- /* We must declare this OS thread to exit InnoDB, since a
- possible other thread holding a lock which this thread waits
- for must be allowed to enter, sooner or later */
-
- srv_conc_force_exit_innodb(trx);
- }
-
had_dict_lock = trx->dict_operation_lock_mode;
switch (had_dict_lock) {
@@ -1592,6 +1626,18 @@ srv_suspend_mysql_thread(
row_mysql_unfreeze_data_dictionary(trx);
break;
case RW_X_LATCH:
+ /* There should never be a lock wait when the
+ dictionary latch is reserved in X mode. Dictionary
+ transactions should only acquire locks on dictionary
+ tables, not other tables. All access to dictionary
+ tables should be covered by dictionary
+ transactions. */
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Error: dict X latch held in "
+ "srv_suspend_mysql_thread\n", stderr);
+ /* This should never occur. This incorrect handling
+ was added in the early development of
+ ha_innobase::add_index() in InnoDB Plugin 1.0. */
/* Release fast index creation latch */
row_mysql_unlock_data_dictionary(trx);
break;
@@ -1599,12 +1645,34 @@ srv_suspend_mysql_thread(
ut_a(trx->dict_operation_lock_mode == 0);
+ if (trx->declared_to_be_inside_innodb) {
+
+ was_declared_inside_innodb = TRUE;
+
+ /* We must declare this OS thread to exit InnoDB, since a
+ possible other thread holding a lock which this thread waits
+ for must be allowed to enter, sooner or later */
+
+ srv_conc_force_exit_innodb(trx);
+ }
+
/* Suspend this thread and wait for the event. */
- thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK);
+ thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_LOCK);
os_event_wait(event);
thd_wait_end(trx->mysql_thd);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+
+ if (was_declared_inside_innodb) {
+
+ /* Return back inside InnoDB */
+
+ srv_conc_force_enter_innodb(trx);
+ }
+
/* After resuming, reacquire the data dictionary latch if
necessary. */
@@ -1613,17 +1681,13 @@ srv_suspend_mysql_thread(
row_mysql_freeze_data_dictionary(trx);
break;
case RW_X_LATCH:
+ /* This should never occur. This incorrect handling
+ was added in the early development of
+ ha_innobase::add_index() in InnoDB Plugin 1.0. */
row_mysql_lock_data_dictionary(trx);
break;
}
- if (was_declared_inside_innodb) {
-
- /* Return back inside InnoDB */
-
- srv_conc_force_enter_innodb(trx);
- }
-
mutex_enter(&kernel_mutex);
/* Release the slot for others to use */
@@ -2017,6 +2081,7 @@ srv_export_innodb_status(void)
export_vars.innodb_rows_inserted = srv_n_rows_inserted;
export_vars.innodb_rows_updated = srv_n_rows_updated;
export_vars.innodb_rows_deleted = srv_n_rows_deleted;
+ export_vars.innodb_truncated_status_writes = srv_truncated_status_writes;
mutex_exit(&srv_innodb_monitor_mutex);
}
@@ -2032,6 +2097,7 @@ srv_monitor_thread(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ ib_int64_t sig_count;
double time_elapsed;
time_t current_time;
time_t last_table_monitor_time;
@@ -2050,26 +2116,28 @@ srv_monitor_thread(
#endif
UT_NOT_USED(arg);
- srv_last_monitor_time = time(NULL);
- last_table_monitor_time = time(NULL);
- last_tablespace_monitor_time = time(NULL);
- last_monitor_time = time(NULL);
+ srv_last_monitor_time = ut_time();
+ last_table_monitor_time = ut_time();
+ last_tablespace_monitor_time = ut_time();
+ last_monitor_time = ut_time();
mutex_skipped = 0;
last_srv_print_monitor = srv_print_innodb_monitor;
loop:
srv_monitor_active = TRUE;
/* Wake up every 5 seconds to see if we need to print
- monitor information. */
+ monitor information or if signalled at shutdown. */
- os_thread_sleep(5000000);
+ sig_count = os_event_reset(srv_monitor_event);
- current_time = time(NULL);
+ os_event_wait_time_low(srv_monitor_event, 5000000, sig_count);
+
+ current_time = ut_time();
time_elapsed = difftime(current_time, last_monitor_time);
if (time_elapsed > 15) {
- last_monitor_time = time(NULL);
+ last_monitor_time = ut_time();
if (srv_print_innodb_monitor) {
/* Reset mutex_skipped counter everytime
@@ -2113,7 +2181,7 @@ loop:
if (srv_print_innodb_tablespace_monitor
&& difftime(current_time,
last_tablespace_monitor_time) > 60) {
- last_tablespace_monitor_time = time(NULL);
+ last_tablespace_monitor_time = ut_time();
fputs("========================"
"========================\n",
@@ -2139,7 +2207,7 @@ loop:
if (srv_print_innodb_table_monitor
&& difftime(current_time, last_table_monitor_time) > 60) {
- last_table_monitor_time = time(NULL);
+ last_table_monitor_time = ut_time();
fputs("===========================================\n",
stderr);
@@ -2199,16 +2267,20 @@ srv_lock_timeout_thread(
ibool some_waits;
double wait_time;
ulint i;
+ ib_int64_t sig_count;
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_lock_timeout_thread_key);
#endif
loop:
+
/* When someone is waiting for a lock, we wake up every second
and check if a timeout has passed for a lock wait */
- os_thread_sleep(1000000);
+ sig_count = os_event_reset(srv_timeout_event);
+
+ os_event_wait_time_low(srv_timeout_event, 1000000, sig_count);
srv_lock_timeout_active = TRUE;
@@ -2303,6 +2375,13 @@ srv_error_monitor_thread(
ulint fatal_cnt = 0;
ib_uint64_t old_lsn;
ib_uint64_t new_lsn;
+ ib_int64_t sig_count;
+ /* longest waiting thread for a semaphore */
+ os_thread_id_t waiter = os_thread_get_curr_id();
+ os_thread_id_t old_waiter = waiter;
+ /* the semaphore that is being waited for */
+ const void* sema = NULL;
+ const void* old_sema = NULL;
old_lsn = srv_start_lsn;
@@ -2356,7 +2435,8 @@ loop:
sync_arr_wake_threads_if_sema_free();
- if (sync_array_print_long_waits()) {
+ if (sync_array_print_long_waits(&waiter, &sema)
+ && sema == old_sema && os_thread_eq(waiter, old_waiter)) {
fatal_cnt++;
if (fatal_cnt > 10) {
@@ -2371,6 +2451,8 @@ loop:
}
} else {
fatal_cnt = 0;
+ old_waiter = waiter;
+ old_sema = sema;
}
/* Flush stderr so that a database user gets the output
@@ -2378,7 +2460,9 @@ loop:
fflush(stderr);
- os_thread_sleep(1000000);
+ sig_count = os_event_reset(srv_error_event);
+
+ os_event_wait_time_low(srv_error_event, 1000000, sig_count);
if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
@@ -2408,7 +2492,7 @@ srv_is_any_background_thread_active(void)
mutex_enter(&kernel_mutex);
- for (i = SRV_COM; i <= SRV_MASTER; ++i) {
+ for (i = 0; i <= SRV_MASTER; ++i) {
if (srv_n_threads_active[i] != 0) {
ret = TRUE;
break;
@@ -2562,7 +2646,7 @@ srv_master_thread(
os_thread_create */
{
buf_pool_stat_t buf_stat;
- os_event_t event;
+ srv_slot_t* slot;
ulint old_activity_count;
ulint n_pages_purged = 0;
ulint n_bytes_merged;
@@ -2588,10 +2672,10 @@ srv_master_thread(
srv_main_thread_process_no = os_proc_get_number();
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
- srv_table_reserve_slot(SRV_MASTER);
-
mutex_enter(&kernel_mutex);
+ slot = srv_table_reserve_slot(SRV_MASTER);
+
srv_n_threads_active[SRV_MASTER]++;
mutex_exit(&kernel_mutex);
@@ -2622,11 +2706,28 @@ loop:
when there is database activity */
srv_last_log_flush_time = time(NULL);
- next_itr_time = ut_time_ms();
+
+ /* Sleep for 1 second on entrying the for loop below the first time. */
+ next_itr_time = ut_time_ms() + 1000;
for (i = 0; i < 10; i++) {
ulint cur_time = ut_time_ms();
+ /* ALTER TABLE in MySQL requires on Unix that the table handler
+ can drop tables lazily after there no longer are SELECT
+ queries to them. */
+
+ srv_main_thread_op_info = "doing background drop tables";
+
+ row_drop_tables_for_mysql_in_background();
+
+ srv_main_thread_op_info = "";
+
+ if (srv_fast_shutdown && srv_shutdown_state > 0) {
+
+ goto background_loop;
+ }
+
buf_get_total_stat(&buf_stat);
n_ios_old = log_sys->n_log_ios + buf_stat.n_pages_read
@@ -2635,7 +2736,8 @@ loop:
srv_main_thread_op_info = "sleeping";
srv_main_1_second_loops++;
- if (next_itr_time > cur_time) {
+ if (next_itr_time > cur_time
+ && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
/* Get sleep interval in micro seconds. We use
ut_min() to avoid long sleep in case of
@@ -2649,21 +2751,6 @@ loop:
/* Each iteration should happen at 1 second interval. */
next_itr_time = ut_time_ms() + 1000;
- /* ALTER TABLE in MySQL requires on Unix that the table handler
- can drop tables lazily after there no longer are SELECT
- queries to them. */
-
- srv_main_thread_op_info = "doing background drop tables";
-
- row_drop_tables_for_mysql_in_background();
-
- srv_main_thread_op_info = "";
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
-
- goto background_loop;
- }
-
/* Flush logs if needed */
srv_sync_log_buffer_in_background();
@@ -2841,7 +2928,9 @@ background_loop:
MySQL tries to drop a table while there are still open handles
to it and we had to put it to the background drop queue.) */
- os_thread_sleep(100000);
+ if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
+ os_thread_sleep(100000);
+ }
}
if (srv_n_purge_threads == 0) {
@@ -2974,7 +3063,7 @@ suspend_thread:
goto loop;
}
- event = srv_suspend_thread();
+ srv_suspend_thread(slot);
mutex_exit(&kernel_mutex);
@@ -2984,22 +3073,16 @@ suspend_thread:
manual also mentions this string in several places. */
srv_main_thread_op_info = "waiting for server activity";
- os_event_wait(event);
+ os_event_wait(slot->event);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- /* This is only extra safety, the thread should exit
- already when the event wait ends */
-
os_thread_exit(NULL);
-
}
/* When there is user activity, InnoDB will set the event and the
main thread goes back to loop. */
goto loop;
-
- OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
}
/*********************************************************************//**
@@ -3013,7 +3096,7 @@ srv_purge_thread(
required by os_thread_create */
{
srv_slot_t* slot;
- ulint slot_no = ULINT_UNDEFINED;
+ ulint retries = 0;
ulint n_total_purged = ULINT_UNDEFINED;
ut_a(srv_n_purge_threads == 1);
@@ -3029,9 +3112,7 @@ srv_purge_thread(
mutex_enter(&kernel_mutex);
- slot_no = srv_table_reserve_slot(SRV_WORKER);
-
- slot = srv_table_get_nth_slot(slot_no);
+ slot = srv_table_reserve_slot(SRV_WORKER);
++srv_n_threads_active[SRV_WORKER];
@@ -3039,7 +3120,7 @@ srv_purge_thread(
while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
- ulint n_pages_purged;
+ ulint n_pages_purged = 0;
/* If there are very few records to purge or the last
purge didn't purge any records then wait for activity.
@@ -3047,17 +3128,18 @@ srv_purge_thread(
because in the worst case we will end up waiting for
the next purge event. */
if (trx_sys->rseg_history_len < srv_purge_batch_size
- || n_total_purged == 0) {
-
- os_event_t event;
+ || (n_total_purged == 0
+ && retries >= TRX_SYS_N_RSEGS)) {
mutex_enter(&kernel_mutex);
- event = srv_suspend_thread();
+ srv_suspend_thread(slot);
mutex_exit(&kernel_mutex);
- os_event_wait(event);
+ os_event_wait(slot->event);
+
+ retries = 0;
}
/* Check for shutdown and whether we should do purge at all. */
@@ -3068,7 +3150,12 @@ srv_purge_thread(
break;
}
- n_total_purged = 0;
+ if (n_total_purged == 0 && retries <= TRX_SYS_N_RSEGS) {
+ ++retries;
+ } else if (n_total_purged > 0) {
+ retries = 0;
+ n_total_purged = 0;
+ }
/* Purge until there are no more records to purge and there is
no change in configuration or server state. */
@@ -3084,16 +3171,11 @@ srv_purge_thread(
mutex_enter(&kernel_mutex);
- ut_ad(srv_table_get_nth_slot(slot_no) == slot);
-
/* Decrement the active count. */
- srv_suspend_thread();
+ srv_suspend_thread(slot);
slot->in_use = FALSE;
- /* Free the thread local memory. */
- thr_local_free(os_thread_get_curr_id());
-
mutex_exit(&kernel_mutex);
#ifdef UNIV_DEBUG_THREAD_CREATION
diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
index 4da836672ec..cf11e75b8e0 100644
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/srv/srv0start.c
@@ -85,7 +85,6 @@ Created 2/16/1996 Heikki Tuuri
# include "row0row.h"
# include "row0mysql.h"
# include "btr0pcur.h"
-# include "thr0loc.h"
# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
# include "zlib.h" /* for ZLIB_VERSION */
@@ -120,11 +119,6 @@ UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE;
/** Files comprising the system tablespace */
static os_file_t files[1000];
-/** Mutex protecting the ios count */
-static mutex_t ios_mutex;
-/** Count of I/O operations in io_handler_thread() */
-static ulint ios;
-
/** io_handler_thread parameters for thread identification */
static ulint n[SRV_MAX_N_IO_THREADS + 6];
/** io_handler_thread identifiers */
@@ -152,11 +146,6 @@ UNIV_INTERN mysql_pfs_key_t srv_master_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_purge_thread_key;
#endif /* UNIV_PFS_THREAD */
-#ifdef UNIV_PFS_MUTEX
-/* Key to register ios_mutex_key with performance schema */
-UNIV_INTERN mysql_pfs_key_t ios_mutex_key;
-#endif /* UNIV_PFS_MUTEX */
-
/*********************************************************************//**
Convert a numeric string that optionally ends in G or M, to a number
containing megabytes.
@@ -477,7 +466,6 @@ io_handler_thread(
the aio array */
{
ulint segment;
- ulint i;
segment = *((ulint*)arg);
@@ -490,16 +478,10 @@ io_handler_thread(
pfs_register_thread(io_handler_thread_key);
#endif /* UNIV_PFS_THREAD */
- for (i = 0;; i++) {
+ while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
fil_aio_wait(segment);
-
- mutex_enter(&ios_mutex);
- ios++;
- mutex_exit(&ios_mutex);
}
- thr_local_free(os_thread_get_curr_id());
-
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit.
The thread actually never comes here because it is exited in an
@@ -1001,10 +983,6 @@ skip_size_check:
srv_data_file_is_raw_partition[i] != 0);
}
- ios = 0;
-
- mutex_create(ios_mutex_key, &ios_mutex, SYNC_NO_ORDER_CHECK);
-
return(DB_SUCCESS);
}
@@ -1047,26 +1025,35 @@ innobase_start_or_create_for_mysql(void)
on Mac OS X 10.3 or later. */
struct utsname utsname;
if (uname(&utsname)) {
- fputs("InnoDB: cannot determine Mac OS X version!\n", stderr);
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: cannot determine Mac OS X version!\n", stderr);
} else {
srv_have_fullfsync = strcmp(utsname.release, "7.") >= 0;
}
if (!srv_have_fullfsync) {
- fputs("InnoDB: On Mac OS X, fsync() may be"
- " broken on internal drives,\n"
- "InnoDB: making transactions unsafe!\n", stderr);
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: On Mac OS X, fsync() may be "
+ "broken on internal drives,\n", stderr);
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: making transactions unsafe!\n", stderr);
}
# endif /* F_FULLFSYNC */
#endif /* HAVE_DARWIN_THREADS */
if (sizeof(ulint) != sizeof(void*)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: size of InnoDB's ulint is %lu, "
+ "but size of void*\n", (ulong) sizeof(ulint));
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: is %lu. The sizes should be the same "
+ "so that on a 64-bit\n",
+ (ulong) sizeof(void*));
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Error: size of InnoDB's ulint is %lu,"
- " but size of void* is %lu.\n"
- "InnoDB: The sizes should be the same"
- " so that on a 64-bit platform you can\n"
- "InnoDB: allocate more than 4 GB of memory.",
- (ulong)sizeof(ulint), (ulong)sizeof(void*));
+ " InnoDB: platforms you can allocate more than 4 GB "
+ "of memory.\n");
}
/* System tables are created in tablespace 0. Thus, we must
@@ -1075,53 +1062,74 @@ innobase_start_or_create_for_mysql(void)
innodb_file_per_table) until this function has returned. */
srv_file_per_table = FALSE;
#ifdef UNIV_DEBUG
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: !!!!!!!! UNIV_DEBUG switched on !!!!!!!!!\n");
+ " InnoDB: !!!!!!!! UNIV_DEBUG switched on !!!!!!!!!\n");
#endif
#ifdef UNIV_IBUF_DEBUG
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: !!!!!!!! UNIV_IBUF_DEBUG switched on !!!!!!!!!\n"
+ " InnoDB: !!!!!!!! UNIV_IBUF_DEBUG switched on !!!!!!!!!\n");
# ifdef UNIV_IBUF_COUNT_DEBUG
- "InnoDB: !!!!!!!! UNIV_IBUF_COUNT_DEBUG switched on !!!!!!!!!\n"
- "InnoDB: Crash recovery will fail with UNIV_IBUF_COUNT_DEBUG\n"
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: !!!!!!!! UNIV_IBUF_COUNT_DEBUG switched on "
+ "!!!!!!!!!\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Crash recovery will fail with UNIV_IBUF_COUNT_DEBUG\n");
# endif
- );
#endif
+#ifdef UNIV_BLOB_DEBUG
+ fprintf(stderr,
+ "InnoDB: !!!!!!!! UNIV_BLOB_DEBUG switched on !!!!!!!!!\n"
+ "InnoDB: Server restart may fail with UNIV_BLOB_DEBUG\n");
+#endif /* UNIV_BLOB_DEBUG */
+
#ifdef UNIV_SYNC_DEBUG
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!\n");
+ " InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!\n");
#endif
#ifdef UNIV_SEARCH_DEBUG
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: !!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!\n");
+ " InnoDB: !!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!\n");
#endif
#ifdef UNIV_LOG_LSN_DEBUG
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: !!!!!!!! UNIV_LOG_LSN_DEBUG switched on !!!!!!!!!\n");
+ " InnoDB: !!!!!!!! UNIV_LOG_LSN_DEBUG switched on !!!!!!!!!\n");
#endif /* UNIV_LOG_LSN_DEBUG */
#ifdef UNIV_MEM_DEBUG
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!\n");
+ " InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!\n");
#endif
if (UNIV_LIKELY(srv_use_sys_malloc)) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: The InnoDB memory heap is disabled\n");
+ " InnoDB: The InnoDB memory heap is disabled\n");
}
- fputs("InnoDB: " IB_ATOMICS_STARTUP_MSG
- "\nInnoDB: Compressed tables use zlib " ZLIB_VERSION
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: " IB_ATOMICS_STARTUP_MSG "\n", stderr);
+
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Compressed tables use zlib " ZLIB_VERSION
#ifdef UNIV_ZIP_DEBUG
" with validation"
#endif /* UNIV_ZIP_DEBUG */
+ "\n" , stderr);
#ifdef UNIV_ZIP_COPY
- " and extra copying"
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: and extra copying\n", stderr);
#endif /* UNIV_ZIP_COPY */
- "\n" , stderr);
/* Since InnoDB does not currently clean up all its internal data
structures in MySQL Embedded Server Library server_end(), we
@@ -1129,13 +1137,17 @@ innobase_start_or_create_for_mysql(void)
second time during the process lifetime. */
if (srv_start_has_been_called) {
- fprintf(stderr,
- "InnoDB: Error: startup called second time"
- " during the process lifetime.\n"
- "InnoDB: In the MySQL Embedded Server Library"
- " you cannot call server_init()\n"
- "InnoDB: more than once during"
- " the process lifetime.\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error: startup called second time "
+ "during the process\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: lifetime. In the MySQL Embedded "
+ "Server Library you\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: cannot call server_init() more "
+ "than once during the\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: process lifetime.\n");
}
srv_start_has_been_called = TRUE;
@@ -1179,7 +1191,7 @@ innobase_start_or_create_for_mysql(void)
if (srv_use_native_aio) {
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: Using Linux native AIO\n");
+ " InnoDB: Using Linux native AIO\n");
}
#else
/* Currently native AIO is supported only on windows and linux
@@ -1224,8 +1236,9 @@ innobase_start_or_create_for_mysql(void)
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
#endif
} else {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Unrecognized value %s for"
+ " InnoDB: Unrecognized value %s for"
" innodb_flush_method\n",
srv_file_flush_method_str);
return(DB_ERROR);
@@ -1306,7 +1319,8 @@ innobase_start_or_create_for_mysql(void)
we'll emit a message telling the user that this parameter
is now deprecated. */
if (srv_n_file_io_threads != 4) {
- fprintf(stderr, "InnoDB: Warning:"
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Warning:"
" innodb_file_io_threads is deprecated."
" Please use innodb_read_io_threads and"
" innodb_write_io_threads instead\n");
@@ -1318,13 +1332,16 @@ innobase_start_or_create_for_mysql(void)
ut_a(srv_n_file_io_threads <= SRV_MAX_N_IO_THREADS);
- /* TODO: Investigate if SRV_N_PENDING_IOS_PER_THREAD (32) limit
- still applies to windows. */
- if (!srv_use_native_aio) {
- io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD;
- } else {
+ io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD;
+
+ /* On Windows when using native aio the number of aio requests
+ that a thread can handle at a given time is limited to 32
+ i.e.: SRV_N_PENDING_IOS_PER_THREAD */
+# ifdef __WIN__
+ if (srv_use_native_aio) {
io_limit = SRV_N_PENDING_IOS_PER_THREAD;
}
+# endif /* __WIN__ */
os_aio_init(io_limit,
srv_n_read_io_threads,
@@ -1334,11 +1351,31 @@ 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));
+ }
+
err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Completed initialization of buffer pool\n");
+
if (err != DB_SUCCESS) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Fatal error: cannot allocate the memory"
+ " InnoDB: Fatal error: cannot allocate memory"
" for the buffer pool\n");
return(DB_ERROR);
@@ -1350,7 +1387,8 @@ innobase_start_or_create_for_mysql(void)
if (srv_buf_pool_size <= 5 * 1024 * 1024) {
- fprintf(stderr, "InnoDB: Warning: Small buffer pool size "
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Warning: Small buffer pool size "
"(%luM), the flst_validate() debug function "
"can cause a deadlock if the buffer pool fills up.\n",
srv_buf_pool_size / 1024 / 1024);
@@ -1372,18 +1410,19 @@ innobase_start_or_create_for_mysql(void)
#ifdef UNIV_LOG_ARCHIVE
if (0 != ut_strcmp(srv_log_group_home_dirs[0], srv_arch_dir)) {
- fprintf(stderr,
- "InnoDB: Error: you must set the log group"
- " home dir in my.cnf the\n"
- "InnoDB: same as log arch dir.\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error: you must set the log group home dir in my.cnf\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: the same as log arch dir.\n");
return(DB_ERROR);
}
#endif /* UNIV_LOG_ARCHIVE */
if (srv_n_log_files * srv_log_file_size >= 262144) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Error: combined size of log files"
+ " InnoDB: Error: combined size of log files"
" must be < 4 GB\n");
return(DB_ERROR);
@@ -1394,10 +1433,13 @@ innobase_start_or_create_for_mysql(void)
for (i = 0; i < srv_n_data_files; i++) {
#ifndef __WIN__
if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= 262144) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: file size must be < 4 GB"
+ " with this MySQL binary\n");
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Error: file size must be < 4 GB"
- " with this MySQL binary\n"
- "InnoDB: and operating system combination,"
+ " InnoDB: and operating system combination,"
" in some OS's < 2 GB\n");
return(DB_ERROR);
@@ -1407,8 +1449,9 @@ innobase_start_or_create_for_mysql(void)
}
if (sum_of_new_sizes < 10485760 / UNIV_PAGE_SIZE) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Error: tablespace size must be"
+ " InnoDB: Error: tablespace size must be"
" at least 10 MB\n");
return(DB_ERROR);
@@ -1421,19 +1464,32 @@ innobase_start_or_create_for_mysql(void)
&min_flushed_lsn, &max_flushed_lsn,
&sum_of_new_sizes);
if (err != DB_SUCCESS) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Could not open or create data files.\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: If you tried to add new data files,"
+ " and it failed here,\n");
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Could not open or create data files.\n"
- "InnoDB: If you tried to add new data files,"
- " and it failed here,\n"
- "InnoDB: you should now edit innodb_data_file_path"
- " in my.cnf back\n"
- "InnoDB: to what it was, and remove the"
- " new ibdata files InnoDB created\n"
- "InnoDB: in this failed attempt. InnoDB only wrote"
- " those files full of\n"
- "InnoDB: zeros, but did not yet use them in any way."
- " But be careful: do not\n"
- "InnoDB: remove old data files"
+ " InnoDB: you should now edit innodb_data_file_path"
+ " in my.cnf back\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: to what it was, and remove the"
+ " new ibdata files InnoDB created\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: in this failed attempt. InnoDB only wrote"
+ " those files full of\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: zeros, but did not yet use them in any way."
+ " But be careful: do not\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: remove old data files"
" which contain your precious data!\n");
return((int) err);
@@ -1459,18 +1515,29 @@ innobase_start_or_create_for_mysql(void)
}
if ((log_opened && create_new_db)
|| (log_opened && log_created)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: all log files must be"
+ " created at the same time.\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: All log files must be"
+ " created also in database creation.\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: If you want bigger or smaller"
+ " log files, shut down the\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: database and make sure there"
+ " were no errors in shutdown.\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Then delete the existing log files."
+ " Edit the .cnf file\n");
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Error: all log files must be"
- " created at the same time.\n"
- "InnoDB: All log files must be"
- " created also in database creation.\n"
- "InnoDB: If you want bigger or smaller"
- " log files, shut down the\n"
- "InnoDB: database and make sure there"
- " were no errors in shutdown.\n"
- "InnoDB: Then delete the existing log files."
- " Edit the .cnf file\n"
- "InnoDB: and start the database again.\n");
+ " InnoDB: and start the database again.\n");
return(DB_ERROR);
}
@@ -1491,27 +1558,41 @@ innobase_start_or_create_for_mysql(void)
|| max_arch_log_no != min_arch_log_no
#endif /* UNIV_LOG_ARCHIVE */
) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Cannot initialize created"
+ " log files because\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: data files were not in sync"
+ " with each other\n");
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Cannot initialize created"
- " log files because\n"
- "InnoDB: data files were not in sync"
- " with each other\n"
- "InnoDB: or the data files are corrupt.\n");
+ " InnoDB: or the data files are corrupt.\n");
return(DB_ERROR);
}
if (max_flushed_lsn < (ib_uint64_t) 1000) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Cannot initialize created"
+ " log files because\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: data files are corrupt,"
+ " or new data files were\n");
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Cannot initialize created"
- " log files because\n"
- "InnoDB: data files are corrupt,"
- " or new data files were\n"
- "InnoDB: created when the database"
- " was started previous\n"
- "InnoDB: time but the database"
- " was not shut down\n"
- "InnoDB: normally after that.\n");
+ " InnoDB: created when the database"
+ " was started previous\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: time but the database"
+ " was not shut down\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: normally after that.\n");
return(DB_ERROR);
}
@@ -1550,8 +1631,9 @@ innobase_start_or_create_for_mysql(void)
#ifdef UNIV_LOG_ARCHIVE
} else if (srv_archive_recovery) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Starting archive"
+ " InnoDB: Starting archive"
" recovery from a backup...\n");
err = recv_recovery_from_archive_start(
min_flushed_lsn, srv_archive_recovery_limit_lsn,
@@ -1759,6 +1841,24 @@ innobase_start_or_create_for_mysql(void)
os_thread_create(&srv_purge_thread, NULL, NULL);
}
+ /* Wait for the purge and master thread to startup. */
+
+ while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
+ if (srv_thread_has_reserved_slot(SRV_MASTER) == ULINT_UNDEFINED
+ || (srv_n_purge_threads == 1
+ && srv_thread_has_reserved_slot(SRV_WORKER)
+ == ULINT_UNDEFINED)) {
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: "
+ "Waiting for the background threads to "
+ "start\n");
+ os_thread_sleep(1000000);
+ } else {
+ break;
+ }
+ }
+
#ifdef UNIV_DEBUG
/* buf_debug_prints = TRUE; */
#endif /* UNIV_DEBUG */
@@ -1773,11 +1873,14 @@ innobase_start_or_create_for_mysql(void)
if (!srv_auto_extend_last_data_file
&& sum_of_data_file_sizes != tablespace_size_in_header) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: tablespace size"
+ " stored in header is %lu pages, but\n",
+ (ulong) tablespace_size_in_header);
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Error: tablespace size"
- " stored in header is %lu pages, but\n"
"InnoDB: the sum of data file sizes is %lu pages\n",
- (ulong) tablespace_size_in_header,
(ulong) sum_of_data_file_sizes);
if (srv_force_recovery == 0
@@ -1785,16 +1888,25 @@ innobase_start_or_create_for_mysql(void)
/* This is a fatal error, the tail of a tablespace is
missing */
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Cannot start InnoDB."
- " The tail of the system tablespace is\n"
- "InnoDB: missing. Have you edited"
- " innodb_data_file_path in my.cnf in an\n"
- "InnoDB: inappropriate way, removing"
- " ibdata files from there?\n"
- "InnoDB: You can set innodb_force_recovery=1"
- " in my.cnf to force\n"
- "InnoDB: a startup if you are trying"
+ " InnoDB: Cannot start InnoDB."
+ " The tail of the system tablespace is\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: missing. Have you edited"
+ " innodb_data_file_path in my.cnf in an\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: inappropriate way, removing"
+ " ibdata files from there?\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: You can set innodb_force_recovery=1"
+ " in my.cnf to force\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: a startup if you are trying"
" to recover a badly corrupt database.\n");
return(DB_ERROR);
@@ -1804,26 +1916,38 @@ innobase_start_or_create_for_mysql(void)
if (srv_auto_extend_last_data_file
&& sum_of_data_file_sizes < tablespace_size_in_header) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Error: tablespace size stored in header"
- " is %lu pages, but\n"
- "InnoDB: the sum of data file sizes"
+ " InnoDB: Error: tablespace size stored in header"
+ " is %lu pages, but\n",
+ (ulong) tablespace_size_in_header);
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: the sum of data file sizes"
" is only %lu pages\n",
- (ulong) tablespace_size_in_header,
(ulong) sum_of_data_file_sizes);
if (srv_force_recovery == 0) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Cannot start InnoDB. The tail of"
+ " the system tablespace is\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: missing. Have you edited"
+ " innodb_data_file_path in my.cnf in an\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: inappropriate way, removing"
+ " ibdata files from there?\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: You can set innodb_force_recovery=1"
+ " in my.cnf to force\n");
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Cannot start InnoDB. The tail of"
- " the system tablespace is\n"
- "InnoDB: missing. Have you edited"
- " innodb_data_file_path in my.cnf in an\n"
- "InnoDB: inappropriate way, removing"
- " ibdata files from there?\n"
- "InnoDB: You can set innodb_force_recovery=1"
- " in my.cnf to force\n"
- "InnoDB: a startup if you are trying to"
+ " InnoDB: a startup if you are trying to"
" recover a badly corrupt database.\n");
return(DB_ERROR);
@@ -1834,10 +1958,13 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_init(&srv_os_test_mutex);
if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: pthread_mutex_trylock returns"
+ " an unexpected value on\n");
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Error: pthread_mutex_trylock returns"
- " an unexpected value on\n"
- "InnoDB: success! Cannot continue.\n");
+ " InnoDB: success! Cannot continue.\n");
exit(1);
}
@@ -1852,14 +1979,15 @@ innobase_start_or_create_for_mysql(void)
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB %s started; "
+ " InnoDB: %s started; "
"log sequence number %llu\n",
INNODB_VERSION_STR, srv_start_lsn);
}
if (srv_force_recovery > 0) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: !!! innodb_force_recovery"
+ " InnoDB: !!! innodb_force_recovery"
" is set to %lu !!!\n",
(ulong) srv_force_recovery);
}
@@ -1880,12 +2008,17 @@ innobase_start_or_create_for_mysql(void)
4.1.1. It is essential that the insert buffer is emptied
here! */
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: You are upgrading to an"
+ " InnoDB version which allows multiple\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: tablespaces. Wait that purge"
+ " and insert buffer merge run to\n");
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: You are upgrading to an"
- " InnoDB version which allows multiple\n"
- "InnoDB: tablespaces. Wait that purge"
- " and insert buffer merge run to\n"
- "InnoDB: completion...\n");
+ " InnoDB: completion...\n");
for (;;) {
os_thread_sleep(1000000);
@@ -1897,21 +2030,29 @@ innobase_start_or_create_for_mysql(void)
break;
}
}
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Full purge and insert buffer merge"
+ " InnoDB: Full purge and insert buffer merge"
" completed.\n");
trx_sys_mark_upgraded_to_multiple_tablespaces();
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: You have now successfully upgraded"
- " to the multiple tablespaces\n"
- "InnoDB: format. You should NOT DOWNGRADE"
- " to an earlier version of\n"
- "InnoDB: InnoDB! But if you absolutely need to"
- " downgrade, see\n"
- "InnoDB: " REFMAN "multiple-tablespaces.html\n"
- "InnoDB: for instructions.\n");
+ " InnoDB: You have now successfully upgraded"
+ " to the multiple tablespaces\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: format. You should NOT DOWNGRADE"
+ " to an earlier version of\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: InnoDB! But if you absolutely need to"
+ " downgrade, see\n");
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: " REFMAN "multiple-tablespaces.html\n"
+ " InnoDB: for instructions.\n");
}
if (srv_force_recovery == 0) {
@@ -1956,17 +2097,6 @@ innobase_shutdown_for_mysql(void)
The step 1 is the real InnoDB shutdown. The remaining steps 2 - ...
just free data structures after the shutdown. */
-
- if (srv_fast_shutdown == 2) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: MySQL has requested a very fast shutdown"
- " without flushing "
- "the InnoDB buffer pool to data files."
- " At the next mysqld startup "
- "InnoDB will do a crash recovery!\n");
- }
-
logs_empty_and_mark_files_at_shutdown();
if (srv_conc_n_threads != 0) {
@@ -1981,17 +2111,9 @@ innobase_shutdown_for_mysql(void)
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
- /* In a 'very fast' shutdown, we do not need to wait for these threads
- to die; all which counts is that we flushed the log; a 'very fast'
- shutdown is essentially a crash. */
-
- if (srv_fast_shutdown == 2) {
- return(DB_SUCCESS);
- }
-
/* All threads end up waiting for certain events. Put those events
- to the signaled state. Then the threads will exit themselves in
- os_thread_event_wait(). */
+ to the signaled state. Then the threads will exit themselves after
+ os_event_wait(). */
for (i = 0; i < 1000; i++) {
/* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
@@ -2068,7 +2190,6 @@ innobase_shutdown_for_mysql(void)
ibuf_close();
log_shutdown();
lock_sys_close();
- thr_local_close();
trx_sys_file_format_close();
trx_sys_close();
diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c
index 753ebd958ac..30caddccced 100644
--- a/storage/innobase/sync/sync0arr.c
+++ b/storage/innobase/sync/sync0arr.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -40,6 +40,7 @@ Created 9/5/1995 Heikki Tuuri
#include "os0sync.h"
#include "os0file.h"
#include "srv0srv.h"
+#include "ha_prototypes.h"
/*
WAIT ARRAY
@@ -478,8 +479,8 @@ sync_array_cell_print(
fprintf(file,
"--Thread %lu has waited at %s line %lu"
" for %.2f seconds the semaphore:\n",
- (ulong) os_thread_pf(cell->thread), cell->file,
- (ulong) cell->line,
+ (ulong) os_thread_pf(cell->thread),
+ innobase_basename(cell->file), (ulong) cell->line,
difftime(time(NULL), cell->reservation_time));
if (type == SYNC_MUTEX) {
@@ -493,7 +494,8 @@ sync_array_cell_print(
"Last time reserved in file %s line %lu, "
#endif /* UNIV_SYNC_DEBUG */
"waiters flag %lu\n",
- (void*) mutex, mutex->cfile_name, (ulong) mutex->cline,
+ (void*) mutex, innobase_basename(mutex->cfile_name),
+ (ulong) mutex->cline,
(ulong) mutex->lock_word,
#ifdef UNIV_SYNC_DEBUG
mutex->file_name, (ulong) mutex->line,
@@ -512,7 +514,7 @@ sync_array_cell_print(
fprintf(file,
" RW-latch at %p created in file %s line %lu\n",
- (void*) rwlock, rwlock->cfile_name,
+ (void*) rwlock, innobase_basename(rwlock->cfile_name),
(ulong) rwlock->cline);
writer = rw_lock_get_writer(rwlock);
if (writer != RW_LOCK_NOT_LOCKED) {
@@ -533,7 +535,7 @@ sync_array_cell_print(
(ulong) rw_lock_get_reader_count(rwlock),
(ulong) rwlock->waiters,
rwlock->lock_word,
- rwlock->last_s_file_name,
+ innobase_basename(rwlock->last_s_file_name),
(ulong) rwlock->last_s_line,
rwlock->last_x_file_name,
(ulong) rwlock->last_x_line);
@@ -590,9 +592,6 @@ sync_array_deadlock_step(
ulint depth) /*!< in: recursion depth */
{
sync_cell_t* new;
- ibool ret;
-
- depth++;
if (pass != 0) {
/* If pass != 0, then we do not know which threads are
@@ -604,7 +603,7 @@ sync_array_deadlock_step(
new = sync_array_find_thread(arr, thread);
- if (new == start) {
+ if (UNIV_UNLIKELY(new == start)) {
/* Stop running of other threads */
ut_dbg_stop_threads = TRUE;
@@ -616,11 +615,7 @@ sync_array_deadlock_step(
return(TRUE);
} else if (new) {
- ret = sync_array_detect_deadlock(arr, start, new, depth);
-
- if (ret) {
- return(TRUE);
- }
+ return(sync_array_detect_deadlock(arr, start, new, depth + 1));
}
return(FALSE);
}
@@ -721,7 +716,7 @@ print:
fprintf(stderr, "rw-lock %p ",
(void*) lock);
sync_array_cell_print(stderr, cell);
- rw_lock_debug_print(debug);
+ rw_lock_debug_print(stderr, debug);
return(TRUE);
}
}
@@ -920,8 +915,10 @@ Prints warnings of long semaphore waits to stderr.
@return TRUE if fatal semaphore wait threshold was exceeded */
UNIV_INTERN
ibool
-sync_array_print_long_waits(void)
-/*=============================*/
+sync_array_print_long_waits(
+/*========================*/
+ os_thread_id_t* waiter, /*!< out: longest waiting thread */
+ const void** sema) /*!< out: longest-waited-for semaphore */
{
sync_cell_t* cell;
ibool old_val;
@@ -929,24 +926,52 @@ sync_array_print_long_waits(void)
ulint i;
ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
ibool fatal = FALSE;
+ double longest_diff = 0;
+
+#ifdef UNIV_DEBUG_VALGRIND
+ /* Increase the timeouts if running under valgrind because it executes
+ extremely slowly. UNIV_DEBUG_VALGRIND does not necessary mean that
+ we are running under valgrind but we have no better way to tell.
+ See Bug#58432 innodb.innodb_bug56143 fails under valgrind
+ for an example */
+# define SYNC_ARRAY_TIMEOUT 2400
+ fatal_timeout *= 10;
+#else
+# define SYNC_ARRAY_TIMEOUT 240
+#endif
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
+ double diff;
+ void* wait_object;
+
cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
- if (cell->wait_object != NULL && cell->waiting
- && difftime(time(NULL), cell->reservation_time) > 240) {
+ wait_object = cell->wait_object;
+
+ if (wait_object == NULL || !cell->waiting) {
+
+ continue;
+ }
+
+ diff = difftime(time(NULL), cell->reservation_time);
+
+ if (diff > SYNC_ARRAY_TIMEOUT) {
fputs("InnoDB: Warning: a long semaphore wait:\n",
stderr);
sync_array_cell_print(stderr, cell);
noticed = TRUE;
}
- if (cell->wait_object != NULL && cell->waiting
- && difftime(time(NULL), cell->reservation_time)
- > fatal_timeout) {
+ if (diff > fatal_timeout) {
fatal = TRUE;
}
+
+ if (diff > longest_diff) {
+ longest_diff = diff;
+ *sema = wait_object;
+ *waiter = cell->thread;
+ }
}
if (noticed) {
@@ -977,6 +1002,8 @@ sync_array_print_long_waits(void)
" to the standard error stream\n");
}
+#undef SYNC_ARRAY_TIMEOUT
+
return(fatal);
}
diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c
index 4dbaaa97bd9..397d505df50 100644
--- a/storage/innobase/sync/sync0rw.c
+++ b/storage/innobase/sync/sync0rw.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -39,6 +39,7 @@ Created 9/11/1995 Heikki Tuuri
#include "mem0mem.h"
#include "srv0srv.h"
#include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
+#include "ha_prototypes.h"
/*
IMPLEMENTATION OF THE RW_LOCK
@@ -271,6 +272,9 @@ rw_lock_create_func(
contains garbage at initialization and cannot be used for
recursive x-locking. */
lock->recursive = FALSE;
+ /* Silence Valgrind when UNIV_DEBUG_VALGRIND is not enabled. */
+ memset((void*) &lock->writer_thread, 0, sizeof lock->writer_thread);
+ UNIV_MEM_INVALID(&lock->writer_thread, sizeof lock->writer_thread);
#ifdef UNIV_SYNC_DEBUG
UT_LIST_INIT(lock->debug_list);
@@ -404,7 +408,8 @@ lock_loop:
" cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()),
(void*) lock,
- lock->cfile_name, (ulong) lock->cline, (ulong) i);
+ innobase_basename(lock->cfile_name),
+ (ulong) lock->cline, (ulong) i);
}
/* We try once again to obtain the lock */
@@ -439,7 +444,8 @@ lock_loop:
"Thread %lu OS wait rw-s-lock at %p"
" cfile %s cline %lu\n",
os_thread_pf(os_thread_get_curr_id()),
- (void*) lock, lock->cfile_name,
+ (void*) lock,
+ innobase_basename(lock->cfile_name),
(ulong) lock->cline);
}
@@ -661,7 +667,8 @@ lock_loop:
"Thread %lu spin wait rw-x-lock at %p"
" cfile %s cline %lu rnds %lu\n",
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
- lock->cfile_name, (ulong) lock->cline, (ulong) i);
+ innobase_basename(lock->cfile_name),
+ (ulong) lock->cline, (ulong) i);
}
sync_array_reserve_cell(sync_primary_wait_array,
@@ -684,7 +691,8 @@ lock_loop:
"Thread %lu OS wait for rw-x-lock at %p"
" cfile %s cline %lu\n",
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
- lock->cfile_name, (ulong) lock->cline);
+ innobase_basename(lock->cfile_name),
+ (ulong) lock->cline);
}
/* these stats may not be accurate */
@@ -936,7 +944,7 @@ rw_lock_list_print_info(
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
- rw_lock_debug_print(info);
+ rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
}
@@ -984,7 +992,7 @@ rw_lock_print(
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
- rw_lock_debug_print(info);
+ rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
}
@@ -996,28 +1004,29 @@ UNIV_INTERN
void
rw_lock_debug_print(
/*================*/
+ FILE* f, /*!< in: output stream */
rw_lock_debug_t* info) /*!< in: debug struct */
{
ulint rwt;
rwt = info->lock_type;
- fprintf(stderr, "Locked: thread %ld file %s line %ld ",
+ fprintf(f, "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) {
- fputs("S-LOCK", stderr);
+ fputs("S-LOCK", f);
} else if (rwt == RW_LOCK_EX) {
- fputs("X-LOCK", stderr);
+ fputs("X-LOCK", f);
} else if (rwt == RW_LOCK_WAIT_EX) {
- fputs("WAIT X-LOCK", stderr);
+ fputs("WAIT X-LOCK", f);
} else {
ut_error;
}
if (info->pass != 0) {
- fprintf(stderr, " pass value %lu", (ulong) info->pass);
+ fprintf(f, " pass value %lu", (ulong) info->pass);
}
- putc('\n', stderr);
+ putc('\n', f);
}
/***************************************************************//**
diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c
index 8062d9e902e..0b56e736209 100644
--- a/storage/innobase/sync/sync0sync.c
+++ b/storage/innobase/sync/sync0sync.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -43,6 +43,7 @@ Created 9/5/1995 Heikki Tuuri
#ifdef UNIV_SYNC_DEBUG
# include "srv0start.h" /* srv_is_being_started */
#endif /* UNIV_SYNC_DEBUG */
+#include "ha_prototypes.h"
/*
REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
@@ -188,12 +189,12 @@ UNIV_INTERN sync_array_t* sync_primary_wait_array;
/** This variable is set to TRUE when sync_init is called */
UNIV_INTERN ibool sync_initialized = FALSE;
+#ifdef UNIV_SYNC_DEBUG
/** An acquired mutex or rw-lock and its level in the latching order */
typedef struct sync_level_struct sync_level_t;
/** Mutexes or rw-locks held by a thread */
typedef struct sync_thread_struct sync_thread_t;
-#ifdef UNIV_SYNC_DEBUG
/** The latch levels currently owned by threads are stored in this data
structure; the size of this array is OS_THREAD_MAX_N */
@@ -220,24 +221,43 @@ UNIV_INTERN mysql_pfs_key_t mutex_list_mutex_key;
#ifdef UNIV_SYNC_DEBUG
/** Latching order checks start when this is set TRUE */
UNIV_INTERN ibool sync_order_checks_on = FALSE;
-#endif /* UNIV_SYNC_DEBUG */
+
+/** Number of slots reserved for each OS thread in the sync level array */
+static const ulint SYNC_THREAD_N_LEVELS = 10000;
+
+typedef struct sync_arr_struct sync_arr_t;
+
+/** Array for tracking sync levels per thread. */
+struct sync_arr_struct {
+ ulint in_use; /*!< Number of active cells */
+ ulint n_elems; /*!< Number of elements in the array */
+ ulint max_elems; /*!< Maximum elements */
+ ulint next_free; /*!< ULINT_UNDEFINED or index of next
+ free slot */
+ sync_level_t* elems; /*!< Array elements */
+};
/** Mutexes or rw-locks held by a thread */
struct sync_thread_struct{
- os_thread_id_t id; /*!< OS thread id */
- sync_level_t* levels; /*!< level array for this thread; if
- this is NULL this slot is unused */
+ os_thread_id_t id; /*!< OS thread id */
+ sync_arr_t* levels; /*!< level array for this thread; if
+ this is NULL this slot is unused */
};
-/** Number of slots reserved for each OS thread in the sync level array */
-#define SYNC_THREAD_N_LEVELS 10000
-
/** An acquired mutex or rw-lock and its level in the latching order */
struct sync_level_struct{
- void* latch; /*!< pointer to a mutex or an rw-lock; NULL means that
- the slot is empty */
- ulint level; /*!< level of the latch in the latching order */
+ void* latch; /*!< pointer to a mutex or an
+ rw-lock; NULL means that
+ the slot is empty */
+ ulint level; /*!< level of the latch in the
+ latching order. This field is
+ overloaded to serve as a node in a
+ linked list of free nodes too. When
+ latch == NULL then this will contain
+ the ordinal value of the next free
+ element */
};
+#endif /* UNIV_SYNC_DEBUG */
/******************************************************************//**
Creates, or rather, initializes a mutex object in a specified memory
@@ -524,7 +544,8 @@ spin_loop:
"Thread %lu spin wait mutex at %p"
" cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
- mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
+ innobase_basename(mutex->cfile_name),
+ (ulong) mutex->cline, (ulong) i);
#endif
mutex_spin_round_count += i;
@@ -601,7 +622,8 @@ spin_loop:
fprintf(stderr,
"Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
- mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
+ innobase_basename(mutex->cfile_name),
+ (ulong) mutex->cline, (ulong) i);
#endif
mutex_os_wait_count++;
@@ -745,27 +767,28 @@ mutex_n_reserved(void)
/*==================*/
{
mutex_t* mutex;
- ulint count = 0;
+ ulint count = 0;
mutex_enter(&mutex_list_mutex);
- mutex = UT_LIST_GET_FIRST(mutex_list);
+ for (mutex = UT_LIST_GET_FIRST(mutex_list);
+ mutex != NULL;
+ mutex = UT_LIST_GET_NEXT(list, mutex)) {
- while (mutex != NULL) {
if (mutex_get_lock_word(mutex) != 0) {
count++;
}
-
- mutex = UT_LIST_GET_NEXT(list, mutex);
}
mutex_exit(&mutex_list_mutex);
ut_a(count >= 1);
- return(count - 1); /* Subtract one, because this function itself
- was holding one mutex (mutex_list_mutex) */
+ /* Subtract one, because this function itself was holding
+ one mutex (mutex_list_mutex) */
+
+ return(count - 1);
}
/******************************************************************//**
@@ -781,20 +804,6 @@ sync_all_freed(void)
}
/******************************************************************//**
-Gets the value in the nth slot in the thread level arrays.
-@return pointer to thread slot */
-static
-sync_thread_t*
-sync_thread_level_arrays_get_nth(
-/*=============================*/
- ulint n) /*!< in: slot number */
-{
- ut_ad(n < OS_THREAD_MAX_N);
-
- return(sync_thread_level_arrays + n);
-}
-
-/******************************************************************//**
Looks for the thread slot for the calling thread.
@return pointer to thread slot, NULL if not found */
static
@@ -803,15 +812,15 @@ sync_thread_level_arrays_find_slot(void)
/*====================================*/
{
- sync_thread_t* slot;
- os_thread_id_t id;
ulint i;
+ os_thread_id_t id;
id = os_thread_get_curr_id();
for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ sync_thread_t* slot;
- slot = sync_thread_level_arrays_get_nth(i);
+ slot = &sync_thread_level_arrays[i];
if (slot->levels && os_thread_eq(slot->id, id)) {
@@ -831,12 +840,12 @@ sync_thread_level_arrays_find_free(void)
/*====================================*/
{
- sync_thread_t* slot;
ulint i;
for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ sync_thread_t* slot;
- slot = sync_thread_level_arrays_get_nth(i);
+ slot = &sync_thread_level_arrays[i];
if (slot->levels == NULL) {
@@ -848,19 +857,45 @@ sync_thread_level_arrays_find_free(void)
}
/******************************************************************//**
-Gets the value in the nth slot in the thread level array.
-@return pointer to level slot */
+Print warning. */
static
-sync_level_t*
-sync_thread_levels_get_nth(
-/*=======================*/
- sync_level_t* arr, /*!< in: pointer to level array for an OS
- thread */
- ulint n) /*!< in: slot number */
+void
+sync_print_warning(
+/*===============*/
+ const sync_level_t* slot) /*!< in: slot for which to
+ print warning */
{
- ut_ad(n < SYNC_THREAD_N_LEVELS);
+ mutex_t* mutex;
+
+ mutex = slot->latch;
- return(arr + n);
+ if (mutex->magic_n == MUTEX_MAGIC_N) {
+ fprintf(stderr,
+ "Mutex created at %s %lu\n",
+ innobase_basename(mutex->cfile_name),
+ (ulong) mutex->cline);
+
+ if (mutex_get_lock_word(mutex) != 0) {
+ ulint line;
+ const char* file_name;
+ os_thread_id_t thread_id;
+
+ mutex_get_debug_info(
+ mutex, &file_name, &line, &thread_id);
+
+ fprintf(stderr,
+ "InnoDB: Locked mutex:"
+ " addr %p thread %ld file %s line %ld\n",
+ (void*) mutex, os_thread_pf(thread_id),
+ file_name, (ulong) line);
+ } else {
+ fputs("Not locked\n", stderr);
+ }
+ } else {
+ rw_lock_t* lock = slot->latch;
+
+ rw_lock_print(lock);
+ }
}
/******************************************************************//**
@@ -871,69 +906,29 @@ static
ibool
sync_thread_levels_g(
/*=================*/
- sync_level_t* arr, /*!< in: pointer to level array for an OS
+ sync_arr_t* arr, /*!< in: pointer to level array for an OS
thread */
ulint limit, /*!< in: level limit */
ulint warn) /*!< in: TRUE=display a diagnostic message */
{
- sync_level_t* slot;
- rw_lock_t* lock;
- mutex_t* mutex;
ulint i;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
-
- slot = sync_thread_levels_get_nth(arr, i);
-
- if (slot->latch != NULL) {
- if (slot->level <= limit) {
-
- if (!warn) {
+ for (i = 0; i < arr->n_elems; i++) {
+ const sync_level_t* slot;
- return(FALSE);
- }
-
- lock = slot->latch;
- mutex = slot->latch;
+ slot = &arr->elems[i];
+ if (slot->latch != NULL && slot->level <= limit) {
+ if (warn) {
fprintf(stderr,
"InnoDB: sync levels should be"
" > %lu but a level is %lu\n",
(ulong) limit, (ulong) slot->level);
- if (mutex->magic_n == MUTEX_MAGIC_N) {
- fprintf(stderr,
- "Mutex created at %s %lu\n",
- mutex->cfile_name,
- (ulong) mutex->cline);
-
- if (mutex_get_lock_word(mutex) != 0) {
- const char* file_name;
- ulint line;
- os_thread_id_t thread_id;
-
- mutex_get_debug_info(
- mutex, &file_name,
- &line, &thread_id);
-
- fprintf(stderr,
- "InnoDB: Locked mutex:"
- " addr %p thread %ld"
- " file %s line %ld\n",
- (void*) mutex,
- os_thread_pf(
- thread_id),
- file_name,
- (ulong) line);
- } else {
- fputs("Not locked\n", stderr);
- }
- } else {
- rw_lock_print(lock);
- }
-
- return(FALSE);
+ sync_print_warning(slot);
}
+
+ return(FALSE);
}
}
@@ -942,31 +937,29 @@ sync_thread_levels_g(
/******************************************************************//**
Checks if the level value is stored in the level array.
-@return TRUE if stored */
+@return slot if found or NULL */
static
-ibool
+const sync_level_t*
sync_thread_levels_contain(
/*=======================*/
- sync_level_t* arr, /*!< in: pointer to level array for an OS
+ sync_arr_t* arr, /*!< in: pointer to level array for an OS
thread */
ulint level) /*!< in: level */
{
- sync_level_t* slot;
ulint i;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ for (i = 0; i < arr->n_elems; i++) {
+ const sync_level_t* slot;
- slot = sync_thread_levels_get_nth(arr, i);
+ slot = &arr->elems[i];
- if (slot->latch != NULL) {
- if (slot->level == level) {
+ if (slot->latch != NULL && slot->level == level) {
- return(TRUE);
- }
+ return(slot);
}
}
- return(FALSE);
+ return(NULL);
}
/******************************************************************//**
@@ -980,10 +973,9 @@ sync_thread_levels_contains(
ulint level) /*!< in: latching order level
(SYNC_DICT, ...)*/
{
- sync_level_t* arr;
- sync_thread_t* thread_slot;
- sync_level_t* slot;
ulint i;
+ sync_arr_t* arr;
+ sync_thread_t* thread_slot;
if (!sync_order_checks_on) {
@@ -1003,9 +995,10 @@ sync_thread_levels_contains(
arr = thread_slot->levels;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ for (i = 0; i < arr->n_elems; i++) {
+ sync_level_t* slot;
- slot = sync_thread_levels_get_nth(arr, i);
+ slot = &arr->elems[i];
if (slot->latch != NULL && slot->level == level) {
@@ -1027,14 +1020,11 @@ void*
sync_thread_levels_nonempty_gen(
/*============================*/
ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is
- allowed to be owned by the thread,
- also purge_is_running mutex is
- allowed */
+ allowed to be owned by the thread */
{
- sync_level_t* arr;
- sync_thread_t* thread_slot;
- sync_level_t* slot;
ulint i;
+ sync_arr_t* arr;
+ sync_thread_t* thread_slot;
if (!sync_order_checks_on) {
@@ -1054,9 +1044,10 @@ sync_thread_levels_nonempty_gen(
arr = thread_slot->levels;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ for (i = 0; i < arr->n_elems; ++i) {
+ const sync_level_t* slot;
- slot = sync_thread_levels_get_nth(arr, i);
+ slot = &arr->elems[i];
if (slot->latch != NULL
&& (!dict_mutex_allowed
@@ -1076,14 +1067,61 @@ sync_thread_levels_nonempty_gen(
}
/******************************************************************//**
-Checks that the level array for the current thread is empty.
-@return TRUE if empty */
+Checks if the level array for the current thread is empty,
+except for the btr_search_latch.
+@return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN
-ibool
-sync_thread_levels_empty(void)
-/*==========================*/
+void*
+sync_thread_levels_nonempty_trx(
+/*============================*/
+ ibool has_search_latch)
+ /*!< in: TRUE if and only if the thread
+ is supposed to hold btr_search_latch */
{
- return(sync_thread_levels_empty_gen(FALSE));
+ ulint i;
+ sync_arr_t* arr;
+ sync_thread_t* thread_slot;
+
+ if (!sync_order_checks_on) {
+
+ return(NULL);
+ }
+
+ ut_a(!has_search_latch
+ || sync_thread_levels_contains(SYNC_SEARCH_SYS));
+
+ mutex_enter(&sync_thread_mutex);
+
+ thread_slot = sync_thread_level_arrays_find_slot();
+
+ if (thread_slot == NULL) {
+
+ mutex_exit(&sync_thread_mutex);
+
+ return(NULL);
+ }
+
+ arr = thread_slot->levels;
+
+ for (i = 0; i < arr->n_elems; ++i) {
+ const sync_level_t* slot;
+
+ slot = &arr->elems[i];
+
+ if (slot->latch != NULL
+ && (!has_search_latch
+ || slot->level != SYNC_SEARCH_SYS)) {
+
+ mutex_exit(&sync_thread_mutex);
+ ut_error;
+
+ return(slot->latch);
+ }
+ }
+
+ mutex_exit(&sync_thread_mutex);
+
+ return(NULL);
}
/******************************************************************//**
@@ -1098,10 +1136,10 @@ sync_thread_add_level(
ulint level) /*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
{
- sync_level_t* array;
+ ulint i;
sync_level_t* slot;
+ sync_arr_t* array;
sync_thread_t* thread_slot;
- ulint i;
if (!sync_order_checks_on) {
@@ -1126,20 +1164,23 @@ sync_thread_add_level(
thread_slot = sync_thread_level_arrays_find_slot();
if (thread_slot == NULL) {
- /* We have to allocate the level array for a new thread */
- array = ut_malloc(sizeof(sync_level_t) * SYNC_THREAD_N_LEVELS);
+ ulint sz;
- thread_slot = sync_thread_level_arrays_find_free();
+ sz = sizeof(*array)
+ + (sizeof(*array->elems) * SYNC_THREAD_N_LEVELS);
- thread_slot->id = os_thread_get_curr_id();
- thread_slot->levels = array;
+ /* We have to allocate the level array for a new thread */
+ array = calloc(sz, sizeof(char));
+ ut_a(array != NULL);
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ array->next_free = ULINT_UNDEFINED;
+ array->max_elems = SYNC_THREAD_N_LEVELS;
+ array->elems = (sync_level_t*) &array[1];
- slot = sync_thread_levels_get_nth(array, i);
+ thread_slot = sync_thread_level_arrays_find_free();
- slot->latch = NULL;
- }
+ thread_slot->levels = array;
+ thread_slot->id = os_thread_get_curr_id();
}
array = thread_slot->levels;
@@ -1180,7 +1221,7 @@ sync_thread_add_level(
case SYNC_RSEG:
case SYNC_TRX_UNDO:
case SYNC_PURGE_LATCH:
- case SYNC_PURGE_SYS:
+ case SYNC_PURGE_QUEUE:
case SYNC_DICT_AUTOINC_MUTEX:
case SYNC_DICT_OPERATION:
case SYNC_DICT_HEADER:
@@ -1207,8 +1248,8 @@ sync_thread_add_level(
case SYNC_BUF_BLOCK:
/* Either the thread must own the buffer pool mutex
- (buf_pool_mutex), or it is allowed to latch only ONE
- buffer block (block->mutex or buf_pool_zip_mutex). */
+ (buf_pool->mutex), or it is allowed to latch only ONE
+ buffer block (block->mutex or buf_pool->zip_mutex). */
if (!sync_thread_levels_g(array, level, FALSE)) {
ut_a(sync_thread_levels_g(array, level - 1, TRUE));
ut_a(sync_thread_levels_contain(array, SYNC_BUF_POOL));
@@ -1247,10 +1288,16 @@ sync_thread_add_level(
|| sync_thread_levels_g(array, SYNC_FSP, TRUE));
break;
case SYNC_TRX_UNDO_PAGE:
+ /* Purge is allowed to read in as many UNDO pages as it likes,
+ there was a bogus rule here earlier that forced the caller to
+ acquire the purge_sys_t::mutex. The purge mutex did not really
+ protect anything because it was only ever acquired by the
+ single purge thread. The purge thread can read the UNDO pages
+ without any covering mutex. */
+
ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO)
|| sync_thread_levels_contain(array, SYNC_RSEG)
- || sync_thread_levels_contain(array, SYNC_PURGE_SYS)
- || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE, TRUE));
+ || sync_thread_levels_g(array, level - 1, TRUE));
break;
case SYNC_RSEG_HEADER:
ut_a(sync_thread_levels_contain(array, SYNC_RSEG));
@@ -1303,19 +1350,26 @@ sync_thread_add_level(
ut_error;
}
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ if (array->next_free == ULINT_UNDEFINED) {
+ ut_a(array->n_elems < array->max_elems);
- slot = sync_thread_levels_get_nth(array, i);
+ i = array->n_elems++;
+ } else {
+ i = array->next_free;
+ array->next_free = array->elems[i].level;
+ }
- if (slot->latch == NULL) {
- slot->latch = latch;
- slot->level = level;
+ ut_a(i < array->n_elems);
+ ut_a(i != ULINT_UNDEFINED);
- break;
- }
- }
+ ++array->in_use;
+
+ slot = &array->elems[i];
- ut_a(i < SYNC_THREAD_N_LEVELS);
+ ut_a(slot->latch == NULL);
+
+ slot->latch = latch;
+ slot->level = level;
mutex_exit(&sync_thread_mutex);
}
@@ -1331,8 +1385,7 @@ sync_thread_reset_level(
/*====================*/
void* latch) /*!< in: pointer to a mutex or an rw-lock */
{
- sync_level_t* array;
- sync_level_t* slot;
+ sync_arr_t* array;
sync_thread_t* thread_slot;
ulint i;
@@ -1363,17 +1416,37 @@ sync_thread_reset_level(
array = thread_slot->levels;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ for (i = 0; i < array->n_elems; i++) {
+ sync_level_t* slot;
- slot = sync_thread_levels_get_nth(array, i);
+ slot = &array->elems[i];
- if (slot->latch == latch) {
- slot->latch = NULL;
+ if (slot->latch != latch) {
+ continue;
+ }
- mutex_exit(&sync_thread_mutex);
+ slot->latch = NULL;
- return(TRUE);
+ /* Update the free slot list. See comment in sync_level_t
+ for the level field. */
+ slot->level = array->next_free;
+ array->next_free = i;
+
+ ut_a(array->in_use >= 1);
+ --array->in_use;
+
+ /* If all cells are idle then reset the free
+ list. The assumption is that this will save
+ time when we need to scan up to n_elems. */
+
+ if (array->in_use == 0) {
+ array->n_elems = 0;
+ array->next_free = ULINT_UNDEFINED;
}
+
+ mutex_exit(&sync_thread_mutex);
+
+ return(TRUE);
}
if (((mutex_t*) latch)->magic_n != MUTEX_MAGIC_N) {
@@ -1403,11 +1476,6 @@ void
sync_init(void)
/*===========*/
{
-#ifdef UNIV_SYNC_DEBUG
- sync_thread_t* thread_slot;
- ulint i;
-#endif /* UNIV_SYNC_DEBUG */
-
ut_a(sync_initialized == FALSE);
sync_initialized = TRUE;
@@ -1421,13 +1489,10 @@ sync_init(void)
/* Create the thread latch level array where the latch levels
are stored for each OS thread */
- sync_thread_level_arrays = ut_malloc(OS_THREAD_MAX_N
- * sizeof(sync_thread_t));
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ sync_thread_level_arrays = calloc(
+ sizeof(sync_thread_t), OS_THREAD_MAX_N);
+ ut_a(sync_thread_level_arrays != NULL);
- thread_slot = sync_thread_level_arrays_get_nth(i);
- thread_slot->levels = NULL;
- }
#endif /* UNIV_SYNC_DEBUG */
/* Init the mutex list and create the mutex to protect it. */
@@ -1454,6 +1519,34 @@ sync_init(void)
#endif /* UNIV_SYNC_DEBUG */
}
+#ifdef UNIV_SYNC_DEBUG
+/******************************************************************//**
+Frees all debug memory. */
+static
+void
+sync_thread_level_arrays_free(void)
+/*===============================*/
+
+{
+ ulint i;
+
+ for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ sync_thread_t* slot;
+
+ slot = &sync_thread_level_arrays[i];
+
+ /* If this slot was allocated then free the slot memory too. */
+ if (slot->levels != NULL) {
+ free(slot->levels);
+ slot->levels = NULL;
+ }
+ }
+
+ free(sync_thread_level_arrays);
+ sync_thread_level_arrays = NULL;
+}
+#endif /* UNIV_SYNC_DEBUG */
+
/******************************************************************//**
Frees the resources in InnoDB's own synchronization data structures. Use
os_sync_free() after calling this. */
@@ -1466,17 +1559,20 @@ sync_close(void)
sync_array_free(sync_primary_wait_array);
- mutex = UT_LIST_GET_FIRST(mutex_list);
+ for (mutex = UT_LIST_GET_FIRST(mutex_list);
+ mutex != NULL;
+ /* No op */) {
- while (mutex) {
#ifdef UNIV_MEM_DEBUG
if (mutex == &mem_hash_mutex) {
mutex = UT_LIST_GET_NEXT(list, mutex);
continue;
}
#endif /* UNIV_MEM_DEBUG */
+
mutex_free(mutex);
- mutex = UT_LIST_GET_FIRST(mutex_list);
+
+ mutex = UT_LIST_GET_FIRST(mutex_list);
}
mutex_free(&mutex_list_mutex);
@@ -1485,6 +1581,8 @@ sync_close(void)
/* Switch latching order checks on in sync0sync.c */
sync_order_checks_on = FALSE;
+
+ sync_thread_level_arrays_free();
#endif /* UNIV_SYNC_DEBUG */
sync_initialized = FALSE;
diff --git a/storage/innobase/thr/thr0loc.c b/storage/innobase/thr/thr0loc.c
deleted file mode 100644
index 045ff3e9fb1..00000000000
--- a/storage/innobase/thr/thr0loc.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file thr/thr0loc.c
-The thread local storage
-
-Created 10/5/1995 Heikki Tuuri
-*******************************************************/
-
-#include "thr0loc.h"
-#ifdef UNIV_NONINL
-#include "thr0loc.ic"
-#endif
-
-#include "sync0sync.h"
-#include "hash0hash.h"
-#include "mem0mem.h"
-#include "srv0srv.h"
-
-/*
- IMPLEMENTATION OF THREAD LOCAL STORAGE
- ======================================
-
-The threads sometimes need private data which depends on the thread id.
-This is implemented as a hash table, where the hash value is calculated
-from the thread id, to prepare for a large number of threads. The hash table
-is protected by a mutex. If you need modify the program and put new data to
-the thread local storage, just add it to struct thr_local_struct in the
-header file. */
-
-/** Mutex protecting thr_local_hash */
-static mutex_t thr_local_mutex;
-
-/** The hash table. The module is not yet initialized when it is NULL. */
-static hash_table_t* thr_local_hash = NULL;
-
-/** Thread local data */
-typedef struct thr_local_struct thr_local_t;
-
-#ifdef UNIV_PFS_MUTEX
-/* Key to register the mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t thr_local_mutex_key;
-#endif /* UNIV_PFS_MUTEX */
-
-/** @brief Thread local data.
-The private data for each thread should be put to
-the structure below and the accessor functions written
-for the field. */
-struct thr_local_struct{
- os_thread_id_t id; /*!< id of the thread which owns this struct */
- os_thread_t handle; /*!< operating system handle to the thread */
- ulint slot_no;/*!< the index of the slot in the thread table
- for this thread */
- ibool in_ibuf;/*!< TRUE if the thread is doing an ibuf
- operation */
- hash_node_t hash; /*!< hash chain node */
- ulint magic_n;/*!< magic number (THR_LOCAL_MAGIC_N) */
-};
-
-/** The value of thr_local_struct::magic_n */
-#define THR_LOCAL_MAGIC_N 1231234
-
-/*******************************************************************//**
-Returns the local storage struct for a thread.
-@return local storage */
-static
-thr_local_t*
-thr_local_get(
-/*==========*/
- os_thread_id_t id) /*!< in: thread id of the thread */
-{
- thr_local_t* local;
-
-try_again:
- ut_ad(thr_local_hash);
- ut_ad(mutex_own(&thr_local_mutex));
-
- /* Look for the local struct in the hash table */
-
- local = NULL;
-
- HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
- thr_local_t*, local,, os_thread_eq(local->id, id));
- if (local == NULL) {
- mutex_exit(&thr_local_mutex);
-
- thr_local_create();
-
- mutex_enter(&thr_local_mutex);
-
- goto try_again;
- }
-
- ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
-
- return(local);
-}
-
-/*******************************************************************//**
-Gets the slot number in the thread table of a thread.
-@return slot number */
-UNIV_INTERN
-ulint
-thr_local_get_slot_no(
-/*==================*/
- os_thread_id_t id) /*!< in: thread id of the thread */
-{
- ulint slot_no;
- thr_local_t* local;
-
- mutex_enter(&thr_local_mutex);
-
- local = thr_local_get(id);
-
- slot_no = local->slot_no;
-
- mutex_exit(&thr_local_mutex);
-
- return(slot_no);
-}
-
-/*******************************************************************//**
-Sets the slot number in the thread table of a thread. */
-UNIV_INTERN
-void
-thr_local_set_slot_no(
-/*==================*/
- os_thread_id_t id, /*!< in: thread id of the thread */
- ulint slot_no)/*!< in: slot number */
-{
- thr_local_t* local;
-
- mutex_enter(&thr_local_mutex);
-
- local = thr_local_get(id);
-
- local->slot_no = slot_no;
-
- mutex_exit(&thr_local_mutex);
-}
-
-/*******************************************************************//**
-Returns pointer to the 'in_ibuf' field within the current thread local
-storage.
-@return pointer to the in_ibuf field */
-UNIV_INTERN
-ibool*
-thr_local_get_in_ibuf_field(void)
-/*=============================*/
-{
- thr_local_t* local;
-
- mutex_enter(&thr_local_mutex);
-
- local = thr_local_get(os_thread_get_curr_id());
-
- mutex_exit(&thr_local_mutex);
-
- return(&(local->in_ibuf));
-}
-
-/*******************************************************************//**
-Creates a local storage struct for the calling new thread. */
-UNIV_INTERN
-void
-thr_local_create(void)
-/*==================*/
-{
- thr_local_t* local;
-
- if (thr_local_hash == NULL) {
- thr_local_init();
- }
-
- local = mem_alloc(sizeof(thr_local_t));
-
- local->id = os_thread_get_curr_id();
- local->handle = os_thread_get_curr();
- local->magic_n = THR_LOCAL_MAGIC_N;
-
- local->in_ibuf = FALSE;
-
- mutex_enter(&thr_local_mutex);
-
- HASH_INSERT(thr_local_t, hash, thr_local_hash,
- os_thread_pf(os_thread_get_curr_id()),
- local);
-
- mutex_exit(&thr_local_mutex);
-}
-
-/*******************************************************************//**
-Frees the local storage struct for the specified thread. */
-UNIV_INTERN
-void
-thr_local_free(
-/*===========*/
- os_thread_id_t id) /*!< in: thread id */
-{
- thr_local_t* local;
-
- mutex_enter(&thr_local_mutex);
-
- /* 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));
- if (local == NULL) {
- mutex_exit(&thr_local_mutex);
-
- return;
- }
-
- HASH_DELETE(thr_local_t, hash, thr_local_hash,
- os_thread_pf(id), local);
-
- mutex_exit(&thr_local_mutex);
-
- ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
-
- mem_free(local);
-}
-
-/****************************************************************//**
-Initializes the thread local storage module. */
-UNIV_INTERN
-void
-thr_local_init(void)
-/*================*/
-{
-
- ut_a(thr_local_hash == NULL);
-
- thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
-
- mutex_create(thr_local_mutex_key,
- &thr_local_mutex, SYNC_THR_LOCAL);
-}
-
-/********************************************************************
-Close the thread local storage module. */
-UNIV_INTERN
-void
-thr_local_close(void)
-/*=================*/
-{
- ulint i;
-
- ut_a(thr_local_hash != NULL);
-
- /* Free the hash elements. We don't remove them from the table
- because we are going to destroy the table anyway. */
- for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
- thr_local_t* local;
-
- local = HASH_GET_FIRST(thr_local_hash, i);
-
- while (local) {
- thr_local_t* prev_local = local;
-
- local = HASH_GET_NEXT(hash, prev_local);
- ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
- mem_free(prev_local);
- }
- }
-
- hash_table_free(thr_local_hash);
- thr_local_hash = NULL;
-}
diff --git a/storage/innobase/trx/trx0i_s.c b/storage/innobase/trx/trx0i_s.c
index 1ad074769c7..c18b747da6d 100644
--- a/storage/innobase/trx/trx0i_s.c
+++ b/storage/innobase/trx/trx0i_s.c
@@ -38,8 +38,6 @@ Created July 17, 2007 Vasil Dimov
#include <mysql/plugin.h>
-#include "mysql_addons.h"
-
#include "buf0buf.h"
#include "dict0dict.h"
#include "ha0storage.h"
@@ -417,6 +415,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.
@@ -447,18 +481,15 @@ fill_trx_row(
row->trx_id = trx->id;
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;
}
@@ -477,7 +508,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) {
@@ -488,9 +518,11 @@ fill_trx_row(
query[stmt_len] = '\0';
row->trx_query = ha_storage_put_memlim(
- cache->storage, stmt, stmt_len + 1,
+ cache->storage, query, 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);
@@ -814,6 +846,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);
}
@@ -834,6 +867,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;
@@ -905,6 +941,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
@@ -962,7 +999,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));
@@ -1002,6 +1039,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
@@ -1039,6 +1077,7 @@ add_lock_to_cache(
} /* for()-loop */
#endif
+ ut_ad(i_s_locks_row_validate(dst_row));
return(dst_row);
}
diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c
index 4c787579a03..02ec9f1c072 100644
--- a/storage/innobase/trx/trx0purge.c
+++ b/storage/innobase/trx/trx0purge.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -57,8 +57,8 @@ UNIV_INTERN mysql_pfs_key_t trx_purge_latch_key;
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_PFS_MUTEX
-/* Key to register purge_sys_mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t purge_sys_mutex_key;
+/* Key to register purge_sys_bh_mutex with performance schema */
+UNIV_INTERN mysql_pfs_key_t purge_sys_bh_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/*****************************************************************//**
@@ -219,13 +219,16 @@ Creates the global purge system control structure and inits the history
mutex. */
UNIV_INTERN
void
-trx_purge_sys_create(void)
-/*======================*/
+trx_purge_sys_create(
+/*=================*/
+ ib_bh_t* ib_bh) /*!< in, own: UNDO log min binary heap */
{
ut_ad(mutex_own(&kernel_mutex));
- purge_sys = mem_alloc(sizeof(trx_purge_t));
+ purge_sys = mem_zalloc(sizeof(trx_purge_t));
+ /* Take ownership of ib_bh, we are responsible for freeing it. */
+ purge_sys->ib_bh = ib_bh;
purge_sys->state = TRX_STOP_PURGE;
purge_sys->n_pages_handled = 0;
@@ -237,8 +240,9 @@ trx_purge_sys_create(void)
rw_lock_create(trx_purge_latch_key,
&purge_sys->latch, SYNC_PURGE_LATCH);
- mutex_create(purge_sys_mutex_key,
- &purge_sys->mutex, SYNC_PURGE_SYS);
+ mutex_create(
+ purge_sys_bh_mutex_key, &purge_sys->bh_mutex,
+ SYNC_PURGE_QUEUE);
purge_sys->heap = mem_heap_create(256);
@@ -288,9 +292,12 @@ trx_purge_sys_close(void)
trx_undo_arr_free(purge_sys->arr);
rw_lock_free(&purge_sys->latch);
- mutex_free(&purge_sys->mutex);
+ mutex_free(&purge_sys->bh_mutex);
mem_heap_free(purge_sys->heap);
+
+ ib_bh_free(purge_sys->ib_bh);
+
mem_free(purge_sys);
purge_sys = NULL;
@@ -311,34 +318,31 @@ trx_purge_add_update_undo_to_history(
mtr_t* mtr) /*!< in: mtr */
{
trx_undo_t* undo;
- trx_rseg_t* rseg;
trx_rsegf_t* rseg_header;
-#ifdef UNIV_DEBUG
- trx_usegf_t* seg_header;
-#endif /* UNIV_DEBUG */
trx_ulogf_t* undo_header;
- ulint hist_size;
undo = trx->update_undo;
ut_ad(undo);
- rseg = undo->rseg;
+ ut_ad(mutex_own(&undo->rseg->mutex));
- ut_ad(mutex_own(&(rseg->mutex)));
-
- rseg_header = trx_rsegf_get(rseg->space, rseg->zip_size,
- rseg->page_no, mtr);
+ rseg_header = trx_rsegf_get(
+ undo->rseg->space, undo->rseg->zip_size, undo->rseg->page_no,
+ mtr);
undo_header = undo_page + undo->hdr_offset;
+ /* Add the log as the first in the history list */
+
+ if (undo->state != TRX_UNDO_CACHED) {
+ ulint hist_size;
#ifdef UNIV_DEBUG
- seg_header = undo_page + TRX_UNDO_SEG_HDR;
+ trx_usegf_t* seg_header = undo_page + TRX_UNDO_SEG_HDR;
#endif /* UNIV_DEBUG */
- if (undo->state != TRX_UNDO_CACHED) {
/* The undo log segment will not be reused */
- if (undo->id >= TRX_RSEG_N_SLOTS) {
+ if (UNIV_UNLIKELY(undo->id >= TRX_RSEG_N_SLOTS)) {
fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n",
(ulong) undo->id);
@@ -347,42 +351,50 @@ trx_purge_add_update_undo_to_history(
trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL, mtr);
- hist_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
- MLOG_4BYTES, mtr);
+ hist_size = mtr_read_ulint(
+ rseg_header + TRX_RSEG_HISTORY_SIZE, MLOG_4BYTES, mtr);
+
ut_ad(undo->size == flst_get_len(
seg_header + TRX_UNDO_PAGE_LIST, mtr));
- mlog_write_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
- hist_size + undo->size, MLOG_4BYTES, mtr);
+ mlog_write_ulint(
+ rseg_header + TRX_RSEG_HISTORY_SIZE,
+ hist_size + undo->size, MLOG_4BYTES, mtr);
}
- /* Add the log as the first in the history list */
- flst_add_first(rseg_header + TRX_RSEG_HISTORY,
- undo_header + TRX_UNDO_HISTORY_NODE, mtr);
- mutex_enter(&kernel_mutex);
- trx_sys->rseg_history_len++;
- mutex_exit(&kernel_mutex);
-
- if (!(trx_sys->rseg_history_len % srv_purge_batch_size)) {
- /* Inform the purge thread that there is work to do. */
- srv_wake_purge_thread_if_not_active();
- }
+ flst_add_first(
+ rseg_header + TRX_RSEG_HISTORY,
+ undo_header + TRX_UNDO_HISTORY_NODE, mtr);
/* Write the trx number to the undo log header */
+
mlog_write_ull(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);
+
/* Write information about delete markings to the undo log header */
if (!undo->del_marks) {
- mlog_write_ulint(undo_header + TRX_UNDO_DEL_MARKS, FALSE,
- MLOG_2BYTES, mtr);
+ mlog_write_ulint(
+ undo_header + TRX_UNDO_DEL_MARKS, FALSE,
+ MLOG_2BYTES, mtr);
}
- if (rseg->last_page_no == FIL_NULL) {
+ if (undo->rseg->last_page_no == FIL_NULL) {
+ undo->rseg->last_trx_no = trx->no;
+ undo->rseg->last_offset = undo->hdr_offset;
+ undo->rseg->last_page_no = undo->hdr_page_no;
+ undo->rseg->last_del_marks = undo->del_marks;
- rseg->last_page_no = undo->hdr_page_no;
- rseg->last_offset = undo->hdr_offset;
- rseg->last_trx_no = trx->no;
- rseg->last_del_marks = undo->del_marks;
+ /* FIXME: Add a bin heap validate function to check that
+ the rseg exists. */
+ }
+
+ mutex_enter(&kernel_mutex);
+ trx_sys->rseg_history_len++;
+ mutex_exit(&kernel_mutex);
+
+ if (!(trx_sys->rseg_history_len % srv_purge_batch_size)) {
+ /* Inform the purge thread that there is work to do. */
+ srv_wake_purge_thread_if_not_active();
}
}
@@ -411,7 +423,6 @@ trx_purge_free_segment(
/* fputs("Freeing an update undo log segment\n", stderr); */
- ut_ad(mutex_own(&(purge_sys->mutex)));
loop:
mtr_start(&mtr);
mutex_enter(&(rseg->mutex));
@@ -515,8 +526,6 @@ trx_purge_truncate_rseg_history(
mtr_t mtr;
trx_id_t undo_trx_no;
- ut_ad(mutex_own(&(purge_sys->mutex)));
-
mtr_start(&mtr);
mutex_enter(&(rseg->mutex));
@@ -609,10 +618,8 @@ trx_purge_truncate_history(void)
trx_id_t limit_trx_no;
undo_no_t limit_undo_no;
- ut_ad(mutex_own(&(purge_sys->mutex)));
-
- trx_purge_arr_get_biggest(purge_sys->arr, &limit_trx_no,
- &limit_undo_no);
+ trx_purge_arr_get_biggest(
+ purge_sys->arr, &limit_trx_no, &limit_undo_no);
if (limit_trx_no == 0) {
@@ -630,34 +637,29 @@ trx_purge_truncate_history(void)
ut_ad(limit_trx_no <= purge_sys->view->low_limit_no);
- rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
+ for (rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
+ rseg != NULL;
+ rseg = UT_LIST_GET_NEXT(rseg_list, rseg)) {
- while (rseg) {
- trx_purge_truncate_rseg_history(rseg, limit_trx_no,
- limit_undo_no);
- rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
+ trx_purge_truncate_rseg_history(
+ rseg, limit_trx_no, limit_undo_no);
}
}
/********************************************************************//**
Does a truncate if the purge array is empty. NOTE that when this function is
-called, the caller must not have any latches on undo log pages!
-@return TRUE if array empty */
+called, the caller must not have any latches on undo log pages! */
UNIV_INLINE
-ibool
+void
trx_purge_truncate_if_arr_empty(void)
/*=================================*/
{
- ut_ad(mutex_own(&(purge_sys->mutex)));
+ static ulint count;
- if (purge_sys->arr->n_used == 0) {
+ if (!(++count % TRX_SYS_N_RSEGS) && purge_sys->arr->n_used == 0) {
trx_purge_truncate_history();
-
- return(TRUE);
}
-
- return(FALSE);
}
/***********************************************************************//**
@@ -675,8 +677,8 @@ trx_purge_rseg_get_next_history_log(
trx_id_t trx_no;
ibool del_marks;
mtr_t mtr;
-
- ut_ad(mutex_own(&(purge_sys->mutex)));
+ rseg_queue_t rseg_queue;
+ const void* ptr;
mutex_enter(&(rseg->mutex));
@@ -688,8 +690,9 @@ trx_purge_rseg_get_next_history_log(
mtr_start(&mtr);
- undo_page = trx_undo_page_get_s_latched(rseg->space, rseg->zip_size,
- rseg->last_page_no, &mtr);
+ undo_page = trx_undo_page_get_s_latched(
+ rseg->space, rseg->zip_size, rseg->last_page_no, &mtr);
+
log_hdr = undo_page + rseg->last_offset;
/* Increase the purge page count by one for every handled log */
@@ -698,6 +701,7 @@ trx_purge_rseg_get_next_history_log(
prev_log_addr = trx_purge_get_log_from_hist(
flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, &mtr));
+
if (prev_log_addr.page == FIL_NULL) {
/* No logs left in the history list */
@@ -712,11 +716,11 @@ trx_purge_rseg_get_next_history_log(
on the MySQL mailing list on Nov 9, 2004. The fut0lst.c
file-based list was corrupt. The prev node pointer was
FIL_NULL, even though the list length was over 8 million nodes!
- We assume that purge truncates the history list in moderate
+ We assume that purge truncates the history list in large
size pieces, and if we here reach the head of the list, the
- list cannot be longer than 20 000 undo logs now. */
+ list cannot be longer than 2000 000 undo logs now. */
- if (trx_sys->rseg_history_len > 20000) {
+ if (trx_sys->rseg_history_len > 2000000) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Warning: purge reached the"
@@ -756,105 +760,150 @@ trx_purge_rseg_get_next_history_log(
rseg->last_trx_no = trx_no;
rseg->last_del_marks = del_marks;
+ rseg_queue.rseg = rseg;
+ rseg_queue.trx_no = rseg->last_trx_no;
+
+ /* Purge can also produce events, however these are already ordered
+ in the rollback segment and any user generated event will be greater
+ than the events that Purge produces. ie. Purge can never produce
+ events from an empty rollback segment. */
+
+ mutex_enter(&purge_sys->bh_mutex);
+
+ ptr = ib_bh_push(purge_sys->ib_bh, &rseg_queue);
+ ut_a(ptr != NULL);
+
+ mutex_exit(&purge_sys->bh_mutex);
+
mutex_exit(&(rseg->mutex));
}
/***********************************************************************//**
-Chooses the next undo log to purge and updates the info in purge_sys. This
-function is used to initialize purge_sys when the next record to purge is
-not known, and also to update the purge system info on the next record when
-purge has handled the whole undo log for a transaction. */
+Chooses the rollback segment with the smallest trx_id.
+@return zip_size if log is for a compressed table, ULINT_UNDEFINED if
+ no rollback segments to purge, 0 for non compressed tables. */
static
-void
-trx_purge_choose_next_log(void)
-/*===========================*/
+ulint
+trx_purge_get_rseg_with_min_trx_id(
+/*===============================*/
+ trx_purge_t* purge_sys) /*!< in/out: purge instance */
+
{
- trx_undo_rec_t* rec;
- trx_rseg_t* rseg;
- trx_rseg_t* min_rseg;
- trx_id_t min_trx_no;
- ulint space = 0; /* remove warning (??? bug ???) */
ulint zip_size = 0;
- ulint page_no = 0; /* remove warning (??? bug ???) */
- ulint offset = 0; /* remove warning (??? bug ???) */
- mtr_t mtr;
- ut_ad(mutex_own(&(purge_sys->mutex)));
- ut_ad(purge_sys->next_stored == FALSE);
+ mutex_enter(&purge_sys->bh_mutex);
- rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
+ /* Only purge consumes events from the binary heap, user
+ threads only produce the events. */
- min_trx_no = IB_ULONGLONG_MAX;
+ if (!ib_bh_is_empty(purge_sys->ib_bh)) {
+ trx_rseg_t* rseg;
- min_rseg = NULL;
+ rseg = ((rseg_queue_t*) ib_bh_first(purge_sys->ib_bh))->rseg;
+ ib_bh_pop(purge_sys->ib_bh);
- while (rseg) {
- mutex_enter(&(rseg->mutex));
+ mutex_exit(&purge_sys->bh_mutex);
- if (rseg->last_page_no != FIL_NULL) {
+ purge_sys->rseg = rseg;
+ } else {
+ mutex_exit(&purge_sys->bh_mutex);
- if (min_rseg == NULL
- || min_trx_no > rseg->last_trx_no) {
+ purge_sys->rseg = NULL;
- min_rseg = rseg;
- min_trx_no = rseg->last_trx_no;
- space = rseg->space;
- zip_size = rseg->zip_size;
- ut_a(space == 0); /* We assume in purge of
- externally stored fields
- that space id == 0 */
- page_no = rseg->last_page_no;
- offset = rseg->last_offset;
- }
- }
+ return(ULINT_UNDEFINED);
+ }
- mutex_exit(&(rseg->mutex));
+ ut_a(purge_sys->rseg != NULL);
- rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
- }
+ mutex_enter(&purge_sys->rseg->mutex);
- if (min_rseg == NULL) {
+ ut_a(purge_sys->rseg->last_page_no != FIL_NULL);
- return;
- }
+ /* We assume in purge of externally stored fields
+ that space id == 0 */
+ ut_a(purge_sys->rseg->space == 0);
- mtr_start(&mtr);
+ zip_size = purge_sys->rseg->zip_size;
- if (!min_rseg->last_del_marks) {
- /* No need to purge this log */
+ ut_a(purge_sys->purge_trx_no <= purge_sys->rseg->last_trx_no);
- rec = &trx_purge_dummy_rec;
- } else {
- rec = trx_undo_get_first_rec(space, zip_size, page_no, offset,
- RW_S_LATCH, &mtr);
- if (rec == NULL) {
- /* Undo log empty */
+ purge_sys->purge_trx_no = purge_sys->rseg->last_trx_no;
+
+ purge_sys->hdr_offset = purge_sys->rseg->last_offset;
+
+ purge_sys->hdr_page_no = purge_sys->rseg->last_page_no;
+
+ mutex_exit(&purge_sys->rseg->mutex);
+
+ return(zip_size);
+}
+
+/***********************************************************************//**
+Position the purge sys "iterator" on the undo record to use for purging. */
+static
+void
+trx_purge_read_undo_rec(
+/*====================*/
+ trx_purge_t* purge_sys, /*!< in/out: purge instance */
+ ulint zip_size) /*!< in: block size or 0 */
+{
+ ulint page_no;
+ ulint offset = 0;
+ ib_uint64_t undo_no = 0;
+
+ purge_sys->hdr_offset = purge_sys->rseg->last_offset;
+ page_no = purge_sys->hdr_page_no = purge_sys->rseg->last_page_no;
+
+ if (purge_sys->rseg->last_del_marks) {
+ mtr_t mtr;
+ trx_undo_rec_t* undo_rec;
- rec = &trx_purge_dummy_rec;
+ mtr_start(&mtr);
+
+ undo_rec = trx_undo_get_first_rec(
+ 0 /* System space id */, zip_size,
+ purge_sys->hdr_page_no,
+ purge_sys->hdr_offset, RW_S_LATCH, &mtr);
+
+ if (undo_rec != NULL) {
+ offset = page_offset(undo_rec);
+ undo_no = trx_undo_rec_get_undo_no(undo_rec);
+ page_no = page_get_page_no(page_align(undo_rec));
}
+
+ mtr_commit(&mtr);
}
+ purge_sys->offset = offset;
+ purge_sys->page_no = page_no;
+ purge_sys->purge_undo_no = undo_no;
+
purge_sys->next_stored = TRUE;
- purge_sys->rseg = min_rseg;
+}
- purge_sys->hdr_page_no = page_no;
- purge_sys->hdr_offset = offset;
+/***********************************************************************//**
+Chooses the next undo log to purge and updates the info in purge_sys. This
+function is used to initialize purge_sys when the next record to purge is
+not known, and also to update the purge system info on the next record when
+purge has handled the whole undo log for a transaction. */
+static
+void
+trx_purge_choose_next_log(void)
+/*===========================*/
+{
+ ulint zip_size;
- purge_sys->purge_trx_no = min_trx_no;
+ ut_ad(purge_sys->next_stored == FALSE);
- if (rec == &trx_purge_dummy_rec) {
+ zip_size = trx_purge_get_rseg_with_min_trx_id(purge_sys);
- purge_sys->purge_undo_no = 0;
- purge_sys->page_no = page_no;
- purge_sys->offset = 0;
- } else {
- purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec);
+ if (purge_sys->rseg != NULL) {
- purge_sys->page_no = page_get_page_no(page_align(rec));
- purge_sys->offset = page_offset(rec);
+ trx_purge_read_undo_rec(purge_sys, zip_size);
+ } else {
+ /* There is nothing to do yet. */
+ os_thread_yield();
}
-
- mtr_commit(&mtr);
}
/***********************************************************************//**
@@ -880,7 +929,6 @@ trx_purge_get_next_rec(
ulint cmpl_info;
mtr_t mtr;
- ut_ad(mutex_own(&(purge_sys->mutex)));
ut_ad(purge_sys->next_stored);
space = purge_sys->rseg->space;
@@ -903,8 +951,8 @@ trx_purge_get_next_rec(
mtr_start(&mtr);
- undo_page = trx_undo_page_get_s_latched(space, zip_size,
- page_no, &mtr);
+ undo_page = trx_undo_page_get_s_latched(space, zip_size, page_no, &mtr);
+
rec = undo_page + offset;
rec2 = rec;
@@ -913,9 +961,9 @@ trx_purge_get_next_rec(
/* Try first to find the next record which requires a purge
operation from the same page of the same undo log */
- next_rec = trx_undo_page_get_next_rec(rec2,
- purge_sys->hdr_page_no,
- purge_sys->hdr_offset);
+ next_rec = trx_undo_page_get_next_rec(
+ rec2, purge_sys->hdr_page_no, purge_sys->hdr_offset);
+
if (next_rec == NULL) {
rec2 = trx_undo_get_next_rec(
rec2, purge_sys->hdr_page_no,
@@ -995,17 +1043,12 @@ trx_purge_fetch_next_rec(
{
trx_undo_rec_t* undo_rec;
- mutex_enter(&(purge_sys->mutex));
if (purge_sys->state == TRX_STOP_PURGE) {
trx_purge_truncate_if_arr_empty();
- mutex_exit(&(purge_sys->mutex));
-
return(NULL);
- }
-
- if (!purge_sys->next_stored) {
+ } else if (!purge_sys->next_stored) {
trx_purge_choose_next_log();
if (!purge_sys->next_stored) {
@@ -1020,8 +1063,6 @@ trx_purge_fetch_next_rec(
(ulong) purge_sys->n_pages_handled);
}
- mutex_exit(&(purge_sys->mutex));
-
return(NULL);
}
}
@@ -1032,18 +1073,12 @@ trx_purge_fetch_next_rec(
trx_purge_truncate_if_arr_empty();
- mutex_exit(&(purge_sys->mutex));
-
return(NULL);
- }
-
- if (purge_sys->purge_trx_no >= purge_sys->view->low_limit_no) {
+ } else if (purge_sys->purge_trx_no >= purge_sys->view->low_limit_no) {
purge_sys->state = TRX_STOP_PURGE;
trx_purge_truncate_if_arr_empty();
- mutex_exit(&(purge_sys->mutex));
-
return(NULL);
}
@@ -1052,12 +1087,13 @@ trx_purge_fetch_next_rec(
(ullint) purge_sys->purge_trx_no,
(ullint) purge_sys->purge_undo_no); */
- *roll_ptr = trx_undo_build_roll_ptr(FALSE, (purge_sys->rseg)->id,
- purge_sys->page_no,
- purge_sys->offset);
- *cell = trx_purge_arr_store_info(purge_sys->purge_trx_no,
- purge_sys->purge_undo_no);
+ *roll_ptr = trx_undo_build_roll_ptr(
+ FALSE, (purge_sys->rseg)->id, purge_sys->page_no,
+ purge_sys->offset);
+
+ *cell = trx_purge_arr_store_info(
+ purge_sys->purge_trx_no, purge_sys->purge_undo_no);
ut_ad(purge_sys->purge_trx_no < purge_sys->view->low_limit_no);
@@ -1066,8 +1102,6 @@ trx_purge_fetch_next_rec(
undo_rec = trx_purge_get_next_rec(heap);
- mutex_exit(&(purge_sys->mutex));
-
return(undo_rec);
}
@@ -1079,11 +1113,7 @@ trx_purge_rec_release(
/*==================*/
trx_undo_inf_t* cell) /*!< in: storage cell */
{
- mutex_enter(&(purge_sys->mutex));
-
trx_purge_arr_remove_info(cell);
-
- mutex_exit(&(purge_sys->mutex));
}
/*******************************************************************//**
@@ -1097,23 +1127,11 @@ trx_purge(
purge in one batch */
{
que_thr_t* thr;
- /* que_thr_t* thr2; */
ulint old_pages_handled;
- mutex_enter(&(purge_sys->mutex));
-
- if (purge_sys->trx->n_active_thrs > 0) {
+ ut_a(purge_sys->trx->n_active_thrs == 0);
- mutex_exit(&(purge_sys->mutex));
-
- /* Should not happen */
-
- ut_error;
-
- return(0);
- }
-
- rw_lock_x_lock(&(purge_sys->latch));
+ rw_lock_x_lock(&purge_sys->latch);
mutex_enter(&kernel_mutex);
@@ -1147,8 +1165,9 @@ trx_purge(
}
}
- purge_sys->view = read_view_oldest_copy_or_open_new(0,
- purge_sys->heap);
+ purge_sys->view = read_view_oldest_copy_or_open_new(
+ 0, purge_sys->heap);
+
mutex_exit(&kernel_mutex);
rw_lock_x_unlock(&(purge_sys->latch));
@@ -1159,7 +1178,6 @@ trx_purge(
old_pages_handled = purge_sys->n_pages_handled;
- mutex_exit(&(purge_sys->mutex));
mutex_enter(&kernel_mutex);
@@ -1167,15 +1185,8 @@ trx_purge(
ut_ad(thr);
- /* thr2 = que_fork_start_command(purge_sys->query);
-
- ut_ad(thr2); */
-
-
mutex_exit(&kernel_mutex);
- /* srv_que_task_enqueue(thr2); */
-
if (srv_print_thread_releases) {
fputs("Starting purge\n", stderr);
diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c
index e7e9a008db4..70b77ace726 100644
--- a/storage/innobase/trx/trx0rec.c
+++ b/storage/innobase/trx/trx0rec.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -351,10 +351,10 @@ trx_undo_rec_get_col_val(
ut_ad(*orig_len >= BTR_EXTERN_FIELD_REF_SIZE);
ut_ad(*len > *orig_len);
/* @see dtuple_convert_big_rec() */
- ut_ad(*len >= BTR_EXTERN_FIELD_REF_SIZE * 2);
+ ut_ad(*len >= BTR_EXTERN_FIELD_REF_SIZE);
/* we do not have access to index->table here
ut_ad(dict_table_get_format(index->table) >= DICT_TF_FORMAT_ZIP
- || *len >= REC_MAX_INDEX_COL_LEN
+ || *len >= col->max_prefix
+ BTR_EXTERN_FIELD_REF_SIZE);
*/
@@ -456,9 +456,10 @@ static
byte*
trx_undo_page_fetch_ext(
/*====================*/
- byte* ext_buf, /*!< in: a buffer of
- REC_MAX_INDEX_COL_LEN
- + BTR_EXTERN_FIELD_REF_SIZE */
+ byte* ext_buf, /*!< in: buffer to hold the prefix
+ data and BLOB pointer */
+ ulint prefix_len, /*!< in: prefix size to store
+ in the undo log */
ulint zip_size, /*!< compressed page size in bytes,
or 0 for uncompressed BLOB */
const byte* field, /*!< in: an externally stored column */
@@ -467,7 +468,7 @@ trx_undo_page_fetch_ext(
{
/* Fetch the BLOB. */
ulint ext_len = btr_copy_externally_stored_field_prefix(
- ext_buf, REC_MAX_INDEX_COL_LEN, zip_size, field, *len);
+ ext_buf, prefix_len, zip_size, field, *len);
/* BLOBs should always be nonempty. */
ut_a(ext_len);
/* Append the BLOB pointer to the prefix. */
@@ -488,10 +489,11 @@ trx_undo_page_report_modify_ext(
byte* ptr, /*!< in: undo log position,
at least 15 bytes must be available */
byte* ext_buf, /*!< in: a buffer of
- REC_MAX_INDEX_COL_LEN
- + BTR_EXTERN_FIELD_REF_SIZE,
+ DICT_MAX_FIELD_LEN_BY_FORMAT() size,
or NULL when should not fetch
a longer prefix */
+ ulint prefix_len, /*!< prefix size to store in the
+ undo log */
ulint zip_size, /*!< compressed page size in bytes,
or 0 for uncompressed BLOB */
const byte** field, /*!< in/out: the locally stored part of
@@ -499,6 +501,8 @@ trx_undo_page_report_modify_ext(
ulint* len) /*!< in/out: length of field, in bytes */
{
if (ext_buf) {
+ ut_a(prefix_len > 0);
+
/* If an ordering column is externally stored, we will
have to store a longer prefix of the field. In this
case, write to the log a marker followed by the
@@ -507,7 +511,7 @@ trx_undo_page_report_modify_ext(
ptr += mach_write_compressed(ptr, *len);
- *field = trx_undo_page_fetch_ext(ext_buf, zip_size,
+ *field = trx_undo_page_fetch_ext(ext_buf, prefix_len, zip_size,
*field, len);
ptr += mach_write_compressed(ptr, *len);
@@ -553,7 +557,7 @@ trx_undo_page_report_modify(
ulint i;
trx_id_t trx_id;
ibool ignore_prefix = FALSE;
- byte ext_buf[REC_MAX_INDEX_COL_LEN
+ byte ext_buf[REC_VERSION_56_MAX_INDEX_COL_LEN
+ BTR_EXTERN_FIELD_REF_SIZE];
ut_a(dict_index_is_clust(index));
@@ -665,6 +669,7 @@ trx_undo_page_report_modify(
/* Save to the undo log the old values of the columns to be updated. */
if (update) {
+
if (trx_undo_left(undo_page, ptr) < 5) {
return(0);
@@ -693,13 +698,21 @@ trx_undo_page_report_modify(
}
if (rec_offs_nth_extern(offsets, pos)) {
+ const dict_col_t* col
+ = dict_index_get_nth_col(index, pos);
+ ulint prefix_len
+ = dict_max_field_len_store_undo(
+ table, col);
+
+ ut_ad(prefix_len + BTR_EXTERN_FIELD_REF_SIZE
+ <= sizeof ext_buf);
+
ptr = trx_undo_page_report_modify_ext(
ptr,
- dict_index_get_nth_col(index, pos)
- ->ord_part
+ col->ord_part
&& !ignore_prefix
- && flen < REC_MAX_INDEX_COL_LEN
- ? ext_buf : NULL,
+ && flen < REC_ANTELOPE_MAX_INDEX_COL_LEN
+ ? ext_buf : NULL, prefix_len,
dict_table_zip_size(table),
&field, &flen);
@@ -778,11 +791,20 @@ trx_undo_page_report_modify(
&flen);
if (rec_offs_nth_extern(offsets, pos)) {
+ const dict_col_t* col =
+ dict_index_get_nth_col(
+ index, pos);
+ ulint prefix_len =
+ dict_max_field_len_store_undo(
+ table, col);
+
+ ut_a(prefix_len < sizeof ext_buf);
+
ptr = trx_undo_page_report_modify_ext(
ptr,
- flen < REC_MAX_INDEX_COL_LEN
+ flen < REC_ANTELOPE_MAX_INDEX_COL_LEN
&& !ignore_prefix
- ? ext_buf : NULL,
+ ? ext_buf : NULL, prefix_len,
dict_table_zip_size(table),
&field, &flen);
} else {
@@ -1082,11 +1104,11 @@ trx_undo_rec_get_partial_row(
undo log record. */
if (!ignore_prefix && col->ord_part) {
ut_a(dfield_get_len(dfield)
- >= 2 * BTR_EXTERN_FIELD_REF_SIZE);
+ >= BTR_EXTERN_FIELD_REF_SIZE);
ut_a(dict_table_get_format(index->table)
>= DICT_TF_FORMAT_ZIP
|| dfield_get_len(dfield)
- >= REC_MAX_INDEX_COL_LEN
+ >= REC_ANTELOPE_MAX_INDEX_COL_LEN
+ BTR_EXTERN_FIELD_REF_SIZE);
}
}
@@ -1571,6 +1593,10 @@ trx_undo_prev_version_build(
return(DB_ERROR);
}
+# ifdef UNIV_BLOB_NULL_DEBUG
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+# endif /* UNIV_BLOB_NULL_DEBUG */
+
if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint n_ext;
diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c
index 876a00fb935..b55471959ce 100644
--- a/storage/innobase/trx/trx0roll.c
+++ b/storage/innobase/trx/trx0roll.c
@@ -47,8 +47,8 @@ Created 3/26/1996 Heikki Tuuri
rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1
-/** In crash recovery, the current trx to be rolled back */
-static trx_t* trx_roll_crash_recv_trx = NULL;
+/** In crash recovery, the current trx to be rolled back; NULL otherwise */
+static const trx_t* trx_roll_crash_recv_trx = NULL;
/** In crash recovery we set this to the undo n:o of the current trx to be
rolled back. Then we can print how many % the rollback has progressed. */
@@ -460,10 +460,6 @@ trx_rollback_active(
(ulong) rows_to_undo, unit);
mutex_exit(&kernel_mutex);
- trx->mysql_thread_id = os_thread_get_curr_id();
-
- trx->mysql_process_no = os_proc_get_number();
-
if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
row_mysql_lock_data_dictionary(trx);
dictionary_locked = TRUE;
diff --git a/storage/innobase/trx/trx0rseg.c b/storage/innobase/trx/trx0rseg.c
index 740320f68c1..85beac8afbc 100644
--- a/storage/innobase/trx/trx0rseg.c
+++ b/storage/innobase/trx/trx0rseg.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle Corpn. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -50,11 +50,11 @@ trx_rseg_get_on_id(
{
trx_rseg_t* rseg;
- rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
+ ut_a(id < TRX_SYS_N_RSEGS);
- while (rseg && rseg->id != id) {
- rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
- }
+ rseg = trx_sys->rseg_array[id];
+
+ ut_a(rseg == NULL || id == rseg->id);
return(rseg);
}
@@ -181,12 +181,15 @@ static
trx_rseg_t*
trx_rseg_mem_create(
/*================*/
- ulint id, /*!< in: rollback segment id */
- ulint space, /*!< in: space where the segment placed */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number of the segment header */
- mtr_t* mtr) /*!< in: mtr */
+ ulint id, /*!< in: rollback segment id */
+ ulint space, /*!< in: space where the segment
+ placed */
+ ulint zip_size, /*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ ulint page_no, /*!< in: page number of the segment
+ header */
+ ib_bh_t* ib_bh, /*!< in/out: rseg queue */
+ mtr_t* mtr) /*!< in: mtr */
{
ulint len;
trx_rseg_t* rseg;
@@ -225,6 +228,9 @@ trx_rseg_mem_create(
len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
if (len > 0) {
+ const void* ptr;
+ rseg_queue_t rseg_queue;
+
trx_sys->rseg_history_len += len;
node_addr = trx_purge_get_log_from_hist(
@@ -240,6 +246,17 @@ trx_rseg_mem_create(
undo_log_hdr + TRX_UNDO_TRX_NO);
rseg->last_del_marks = mtr_read_ulint(
undo_log_hdr + TRX_UNDO_DEL_MARKS, MLOG_2BYTES, mtr);
+
+ rseg_queue.rseg = rseg;
+ rseg_queue.trx_no = rseg->last_trx_no;
+
+ if (rseg->last_page_no != FIL_NULL) {
+ /* There is no need to cover this operation by the purge
+ mutex because we are still bootstrapping. */
+
+ ptr = ib_bh_push(ib_bh, &rseg_queue);
+ ut_a(ptr != NULL);
+ }
} else {
rseg->last_page_no = FIL_NULL;
}
@@ -255,6 +272,7 @@ void
trx_rseg_create_instance(
/*=====================*/
trx_sysf_t* sys_header, /*!< in: trx system header */
+ ib_bh_t* ib_bh, /*!< in/out: rseg queue */
mtr_t* mtr) /*!< in: mtr */
{
ulint i;
@@ -278,7 +296,7 @@ trx_rseg_create_instance(
zip_size = space ? fil_space_get_zip_size(space) : 0;
rseg = trx_rseg_mem_create(
- i, space, zip_size, page_no, mtr);
+ i, space, zip_size, page_no, ib_bh, mtr);
ut_a(rseg->id == i);
}
@@ -327,7 +345,8 @@ trx_rseg_create(void)
zip_size = space ? fil_space_get_zip_size(space) : 0;
rseg = trx_rseg_mem_create(
- slot_no, space, zip_size, page_no, &mtr);
+ slot_no, space, zip_size, page_no,
+ purge_sys->ib_bh, &mtr);
}
mutex_exit(&kernel_mutex);
@@ -342,13 +361,14 @@ UNIV_INTERN
void
trx_rseg_list_and_array_init(
/*=========================*/
- trx_sysf_t* sys_header, /* in: trx system header */
- mtr_t* mtr) /* in: mtr */
+ trx_sysf_t* sys_header, /*!< in: trx system header */
+ ib_bh_t* ib_bh, /*!< in: rseg queue */
+ mtr_t* mtr) /*!< in: mtr */
{
UT_LIST_INIT(trx_sys->rseg_list);
trx_sys->rseg_history_len = 0;
- trx_rseg_create_instance(sys_header, mtr);
+ trx_rseg_create_instance(sys_header, ib_bh, mtr);
}
diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c
index 26498a1b712..8e595353024 100644
--- a/storage/innobase/trx/trx0sys.c
+++ b/storage/innobase/trx/trx0sys.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -37,6 +37,7 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0rseg.h"
#include "trx0undo.h"
#include "srv0srv.h"
+#include "srv0start.h"
#include "trx0purge.h"
#include "log0log.h"
#include "log0recv.h"
@@ -946,6 +947,31 @@ trx_sysf_create(
}
/*****************************************************************//**
+Compare two trx_rseg_t instances on last_trx_no. */
+static
+int
+trx_rseg_compare_last_trx_no(
+/*=========================*/
+ const void* p1, /*!< in: elem to compare */
+ const void* p2) /*!< in: elem to compare */
+{
+ ib_int64_t cmp;
+
+ const rseg_queue_t* rseg_q1 = (const rseg_queue_t*) p1;
+ const rseg_queue_t* rseg_q2 = (const rseg_queue_t*) p2;
+
+ cmp = rseg_q1->trx_no - rseg_q2->trx_no;
+
+ if (cmp < 0) {
+ return(-1);
+ } else if (cmp > 0) {
+ return(1);
+ }
+
+ return(0);
+}
+
+/*****************************************************************//**
Creates and initializes the central memory structures for the transaction
system. This is called when the database is started. */
UNIV_INTERN
@@ -958,6 +984,7 @@ trx_sys_init_at_db_start(void)
const char* unit = "";
trx_t* trx;
mtr_t mtr;
+ ib_bh_t* ib_bh;
mtr_start(&mtr);
@@ -965,11 +992,19 @@ trx_sys_init_at_db_start(void)
mutex_enter(&kernel_mutex);
- trx_sys = mem_alloc(sizeof(trx_sys_t));
+ /* We create the min binary heap here and pass ownership to
+ purge when we init the purge sub-system. Purge is responsible
+ for freeing the binary heap. */
+
+ ib_bh = ib_bh_create(
+ trx_rseg_compare_last_trx_no,
+ sizeof(rseg_queue_t), TRX_SYS_N_RSEGS);
+
+ trx_sys = mem_zalloc(sizeof(*trx_sys));
sys_header = trx_sysf_get(&mtr);
- trx_rseg_list_and_array_init(sys_header, &mtr);
+ trx_rseg_list_and_array_init(sys_header, ib_bh, &mtr);
trx_sys->latest_rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
@@ -1023,7 +1058,8 @@ trx_sys_init_at_db_start(void)
UT_LIST_INIT(trx_sys->view_list);
- trx_purge_sys_create();
+ /* Transfer ownership to purge. */
+ trx_purge_sys_create(ib_bh);
mutex_exit(&kernel_mutex);
@@ -1160,7 +1196,7 @@ trx_sys_file_format_max_check(
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: highest supported file format is %s.\n",
+ " InnoDB: highest supported file format is %s.\n",
trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
if (format_id > DICT_TF_FORMAT_MAX) {
@@ -1169,7 +1205,7 @@ trx_sys_file_format_max_check(
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: %s: the system tablespace is in a file "
+ " InnoDB: %s: the system tablespace is in a file "
"format that this version doesn't support - %s\n",
((max_format_id <= DICT_TF_FORMAT_MAX)
? "Error" : "Warning"),
@@ -1582,10 +1618,12 @@ void
trx_sys_close(void)
/*===============*/
{
+ trx_t* trx;
trx_rseg_t* rseg;
read_view_t* view;
ut_ad(trx_sys != NULL);
+ ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
/* Check that all read views are closed except read view owned
by a purge. */
@@ -1617,6 +1655,13 @@ trx_sys_close(void)
mem_free(trx_doublewrite);
trx_doublewrite = NULL;
+ /* Only prepared transactions may be left in the system. Free them. */
+ ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == trx_n_prepared);
+
+ while ((trx = UT_LIST_GET_FIRST(trx_sys->trx_list)) != NULL) {
+ trx_free_prepared(trx);
+ }
+
/* There can't be any active transactions. */
rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
index 6ef47a8dc16..7b99b86c732 100644
--- a/storage/innobase/trx/trx0trx.c
+++ b/storage/innobase/trx/trx0trx.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -38,10 +38,10 @@ Created 3/26/1996 Heikki Tuuri
#include "usr0sess.h"
#include "read0read.h"
#include "srv0srv.h"
-#include "thr0loc.h"
#include "btr0sea.h"
#include "os0proc.h"
#include "trx0xa.h"
+#include "trx0purge.h"
#include "ha_prototypes.h"
/** Dummy session used currently in MySQL interface */
@@ -50,6 +50,9 @@ UNIV_INTERN sess_t* trx_dummy_sess = NULL;
/** Number of transactions currently allocated for MySQL: protected by
the kernel mutex */
UNIV_INTERN ulint trx_n_mysql_transactions = 0;
+/** Number of transactions currently in the XA PREPARED state: protected by
+the kernel mutex */
+UNIV_INTERN ulint trx_n_prepared = 0;
#ifdef UNIV_PFS_MUTEX
/* Key to register the mutex with performance schema */
@@ -105,7 +108,11 @@ trx_create(
trx->is_purge = 0;
trx->is_recovered = 0;
trx->conc_state = TRX_NOT_STARTED;
- trx->start_time = time(NULL);
+
+ trx->is_registered = 0;
+ trx->owns_prepare_mutex = 0;
+
+ trx->start_time = ut_time();
trx->isolation_level = TRX_ISO_REPEATABLE_READ;
@@ -124,7 +131,6 @@ trx_create(
trx->table_id = 0;
trx->mysql_thd = NULL;
- trx->active_trans = 0;
trx->duplicates = 0;
trx->n_mysql_tables_in_use = 0;
@@ -211,10 +217,6 @@ trx_allocate_for_mysql(void)
mutex_exit(&kernel_mutex);
- trx->mysql_thread_id = os_thread_get_curr_id();
-
- trx->mysql_process_no = os_proc_get_number();
-
return(trx);
}
@@ -339,6 +341,60 @@ trx_free(
}
/********************************************************************//**
+At shutdown, frees a transaction object that is in the PREPARED state. */
+UNIV_INTERN
+void
+trx_free_prepared(
+/*==============*/
+ trx_t* trx) /*!< in, own: trx object */
+{
+ ut_ad(mutex_own(&kernel_mutex));
+ ut_a(trx->conc_state == TRX_PREPARED);
+ ut_a(trx->magic_n == TRX_MAGIC_N);
+
+ /* Prepared transactions are sort of active; they allow
+ ROLLBACK and COMMIT operations. Because the system does not
+ contain any other transactions than prepared transactions at
+ the shutdown stage and because a transaction cannot become
+ PREPARED while holding locks, it is safe to release the locks
+ held by PREPARED transactions here at shutdown.*/
+ lock_release_off_kernel(trx);
+
+ trx_undo_free_prepared(trx);
+
+ mutex_free(&trx->undo_mutex);
+
+ if (trx->undo_no_arr) {
+ trx_undo_arr_free(trx->undo_no_arr);
+ }
+
+ ut_a(UT_LIST_GET_LEN(trx->signals) == 0);
+ ut_a(UT_LIST_GET_LEN(trx->reply_signals) == 0);
+
+ ut_a(trx->wait_lock == NULL);
+ ut_a(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
+
+ ut_a(!trx->has_search_latch);
+
+ ut_a(trx->dict_operation_lock_mode == 0);
+
+ if (trx->lock_heap) {
+ mem_heap_free(trx->lock_heap);
+ }
+
+ if (trx->global_read_view_heap) {
+ mem_heap_free(trx->global_read_view_heap);
+ }
+
+ ut_a(ib_vector_is_empty(trx->autoinc_locks));
+ ib_vector_free(trx->autoinc_locks);
+
+ UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
+
+ mem_free(trx);
+}
+
+/********************************************************************//**
Frees a transaction object for MySQL. */
UNIV_INTERN
void
@@ -468,6 +524,7 @@ trx_lists_init_at_db_start(void)
if (srv_force_recovery == 0) {
trx->conc_state = TRX_PREPARED;
+ trx_n_prepared++;
} else {
fprintf(stderr,
"InnoDB: Since"
@@ -544,6 +601,7 @@ trx_lists_init_at_db_start(void)
trx->conc_state
= TRX_PREPARED;
+ trx_n_prepared++;
} else {
fprintf(stderr,
"InnoDB: Since"
@@ -601,36 +659,26 @@ trx_lists_init_at_db_start(void)
/******************************************************************//**
Assigns a rollback segment to a transaction in a round-robin fashion.
-Skips the SYSTEM rollback segment if another is available.
-@return assigned rollback segment id */
+@return assigned rollback segment instance */
UNIV_INLINE
-ulint
-trx_assign_rseg(void)
-/*=================*/
+trx_rseg_t*
+trx_assign_rseg(
+/*============*/
+ ulint max_undo_logs) /*!< in: maximum number of UNDO logs to use */
{
- trx_rseg_t* rseg = trx_sys->latest_rseg;
+ trx_rseg_t* rseg = trx_sys->latest_rseg;
ut_ad(mutex_own(&kernel_mutex));
-loop:
- /* Get next rseg in a round-robin fashion */
rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
- if (rseg == NULL) {
+ if (rseg == NULL || rseg->id == max_undo_logs - 1) {
rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
}
- /* If it is the SYSTEM rollback segment, and there exist others, skip
- it */
-
- if ((rseg->id == TRX_SYS_SYSTEM_RSEG_ID)
- && (UT_LIST_GET_LEN(trx_sys->rseg_list) > 1)) {
- goto loop;
- }
-
trx_sys->latest_rseg = rseg;
- return(rseg->id);
+ return(rseg);
}
/****************************************************************//**
@@ -660,12 +708,9 @@ trx_start_low(
ut_ad(trx->conc_state != TRX_ACTIVE);
- if (rseg_id == ULINT_UNDEFINED) {
-
- rseg_id = trx_assign_rseg();
- }
+ ut_a(rseg_id == ULINT_UNDEFINED);
- rseg = trx_sys_get_nth_rseg(trx_sys, rseg_id);
+ rseg = trx_assign_rseg(srv_rollback_segments);
trx->id = trx_sys_get_new_trx_id();
@@ -716,110 +761,186 @@ trx_start(
}
/****************************************************************//**
-Commits a transaction. */
-UNIV_INTERN
+Set the transaction serialisation number. */
+static
void
-trx_commit_off_kernel(
-/*==================*/
- trx_t* trx) /*!< in: transaction */
+trx_serialisation_number_get(
+/*=========================*/
+ trx_t* trx) /*!< in: transaction */
{
- page_t* update_hdr_page;
- ib_uint64_t lsn = 0;
trx_rseg_t* rseg;
- trx_undo_t* undo;
- mtr_t mtr;
- ut_ad(mutex_own(&kernel_mutex));
+ rseg = trx->rseg;
- trx->must_flush_log_later = FALSE;
+ ut_ad(mutex_own(&rseg->mutex));
- rseg = trx->rseg;
+ mutex_enter(&kernel_mutex);
- if (trx->insert_undo != NULL || trx->update_undo != NULL) {
+ trx->no = trx_sys_get_new_trx_id();
+
+ /* If the rollack segment is not empty then the
+ new trx_t::no can't be less than any trx_t::no
+ already in the rollback segment. User threads only
+ produce events when a rollback segment is empty. */
+
+ if (rseg->last_page_no == FIL_NULL) {
+ void* ptr;
+ rseg_queue_t rseg_queue;
+
+ rseg_queue.rseg = rseg;
+ rseg_queue.trx_no = trx->no;
+
+ mutex_enter(&purge_sys->bh_mutex);
+
+ /* This is to reduce the pressure on the kernel mutex,
+ though in reality it should make very little (read no)
+ difference because this code path is only taken when the
+ rbs is empty. */
mutex_exit(&kernel_mutex);
- mtr_start(&mtr);
+ ptr = ib_bh_push(purge_sys->ib_bh, &rseg_queue);
+ ut_a(ptr);
- /* Change the undo log segment states from TRX_UNDO_ACTIVE
- to some other state: these modifications to the file data
- structure define the transaction as committed in the file
- based world, at the serialization point of the log sequence
- number lsn obtained below. */
+ mutex_exit(&purge_sys->bh_mutex);
+ } else {
+ mutex_exit(&kernel_mutex);
+ }
+}
- mutex_enter(&(rseg->mutex));
+/****************************************************************//**
+Assign the transaction its history serialisation number and write the
+update UNDO log record to the assigned rollback segment.
+@return the LSN of the UNDO log write. */
+static
+ib_uint64_t
+trx_write_serialisation_history(
+/*============================*/
+ trx_t* trx) /*!< in: transaction */
+{
+ mtr_t mtr;
+ trx_rseg_t* rseg;
- if (trx->insert_undo != NULL) {
- trx_undo_set_state_at_finish(
- rseg, trx, trx->insert_undo, &mtr);
- }
+ ut_ad(!mutex_own(&kernel_mutex));
- undo = trx->update_undo;
+ rseg = trx->rseg;
- if (undo) {
- mutex_enter(&kernel_mutex);
- trx->no = trx_sys_get_new_trx_no();
- mutex_exit(&kernel_mutex);
+ mtr_start(&mtr);
- /* It is not necessary to obtain trx->undo_mutex here
- because only a single OS thread is allowed to do the
- transaction commit for this transaction. */
+ /* Change the undo log segment states from TRX_UNDO_ACTIVE
+ to some other state: these modifications to the file data
+ structure define the transaction as committed in the file
+ based domain, at the serialization point of the log sequence
+ number lsn obtained below. */
- update_hdr_page = trx_undo_set_state_at_finish(
- rseg, trx, undo, &mtr);
+ if (trx->update_undo != NULL) {
+ page_t* undo_hdr_page;
+ trx_undo_t* undo = trx->update_undo;
- /* We have to do the cleanup for the update log while
- holding the rseg mutex because update log headers
- have to be put to the history list in the order of
- the trx number. */
+ /* We have to hold the rseg mutex because update
+ log headers have to be put to the history list in the
+ (serialisation) order of the UNDO trx number. This is
+ required for the purge in-memory data structures too. */
- trx_undo_update_cleanup(trx, update_hdr_page, &mtr);
- }
+ mutex_enter(&rseg->mutex);
- mutex_exit(&(rseg->mutex));
+ /* Assign the transaction serialisation number and also
+ update the purge min binary heap if this is the first
+ UNDO log being written to the assigned rollback segment. */
- /* Update the latest MySQL binlog name and offset info
- in trx sys header if MySQL binlogging is on or the database
- server is a MySQL replication slave */
-
- if (trx->mysql_log_file_name
- && trx->mysql_log_file_name[0] != '\0') {
- trx_sys_update_mysql_binlog_offset(
- trx->mysql_log_file_name,
- trx->mysql_log_offset,
- TRX_SYS_MYSQL_LOG_INFO, &mtr);
- trx->mysql_log_file_name = NULL;
- }
+ trx_serialisation_number_get(trx);
- /* The following call commits the mini-transaction, making the
- whole transaction committed in the file-based world, at this
- log sequence number. The transaction becomes 'durable' when
- we write the log to disk, but in the logical sense the commit
- in the file-based data structures (undo logs etc.) happens
- here.
-
- NOTE that transaction numbers, which are assigned only to
- transactions with an update undo log, do not necessarily come
- in exactly the same order as commit lsn's, if the transactions
- have different rollback segments. To get exactly the same
- order we should hold the kernel mutex up to this point,
- adding to the contention of the kernel mutex. However, if
- a transaction T2 is able to see modifications made by
- a transaction T1, T2 will always get a bigger transaction
- number and a bigger commit lsn than T1. */
+ /* It is not necessary to obtain trx->undo_mutex here
+ because only a single OS thread is allowed to do the
+ transaction commit for this transaction. */
- /*--------------*/
- mtr_commit(&mtr);
- /*--------------*/
- lsn = mtr.end_lsn;
+ undo_hdr_page = trx_undo_set_state_at_finish(undo, &mtr);
+
+ trx_undo_update_cleanup(trx, undo_hdr_page, &mtr);
+ } else {
+ mutex_enter(&rseg->mutex);
+ }
+
+ if (trx->insert_undo != NULL) {
+ trx_undo_set_state_at_finish(trx->insert_undo, &mtr);
+ }
+
+ mutex_exit(&rseg->mutex);
+
+ /* Update the latest MySQL binlog name and offset info
+ in trx sys header if MySQL binlogging is on or the database
+ server is a MySQL replication slave */
+
+ if (trx->mysql_log_file_name
+ && trx->mysql_log_file_name[0] != '\0') {
+
+ trx_sys_update_mysql_binlog_offset(
+ trx->mysql_log_file_name,
+ trx->mysql_log_offset,
+ TRX_SYS_MYSQL_LOG_INFO, &mtr);
+
+ trx->mysql_log_file_name = NULL;
+ }
+
+ /* The following call commits the mini-transaction, making the
+ whole transaction committed in the file-based world, at this
+ log sequence number. The transaction becomes 'durable' when
+ we write the log to disk, but in the logical sense the commit
+ in the file-based data structures (undo logs etc.) happens
+ here.
+
+ NOTE that transaction numbers, which are assigned only to
+ transactions with an update undo log, do not necessarily come
+ in exactly the same order as commit lsn's, if the transactions
+ have different rollback segments. To get exactly the same
+ order we should hold the kernel mutex up to this point,
+ adding to the contention of the kernel mutex. However, if
+ a transaction T2 is able to see modifications made by
+ a transaction T1, T2 will always get a bigger transaction
+ number and a bigger commit lsn than T1. */
+
+ /*--------------*/
+ mtr_commit(&mtr);
+ /*--------------*/
+
+ return(mtr.end_lsn);
+}
+
+/****************************************************************//**
+Commits a transaction. */
+UNIV_INTERN
+void
+trx_commit_off_kernel(
+/*==================*/
+ trx_t* trx) /*!< in: transaction */
+{
+ ib_uint64_t lsn;
+
+ ut_ad(mutex_own(&kernel_mutex));
+
+ trx->must_flush_log_later = FALSE;
+
+ /* If the transaction made any updates then we need to write the
+ UNDO logs for the updates to the assigned rollback segment. */
+
+ if (trx->insert_undo != NULL || trx->update_undo != NULL) {
+ mutex_exit(&kernel_mutex);
+
+ lsn = trx_write_serialisation_history(trx);
mutex_enter(&kernel_mutex);
+ } else {
+ lsn = 0;
}
- ut_ad(trx->conc_state == TRX_ACTIVE
- || trx->conc_state == TRX_PREPARED);
+ ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED);
ut_ad(mutex_own(&kernel_mutex));
+ if (UNIV_UNLIKELY(trx->conc_state == TRX_PREPARED)) {
+ ut_a(trx_n_prepared > 0);
+ trx_n_prepared--;
+ }
+
/* The following assignment makes the transaction committed in memory
and makes its changes to data visible to other transactions.
NOTE that there is a small discrepancy from the strict formal
@@ -1668,12 +1789,6 @@ trx_print(
fprintf(f, " state %lu", (ulong) trx->conc_state);
}
-#ifdef UNIV_LINUX
- fprintf(f, ", process no %lu", trx->mysql_process_no);
-#endif
- fprintf(f, ", OS thread id %lu",
- (ulong) os_thread_pf(trx->mysql_thread_id));
-
if (*trx->op_info) {
putc(' ', f);
fputs(trx->op_info, f);
@@ -1850,6 +1965,7 @@ trx_prepare_off_kernel(
/*--------------------------------------*/
trx->conc_state = TRX_PREPARED;
+ trx_n_prepared++;
/*--------------------------------------*/
if (lsn) {
@@ -2002,18 +2118,18 @@ trx_recover_for_mysql(
/*******************************************************************//**
This function is used to find one X/Open XA distributed transaction
which is in the prepared state
-@return trx or NULL */
+@return trx or NULL; on match, the trx->xid will be invalidated */
UNIV_INTERN
trx_t*
trx_get_trx_by_xid(
/*===============*/
- XID* xid) /*!< in: X/Open XA transaction identification */
+ const XID* xid) /*!< in: X/Open XA transaction identifier */
{
trx_t* trx;
if (xid == NULL) {
- return (NULL);
+ return(NULL);
}
mutex_enter(&kernel_mutex);
@@ -2026,10 +2142,17 @@ trx_get_trx_by_xid(
of gtrid_length+bqual_length bytes should be
the same */
- if (xid->gtrid_length == trx->xid.gtrid_length
+ if (trx->is_recovered
+ && trx->conc_state == TRX_PREPARED
+ && xid->gtrid_length == trx->xid.gtrid_length
&& xid->bqual_length == trx->xid.bqual_length
&& memcmp(xid->data, trx->xid.data,
xid->gtrid_length + xid->bqual_length) == 0) {
+
+ /* Invalidate the XID, so that subsequent calls
+ will not find it. */
+ memset(&trx->xid, 0, sizeof(trx->xid));
+ trx->xid.formatID = -1;
break;
}
@@ -2038,14 +2161,5 @@ trx_get_trx_by_xid(
mutex_exit(&kernel_mutex);
- if (trx) {
- if (trx->conc_state != TRX_PREPARED) {
-
- return(NULL);
- }
-
- return(trx);
- } else {
- return(NULL);
- }
+ return(trx);
}
diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c
index 9162c82e423..4cb4b7b79c5 100644
--- a/storage/innobase/trx/trx0undo.c
+++ b/storage/innobase/trx/trx0undo.c
@@ -36,6 +36,7 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0rseg.h"
#include "trx0trx.h"
#include "srv0srv.h"
+#include "srv0start.h"
#include "trx0rec.h"
#include "trx0purge.h"
@@ -1798,8 +1799,6 @@ UNIV_INTERN
page_t*
trx_undo_set_state_at_finish(
/*=========================*/
- trx_rseg_t* rseg, /*!< in: rollback segment memory object */
- trx_t* trx __attribute__((unused)), /*!< in: transaction */
trx_undo_t* undo, /*!< in: undo log memory copy */
mtr_t* mtr) /*!< in: mtr */
{
@@ -1808,10 +1807,8 @@ trx_undo_set_state_at_finish(
page_t* undo_page;
ulint state;
- ut_ad(trx);
ut_ad(undo);
ut_ad(mtr);
- ut_ad(mutex_own(&rseg->mutex));
if (undo->id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
@@ -1830,19 +1827,7 @@ trx_undo_set_state_at_finish(
&& mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
< TRX_UNDO_PAGE_REUSE_LIMIT) {
- /* This is a heuristic to avoid the problem of all UNDO
- slots ending up in one of the UNDO lists. Previously if
- the server crashed with all the slots in one of the lists,
- transactions that required the slots of a different type
- would fail for lack of slots. */
-
- if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500
- && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) {
-
- state = TRX_UNDO_CACHED;
- } else {
- state = TRX_UNDO_TO_FREE;
- }
+ state = TRX_UNDO_CACHED;
} else if (undo->type == TRX_UNDO_INSERT) {
@@ -1991,4 +1976,28 @@ trx_undo_insert_cleanup(
mutex_exit(&(rseg->mutex));
}
+
+/********************************************************************//**
+At shutdown, frees the undo logs of a PREPARED transaction. */
+UNIV_INTERN
+void
+trx_undo_free_prepared(
+/*===================*/
+ trx_t* trx) /*!< in/out: PREPARED transaction */
+{
+ ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
+
+ if (trx->update_undo) {
+ ut_a(trx->update_undo->state == TRX_UNDO_PREPARED);
+ UT_LIST_REMOVE(undo_list, trx->rseg->update_undo_list,
+ trx->update_undo);
+ trx_undo_mem_free(trx->update_undo);
+ }
+ if (trx->insert_undo) {
+ ut_a(trx->insert_undo->state == TRX_UNDO_PREPARED);
+ UT_LIST_REMOVE(undo_list, trx->rseg->insert_undo_list,
+ trx->insert_undo);
+ trx_undo_mem_free(trx->insert_undo);
+ }
+}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innobase/ut/ut0auxconf_atomic_pthread_t_gcc.c b/storage/innobase/ut/ut0auxconf_atomic_pthread_t_gcc.c
deleted file mode 100644
index 30de5aa6f17..00000000000
--- a/storage/innobase/ut/ut0auxconf_atomic_pthread_t_gcc.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/*****************************************************************************
-If this program compiles, then pthread_t objects can be used as arguments
-to GCC atomic builtin functions.
-
-Created March 5, 2009 Vasil Dimov
-*****************************************************************************/
-
-#include <pthread.h>
-#include <string.h>
-
-int
-main(int argc, char** argv)
-{
- pthread_t x1;
- pthread_t x2;
- pthread_t x3;
-
- memset(&x1, 0x0, sizeof(x1));
- memset(&x2, 0x0, sizeof(x2));
- memset(&x3, 0x0, sizeof(x3));
-
- __sync_bool_compare_and_swap(&x1, x2, x3);
-
- return(0);
-}
diff --git a/storage/innobase/ut/ut0auxconf_atomic_pthread_t_solaris.c b/storage/innobase/ut/ut0auxconf_atomic_pthread_t_solaris.c
deleted file mode 100644
index 310603c7503..00000000000
--- a/storage/innobase/ut/ut0auxconf_atomic_pthread_t_solaris.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/*****************************************************************************
-If this program compiles and returns 0, then pthread_t objects can be used as
-arguments to Solaris libc atomic functions.
-
-Created April 18, 2009 Vasil Dimov
-*****************************************************************************/
-
-#include <pthread.h>
-#include <string.h>
-
-int
-main(int argc, char** argv)
-{
- pthread_t x1;
- pthread_t x2;
- pthread_t x3;
-
- memset(&x1, 0x0, sizeof(x1));
- memset(&x2, 0x0, sizeof(x2));
- memset(&x3, 0x0, sizeof(x3));
-
- if (sizeof(pthread_t) == 4) {
-
- atomic_cas_32(&x1, x2, x3);
-
- } else if (sizeof(pthread_t) == 8) {
-
- atomic_cas_64(&x1, x2, x3);
-
- } else {
-
- return(1);
- }
-
- return(0);
-}
diff --git a/storage/innobase/ut/ut0auxconf_have_gcc_atomics.c b/storage/innobase/ut/ut0auxconf_have_gcc_atomics.c
deleted file mode 100644
index da5c13d7d79..00000000000
--- a/storage/innobase/ut/ut0auxconf_have_gcc_atomics.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/*****************************************************************************
-If this program compiles and returns 0, then GCC atomic funcions are available.
-
-Created September 12, 2009 Vasil Dimov
-*****************************************************************************/
-
-int
-main(int argc, char** argv)
-{
- long x;
- long y;
- long res;
- char c;
-
- x = 10;
- y = 123;
- res = __sync_bool_compare_and_swap(&x, x, y);
- if (!res || x != y) {
- return(1);
- }
-
- x = 10;
- y = 123;
- res = __sync_bool_compare_and_swap(&x, x + 1, y);
- if (res || x != 10) {
- return(1);
- }
-
- x = 10;
- y = 123;
- res = __sync_add_and_fetch(&x, y);
- if (res != 123 + 10 || x != 123 + 10) {
- return(1);
- }
-
- c = 10;
- res = __sync_lock_test_and_set(&c, 123);
- if (res != 10 || c != 123) {
- return(1);
- }
-
- return(0);
-}
diff --git a/storage/innobase/ut/ut0auxconf_have_solaris_atomics.c b/storage/innobase/ut/ut0auxconf_have_solaris_atomics.c
deleted file mode 100644
index 7eb704edd4b..00000000000
--- a/storage/innobase/ut/ut0auxconf_have_solaris_atomics.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/*****************************************************************************
-If this program compiles, then Solaris libc atomic funcions are available.
-
-Created April 18, 2009 Vasil Dimov
-*****************************************************************************/
-#include <atomic.h>
-
-int
-main(int argc, char** argv)
-{
- ulong_t ulong = 0;
- uint32_t uint32 = 0;
- uint64_t uint64 = 0;
-
- atomic_cas_ulong(&ulong, 0, 1);
- atomic_cas_32(&uint32, 0, 1);
- atomic_cas_64(&uint64, 0, 1);
- atomic_add_long(&ulong, 0);
-
- return(0);
-}
diff --git a/storage/innobase/ut/ut0auxconf_pause.c b/storage/innobase/ut/ut0auxconf_pause.c
deleted file mode 100644
index 54d63bdd9bc..00000000000
--- a/storage/innobase/ut/ut0auxconf_pause.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/*****************************************************************************
-If this program compiles and can be run and returns 0, then the pause
-instruction is available.
-
-Created Jul 21, 2009 Vasil Dimov
-*****************************************************************************/
-
-int
-main(int argc, char** argv)
-{
- __asm__ __volatile__ ("pause");
-
- return(0);
-}
diff --git a/storage/innobase/ut/ut0auxconf_sizeof_pthread_t.c b/storage/innobase/ut/ut0auxconf_sizeof_pthread_t.c
deleted file mode 100644
index 96add4526ef..00000000000
--- a/storage/innobase/ut/ut0auxconf_sizeof_pthread_t.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/*****************************************************************************
-This program should compile and when run, print a single line like:
-#define SIZEOF_PTHREAD_T %d
-
-Created April 18, 2009 Vasil Dimov
-*****************************************************************************/
-
-#include <stdio.h>
-#include <pthread.h>
-
-int
-main(int argc, char** argv)
-{
- printf("#define SIZEOF_PTHREAD_T %d\n", (int) sizeof(pthread_t));
-
- return(0);
-}
diff --git a/storage/innobase/ut/ut0bh.c b/storage/innobase/ut/ut0bh.c
new file mode 100644
index 00000000000..ae0b1aff207
--- /dev/null
+++ b/storage/innobase/ut/ut0bh.c
@@ -0,0 +1,164 @@
+/***************************************************************************//**
+Copyright (c) 2010, 2011, Oracle Corpn. All Rights Reserved.
+
+Portions of this file contain modifications contributed and copyrighted by
+Sun Microsystems, Inc. Those modifications are gratefully acknowledged and
+are described briefly in the InnoDB documentation. The contributions by
+Sun Microsystems are incorporated with their permission, and subject to the
+conditions contained in the file COPYING.Sun_Microsystems.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/******************************************************************//**
+@file ut/ut0bh.c
+Binary min-heap implementation.
+
+Created 2010-05-28 by Sunny Bains
+*******************************************************/
+
+#include "ut0bh.h"
+#include "ut0mem.h"
+
+#ifdef UNIV_NONINL
+#include "ut0bh.ic"
+#endif
+
+#include <string.h>
+
+/**********************************************************************//**
+Create a binary heap.
+@return a new binary heap */
+UNIV_INTERN
+ib_bh_t*
+ib_bh_create(
+/*=========*/
+ ib_bh_cmp_t compare, /*!< in: comparator */
+ ulint sizeof_elem, /*!< in: size of one element */
+ ulint max_elems) /*!< in: max elements allowed */
+{
+ ulint sz;
+ ib_bh_t* ib_bh;
+
+ sz = sizeof(*ib_bh) + (sizeof_elem * max_elems);
+
+ ib_bh = (ib_bh_t*) ut_malloc(sz);
+ memset(ib_bh, 0x0, sz);
+
+ ib_bh->compare = compare;
+ ib_bh->max_elems = max_elems;
+ ib_bh->sizeof_elem = sizeof_elem;
+
+ return(ib_bh);
+}
+
+/**********************************************************************//**
+Free a binary heap.
+@return a new binary heap */
+UNIV_INTERN
+void
+ib_bh_free(
+/*=======*/
+ ib_bh_t* ib_bh) /*!< in/own: instance */
+{
+ ut_free(ib_bh);
+}
+
+/**********************************************************************//**
+Add an element to the binary heap. Note: The element is copied.
+@return pointer to added element or NULL if full. */
+UNIV_INTERN
+void*
+ib_bh_push(
+/*=======*/
+ ib_bh_t* ib_bh, /*!< in/out: instance */
+ const void* elem) /*!< in: element to add */
+{
+ void* ptr;
+
+ if (ib_bh_is_full(ib_bh)) {
+ return(NULL);
+ } else if (ib_bh_is_empty(ib_bh)) {
+ ++ib_bh->n_elems;
+ return(ib_bh_set(ib_bh, 0, elem));
+ } else {
+ ulint i;
+
+ i = ib_bh->n_elems;
+
+ ++ib_bh->n_elems;
+
+ for (ptr = ib_bh_get(ib_bh, i >> 1);
+ i > 0 && ib_bh->compare(ptr, elem) > 0;
+ i >>= 1, ptr = ib_bh_get(ib_bh, i >> 1)) {
+
+ ib_bh_set(ib_bh, i, ptr);
+ }
+
+ ptr = ib_bh_set(ib_bh, i, elem);
+ }
+
+ return(ptr);
+}
+
+/**********************************************************************//**
+Remove the first element from the binary heap. */
+UNIV_INTERN
+void
+ib_bh_pop(
+/*======*/
+ ib_bh_t* ib_bh) /*!< in/out: instance */
+{
+ byte* ptr;
+ byte* last;
+ ulint parent = 0;
+
+ if (ib_bh_is_empty(ib_bh)) {
+ return;
+ } else if (ib_bh_size(ib_bh) == 1) {
+ --ib_bh->n_elems;
+ return;
+ }
+
+ last = (byte*) ib_bh_last(ib_bh);
+
+ /* Start from the child node */
+ ptr = (byte*) ib_bh_get(ib_bh, 1);
+
+ while (ptr < last) {
+ /* If the "right" child node is < "left" child node */
+ if (ib_bh->compare(ptr + ib_bh->sizeof_elem, ptr) < 0) {
+ ptr += ib_bh->sizeof_elem;
+ }
+
+ if (ib_bh->compare(last, ptr) <= 0) {
+ break;
+ }
+
+ ib_bh_set(ib_bh, parent, ptr);
+
+ parent = (ptr - (byte*) ib_bh_first(ib_bh))
+ / ib_bh->sizeof_elem;
+
+ if ((parent << 1) >= ib_bh_size(ib_bh)) {
+ break;
+ }
+
+ ptr = (byte*) ib_bh_get(ib_bh, parent << 1);
+ }
+
+ --ib_bh->n_elems;
+
+ ib_bh_set(ib_bh, parent, last);
+}
diff --git a/storage/innobase/ut/ut0dbg.c b/storage/innobase/ut/ut0dbg.c
index e79217d5b86..64fadd76d1c 100644
--- a/storage/innobase/ut/ut0dbg.c
+++ b/storage/innobase/ut/ut0dbg.c
@@ -25,6 +25,7 @@ Created 1/30/1994 Heikki Tuuri
#include "univ.i"
#include "ut0dbg.h"
+#include "ha_prototypes.h"
#if defined(__GNUC__) && (__GNUC__ > 2)
#else
@@ -55,12 +56,13 @@ ut_dbg_assertion_failed(
ut_print_timestamp(stderr);
#ifdef UNIV_HOTBACKUP
fprintf(stderr, " InnoDB: Assertion failure in file %s line %lu\n",
- file, line);
+ innobase_basename(file), line);
#else /* UNIV_HOTBACKUP */
fprintf(stderr,
" InnoDB: Assertion failure in thread %lu"
" in file %s line %lu\n",
- os_thread_pf(os_thread_get_curr_id()), file, line);
+ os_thread_pf(os_thread_get_curr_id()),
+ innobase_basename(file), line);
#endif /* UNIV_HOTBACKUP */
if (expr) {
fprintf(stderr,
@@ -74,7 +76,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;
@@ -93,7 +95,8 @@ ut_dbg_stop_thread(
{
#ifndef UNIV_HOTBACKUP
fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n",
- os_thread_pf(os_thread_get_curr_id()), file, line);
+ os_thread_pf(os_thread_get_curr_id()),
+ innobase_basename(file), line);
os_thread_sleep(1000000000);
#endif /* !UNIV_HOTBACKUP */
}
diff --git a/storage/innobase/ut/ut0ut.c b/storage/innobase/ut/ut0ut.c
index 39978304696..a9c0d381e16 100644
--- a/storage/innobase/ut/ut0ut.c
+++ b/storage/innobase/ut/ut0ut.c
@@ -1,13 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
-Copyright (c) 2009, Sun Microsystems, Inc.
-
-Portions of this file contain modifications contributed and copyrighted by
-Sun Microsystems, Inc. Those modifications are gratefully acknowledged and
-are described briefly in the InnoDB documentation. The contributions by
-Sun Microsystems are incorporated with their permission, and subject to the
-conditions contained in the file COPYING.Sun_Microsystems.
+Copyright (c) 2011, Oracle Corpn. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -669,6 +662,8 @@ ut_strerr(
return("Table is being used");
case DB_TOO_BIG_RECORD:
return("Record too big");
+ case DB_TOO_BIG_INDEX_COL:
+ return("Index columns size too big");
case DB_LOCK_WAIT_TIMEOUT:
return("Lock wait timeout");
case DB_NO_REFERENCED_ROW:
@@ -693,6 +688,8 @@ ut_strerr(
return("Lock structs have exhausted the buffer pool");
case DB_FOREIGN_DUPLICATE_KEY:
return("Foreign key activated with duplicate keys");
+ case DB_FOREIGN_EXCEED_MAX_CASCADE:
+ return("Foreign key cascade delete/update exceeds max depth");
case DB_TOO_MANY_CONCURRENT_TRXS:
return("Too many concurrent transactions");
case DB_UNSUPPORTED:
@@ -713,6 +710,10 @@ ut_strerr(
return("Zip overflow");
case DB_RECORD_NOT_FOUND:
return("Record not found");
+ case DB_CHILD_NO_INDEX:
+ return("No index on referencing keys in referencing table");
+ case DB_PARENT_NO_INDEX:
+ return("No index on referenced keys in referenced table");
case DB_END_OF_INDEX:
return("End of index");
/* do not add default: in order to produce a warning if new code
diff --git a/storage/myisam/Makefile.am b/storage/myisam/Makefile.am
deleted file mode 100644
index 5d8a5e9753b..00000000000
--- a/storage/myisam/Makefile.am
+++ /dev/null
@@ -1,169 +0,0 @@
-# Copyright (C) 2000-2006 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
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir)
-WRAPLIBS=
-
-LDADD =
-
-DEFS = @DEFS@
-
-EXTRA_DIST = mi_test_all.sh mi_test_all.res CMakeLists.txt plug.in
-pkgdata_DATA =
-
-pkglib_LIBRARIES = libmyisam.a
-bin_PROGRAMS = myisamchk myisamlog myisampack myisam_ftdump
-myisamchk_DEPENDENCIES= $(LIBRARIES)
-myisamchk_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-myisamlog_DEPENDENCIES= $(LIBRARIES)
-myisamlog_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-myisampack_DEPENDENCIES=$(LIBRARIES)
-myisampack_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-noinst_PROGRAMS = mi_test1 mi_test2 mi_test3 rt_test sp_test
-noinst_HEADERS = myisamdef.h rt_index.h rt_key.h rt_mbr.h sp_defs.h \
- fulltext.h ftdefs.h ha_myisam.h mi_extrafunc.h
-mi_test1_DEPENDENCIES= $(LIBRARIES)
-mi_test1_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-mi_test2_DEPENDENCIES= $(LIBRARIES)
-mi_test2_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-mi_test3_DEPENDENCIES= $(LIBRARIES)
-mi_test3_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-myisam_ftdump_DEPENDENCIES= $(LIBRARIES)
-myisam_ftdump_LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-rt_test_DEPENDENCIES= $(LIBRARIES)
-rt_test_LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-sp_test_DEPENDENCIES= $(LIBRARIES)
-sp_test_LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
- mi_rnext.c mi_rnext_same.c \
- mi_search.c mi_page.c mi_key.c mi_locking.c \
- mi_rrnd.c mi_scan.c mi_cache.c \
- mi_statrec.c mi_packrec.c mi_dynrec.c \
- mi_update.c mi_write.c mi_unique.c \
- mi_delete.c \
- mi_rprev.c mi_rfirst.c mi_rlast.c mi_rsame.c \
- mi_rsamepos.c mi_panic.c mi_close.c mi_create.c\
- mi_range.c mi_dbug.c mi_checksum.c mi_log.c \
- mi_changed.c mi_static.c mi_delete_all.c \
- mi_delete_table.c mi_rename.c mi_check.c \
- mi_keycache.c mi_preload.c \
- ft_parser.c ft_stopwords.c ft_static.c \
- ft_update.c ft_boolean_search.c ft_nlq_search.c \
- sort.c ha_myisam.cc ft_myisam.c \
- rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c
-CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all rt_test.MY? sp_test.MY?
-
-# Move to automake rules ?
-prolint:; plparse -b -u -hF1 "-width(0,0)" "-format=%f:%l:\s%t:%n\s%m" \
- "-elib(????)" "+elib(?3??)" my.lnt $(nisam_SOURCES)
-
-SUFFIXES = .sh
-
-.sh:
- @RM@ -f $@ $@-t
- @SED@ \
- -e 's!@''bindir''@!$(bindir)!g' \
- -e 's!@''scriptdir''@!$(bindir)!g' \
- -e 's!@''prefix''@!$(prefix)!g' \
- -e 's!@''datadir''@!$(datadir)!g' \
- -e 's!@''localstatedir''@!$(localstatedir)!g' \
- -e 's!@''libexecdir''@!$(libexecdir)!g' \
- -e 's!@''CC''@!@CC@!'\
- -e 's!@''CXX''@!@CXX@!'\
- -e 's!@''GXX''@!@GXX@!'\
- -e 's!@''PERL''@!@PERL@!' \
- -e 's!@''CFLAGS''@!@SAVE_CFLAGS@!'\
- -e 's!@''CXXFLAGS''@!@SAVE_CXXFLAGS@!'\
- -e 's!@''LDFLAGS''@!@SAVE_LDFLAGS@!'\
- -e 's!@''VERSION''@!@VERSION@!' \
- -e 's!@''MYSQL_SERVER_SUFFIX''@!@MYSQL_SERVER_SUFFIX@!' \
- -e 's!@''COMPILATION_COMMENT''@!@COMPILATION_COMMENT@!' \
- -e 's!@''MACHINE_TYPE''@!@MACHINE_TYPE@!' \
- -e 's!@''HOSTNAME''@!@HOSTNAME@!' \
- -e 's!@''SYSTEM_TYPE''@!@SYSTEM_TYPE@!' \
- -e 's!@''CHECK_PID''@!@CHECK_PID@!' \
- -e 's!@''FIND_PROC''@!@FIND_PROC@!' \
- -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \
- -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \
- -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \
- -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \
- -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \
- -e 's!@''sysconfdir''@!@sysconfdir@!' \
- -e 's!@''SHORT_MYSQL_INTRO''@!@SHORT_MYSQL_INTRO@!' \
- -e 's!@''SHARED_LIB_VERSION''@!@SHARED_LIB_VERSION@!' \
- -e 's!@''MYSQL_BASE_VERSION''@!@MYSQL_BASE_VERSION@!' \
- -e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \
- -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \
- -e 's!@''PERL_DBI_VERSION''@!@PERL_DBI_VERSION@!' \
- -e 's!@''PERL_DBD_VERSION''@!@PERL_DBD_VERSION@!' \
- -e 's!@''PERL_DATA_DUMPER''@!@PERL_DATA_DUMPER@!' \
- $< > $@-t
- @CHMOD@ +x $@-t
- @MV@ $@-t $@
-
-if HAVE_DTRACE_DASH_G
-libmyisam_a_LIBADD = probes_mysql.o
-libmyisam_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-CLEANFILES += probes_mysql.o dtrace_files dtrace_providers
-DTRACEFILES = ha_myisam.o
-DTRACEPROVIDER = probes_mysql.d
-CLEANFILES += $(DTRACEPROVIDER) dtrace_sources
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-endif
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index bf0af370838..650eb160866 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -92,8 +92,6 @@ static double *nwghts=_nwghts+5; /* nwghts[i] = -0.5*1.5**i */
#define FTB_FLAG_NO 4
#define FTB_FLAG_WONLY 8
-#define CMP_NUM(a,b) (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1)
-
typedef struct st_ftb_expr FTB_EXPR;
struct st_ftb_expr
{
diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c
index b0911403996..9eb8b68bf13 100644
--- a/storage/myisam/ft_stopwords.c
+++ b/storage/myisam/ft_stopwords.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2005 MySQL AB
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
#include "ftdefs.h"
-#include "my_handler.h"
+#include "my_compare.h"
static CHARSET_INFO *ft_stopword_cs= NULL;
diff --git a/storage/myisam/ftbench/Ecompare.pl b/storage/myisam/ftbench/Ecompare.pl
index 265534e704d..2c50ae9b9ce 100755
--- a/storage/myisam/ftbench/Ecompare.pl
+++ b/storage/myisam/ftbench/Ecompare.pl
@@ -1,5 +1,20 @@
#!/usr/bin/perl
+# Copyright (C) 2003 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
+
# compares out-files (as created by Ereport.pl) from dir1/*.out and dir2/*.out
# for each effectiveness column computes the probability of the hypothesis
# "Both files have the same effectiveness"
diff --git a/storage/myisam/ftbench/Ecreate.pl b/storage/myisam/ftbench/Ecreate.pl
index d90a6f7a0ad..123ca729c31 100755
--- a/storage/myisam/ftbench/Ecreate.pl
+++ b/storage/myisam/ftbench/Ecreate.pl
@@ -1,5 +1,20 @@
#!/usr/bin/perl
+# Copyright (C) 2003 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
+
$test=shift || die "Usage $0 testname [option]";
$option=shift;
diff --git a/storage/myisam/ftbench/Ereport.pl b/storage/myisam/ftbench/Ereport.pl
index 5969304da09..2f63d7ea37a 100755
--- a/storage/myisam/ftbench/Ereport.pl
+++ b/storage/myisam/ftbench/Ereport.pl
@@ -1,5 +1,20 @@
#!/usr/bin/perl
+# Copyright (C) 2003 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 "Use: $0 eval_output qrels_file\n" unless @ARGV==2;
open(EOUT,$eout=shift) || die "Cannot open $eout: $!";
diff --git a/storage/myisam/ftbench/ft-test-run.sh b/storage/myisam/ftbench/ft-test-run.sh
index 0908e55b400..8726c263de9 100755
--- a/storage/myisam/ftbench/ft-test-run.sh
+++ b/storage/myisam/ftbench/ft-test-run.sh
@@ -1,5 +1,22 @@
#!/bin/sh
+# Copyright (C) 2003 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
+
if [ ! -x ./ft-test-run.sh ] ; then
echo "Usage: ./ft-test-run.sh"
exit 1
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 2913cdc421d..3121deb66e4 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -168,10 +168,9 @@ static void mi_check_print_msg(HA_CHECK *param, const char* msg_type,
Also we likely need to lock mutex here (in both cases with protocol and
push_warning).
*/
-#ifdef THREAD
if (param->need_print_msg_lock)
mysql_mutex_lock(&param->print_msg_mutex);
-#endif
+
protocol->prepare_for_resend();
protocol->store(name, length, system_charset_info);
protocol->store(param->op_name, system_charset_info);
@@ -180,10 +179,10 @@ static void mi_check_print_msg(HA_CHECK *param, const char* msg_type,
if (protocol->write())
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf);
-#ifdef THREAD
+
if (param->need_print_msg_lock)
mysql_mutex_unlock(&param->print_msg_mutex);
-#endif
+
return;
}
@@ -640,13 +639,14 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
- HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT),
+ HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_REPAIR),
can_enable_indexes(1)
{}
-handler *ha_myisam::clone(MEM_ROOT *mem_root)
+handler *ha_myisam::clone(const char *name, MEM_ROOT *mem_root)
{
- ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
+ ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(name,
+ mem_root));
if (new_handler)
new_handler->file->state= file->state;
return new_handler;
@@ -1530,8 +1530,6 @@ bool ha_myisam::check_and_repair(THD *thd)
{
int error=0;
int marked_crashed;
- char *old_query;
- uint old_query_length;
HA_CHECK_OPT check_opt;
DBUG_ENTER("ha_myisam::check_and_repair");
@@ -1542,10 +1540,9 @@ bool ha_myisam::check_and_repair(THD *thd)
check_opt.flags|=T_QUICK;
sql_print_warning("Checking table: '%s'",table->s->path.str);
- old_query= thd->query();
- old_query_length= thd->query_length();
+ const CSET_STRING query_backup= thd->query_string;
thd->set_query(table->s->table_name.str,
- (uint) table->s->table_name.length);
+ (uint) table->s->table_name.length, system_charset_info);
if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
{
@@ -1558,7 +1555,7 @@ bool ha_myisam::check_and_repair(THD *thd)
if (repair(thd, &check_opt))
error=1;
}
- thd->set_query(old_query, old_query_length);
+ thd->set_query(query_backup);
DBUG_RETURN(error);
}
@@ -1848,6 +1845,18 @@ int ha_myisam::delete_all_rows()
return mi_delete_all_rows(file);
}
+
+/*
+ Intended to support partitioning.
+ Allows a particular partition to be truncated.
+*/
+
+int ha_myisam::truncate()
+{
+ int error= delete_all_rows();
+ return error ? error : reset_auto_increment(0);
+}
+
int ha_myisam::reset_auto_increment(ulonglong value)
{
file->s->state.auto_increment= value;
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index 61585013678..b5415bb0dc7 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -55,7 +55,7 @@ class ha_myisam: public handler
public:
ha_myisam(handlerton *hton, TABLE_SHARE *table_arg);
~ha_myisam() {}
- handler *clone(MEM_ROOT *mem_root);
+ handler *clone(const char *name, MEM_ROOT *mem_root);
const char *table_type() const { return "MyISAM"; }
const char *index_type(uint key_number);
const char **bas_ext() const;
@@ -116,6 +116,7 @@ class ha_myisam: public handler
int reset(void);
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
+ int truncate();
int reset_auto_increment(ulonglong value);
int disable_indexes(uint mode);
int enable_indexes(uint mode);
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index a69ed41f67d..daae02e6846 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -79,7 +79,8 @@ static int sort_delete_record(MI_SORT_PARAM *sort_param);
static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks,
uint buffer_length);
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
-static void set_data_file_type(MI_SORT_INFO *sort_info, MYISAM_SHARE *share);
+static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
+static HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a);
void myisamchk_init(HA_CHECK *param)
{
@@ -98,6 +99,7 @@ void myisamchk_init(HA_CHECK *param)
param->max_record_length= LONGLONG_MAX;
param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
+ param->need_print_msg_lock= 0;
}
/* Check the status flags for the table */
@@ -1748,6 +1750,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)
@@ -2633,9 +2637,6 @@ err:
int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
const char * name, int rep_quick)
{
-#ifndef THREAD
- return mi_repair_by_sort(param, info, name, rep_quick);
-#else
int got_error;
uint i,key, total_key_length, istep;
ulong rec_length;
@@ -3125,7 +3126,6 @@ err:
share->pack.header_length=0;
}
DBUG_RETURN(got_error);
-#endif /* THREAD */
}
/* Read next record and return next key */
@@ -4747,3 +4747,4 @@ set_data_file_type(MI_SORT_INFO *sort_info, MYISAM_SHARE *share)
share->delete_record=tmp.delete_record;
}
}
+
diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c
index fd10ef47968..660863d4f7c 100644
--- a/storage/myisam/mi_close.c
+++ b/storage/myisam/mi_close.c
@@ -94,7 +94,6 @@ int mi_close(register MI_INFO *info)
my_free(share->decode_trees);
my_free(share->decode_tables);
}
-#ifdef THREAD
thr_lock_delete(&share->lock);
mysql_mutex_destroy(&share->intern_lock);
{
@@ -105,7 +104,6 @@ int mi_close(register MI_INFO *info)
mysql_rwlock_destroy(&share->key_root_lock[i]);
}
}
-#endif
my_free(info->s);
}
mysql_mutex_unlock(&THR_LOCK_myisam);
diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c
index 7222542847d..3ec429535d4 100644
--- a/storage/myisam/mi_create.c
+++ b/storage/myisam/mi_create.c
@@ -829,8 +829,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
err:
mysql_mutex_unlock(&THR_LOCK_myisam);
-err_no_lock:
+err_no_lock:
save_errno=my_errno;
switch (errpos) {
case 3:
diff --git a/storage/myisam/mi_delete.c b/storage/myisam/mi_delete.c
index 0817d9926ca..6d2ca5b1f8d 100644
--- a/storage/myisam/mi_delete.c
+++ b/storage/myisam/mi_delete.c
@@ -102,7 +102,7 @@ int mi_delete(MI_INFO *info,const uchar *record)
mi_sizestore(lastpos,info->lastpos);
myisam_log_command(MI_LOG_DELETE,info,(uchar*) lastpos,sizeof(lastpos),0);
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
- allow_break(); /* Allow SIGHUP & SIGINT */
+
if (info->invalidator != 0)
{
DBUG_PRINT("info", ("invalidator... '%s' (delete)", info->filename));
@@ -122,7 +122,6 @@ err:
}
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
- allow_break(); /* Allow SIGHUP & SIGINT */
my_errno=save_errno;
if (save_errno == HA_ERR_KEY_NOT_FOUND)
{
diff --git a/storage/myisam/mi_delete_all.c b/storage/myisam/mi_delete_all.c
index 5940b927d9a..a21a2a3093a 100644
--- a/storage/myisam/mi_delete_all.c
+++ b/storage/myisam/mi_delete_all.c
@@ -67,7 +67,6 @@ int mi_delete_all_rows(MI_INFO *info)
if (share->file_map)
mi_dynmap_file(info, (my_off_t) 0);
#endif
- allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
err:
@@ -75,7 +74,6 @@ err:
int save_errno=my_errno;
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
- allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(my_errno=save_errno);
}
} /* mi_delete */
diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c
index 70a59a11346..aeb81d4e09c 100644
--- a/storage/myisam/mi_dynrec.c
+++ b/storage/myisam/mi_dynrec.c
@@ -39,13 +39,11 @@ static int delete_dynamic_record(MI_INFO *info,my_off_t filepos,
static int _mi_cmp_buffer(File file, const uchar *buff, my_off_t filepos,
uint length);
-#ifdef THREAD
/* Play it safe; We have a small stack when using threads */
#undef my_alloca
#undef my_afree
#define my_alloca(A) my_malloc((A),MYF(0))
#define my_afree(A) my_free((A))
-#endif
/* Interface function from MI_INFO */
@@ -1579,9 +1577,6 @@ int _mi_cmp_dynamic_record(register MI_INFO *info, register const uchar *record)
MI_BLOCK_INFO block_info;
DBUG_ENTER("_mi_cmp_dynamic_record");
- /* We are going to do changes; dont let anybody disturb */
- dont_break(); /* Dont allow SIGHUP or SIGINT */
-
if (info->opt_flag & WRITE_CACHE_USED)
{
info->update&= ~(HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK);
diff --git a/storage/myisam/mi_log.c b/storage/myisam/mi_log.c
index e0c66bef996..ac3aa7c149b 100644
--- a/storage/myisam/mi_log.c
+++ b/storage/myisam/mi_log.c
@@ -24,11 +24,7 @@
#endif
#undef GETPID /* For HPUX */
-#ifdef THREAD
#define GETPID() (log_type == 1 ? (long) myisam_pid : (long) my_thread_dbug_id())
-#else
-#define GETPID() myisam_pid
-#endif
/* Activate logging if flag is 1 and reset logging if flag is 0 */
diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c
index abc731aead6..3c52016a1ba 100644
--- a/storage/myisam/mi_open.c
+++ b/storage/myisam/mi_open.c
@@ -291,9 +291,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
&share->state.key_root,keys*sizeof(my_off_t),
&share->state.key_del,
(share->state.header.max_block_size_index*sizeof(my_off_t)),
-#ifdef THREAD
&share->key_root_lock, sizeof(mysql_rwlock_t)*keys,
-#endif
&share->mmap_lock, sizeof(mysql_rwlock_t),
NullS))
goto err;
@@ -510,7 +508,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
my_afree(disk_cache);
mi_setup_functions(share);
share->is_log_table= FALSE;
-#ifdef THREAD
thr_lock_init(&share->lock);
mysql_mutex_init(mi_key_mutex_MYISAM_SHARE_intern_lock,
&share->intern_lock, MY_MUTEX_INIT_FAST);
@@ -541,7 +538,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share->lock.fix_status= (void (*)(void *, void *)) mi_fix_status;
}
}
-#endif
/*
Memory mapping can only be requested after initializing intern_lock.
*/
@@ -639,9 +635,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
bzero(info.rec_buff, mi_get_rec_buff_len(&info, info.rec_buff));
*m_info=info;
-#ifdef THREAD
thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
-#endif
m_info->open_list.data=(void*) m_info;
myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
diff --git a/storage/myisam/mi_static.c b/storage/myisam/mi_static.c
index 55967fc9001..711287ca16f 100644
--- a/storage/myisam/mi_static.c
+++ b/storage/myisam/mi_static.c
@@ -32,7 +32,7 @@ File myisam_log_file= -1;
uint myisam_quick_table_bits=9;
ulong myisam_block_size= MI_KEY_BLOCK_LENGTH; /* Best by test */
my_bool myisam_flush=0, myisam_delay_key_write=0, myisam_single_user=0;
-#if defined(THREAD) && !defined(DONT_USE_RW_LOCKS)
+#if !defined(DONT_USE_RW_LOCKS)
ulong myisam_concurrent_insert= 2;
#else
ulong myisam_concurrent_insert= 0;
diff --git a/storage/myisam/mi_statrec.c b/storage/myisam/mi_statrec.c
index f83afa3c886..bf791726aa9 100644
--- a/storage/myisam/mi_statrec.c
+++ b/storage/myisam/mi_statrec.c
@@ -114,9 +114,6 @@ int _mi_cmp_static_record(register MI_INFO *info, register const uchar *old)
{
DBUG_ENTER("_mi_cmp_static_record");
- /* We are going to do changes; dont let anybody disturb */
- dont_break(); /* Dont allow SIGHUP or SIGINT */
-
if (info->opt_flag & WRITE_CACHE_USED)
{
if (flush_io_cache(&info->rec_cache))
diff --git a/storage/myisam/mi_test_all.sh b/storage/myisam/mi_test_all.sh
index c6bc686e885..641f1cc0a35 100755
--- a/storage/myisam/mi_test_all.sh
+++ b/storage/myisam/mi_test_all.sh
@@ -1,4 +1,22 @@
#!/bin/sh
+
+# 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 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
+
#
# Execute some simple basic test on MyISAM libary to check if things
# works at all.
diff --git a/storage/myisam/mi_update.c b/storage/myisam/mi_update.c
index 6d4150e5b79..2104e4c4117 100644
--- a/storage/myisam/mi_update.c
+++ b/storage/myisam/mi_update.c
@@ -179,7 +179,6 @@ int mi_update(register MI_INFO *info, const uchar *oldrec, uchar *newrec)
there is no index change there could be data change.
*/
(void) _mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE);
- allow_break(); /* Allow SIGHUP & SIGINT */
if (info->invalidator != 0)
{
DBUG_PRINT("info", ("invalidator... '%s' (update)", info->filename));
@@ -193,8 +192,8 @@ err:
save_errno=my_errno;
if (changed)
key_changed|= HA_STATE_CHANGED;
- if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_OUT_OF_MEM ||
- my_errno == HA_ERR_RECORD_FILE_FULL)
+ if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL ||
+ my_errno == HA_ERR_NULL_IN_SPATIAL || my_errno == HA_ERR_OUT_OF_MEM)
{
info->errkey= (int) i;
flag=0;
@@ -212,8 +211,9 @@ err:
{
uint new_length=_mi_make_key(info,i,new_key,newrec,pos);
uint old_length= _mi_make_key(info,i,old_key,oldrec,pos);
- if ((flag++ && _mi_ck_delete(info,i,new_key,new_length)) ||
- _mi_ck_write(info,i,old_key,old_length))
+ if ((flag++ &&
+ share->keyinfo[i].ck_delete(info, i, new_key, new_length)) ||
+ share->keyinfo[i].ck_insert(info, i, old_key, old_length))
break;
}
}
@@ -230,7 +230,6 @@ err:
err_end:
myisam_log_record(MI_LOG_UPDATE,info,newrec,info->lastpos,my_errno);
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
- allow_break(); /* Allow SIGHUP & SIGINT */
if (save_errno == HA_ERR_KEY_NOT_FOUND)
{
mi_print_error(info->s, HA_ERR_CRASHED);
diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c
index 7b40a11f7c6..1c9a25f8e86 100644
--- a/storage/myisam/mi_write.c
+++ b/storage/myisam/mi_write.c
@@ -60,7 +60,7 @@ int mi_write(MI_INFO *info, uchar *record)
}
if (_mi_readinfo(info,F_WRLCK,1))
DBUG_RETURN(my_errno);
- dont_break(); /* Dont allow SIGHUP or SIGINT */
+
filepos= ((share->state.dellink != HA_OFFSET_ERROR &&
!info->append_insert_at_end) ?
share->state.dellink :
@@ -169,7 +169,6 @@ int mi_write(MI_INFO *info, uchar *record)
if (share->is_log_table)
mi_update_status((void*) info);
- allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
err:
@@ -205,7 +204,7 @@ err:
else
{
uint key_length=_mi_make_key(info,i,buff,record,filepos);
- if (_mi_ck_delete(info,i,buff,key_length))
+ if (share->keyinfo[i].ck_delete(info, i, buff, key_length))
{
if (local_lock_tree)
mysql_rwlock_unlock(&share->key_root_lock[i]);
@@ -228,7 +227,6 @@ err2:
save_errno=my_errno;
myisam_log_record(MI_LOG_WRITE,info,record,filepos,my_errno);
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
- allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(my_errno=save_errno);
} /* mi_write */
diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c
index 70406203f63..e932234a998 100644
--- a/storage/myisam/myisamchk.c
+++ b/storage/myisam/myisamchk.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -670,10 +670,10 @@ get_one_option(int optid,
case OPT_STATS_METHOD:
{
int method;
- enum_handler_stats_method method_conv;
- LINT_INIT(method_conv);
+ enum_mi_stats_method UNINIT_VAR(method_conv);
myisam_stats_method_str= argument;
- if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0)
+ if ((method= find_type(argument, &myisam_stats_method_typelib,
+ FIND_TYPE_BASIC)) <= 0)
{
fprintf(stderr, "Invalid value of stats_method: %s.\n", argument);
exit(1);
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index 894ec827b85..3f82d96b88b 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -18,12 +18,8 @@
#include "myisam.h" /* Structs & some defines */
#include "myisampack.h" /* packing of keys */
#include <my_tree.h>
-#ifdef THREAD
#include <my_pthread.h>
#include <thr_lock.h>
-#else
-#include <my_no_pthread.h>
-#endif
#include <mysql/psi/mysql_file.h>
/* undef map from my_nosys; We need test-if-disk full */
@@ -220,11 +216,9 @@ typedef struct st_mi_isam_share
global_changed, /* If changed since open */
not_flushed, temporary, delay_key_write, concurrent_insert;
my_bool deleting; /* we are going to delete this table */
-#ifdef THREAD
THR_LOCK lock;
mysql_mutex_t intern_lock; /* Locking for use with _locking */
mysql_rwlock_t *key_root_lock;
-#endif
my_off_t mmaped_length;
uint nonmmaped_inserts; /* counter of writing in non-mmaped
area */
@@ -304,9 +298,7 @@ struct st_myisam_info
my_bool buff_used;
index_cond_func_t index_cond_func; /* Index condition function */
void *index_cond_func_arg; /* parameter for the func */
-#ifdef THREAD
THR_LOCK_DATA lock;
-#endif
uchar *rtree_recursion_state; /* For RTREE */
int rtree_recursion_depth;
};
@@ -415,10 +407,8 @@ struct st_myisam_info
#define MI_UNIQUE_HASH_TYPE HA_KEYTYPE_ULONG_INT
#define mi_unique_store(A,B) mi_int4store((A),(B))
-#ifdef THREAD
extern mysql_mutex_t THR_LOCK_myisam;
-#endif
-#if !defined(THREAD) || defined(DONT_USE_RW_LOCKS)
+#ifdef DONT_USE_RW_LOCKS
#define mysql_rwlock_wrlock(A) {}
#define mysql_rwlock_rdlock(A) {}
#define mysql_rwlock_unlock(A) {}
@@ -730,9 +720,7 @@ int killed_ptr(HA_CHECK *param);
void mi_check_print_error(HA_CHECK *param, const char *fmt, ...);
void mi_check_print_warning(HA_CHECK *param, const char *fmt, ...);
void mi_check_print_info(HA_CHECK *param, const char *fmt, ...);
-#ifdef THREAD
pthread_handler_t thr_find_all_keys(void *arg);
-#endif
extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func,
void *func_arg);
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index 017f7d160b6..b48e95f1171 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/myisam/plug.in b/storage/myisam/plug.in
deleted file mode 100644
index e92b5e56d7f..00000000000
--- a/storage/myisam/plug.in
+++ /dev/null
@@ -1,7 +0,0 @@
-dnl MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine],
-dnl [Traditional non-transactional MySQL tables])
-dnl MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam])
-dnl MYSQL_PLUGIN_STATIC(myisam, [libmyisam.a])
-dnl MYSQL_PLUGIN_MANDATORY(myisam) dnl Default
-dnl MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(myisam, [ha_myisam.cc])
-
diff --git a/storage/myisam/rt_index.c b/storage/myisam/rt_index.c
index 48eb48cc5e8..888d3c7e56a 100644
--- a/storage/myisam/rt_index.c
+++ b/storage/myisam/rt_index.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2006 MySQL AB & Ramil Kalimullin
+/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c
index 903a893e779..eb462d8c23e 100644
--- a/storage/myisam/sort.c
+++ b/storage/myisam/sort.c
@@ -302,7 +302,6 @@ static ha_rows find_all_keys(MI_SORT_PARAM *info, uint keys,
} /* find_all_keys */
-#ifdef THREAD
/* Search after all keys and place them in a temp. file */
pthread_handler_t thr_find_all_keys(void *arg)
@@ -637,7 +636,6 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
my_free(mergebuf);
DBUG_RETURN(got_error);
}
-#endif /* THREAD */
/* Write all keys in memory to file for later merge */
diff --git a/storage/myisammrg/Makefile.am b/storage/myisammrg/Makefile.am
deleted file mode 100644
index 43dec3ae3d9..00000000000
--- a/storage/myisammrg/Makefile.am
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright (C) 2000-2002, 2005-2006 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
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir)
-WRAPLIBS=
-
-LDADD =
-
-DEFS = @DEFS@
-pkglib_LIBRARIES = libmyisammrg.a
-noinst_HEADERS = myrg_def.h ha_myisammrg.h
-noinst_LIBRARIES = libmyisammrg.a
-libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \
- myrg_rrnd.c myrg_update.c myrg_delete.c myrg_rsame.c \
- myrg_panic.c myrg_close.c myrg_create.c myrg_static.c \
- myrg_rkey.c myrg_rfirst.c myrg_rlast.c myrg_rnext.c \
- myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c \
- ha_myisammrg.cc \
- myrg_rnext_same.c myrg_records.c
-
-
-EXTRA_DIST = CMakeLists.txt plug.in
-
-if HAVE_DTRACE_DASH_G
-libmyisammrg_a_LIBADD = probes_mysql.o
-libmyisammrg_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-CLEANFILES = probes_mysql.o dtrace_files dtrace_providers
-DTRACEFILES = ha_myisammrg.o
-DTRACEPROVIDER = probes_mysql.d
-CLEANFILES += $(DTRACEPROVIDER) dtrace_sources
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-endif
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index ef7cd5712e8..22b4794dbde 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -480,6 +480,31 @@ int ha_myisammrg::add_children_list(void)
/* Set the expected table version, to not cause spurious re-prepare. */
child_l->set_table_ref_id(mrg_child_def->get_child_table_ref_type(),
mrg_child_def->get_child_def_version());
+ /*
+ For statements which acquire a SNW metadata lock on a parent table and
+ then later try to upgrade it to an X lock (e.g. ALTER TABLE), SNW
+ locks should be also taken on the children tables.
+
+ Otherwise we end up in a situation where the thread trying to upgrade SNW
+ to X lock on the parent also holds a SR metadata lock and a read
+ thr_lock.c lock on the child. As a result, another thread might be
+ blocked on the thr_lock.c lock for the child after successfully acquiring
+ a SR or SW metadata lock on it. If at the same time this second thread
+ has a shared metadata lock on the parent table or there is some other
+ thread which has a shared metadata lock on the parent and is waiting for
+ this second thread, we get a deadlock. This deadlock cannot be properly
+ detected by the MDL subsystem as part of the waiting happens within
+ thr_lock.c. By taking SNW locks on the child tables we ensure that any
+ thread which waits for a thread doing SNW -> X upgrade, does this within
+ the MDL subsystem and thus potential deadlocks are exposed to the deadlock
+ detector.
+
+ We don't do the same thing for SNRW locks as this would allow
+ DDL on implicitly locked underlying tables of a MERGE table.
+ */
+ if (! thd->locked_tables_mode &&
+ parent_l->mdl_request.type == MDL_SHARED_NO_WRITE)
+ child_l->mdl_request.set_type(MDL_SHARED_NO_WRITE);
/* Link TABLE_LIST object into the children list. */
if (this->children_last_l)
child_l->prev_global= this->children_last_l;
@@ -657,7 +682,7 @@ CPP_UNNAMED_NS_END
@return A cloned handler instance.
*/
-handler *ha_myisammrg::clone(MEM_ROOT *mem_root)
+handler *ha_myisammrg::clone(const char *name, MEM_ROOT *mem_root)
{
MYRG_TABLE *u_table,*newu_table;
ha_myisammrg *new_handler=
@@ -678,8 +703,8 @@ handler *ha_myisammrg::clone(MEM_ROOT *mem_root)
return NULL;
}
- if (new_handler->ha_open(table, table->s->normalized_path.str, table->db_stat,
- HA_OPEN_IGNORE_IF_LOCKED))
+ if (new_handler->ha_open(table, name, table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED))
{
delete new_handler;
return NULL;
@@ -1202,6 +1227,22 @@ ha_rows ha_myisammrg::records_in_range(uint inx, key_range *min_key,
}
+int ha_myisammrg::truncate()
+{
+ int err= 0;
+ MYRG_TABLE *table;
+ DBUG_ENTER("ha_myisammrg::truncate");
+
+ for (table= file->open_tables; table != file->end_table; table++)
+ {
+ if ((err= mi_delete_all_rows(table->table)))
+ break;
+ }
+
+ DBUG_RETURN(err);
+}
+
+
int ha_myisammrg::info(uint flag)
{
MYMERGE_INFO mrg_info;
diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h
index c434dc28426..14734eed064 100644
--- a/storage/myisammrg/ha_myisammrg.h
+++ b/storage/myisammrg/ha_myisammrg.h
@@ -110,7 +110,7 @@ public:
int add_children_list(void);
int attach_children(void);
int detach_children(void);
- virtual handler *clone(MEM_ROOT *mem_root);
+ virtual handler *clone(const char *name, MEM_ROOT *mem_root);
int close(void);
int write_row(uchar * buf);
int update_row(const uchar * old_data, uchar * new_data);
@@ -131,6 +131,7 @@ public:
int rnd_pos(uchar * buf, uchar *pos);
void position(const uchar *record);
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
+ int truncate();
int info(uint);
int reset(void);
int extra(enum ha_extra_function operation);
diff --git a/storage/myisammrg/myrg_def.h b/storage/myisammrg/myrg_def.h
index b916243be21..9bc0881b212 100644
--- a/storage/myisammrg/myrg_def.h
+++ b/storage/myisammrg/myrg_def.h
@@ -23,9 +23,7 @@
extern LIST *myrg_open_list;
-#ifdef THREAD
extern mysql_mutex_t THR_LOCK_open;
-#endif
int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag);
int _myrg_mi_read_record(MI_INFO *info, uchar *buf);
diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c
index 156660d00c0..ab1d9ad7f7e 100644
--- a/storage/myisammrg/myrg_open.c
+++ b/storage/myisammrg/myrg_open.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -78,7 +78,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{
if (!strncmp(buff+1,"INSERT_METHOD=",14))
{ /* Lookup insert method */
- int tmp=find_type(buff+15,&merge_insert_method,2);
+ int tmp= find_type(buff + 15, &merge_insert_method, FIND_TYPE_BASIC);
found_merge_insert_method = (uint) (tmp >= 0 ? tmp : 0);
}
continue; /* Skip comments */
@@ -222,7 +222,7 @@ MYRG_INFO *myrg_parent_open(const char *parent_name,
int (*callback)(void*, const char*),
void *callback_param)
{
- MYRG_INFO *m_info;
+ MYRG_INFO *UNINIT_VAR(m_info);
int rc;
int errpos;
int save_errno;
@@ -274,7 +274,7 @@ MYRG_INFO *myrg_parent_open(const char *parent_name,
{
/* Compare buffer with global methods list: merge_insert_method. */
insert_method= find_type(child_name_buff + 15,
- &merge_insert_method, 2);
+ &merge_insert_method, FIND_TYPE_BASIC);
}
continue;
}
diff --git a/storage/myisammrg/plug.in b/storage/myisammrg/plug.in
deleted file mode 100644
index 1f94e07d881..00000000000
--- a/storage/myisammrg/plug.in
+++ /dev/null
@@ -1,6 +0,0 @@
-MYSQL_STORAGE_ENGINE(myisammrg,no,[MyISAM MERGE Engine],
- [Merge multiple MySQL tables into one])
-MYSQL_PLUGIN_DIRECTORY(myisammrg,[storage/myisammrg])
-MYSQL_PLUGIN_STATIC(myisammrg, [libmyisammrg.a])
-MYSQL_PLUGIN_MANDATORY(myisammrg)
-MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(myisammrg, [ha_myisammrg.cc])
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/ndb_configure.m4 b/storage/ndb/ndb_configure.m4
new file mode 100644
index 00000000000..21e4627515f
--- /dev/null
+++ b/storage/ndb/ndb_configure.m4
@@ -0,0 +1,349 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_NDBCLUSTER
+dnl ---------------------------------------------------------------------------
+
+# The version of NDB in this version of MySQL is currently fixed
+# and not supposed to be changed unless major changes happen in
+# storage/ndb directory.
+# NOTE! To avoid mixup with MySQL Cluster's version numbers
+# this version of NDB is set to 5.5.7 although it's basically
+# a copy of MySQL Cluster 6.2.18
+NDB_VERSION_MAJOR=5
+NDB_VERSION_MINOR=5
+NDB_VERSION_BUILD=7
+NDB_VERSION_STATUS=""
+TEST_NDBCLUSTER=""
+
+dnl for build ndb docs
+
+AC_PATH_PROG(DOXYGEN, doxygen, no)
+AC_PATH_PROG(PDFLATEX, pdflatex, no)
+AC_PATH_PROG(MAKEINDEX, makeindex, no)
+
+AC_SUBST(DOXYGEN)
+AC_SUBST(PDFLATEX)
+AC_SUBST(MAKEINDEX)
+
+
+AC_DEFUN([MYSQL_CHECK_NDB_OPTIONS], [
+ AC_ARG_WITH([ndb-sci],
+ AC_HELP_STRING([--with-ndb-sci=DIR],
+ [Provide MySQL with a custom location of
+ sci library. Given DIR, sci library is
+ assumed to be in $DIR/lib and header files
+ in $DIR/include.]),
+ [mysql_sci_dir=${withval}],
+ [mysql_sci_dir=""])
+
+ case "$mysql_sci_dir" in
+ "no" )
+ have_ndb_sci=no
+ AC_MSG_RESULT([-- not including sci transporter])
+ ;;
+ * )
+ if test -f "$mysql_sci_dir/lib/libsisci.a" -a \
+ -f "$mysql_sci_dir/include/sisci_api.h"; then
+ NDB_SCI_INCLUDES="-I$mysql_sci_dir/include"
+ NDB_SCI_LIBS="$mysql_sci_dir/lib/libsisci.a"
+ AC_MSG_RESULT([-- including sci transporter])
+ AC_DEFINE([NDB_SCI_TRANSPORTER], [1],
+ [Including Ndb Cluster DB sci transporter])
+ AC_SUBST(NDB_SCI_INCLUDES)
+ AC_SUBST(NDB_SCI_LIBS)
+ have_ndb_sci="yes"
+ AC_MSG_RESULT([found sci transporter in $mysql_sci_dir/{include, lib}])
+ else
+ AC_MSG_RESULT([could not find sci transporter in $mysql_sci_dir/{include, lib}])
+ fi
+ ;;
+ esac
+
+ AC_ARG_WITH([ndb-test],
+ [
+ --with-ndb-test Include the NDB Cluster ndbapi test programs],
+ [ndb_test="$withval"],
+ [ndb_test=no])
+ AC_ARG_WITH([ndb-docs],
+ [
+ --with-ndb-docs Include the NDB Cluster ndbapi and mgmapi documentation],
+ [ndb_docs="$withval"],
+ [ndb_docs=no])
+ AC_ARG_WITH([ndb-port],
+ [
+ --with-ndb-port Port for NDB Cluster management server],
+ [ndb_port="$withval"],
+ [ndb_port="default"])
+ AC_ARG_WITH([ndb-port-base],
+ [
+ --with-ndb-port-base Base port for NDB Cluster transporters],
+ [ndb_port_base="$withval"],
+ [ndb_port_base="default"])
+ AC_ARG_WITH([ndb-debug],
+ [
+ --without-ndb-debug Disable special ndb debug features],
+ [ndb_debug="$withval"],
+ [ndb_debug="default"])
+ AC_ARG_WITH([ndb-ccflags],
+ AC_HELP_STRING([--with-ndb-ccflags=CFLAGS],
+ [Extra CFLAGS for ndb compile]),
+ [ndb_ccflags=${withval}],
+ [ndb_ccflags=""])
+ AC_ARG_WITH([ndb-binlog],
+ [
+ --without-ndb-binlog Disable ndb binlog],
+ [ndb_binlog="$withval"],
+ [ndb_binlog="default"])
+
+ case "$ndb_ccflags" in
+ "yes")
+ AC_MSG_RESULT([The --ndb-ccflags option requires a parameter (passed to CC for ndb compilation)])
+ ;;
+ *)
+ ndb_cxxflags_fix="$ndb_cxxflags_fix $ndb_ccflags"
+ ;;
+ esac
+
+ AC_MSG_CHECKING([for NDB Cluster options])
+ AC_MSG_RESULT([])
+
+ have_ndb_test=no
+ case "$ndb_test" in
+ yes )
+ AC_MSG_RESULT([-- including ndbapi test programs])
+ have_ndb_test="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including ndbapi test programs])
+ ;;
+ esac
+
+ have_ndb_docs=no
+ case "$ndb_docs" in
+ yes )
+ AC_MSG_RESULT([-- including ndbapi and mgmapi documentation])
+ have_ndb_docs="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including ndbapi and mgmapi documentation])
+ ;;
+ esac
+
+ case "$ndb_debug" in
+ yes )
+ AC_MSG_RESULT([-- including ndb extra debug options])
+ have_ndb_debug="yes"
+ ;;
+ full )
+ AC_MSG_RESULT([-- including ndb extra extra debug options])
+ have_ndb_debug="full"
+ ;;
+ no )
+ AC_MSG_RESULT([-- not including ndb extra debug options])
+ have_ndb_debug="no"
+ ;;
+ * )
+ have_ndb_debug="default"
+ ;;
+ esac
+
+ AC_MSG_RESULT([done.])
+])
+
+AC_DEFUN([NDBCLUSTER_WORKAROUNDS], [
+
+ #workaround for Sun Forte/x86 see BUG#4681
+ case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in
+ *solaris*-i?86-no)
+ CFLAGS="$CFLAGS -DBIG_TABLES"
+ CXXFLAGS="$CXXFLAGS -DBIG_TABLES"
+ ;;
+ *)
+ ;;
+ esac
+
+ # workaround for Sun Forte compile problem for ndb
+ case $SYSTEM_TYPE-$ac_cv_prog_gcc in
+ *solaris*-no)
+ ndb_cxxflags_fix="$ndb_cxxflags_fix -instances=static"
+ ;;
+ *)
+ ;;
+ esac
+
+ # ndb fail for whatever strange reason to link Sun Forte/x86
+ # unless using incremental linker
+ case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc-$have_ndbcluster in
+ *solaris*-i?86-no-yes)
+ CXXFLAGS="$CXXFLAGS -xildon"
+ ;;
+ *)
+ ;;
+ esac
+])
+
+AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
+
+ AC_MSG_RESULT([Using NDB Cluster])
+ with_partition="yes"
+ ndb_cxxflags_fix=""
+ TEST_NDBCLUSTER="--ndbcluster"
+
+ ndbcluster_includes="-I\$(top_builddir)/storage/ndb/include -I\$(top_srcdir)/storage/ndb/include -I\$(top_srcdir)/storage/ndb/include/ndbapi -I\$(top_srcdir)/storage/ndb/include/mgmapi"
+ ndbcluster_libs="\$(top_builddir)/storage/ndb/src/.libs/libndbclient.a"
+ ndbcluster_system_libs=""
+ ndb_mgmclient_libs="\$(top_builddir)/storage/ndb/src/mgmclient/libndbmgmclient.la"
+
+ MYSQL_CHECK_NDB_OPTIONS
+ NDBCLUSTER_WORKAROUNDS
+
+ MAKE_BINARY_DISTRIBUTION_OPTIONS="$MAKE_BINARY_DISTRIBUTION_OPTIONS --with-ndbcluster"
+
+ if test "$have_ndb_debug" = "default"
+ then
+ have_ndb_debug=$with_debug
+ fi
+
+ if test "$have_ndb_debug" = "yes"
+ then
+ # Medium debug.
+ NDB_DEFS="-DNDB_DEBUG -DVM_TRACE -DERROR_INSERT -DARRAY_GUARD"
+ elif test "$have_ndb_debug" = "full"
+ then
+ NDB_DEFS="-DNDB_DEBUG_FULL -DVM_TRACE -DERROR_INSERT -DARRAY_GUARD"
+ else
+ # no extra ndb debug but still do asserts if debug version
+ if test "$with_debug" = "yes"
+ then
+ NDB_DEFS=""
+ else
+ NDB_DEFS="-DNDEBUG"
+ fi
+ fi
+
+ if test X"$ndb_port" = Xdefault
+ then
+ ndb_port="1186"
+ fi
+
+ have_ndb_binlog="no"
+ if test X"$ndb_binlog" = Xdefault ||
+ test X"$ndb_binlog" = Xyes
+ then
+ have_ndb_binlog="yes"
+ fi
+
+ if test X"$have_ndb_binlog" = Xyes
+ then
+ AC_DEFINE([WITH_NDB_BINLOG], [1],
+ [Including Ndb Cluster Binlog])
+ AC_MSG_RESULT([Including Ndb Cluster Binlog])
+ else
+ AC_MSG_RESULT([Not including Ndb Cluster Binlog])
+ fi
+
+ ndb_transporter_opt_objs=""
+ if test "$ac_cv_func_shmget" = "yes" &&
+ test "$ac_cv_func_shmat" = "yes" &&
+ test "$ac_cv_func_shmdt" = "yes" &&
+ test "$ac_cv_func_shmctl" = "yes" &&
+ test "$ac_cv_func_sigaction" = "yes" &&
+ test "$ac_cv_func_sigemptyset" = "yes" &&
+ test "$ac_cv_func_sigaddset" = "yes" &&
+ test "$ac_cv_func_pthread_sigmask" = "yes"
+ then
+ AC_DEFINE([NDB_SHM_TRANSPORTER], [1],
+ [Including Ndb Cluster DB shared memory transporter])
+ AC_MSG_RESULT([Including ndb shared memory transporter])
+ ndb_transporter_opt_objs="$ndb_transporter_opt_objs SHM_Transporter.lo SHM_Transporter.unix.lo"
+ else
+ AC_MSG_RESULT([Not including ndb shared memory transporter])
+ fi
+
+ if test X"$have_ndb_sci" = Xyes
+ then
+ ndb_transporter_opt_objs="$ndb_transporter_opt_objs SCI_Transporter.lo"
+ fi
+
+ ndb_opt_subdirs=
+ ndb_bin_am_ldflags="-static"
+ if test X"$have_ndb_test" = Xyes
+ then
+ ndb_opt_subdirs="test"
+ ndb_bin_am_ldflags=""
+ fi
+
+ if test X"$have_ndb_docs" = Xyes
+ then
+ ndb_opt_subdirs="$ndb_opt_subdirs docs"
+ ndb_bin_am_ldflags=""
+ fi
+
+ # building dynamic breaks on AIX. (If you want to try it and get unresolved
+ # __vec__delete2 and some such, try linking against libhC.)
+ case "$host_os" in
+ aix3.* | aix4.0.* | aix4.1.*) ;;
+ *) ndb_bin_am_ldflags="-static";;
+ esac
+
+ # libndbclient versioning when linked with GNU ld.
+ if $LD --version 2>/dev/null|grep GNU >/dev/null 2>&1 ; then
+ NDB_LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_builddir)/storage/ndb/src/libndb.ver"
+ AC_CONFIG_FILES(storage/ndb/src/libndb.ver)
+ fi
+ AC_SUBST(NDB_LD_VERSION_SCRIPT)
+
+ AC_SUBST(NDB_SHARED_LIB_MAJOR_VERSION)
+ AC_SUBST(NDB_SHARED_LIB_VERSION)
+
+
+ AC_SUBST(NDB_VERSION_MAJOR)
+ AC_SUBST(NDB_VERSION_MINOR)
+ AC_SUBST(NDB_VERSION_BUILD)
+ AC_SUBST(NDB_VERSION_STATUS)
+ AC_DEFINE_UNQUOTED([NDB_VERSION_MAJOR], [$NDB_VERSION_MAJOR],
+ [NDB major version])
+ AC_DEFINE_UNQUOTED([NDB_VERSION_MINOR], [$NDB_VERSION_MINOR],
+ [NDB minor version])
+ AC_DEFINE_UNQUOTED([NDB_VERSION_BUILD], [$NDB_VERSION_BUILD],
+ [NDB build version])
+ AC_DEFINE_UNQUOTED([NDB_VERSION_STATUS], ["$NDB_VERSION_STATUS"],
+ [NDB status version])
+
+ AC_SUBST(ndbcluster_includes)
+ AC_SUBST(ndbcluster_libs)
+ AC_SUBST(ndbcluster_system_libs)
+ AC_SUBST(ndb_mgmclient_libs)
+ AC_SUBST(NDB_SCI_LIBS)
+
+ AC_SUBST(ndb_transporter_opt_objs)
+ AC_SUBST(ndb_port)
+ AC_SUBST(ndb_bin_am_ldflags)
+ AC_SUBST(ndb_opt_subdirs)
+
+ AC_SUBST(NDB_DEFS)
+ AC_SUBST(ndb_cxxflags_fix)
+
+ NDB_SIZEOF_CHARP="$ac_cv_sizeof_charp"
+ NDB_SIZEOF_CHAR="$ac_cv_sizeof_char"
+ NDB_SIZEOF_SHORT="$ac_cv_sizeof_short"
+ NDB_SIZEOF_INT="$ac_cv_sizeof_int"
+ NDB_SIZEOF_LONG="$ac_cv_sizeof_long"
+ NDB_SIZEOF_LONG_LONG="$ac_cv_sizeof_long_long"
+ AC_SUBST([NDB_SIZEOF_CHARP])
+ AC_SUBST([NDB_SIZEOF_CHAR])
+ AC_SUBST([NDB_SIZEOF_SHORT])
+ AC_SUBST([NDB_SIZEOF_INT])
+ AC_SUBST([NDB_SIZEOF_LONG])
+ AC_SUBST([NDB_SIZEOF_LONG_LONG])
+
+ AC_CONFIG_FILES([
+ storage/ndb/include/ndb_version.h
+ storage/ndb/include/ndb_global.h
+ storage/ndb/include/ndb_types.h
+ ])
+])
+
+AC_SUBST(TEST_NDBCLUSTER)
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_NDBCLUSTER SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/storage/ndb/plug.in b/storage/ndb/plug.in
index 3d3349f7a8b..04e618923e4 100644
--- a/storage/ndb/plug.in
+++ b/storage/ndb/plug.in
@@ -1,3 +1,5 @@
+sinclude(storage/ndb/ndb_configure.m4)
+
MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine],
[High Availability Clustered tables],)
MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb])
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/lgman.cpp b/storage/ndb/src/kernel/blocks/lgman.cpp
index 53cb1e113e1..7dc71e7399a 100644
--- a/storage/ndb/src/kernel/blocks/lgman.cpp
+++ b/storage/ndb/src/kernel/blocks/lgman.cpp
@@ -1,17 +1,19 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
+ 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
+ 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 */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA */
#include "lgman.hpp"
#include "diskpage.hpp"
@@ -2501,7 +2503,7 @@ Lgman::init_run_undo_log(Signal* signal)
sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
/**
- * Insert in correct postion in list of logfile_group's
+ * Insert in correct position in list of logfile_group's
*/
Ptr<Logfile_group> pos;
for(tmp.first(pos); !pos.isNull(); tmp.next(pos))
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/src/mgmsrv/InitConfigFileParser.cpp b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
index 560a9559999..7493e5e9c89 100644
--- a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
+++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
@@ -702,7 +702,7 @@ load_defaults(Vector<struct my_option>& options, const char* groups[])
BaseString group_suffix;
const char *save_file = my_defaults_file;
- char *save_extra_file = my_defaults_extra_file;
+ const char *save_extra_file = my_defaults_extra_file;
const char *save_group_suffix = my_defaults_group_suffix;
if (my_defaults_file)
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/run-test/setup.cpp b/storage/ndb/test/run-test/setup.cpp
index 60f8285888c..fc30c998865 100644
--- a/storage/ndb/test/run-test/setup.cpp
+++ b/storage/ndb/test/run-test/setup.cpp
@@ -105,7 +105,7 @@ setup_config(atrt_config& config)
*/
for (j = 0; j<(size_t)argc; j++)
{
- if (tmp[j] == args_separator) /* skip arguments separator */
+ if (my_getopt_is_args_separator(tmp[j])) /* skip arguments separator */
continue;
for (k = 0; proc_args[k].name; k++)
{
@@ -375,7 +375,7 @@ load_options(int argc, char** argv, int type, atrt_options& opts)
* Skip the separator for arguments from config file and command
* line
*/
- if (argv[i] == args_separator)
+ if (my_getopt_is_args_separator(argv[i]))
continue;
for (size_t j = 0; f_options[j].name; j++)
{
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/perfschema/Makefile.am b/storage/perfschema/Makefile.am
deleted file mode 100644
index 762f5b85790..00000000000
--- a/storage/perfschema/Makefile.am
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software 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,
-# 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
-
-#called from the top level Makefile
-
-SUBDIRS = . unittest
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-MYSQLLIBdir= $(pkglibdir)
-pkgplugindir = $(pkglibdir)/plugin
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/sql \
- -I$(srcdir)
-WRAPLIBS=
-
-LDADD =
-
-DEFS = -DMYSQL_SERVER @DEFS@
-
-
-noinst_HEADERS = ha_perfschema.h pfs_engine_table.h pfs.h pfs_server.h \
- pfs_global.h pfs_instr_class.h pfs_instr.h \
- pfs_column_types.h pfs_column_values.h \
- table_setup_instruments.h table_performance_timers.h \
- table_setup_timers.h \
- table_setup_consumers.h table_events_waits.h \
- pfs_events_waits.h pfs_timer.h table_threads.h \
- table_sync_instances.h \
- table_events_waits_summary.h pfs_stat.h \
- table_ews_global_by_event_name.h table_all_instr.h \
- table_file_instances.h table_file_summary.h \
- pfs_lock.h pfs_atomic.h
-
-PSE_SOURCES = ha_perfschema.cc pfs_engine_table.cc pfs.cc pfs_server.cc \
- pfs_global.cc pfs_instr_class.cc pfs_instr.cc \
- pfs_column_values.cc \
- table_setup_instruments.cc table_performance_timers.cc \
- table_setup_timers.cc \
- table_setup_consumers.cc table_events_waits.cc \
- pfs_events_waits.cc pfs_timer.cc table_threads.cc \
- table_sync_instances.cc \
- table_events_waits_summary.cc \
- table_ews_global_by_event_name.cc table_all_instr.cc \
- table_file_instances.cc table_file_summary.cc \
- pfs_atomic.cc pfs_check.cc
-
-EXTRA_LIBRARIES = libperfschema.a
-noinst_LIBRARIES = @plugin_perfschema_static_target@
-
-libperfschema_a_SOURCES= $(PSE_SOURCES)
-
-EXTRA_DIST = plug.in CMakeLists.txt
-
-unittests = unittest
-
-test:
- perl $(top_srcdir)/unittest/unit.pl run $(unittests)
-
-test-verbose:
- HARNESS_VERBOSE=1 perl $(top_srcdir)/unittest/unit.pl run $(unittests)
-
diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc
index b6438808869..ec063b782c1 100644
--- a/storage/perfschema/ha_perfschema.cc
+++ b/storage/perfschema/ha_perfschema.cc
@@ -246,7 +246,6 @@ int ha_perfschema::write_row(uchar *buf)
result= m_table_share->m_write_row(table, buf, table->field);
else
{
- my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
result= HA_ERR_WRONG_COMMAND;
}
@@ -357,12 +356,16 @@ int ha_perfschema::delete_all_rows(void)
result= m_table_share->m_delete_all_rows();
else
{
- my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
result= HA_ERR_WRONG_COMMAND;
}
DBUG_RETURN(result);
}
+int ha_perfschema::truncate()
+{
+ return delete_all_rows();
+}
+
THR_LOCK_DATA **ha_perfschema::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
@@ -383,7 +386,6 @@ int ha_perfschema::delete_table(const char *name)
int ha_perfschema::rename_table(const char * from, const char * to)
{
DBUG_ENTER("ha_perfschema::rename_table ");
- my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -408,7 +410,37 @@ int ha_perfschema::create(const char *name, TABLE *table_arg,
This is not a general purpose engine.
Failure to CREATE TABLE is the expected result.
*/
- my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
+void ha_perfschema::print_error(int error, myf errflag)
+{
+ switch (error)
+ {
+ case HA_ERR_TABLE_NEEDS_UPGRADE:
+ /*
+ The error message for ER_TABLE_NEEDS_UPGRADE refers to REPAIR table,
+ which does not apply to performance schema tables.
+ */
+ my_error(ER_WRONG_NATIVE_TABLE_STRUCTURE, MYF(0),
+ table_share->db.str, table_share->table_name.str);
+ break;
+ case HA_ERR_WRONG_COMMAND:
+ /*
+ The performance schema is not a general purpose storage engine,
+ some operations are not supported, by design.
+ We do not want to print "Command not supported",
+ which gives the impression that a command implementation is missing,
+ and that the failure should be considered a bug.
+ We print "Invalid performance_schema usage." instead,
+ to emphasise that the operation attempted is not meant to be legal,
+ and that the failure returned is indeed the expected result.
+ */
+ my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
+ break;
+ default:
+ handler::print_error(error, errflag);
+ break;
+ }
+}
+
diff --git a/storage/perfschema/ha_perfschema.h b/storage/perfschema/ha_perfschema.h
index 2c7b45fbbf7..c0ee0827dbc 100644
--- a/storage/perfschema/ha_perfschema.h
+++ b/storage/perfschema/ha_perfschema.h
@@ -100,9 +100,6 @@ public:
double scan_time(void)
{ return 1.0; }
- double read_time(ha_rows)
- { return 1.0; }
-
int open(const char *name, int mode, uint test_if_locked);
int close(void);
@@ -127,6 +124,8 @@ public:
int delete_all_rows(void);
+ int truncate();
+
int delete_table(const char *from);
int rename_table(const char * from, const char * to);
@@ -147,6 +146,8 @@ public:
return FALSE;
}
+ virtual void print_error(int error, myf errflags);
+
private:
/** MySQL lock */
THR_LOCK_DATA m_thr_lock;
diff --git a/storage/perfschema/pfs_engine_table.cc b/storage/perfschema/pfs_engine_table.cc
index 3b1959c98d2..38f6df3003d 100644
--- a/storage/perfschema/pfs_engine_table.cc
+++ b/storage/perfschema/pfs_engine_table.cc
@@ -232,8 +232,6 @@ int PFS_engine_table::read_row(TABLE *table,
*/
if (! m_share_ptr->m_checked)
{
- my_error(ER_WRONG_NATIVE_TABLE_STRUCTURE, MYF(0),
- PERFORMANCE_SCHEMA_str.str, m_share_ptr->m_name.str);
return HA_ERR_TABLE_NEEDS_UPGRADE;
}
@@ -279,8 +277,6 @@ int PFS_engine_table::update_row(TABLE *table,
*/
if (! m_share_ptr->m_checked)
{
- my_error(ER_WRONG_NATIVE_TABLE_STRUCTURE, MYF(0),
- PERFORMANCE_SCHEMA_str.str, m_share_ptr->m_name.str);
return HA_ERR_TABLE_NEEDS_UPGRADE;
}
@@ -351,7 +347,6 @@ int PFS_engine_table::update_row_values(TABLE *,
unsigned char *,
Field **)
{
- my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
return HA_ERR_WRONG_COMMAND;
}
@@ -524,9 +519,9 @@ bool pfs_show_status(handlerton *hton, THD *thd,
/*
Note about naming conventions:
- Internal buffers exposed as a table in the performance schema are named
- after the table, as in 'EVENTS_WAITS_CURRENT'
+ after the table, as in 'events_waits_current'
- Internal buffers not exposed by a table are named with parenthesis,
- as in '(PFS_MUTEX_CLASS)'.
+ as in '(pfs_mutex_class)'.
*/
if (stat != HA_ENGINE_STATUS)
DBUG_RETURN(false);
@@ -537,219 +532,219 @@ bool pfs_show_status(handlerton *hton, THD *thd,
{
switch (i){
case 0:
- name= "EVENTS_WAITS_CURRENT.ROW_SIZE";
+ name= "events_waits_current.row_size";
size= sizeof(PFS_wait_locker);
break;
case 1:
- name= "EVENTS_WAITS_CURRENT.ROW_COUNT";
+ name= "events_waits_current.row_count";
size= LOCKER_STACK_SIZE * thread_max;
break;
case 2:
- name= "EVENTS_WAITS_HISTORY.ROW_SIZE";
+ name= "events_waits_history.row_size";
size= sizeof(PFS_events_waits);
break;
case 3:
- name= "EVENTS_WAITS_HISTORY.ROW_COUNT";
+ name= "events_waits_history.row_count";
size= events_waits_history_per_thread * thread_max;
break;
case 4:
- name= "EVENTS_WAITS_HISTORY.MEMORY";
+ name= "events_waits_history.memory";
size= events_waits_history_per_thread * thread_max
* sizeof(PFS_events_waits);
total_memory+= size;
break;
case 5:
- name= "EVENTS_WAITS_HISTORY_LONG.ROW_SIZE";
+ name= "events_waits_history_long.row_size";
size= sizeof(PFS_events_waits);
break;
case 6:
- name= "EVENTS_WAITS_HISTORY_LONG.ROW_COUNT";
+ name= "events_waits_history_long.row_count";
size= events_waits_history_long_size;
break;
case 7:
- name= "EVENTS_WAITS_HISTORY_LONG.MEMORY";
+ name= "events_waits_history_long.memory";
size= events_waits_history_long_size * sizeof(PFS_events_waits);
total_memory+= size;
break;
case 8:
- name= "(PFS_MUTEX_CLASS).ROW_SIZE";
+ name= "(pfs_mutex_class).row_size";
size= sizeof(PFS_mutex_class);
break;
case 9:
- name= "(PFS_MUTEX_CLASS).ROW_COUNT";
+ name= "(pfs_mutex_class).row_count";
size= mutex_class_max;
break;
case 10:
- name= "(PFS_MUTEX_CLASS).MEMORY";
+ name= "(pfs_mutex_class).memory";
size= mutex_class_max * sizeof(PFS_mutex_class);
total_memory+= size;
break;
case 11:
- name= "(PFS_RWLOCK_CLASS).ROW_SIZE";
+ name= "(pfs_rwlock_class).row_size";
size= sizeof(PFS_rwlock_class);
break;
case 12:
- name= "(PFS_RWLOCK_CLASS).ROW_COUNT";
+ name= "(pfs_rwlock_class).row_count";
size= rwlock_class_max;
break;
case 13:
- name= "(PFS_RWLOCK_CLASS).MEMORY";
+ name= "(pfs_rwlock_class).memory";
size= rwlock_class_max * sizeof(PFS_rwlock_class);
total_memory+= size;
break;
case 14:
- name= "(PFS_COND_CLASS).ROW_SIZE";
+ name= "(pfs_cond_class).row_size";
size= sizeof(PFS_cond_class);
break;
case 15:
- name= "(PFS_COND_CLASS).ROW_COUNT";
+ name= "(pfs_cond_class).row_count";
size= cond_class_max;
break;
case 16:
- name= "(PFS_COND_CLASS).MEMORY";
+ name= "(pfs_cond_class).memory";
size= cond_class_max * sizeof(PFS_cond_class);
total_memory+= size;
break;
case 17:
- name= "(PFS_THREAD_CLASS).ROW_SIZE";
+ name= "(pfs_thread_class).row_size";
size= sizeof(PFS_thread_class);
break;
case 18:
- name= "(PFS_THREAD_CLASS).ROW_COUNT";
+ name= "(pfs_thread_class).row_count";
size= thread_class_max;
break;
case 19:
- name= "(PFS_THREAD_CLASS).MEMORY";
+ name= "(pfs_thread_class).memory";
size= thread_class_max * sizeof(PFS_thread_class);
total_memory+= size;
break;
case 20:
- name= "(PFS_FILE_CLASS).ROW_SIZE";
+ name= "(pfs_file_class).row_size";
size= sizeof(PFS_file_class);
break;
case 21:
- name= "(PFS_FILE_CLASS).ROW_COUNT";
+ name= "(pfs_file_class).row_count";
size= file_class_max;
break;
case 22:
- name= "(PFS_FILE_CLASS).MEMORY";
+ name= "(pfs_file_class).memory";
size= file_class_max * sizeof(PFS_file_class);
total_memory+= size;
break;
case 23:
- name= "MUTEX_INSTANCES.ROW_SIZE";
+ name= "mutex_instances.row_size";
size= sizeof(PFS_mutex);
break;
case 24:
- name= "MUTEX_INSTANCES.ROW_COUNT";
+ name= "mutex_instances.row_count";
size= mutex_max;
break;
case 25:
- name= "MUTEX_INSTANCES.MEMORY";
+ name= "mutex_instances.memory";
size= mutex_max * sizeof(PFS_mutex);
total_memory+= size;
break;
case 26:
- name= "RWLOCK_INSTANCES.ROW_SIZE";
+ name= "rwlock_instances.row_size";
size= sizeof(PFS_rwlock);
break;
case 27:
- name= "RWLOCK_INSTANCES.ROW_COUNT";
+ name= "rwlock_instances.row_count";
size= rwlock_max;
break;
case 28:
- name= "RWLOCK_INSTANCES.MEMORY";
+ name= "rwlock_instances.memory";
size= rwlock_max * sizeof(PFS_rwlock);
total_memory+= size;
break;
case 29:
- name= "COND_INSTANCES.ROW_SIZE";
+ name= "cond_instances.row_size";
size= sizeof(PFS_cond);
break;
case 30:
- name= "COND_INSTANCES.ROW_COUNT";
+ name= "cond_instances.row_count";
size= cond_max;
break;
case 31:
- name= "COND_INSTANCES.MEMORY";
+ name= "cond_instances.memory";
size= cond_max * sizeof(PFS_cond);
total_memory+= size;
break;
case 32:
- name= "PROCESSLIST.ROW_SIZE";
+ name= "threads.row_size";
size= sizeof(PFS_thread);
break;
case 33:
- name= "PROCESSLIST.ROW_COUNT";
+ name= "threads.row_count";
size= thread_max;
break;
case 34:
- name= "PROCESSLIST.MEMORY";
+ name= "threads.memory";
size= thread_max * sizeof(PFS_thread);
total_memory+= size;
break;
case 35:
- name= "FILE_INSTANCES.ROW_SIZE";
+ name= "file_instances.row_size";
size= sizeof(PFS_file);
break;
case 36:
- name= "FILE_INSTANCES.ROW_COUNT";
+ name= "file_instances.row_count";
size= file_max;
break;
case 37:
- name= "FILE_INSTANCES.MEMORY";
+ name= "file_instances.memory";
size= file_max * sizeof(PFS_file);
total_memory+= size;
break;
case 38:
- name= "(PFS_FILE_HANDLE).ROW_SIZE";
+ name= "(pfs_file_handle).row_size";
size= sizeof(PFS_file*);
break;
case 39:
- name= "(PFS_FILE_HANDLE).ROW_COUNT";
+ name= "(pfs_file_handle).row_count";
size= file_handle_max;
break;
case 40:
- name= "(PFS_FILE_HANDLE).MEMORY";
+ name= "(pfs_file_handle).memory";
size= file_handle_max * sizeof(PFS_file*);
total_memory+= size;
break;
case 41:
- name= "EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.ROW_SIZE";
+ name= "events_waits_summary_by_thread_by_event_name.row_size";
size= sizeof(PFS_single_stat_chain);
break;
case 42:
- name= "EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.ROW_COUNT";
+ name= "events_waits_summary_by_thread_by_event_name.row_count";
size= thread_max * instr_class_per_thread;
break;
case 43:
- name= "EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.MEMORY";
+ name= "events_waits_summary_by_thread_by_event_name.memory";
size= thread_max * instr_class_per_thread * sizeof(PFS_single_stat_chain);
total_memory+= size;
break;
case 44:
- name= "(PFS_TABLE_SHARE).ROW_SIZE";
+ name= "(pfs_table_share).row_size";
size= sizeof(PFS_table_share);
break;
case 45:
- name= "(PFS_TABLE_SHARE).ROW_COUNT";
+ name= "(pfs_table_share).row_count";
size= table_share_max;
break;
case 46:
- name= "(PFS_TABLE_SHARE).MEMORY";
+ name= "(pfs_table_share).memory";
size= table_share_max * sizeof(PFS_table_share);
total_memory+= size;
break;
case 47:
- name= "(PFS_TABLE).ROW_SIZE";
+ name= "(pfs_table).row_size";
size= sizeof(PFS_table);
break;
case 48:
- name= "(PFS_TABLE).ROW_COUNT";
+ name= "(pfs_table).row_count";
size= table_max;
break;
case 49:
- name= "(PFS_TABLE).MEMORY";
+ name= "(pfs_table).memory";
size= table_max * sizeof(PFS_table);
total_memory+= size;
break;
@@ -758,7 +753,7 @@ bool pfs_show_status(handlerton *hton, THD *thd,
for aggregation in total_memory.
*/
case 50:
- name= "PERFORMANCE_SCHEMA.MEMORY";
+ name= "performance_schema.memory";
size= total_memory;
/* This will fail if something is not advertised here */
DBUG_ASSERT(size == pfs_allocated_memory);
diff --git a/storage/perfschema/pfs_global.h b/storage/perfschema/pfs_global.h
index 6050612e24c..c0c0490a380 100644
--- a/storage/perfschema/pfs_global.h
+++ b/storage/perfschema/pfs_global.h
@@ -79,5 +79,21 @@ inline uint randomized_index(const void *ptr, uint max_size)
void pfs_print_error(const char *format, ...);
+/**
+ Given an array defined as T ARRAY[MAX],
+ check that an UNSAFE pointer actually points to an element
+ within the array.
+*/
+#define SANITIZE_ARRAY_BODY(T, ARRAY, MAX, UNSAFE) \
+ intptr offset; \
+ if ((&ARRAY[0] <= UNSAFE) && \
+ (UNSAFE < &ARRAY[MAX])) \
+ { \
+ offset= ((intptr) UNSAFE - (intptr) ARRAY) % sizeof(T); \
+ if (offset == 0) \
+ return UNSAFE; \
+ } \
+ return NULL
+
#endif
diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc
index 0c7b25a03de..a09920737c8 100644
--- a/storage/perfschema/pfs_instr.cc
+++ b/storage/perfschema/pfs_instr.cc
@@ -18,9 +18,9 @@
Performance schema instruments (implementation).
*/
+#include <my_global.h>
#include <string.h>
-#include "my_global.h"
#include "my_sys.h"
#include "pfs.h"
#include "pfs_stat.h"
@@ -758,9 +758,26 @@ PFS_thread* create_thread(PFS_thread_class *klass, const void *identity,
*/
PFS_thread *sanitize_thread(PFS_thread *unsafe)
{
- if ((&thread_array[0] <= unsafe) &&
- (unsafe < &thread_array[thread_max]))
- return unsafe;
+ SANITIZE_ARRAY_BODY(PFS_thread, thread_array, thread_max, unsafe);
+}
+
+const char *sanitize_file_name(const char *unsafe)
+{
+ intptr ptr= (intptr) unsafe;
+ intptr first= (intptr) &file_array[0];
+ intptr last= (intptr) &file_array[file_max];
+
+ /* Check if unsafe points inside file_array[] */
+ if (likely((first <= ptr) && (ptr < last)))
+ {
+ /* Check if unsafe points to PFS_file::m_filename */
+ intptr offset= (ptr - first) % sizeof(PFS_file);
+ intptr valid_offset= my_offsetof(PFS_file, m_filename[0]);
+ if (likely(offset == valid_offset))
+ {
+ return unsafe;
+ }
+ }
return NULL;
}
diff --git a/storage/perfschema/pfs_instr.h b/storage/perfschema/pfs_instr.h
index 791e2cd1f8d..2f6b729628e 100644
--- a/storage/perfschema/pfs_instr.h
+++ b/storage/perfschema/pfs_instr.h
@@ -227,6 +227,7 @@ struct PFS_thread
};
PFS_thread *sanitize_thread(PFS_thread *unsafe);
+const char *sanitize_file_name(const char *unsafe);
PFS_single_stat_chain*
find_per_thread_mutex_class_wait_stat(PFS_thread *thread,
diff --git a/storage/perfschema/pfs_instr_class.cc b/storage/perfschema/pfs_instr_class.cc
index 48547f73628..d99ca4d513c 100644
--- a/storage/perfschema/pfs_instr_class.cc
+++ b/storage/perfschema/pfs_instr_class.cc
@@ -543,15 +543,9 @@ PFS_mutex_class *find_mutex_class(PFS_sync_key key)
FIND_CLASS_BODY(key, mutex_class_allocated_count, mutex_class_array);
}
-#define SANITIZE_ARRAY_BODY(ARRAY, MAX, UNSAFE) \
- if ((&ARRAY[0] <= UNSAFE) && \
- (UNSAFE < &ARRAY[MAX])) \
- return UNSAFE; \
- return NULL
-
PFS_mutex_class *sanitize_mutex_class(PFS_mutex_class *unsafe)
{
- SANITIZE_ARRAY_BODY(mutex_class_array, mutex_class_max, unsafe);
+ SANITIZE_ARRAY_BODY(PFS_mutex_class, mutex_class_array, mutex_class_max, unsafe);
}
/**
@@ -566,7 +560,7 @@ PFS_rwlock_class *find_rwlock_class(PFS_sync_key key)
PFS_rwlock_class *sanitize_rwlock_class(PFS_rwlock_class *unsafe)
{
- SANITIZE_ARRAY_BODY(rwlock_class_array, rwlock_class_max, unsafe);
+ SANITIZE_ARRAY_BODY(PFS_rwlock_class, rwlock_class_array, rwlock_class_max, unsafe);
}
/**
@@ -581,7 +575,7 @@ PFS_cond_class *find_cond_class(PFS_sync_key key)
PFS_cond_class *sanitize_cond_class(PFS_cond_class *unsafe)
{
- SANITIZE_ARRAY_BODY(cond_class_array, cond_class_max, unsafe);
+ SANITIZE_ARRAY_BODY(PFS_cond_class, cond_class_array, cond_class_max, unsafe);
}
/**
@@ -636,7 +630,7 @@ PFS_thread_class *find_thread_class(PFS_sync_key key)
PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe)
{
- SANITIZE_ARRAY_BODY(thread_class_array, thread_class_max, unsafe);
+ SANITIZE_ARRAY_BODY(PFS_thread_class, thread_class_array, thread_class_max, unsafe);
}
/**
@@ -687,7 +681,7 @@ PFS_file_class *find_file_class(PFS_file_key key)
PFS_file_class *sanitize_file_class(PFS_file_class *unsafe)
{
- SANITIZE_ARRAY_BODY(file_class_array, file_class_max, unsafe);
+ SANITIZE_ARRAY_BODY(PFS_file_class, file_class_array, file_class_max, unsafe);
}
/**
@@ -820,7 +814,59 @@ search:
PFS_table_share *sanitize_table_share(PFS_table_share *unsafe)
{
- SANITIZE_ARRAY_BODY(table_share_array, table_share_max, unsafe);
+ SANITIZE_ARRAY_BODY(PFS_table_share, table_share_array, table_share_max, unsafe);
+}
+
+const char *sanitize_table_schema_name(const char *unsafe)
+{
+ intptr ptr= (intptr) unsafe;
+ intptr first= (intptr) &table_share_array[0];
+ intptr last= (intptr) &table_share_array[table_share_max];
+
+ PFS_table_share dummy;
+
+ /* Check if unsafe points inside table_share_array[] */
+ if (likely((first <= ptr) && (ptr < last)))
+ {
+ intptr offset= (ptr - first) % sizeof(PFS_table_share);
+ intptr from= my_offsetof(PFS_table_share, m_key.m_hash_key);
+ intptr len= sizeof(dummy.m_key.m_hash_key);
+ /* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */
+ if (likely((from <= offset) && (offset < from + len)))
+ {
+ PFS_table_share *base= (PFS_table_share*) (ptr - offset);
+ /* Check if unsafe really is the schema name */
+ if (likely(base->m_schema_name == unsafe))
+ return unsafe;
+ }
+ }
+ return NULL;
+}
+
+const char *sanitize_table_object_name(const char *unsafe)
+{
+ intptr ptr= (intptr) unsafe;
+ intptr first= (intptr) &table_share_array[0];
+ intptr last= (intptr) &table_share_array[table_share_max];
+
+ PFS_table_share dummy;
+
+ /* Check if unsafe points inside table_share_array[] */
+ if (likely((first <= ptr) && (ptr < last)))
+ {
+ intptr offset= (ptr - first) % sizeof(PFS_table_share);
+ intptr from= my_offsetof(PFS_table_share, m_key.m_hash_key);
+ intptr len= sizeof(dummy.m_key.m_hash_key);
+ /* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */
+ if (likely((from <= offset) && (offset < from + len)))
+ {
+ PFS_table_share *base= (PFS_table_share*) (ptr - offset);
+ /* Check if unsafe really is the table name */
+ if (likely(base->m_table_name == unsafe))
+ return unsafe;
+ }
+ }
+ return NULL;
}
static void reset_mutex_class_waits(void)
diff --git a/storage/perfschema/pfs_instr_class.h b/storage/perfschema/pfs_instr_class.h
index bd6560dbb55..107db628226 100644
--- a/storage/perfschema/pfs_instr_class.h
+++ b/storage/perfschema/pfs_instr_class.h
@@ -222,6 +222,8 @@ PFS_thread_class *find_thread_class(PSI_thread_key key);
PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe);
PFS_file_class *find_file_class(PSI_file_key key);
PFS_file_class *sanitize_file_class(PFS_file_class *unsafe);
+const char *sanitize_table_schema_name(const char *unsafe);
+const char *sanitize_table_object_name(const char *unsafe);
PFS_table_share *find_or_create_table_share(PFS_thread *thread,
const char *schema_name,
diff --git a/storage/perfschema/pfs_lock.h b/storage/perfschema/pfs_lock.h
index 5c74d3944ba..d253cfa4366 100644
--- a/storage/perfschema/pfs_lock.h
+++ b/storage/perfschema/pfs_lock.h
@@ -135,7 +135,25 @@ struct pfs_lock
*/
void allocated_to_free(void)
{
- DBUG_ASSERT(m_state == PFS_LOCK_ALLOCATED);
+#ifndef DBUG_OFF
+ extern volatile bool ready_to_exit;
+#endif
+
+ /*
+ If this record is not in the ALLOCATED state and the caller is trying
+ to free it, this is a bug: the caller is confused,
+ and potentially damaging data owned by another thread or object.
+ The correct assert to use here to guarantee data integrity is simply:
+ DBUG_ASSERT(m_state == PFS_LOCK_ALLOCATED);
+ Now, because of Bug#56666 (Race condition between the server main thread
+ and the kill server thread), this assert actually fails during shutdown,
+ and the failure is legitimate, on concurrent calls to mysql_*_destroy(),
+ when destroying the instrumentation of an object ... twice.
+ During shutdown this has no consequences for the performance schema,
+ so the assert is relaxed with the "|| ready_to_exit" condition as a work
+ around until Bug#56666 is fixed.
+ */
+ DBUG_ASSERT((m_state == PFS_LOCK_ALLOCATED) || ready_to_exit);
PFS_atomic::store_32(&m_state, PFS_LOCK_FREE);
}
diff --git a/storage/perfschema/plug.in b/storage/perfschema/plug.in
deleted file mode 100644
index 36a1c1e8bda..00000000000
--- a/storage/perfschema/plug.in
+++ /dev/null
@@ -1,26 +0,0 @@
-dnl -*- ksh -*-
-
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software 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,
-# 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
-
-dnl This file is part of the configure scripts used by autoconf.
-
-MYSQL_STORAGE_ENGINE(perfschema,
- perfschema,
- [Performance Schema],
- [Performance Schema],
- [default,max,max-no-ndb])
-MYSQL_PLUGIN_DIRECTORY(perfschema, [storage/perfschema])
-MYSQL_PLUGIN_STATIC(perfschema, [libperfschema.a])
diff --git a/storage/perfschema/table_events_waits.cc b/storage/perfschema/table_events_waits.cc
index d34f6fbe722..8408cc55975 100644
--- a/storage/perfschema/table_events_waits.cc
+++ b/storage/perfschema/table_events_waits.cc
@@ -118,7 +118,7 @@ table_events_waits_current::m_field_def=
PFS_engine_table_share
table_events_waits_current::m_share=
{
- { C_STRING_WITH_LEN("EVENTS_WAITS_CURRENT") },
+ { C_STRING_WITH_LEN("events_waits_current") },
&pfs_truncatable_acl,
&table_events_waits_current::create,
NULL, /* write_row */
@@ -135,7 +135,7 @@ THR_LOCK table_events_waits_history::m_table_lock;
PFS_engine_table_share
table_events_waits_history::m_share=
{
- { C_STRING_WITH_LEN("EVENTS_WAITS_HISTORY") },
+ { C_STRING_WITH_LEN("events_waits_history") },
&pfs_truncatable_acl,
&table_events_waits_history::create,
NULL, /* write_row */
@@ -152,7 +152,7 @@ THR_LOCK table_events_waits_history_long::m_table_lock;
PFS_engine_table_share
table_events_waits_history_long::m_share=
{
- { C_STRING_WITH_LEN("EVENTS_WAITS_HISTORY_LONG") },
+ { C_STRING_WITH_LEN("events_waits_history_long") },
&pfs_truncatable_acl,
&table_events_waits_history_long::create,
NULL, /* write_row */
@@ -194,6 +194,9 @@ void table_events_waits_common::make_row(bool thread_own_wait,
PFS_instr_class *safe_class;
const char *base;
const char *safe_source_file;
+ const char *safe_table_schema_name;
+ const char *safe_table_object_name;
+ const char *safe_file_name;
m_row_exists= false;
safe_thread= sanitize_thread(pfs_thread);
@@ -252,15 +255,19 @@ void table_events_waits_common::make_row(bool thread_own_wait,
m_row.m_object_type= "TABLE";
m_row.m_object_type_length= 5;
m_row.m_object_schema_length= wait->m_schema_name_length;
+ safe_table_schema_name= sanitize_table_schema_name(wait->m_schema_name);
if (unlikely((m_row.m_object_schema_length == 0) ||
- (m_row.m_object_schema_length > sizeof(m_row.m_object_schema))))
+ (m_row.m_object_schema_length > sizeof(m_row.m_object_schema)) ||
+ (safe_table_schema_name == NULL)))
return;
- memcpy(m_row.m_object_schema, wait->m_schema_name, m_row.m_object_schema_length);
+ memcpy(m_row.m_object_schema, safe_table_schema_name, m_row.m_object_schema_length);
m_row.m_object_name_length= wait->m_object_name_length;
+ safe_table_object_name= sanitize_table_object_name(wait->m_object_name);
if (unlikely((m_row.m_object_name_length == 0) ||
- (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
+ (m_row.m_object_name_length > sizeof(m_row.m_object_name)) ||
+ (safe_table_object_name == NULL)))
return;
- memcpy(m_row.m_object_name, wait->m_object_name, m_row.m_object_name_length);
+ memcpy(m_row.m_object_name, safe_table_object_name, m_row.m_object_name_length);
safe_class= &global_table_class;
break;
case WAIT_CLASS_FILE:
@@ -268,10 +275,12 @@ void table_events_waits_common::make_row(bool thread_own_wait,
m_row.m_object_type_length= 4;
m_row.m_object_schema_length= 0;
m_row.m_object_name_length= wait->m_object_name_length;
+ safe_file_name= sanitize_file_name(wait->m_object_name);
if (unlikely((m_row.m_object_name_length == 0) ||
- (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
+ (m_row.m_object_name_length > sizeof(m_row.m_object_name)) ||
+ (safe_file_name == NULL)))
return;
- memcpy(m_row.m_object_name, wait->m_object_name, m_row.m_object_name_length);
+ memcpy(m_row.m_object_name, safe_file_name, m_row.m_object_name_length);
safe_class= sanitize_file_class((PFS_file_class*) wait->m_class);
break;
case NO_WAIT_CLASS:
diff --git a/storage/perfschema/table_events_waits_summary.cc b/storage/perfschema/table_events_waits_summary.cc
index 435a3500f06..05f280f8521 100644
--- a/storage/perfschema/table_events_waits_summary.cc
+++ b/storage/perfschema/table_events_waits_summary.cc
@@ -74,7 +74,7 @@ table_events_waits_summary_by_thread_by_event_name::m_field_def=
PFS_engine_table_share
table_events_waits_summary_by_thread_by_event_name::m_share=
{
- { C_STRING_WITH_LEN("EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME") },
+ { C_STRING_WITH_LEN("events_waits_summary_by_thread_by_event_name") },
&pfs_truncatable_acl,
&table_events_waits_summary_by_thread_by_event_name::create,
NULL, /* write_row */
@@ -386,7 +386,7 @@ table_events_waits_summary_by_instance::m_field_def=
PFS_engine_table_share
table_events_waits_summary_by_instance::m_share=
{
- { C_STRING_WITH_LEN("EVENTS_WAITS_SUMMARY_BY_INSTANCE") },
+ { C_STRING_WITH_LEN("events_waits_summary_by_instance") },
&pfs_truncatable_acl,
&table_events_waits_summary_by_instance::create,
NULL, /* write_row */
diff --git a/storage/perfschema/table_ews_global_by_event_name.cc b/storage/perfschema/table_ews_global_by_event_name.cc
index 35e744ed96b..c983a967c4e 100644
--- a/storage/perfschema/table_ews_global_by_event_name.cc
+++ b/storage/perfschema/table_ews_global_by_event_name.cc
@@ -69,7 +69,7 @@ table_ews_global_by_event_name::m_field_def=
PFS_engine_table_share
table_ews_global_by_event_name::m_share=
{
- { C_STRING_WITH_LEN("EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME") },
+ { C_STRING_WITH_LEN("events_waits_summary_global_by_event_name") },
&pfs_truncatable_acl,
&table_ews_global_by_event_name::create,
NULL, /* write_row */
diff --git a/storage/perfschema/table_file_instances.cc b/storage/perfschema/table_file_instances.cc
index f1676421616..9ae732a0e1c 100644
--- a/storage/perfschema/table_file_instances.cc
+++ b/storage/perfschema/table_file_instances.cc
@@ -54,7 +54,7 @@ table_file_instances::m_field_def=
PFS_engine_table_share
table_file_instances::m_share=
{
- { C_STRING_WITH_LEN("FILE_INSTANCES") },
+ { C_STRING_WITH_LEN("file_instances") },
&pfs_readonly_acl,
&table_file_instances::create,
NULL, /* write_row */
diff --git a/storage/perfschema/table_file_summary.cc b/storage/perfschema/table_file_summary.cc
index f8b9e66118b..a954db7ef4e 100644
--- a/storage/perfschema/table_file_summary.cc
+++ b/storage/perfschema/table_file_summary.cc
@@ -64,7 +64,7 @@ table_file_summary_by_event_name::m_field_def=
PFS_engine_table_share
table_file_summary_by_event_name::m_share=
{
- { C_STRING_WITH_LEN("FILE_SUMMARY_BY_EVENT_NAME") },
+ { C_STRING_WITH_LEN("file_summary_by_event_name") },
&pfs_truncatable_acl,
&table_file_summary_by_event_name::create,
NULL, /* write_row */
@@ -227,7 +227,7 @@ table_file_summary_by_instance::m_field_def=
PFS_engine_table_share
table_file_summary_by_instance::m_share=
{
- { C_STRING_WITH_LEN("FILE_SUMMARY_BY_INSTANCE") },
+ { C_STRING_WITH_LEN("file_summary_by_instance") },
&pfs_truncatable_acl,
&table_file_summary_by_instance::create,
NULL, /* write_row */
diff --git a/storage/perfschema/table_performance_timers.cc b/storage/perfschema/table_performance_timers.cc
index f400e37366c..acd379bc57b 100644
--- a/storage/perfschema/table_performance_timers.cc
+++ b/storage/perfschema/table_performance_timers.cc
@@ -58,7 +58,7 @@ table_performance_timers::m_field_def=
PFS_engine_table_share
table_performance_timers::m_share=
{
- { C_STRING_WITH_LEN("PERFORMANCE_TIMERS") },
+ { C_STRING_WITH_LEN("performance_timers") },
&pfs_readonly_acl,
&table_performance_timers::create,
NULL, /* write_row */
diff --git a/storage/perfschema/table_setup_consumers.cc b/storage/perfschema/table_setup_consumers.cc
index 3cc6a1441c1..601e0483b14 100644
--- a/storage/perfschema/table_setup_consumers.cc
+++ b/storage/perfschema/table_setup_consumers.cc
@@ -84,7 +84,7 @@ table_setup_consumers::m_field_def=
PFS_engine_table_share
table_setup_consumers::m_share=
{
- { C_STRING_WITH_LEN("SETUP_CONSUMERS") },
+ { C_STRING_WITH_LEN("setup_consumers") },
&pfs_updatable_acl,
&table_setup_consumers::create,
NULL, /* write_row */
@@ -192,7 +192,6 @@ int table_setup_consumers::update_row_values(TABLE *table,
switch(f->field_index)
{
case 0: /* NAME */
- my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
return HA_ERR_WRONG_COMMAND;
case 1: /* ENABLED */
{
diff --git a/storage/perfschema/table_setup_instruments.cc b/storage/perfschema/table_setup_instruments.cc
index 259ccee3c84..480c0dbc13f 100644
--- a/storage/perfschema/table_setup_instruments.cc
+++ b/storage/perfschema/table_setup_instruments.cc
@@ -54,7 +54,7 @@ table_setup_instruments::m_field_def=
PFS_engine_table_share
table_setup_instruments::m_share=
{
- { C_STRING_WITH_LEN("SETUP_INSTRUMENTS") },
+ { C_STRING_WITH_LEN("setup_instruments") },
&pfs_updatable_acl,
&table_setup_instruments::create,
NULL, /* write_row */
@@ -253,7 +253,6 @@ int table_setup_instruments::update_row_values(TABLE *table,
switch(f->field_index)
{
case 0: /* NAME */
- my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
return HA_ERR_WRONG_COMMAND;
case 1: /* ENABLED */
value= (enum_yes_no) get_field_enum(f);
diff --git a/storage/perfschema/table_setup_timers.cc b/storage/perfschema/table_setup_timers.cc
index 8ca218913bb..f8b1bfa4fe2 100644
--- a/storage/perfschema/table_setup_timers.cc
+++ b/storage/perfschema/table_setup_timers.cc
@@ -57,7 +57,7 @@ table_setup_timers::m_field_def=
PFS_engine_table_share
table_setup_timers::m_share=
{
- { C_STRING_WITH_LEN("SETUP_TIMERS") },
+ { C_STRING_WITH_LEN("setup_timers") },
&pfs_updatable_acl,
&table_setup_timers::create,
NULL, /* write_row */
@@ -164,7 +164,6 @@ int table_setup_timers::update_row_values(TABLE *table,
switch(f->field_index)
{
case 0: /* NAME */
- my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
return HA_ERR_WRONG_COMMAND;
case 1: /* TIMER_NAME */
value= get_field_enum(f);
diff --git a/storage/perfschema/table_sync_instances.cc b/storage/perfschema/table_sync_instances.cc
index 82587ce493d..f2bd9fa1a28 100644
--- a/storage/perfschema/table_sync_instances.cc
+++ b/storage/perfschema/table_sync_instances.cc
@@ -55,7 +55,7 @@ table_mutex_instances::m_field_def=
PFS_engine_table_share
table_mutex_instances::m_share=
{
- { C_STRING_WITH_LEN("MUTEX_INSTANCES") },
+ { C_STRING_WITH_LEN("mutex_instances") },
&pfs_readonly_acl,
&table_mutex_instances::create,
NULL, /* write_row */
@@ -223,7 +223,7 @@ table_rwlock_instances::m_field_def=
PFS_engine_table_share
table_rwlock_instances::m_share=
{
- { C_STRING_WITH_LEN("RWLOCK_INSTANCES") },
+ { C_STRING_WITH_LEN("rwlock_instances") },
&pfs_readonly_acl,
&table_rwlock_instances::create,
NULL, /* write_row */
@@ -388,7 +388,7 @@ table_cond_instances::m_field_def=
PFS_engine_table_share
table_cond_instances::m_share=
{
- { C_STRING_WITH_LEN("COND_INSTANCES") },
+ { C_STRING_WITH_LEN("cond_instances") },
&pfs_readonly_acl,
&table_cond_instances::create,
NULL, /* write_row */
diff --git a/storage/perfschema/table_threads.cc b/storage/perfschema/table_threads.cc
index bba7806cab9..541ba860386 100644
--- a/storage/perfschema/table_threads.cc
+++ b/storage/perfschema/table_threads.cc
@@ -34,13 +34,13 @@ static const TABLE_FIELD_TYPE field_types[]=
{ NULL, 0}
},
{
- { C_STRING_WITH_LEN("ID") },
+ { C_STRING_WITH_LEN("PROCESSLIST_ID") },
{ C_STRING_WITH_LEN("int(11)") },
{ NULL, 0}
},
{
{ C_STRING_WITH_LEN("NAME") },
- { C_STRING_WITH_LEN("varchar(64)") },
+ { C_STRING_WITH_LEN("varchar(128)") },
{ NULL, 0}
}
};
@@ -52,7 +52,7 @@ table_threads::m_field_def=
PFS_engine_table_share
table_threads::m_share=
{
- { C_STRING_WITH_LEN("THREADS") },
+ { C_STRING_WITH_LEN("threads") },
&pfs_readonly_acl,
&table_threads::create,
NULL, /* write_row */
@@ -140,7 +140,7 @@ void table_threads::make_row(PFS_thread *pfs)
}
int table_threads::read_row_values(TABLE *table,
- unsigned char *,
+ unsigned char *buf,
Field **fields,
bool read_all)
{
@@ -150,7 +150,8 @@ int table_threads::read_row_values(TABLE *table,
return HA_ERR_RECORD_DELETED;
/* Set the null bits */
- DBUG_ASSERT(table->s->null_bytes == 0);
+ DBUG_ASSERT(table->s->null_bytes == 1);
+ buf[0]= 0;
for (; (f= *fields) ; fields++)
{
@@ -161,7 +162,7 @@ int table_threads::read_row_values(TABLE *table,
case 0: /* THREAD_ID */
set_field_ulong(f, m_row.m_thread_internal_id);
break;
- case 1: /* ID */
+ case 1: /* PROCESSLIST_ID */
set_field_ulong(f, m_row.m_thread_id);
break;
case 2: /* NAME */
diff --git a/storage/perfschema/table_threads.h b/storage/perfschema/table_threads.h
index 9df323f6d82..fb239007069 100644
--- a/storage/perfschema/table_threads.h
+++ b/storage/perfschema/table_threads.h
@@ -36,7 +36,7 @@ struct row_threads
{
/** Column THREAD_ID. */
ulong m_thread_internal_id;
- /** Column ID. */
+ /** Column PROCESSLIST_ID. */
ulong m_thread_id;
/** Column NAME. */
const char *m_name;
@@ -79,7 +79,7 @@ private:
/** Current row. */
row_threads m_row;
- /** True is the current row exists. */
+ /** True if the current row exists. */
bool m_row_exists;
/** Current position. */
PFS_simple_index m_pos;
diff --git a/storage/perfschema/unittest/Makefile.am b/storage/perfschema/unittest/Makefile.am
deleted file mode 100644
index 7d82753c9e5..00000000000
--- a/storage/perfschema/unittest/Makefile.am
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) 2008-2009 Sun Microsystems, Inc.
-#
-# 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
-
-INCLUDES = -I$(top_builddir)/include \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/include/mysql \
- -I$(top_srcdir)/regex \
- -I$(top_srcdir)/unittest/mytap \
- -I$(top_srcdir)/sql \
- -I$(top_srcdir)/storage/perfschema
-
-DEFS = -DMYSQL_SERVER @DEFS@
-
-TEST_CODE = $(top_builddir)/unittest/mytap/libmytap.a
-
-$(TEST_CODE) :
- (cd $(top_builddir)/unittest/mytap; $(MAKE))
-
-PROD_CODE = $(top_builddir)/storage/perfschema/libperfschema.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a
-
-noinst_PROGRAMS = pfs_instr_class-t pfs_instr_class-oom-t \
- pfs_instr-t pfs_instr-oom-t pfs_timer-t pfs-t
-
-pfs_t_SOURCES = pfs-t.cc stub_print_error.h
-pfs_t_LDADD = $(TEST_CODE) $(PROD_CODE)
-
-pfs_instr_class_t_SOURCES = pfs_instr_class-t.cc
-pfs_instr_class_t_LDADD = $(TEST_CODE) $(PROD_CODE)
-
-pfs_instr_class_oom_t_SOURCES = pfs_instr_class-oom-t.cc stub_pfs_global.h
-pfs_instr_class_oom_t_LDADD = $(TEST_CODE) $(PROD_CODE)
-
-pfs_instr_t_SOURCES = pfs_instr-t.cc
-pfs_instr_t_LDADD = $(TEST_CODE) $(PROD_CODE)
-
-pfs_instr_oom_t_SOURCES = pfs_instr-oom-t.cc stub_pfs_global.h
-pfs_instr_oom_t_LDADD = $(TEST_CODE) $(PROD_CODE)
-
-pfs_timer_t_SOURCES = pfs_timer-t.cc
-pfs_timer_t_LDADD = $(TEST_CODE) $(PROD_CODE)
-
-EXTRA_DIST = conf.txt CMakeLists.txt
-
diff --git a/storage/perfschema/unittest/pfs-t.cc b/storage/perfschema/unittest/pfs-t.cc
index c51f358c4d8..46e02306aca 100644
--- a/storage/perfschema/unittest/pfs-t.cc
+++ b/storage/perfschema/unittest/pfs-t.cc
@@ -25,6 +25,7 @@
#include <memory.h>
#include "stub_print_error.h"
+#include "stub_server_misc.h"
/* test helpers, to simulate the setup */
@@ -1204,6 +1205,8 @@ void test_enabled()
void do_all_tests()
{
+ /* Using initialize_performance_schema(), no partial init needed. */
+
test_bootstrap();
test_bad_registration();
test_init_disabled();
diff --git a/storage/perfschema/unittest/pfs_instr-oom-t.cc b/storage/perfschema/unittest/pfs_instr-oom-t.cc
index 9a3b179aa56..a00afe8b36a 100644
--- a/storage/perfschema/unittest/pfs_instr-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_instr-oom-t.cc
@@ -21,6 +21,7 @@
#include <tap.h>
#include "stub_pfs_global.h"
+#include "stub_server_misc.h"
void test_oom()
{
@@ -198,7 +199,11 @@ void test_oom()
void do_all_tests()
{
+ PFS_atomic::init();
+
test_oom();
+
+ PFS_atomic::cleanup();
}
int main(int, char **)
diff --git a/storage/perfschema/unittest/pfs_instr-t.cc b/storage/perfschema/unittest/pfs_instr-t.cc
index 7dcc8cec7f8..b13135aa615 100644
--- a/storage/perfschema/unittest/pfs_instr-t.cc
+++ b/storage/perfschema/unittest/pfs_instr-t.cc
@@ -22,6 +22,8 @@
#include <memory.h>
+#include "stub_server_misc.h"
+
void test_no_instruments()
{
int rc;
@@ -398,10 +400,14 @@ void test_per_thread_wait()
void do_all_tests()
{
+ PFS_atomic::init();
+
test_no_instruments();
test_no_instances();
test_with_instances();
test_per_thread_wait();
+
+ PFS_atomic::cleanup();
}
int main(int, char **)
diff --git a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
index 20fa0f3e6ff..95dccc420d7 100644
--- a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
@@ -20,6 +20,7 @@
#include <tap.h>
#include "stub_pfs_global.h"
+#include "stub_server_misc.h"
void test_oom()
{
@@ -46,7 +47,11 @@ void test_oom()
void do_all_tests()
{
+ PFS_atomic::init();
+
test_oom();
+
+ PFS_atomic::cleanup();
}
int main(int, char **)
diff --git a/storage/perfschema/unittest/pfs_instr_class-t.cc b/storage/perfschema/unittest/pfs_instr_class-t.cc
index c5a199727d5..ac34f082fe8 100644
--- a/storage/perfschema/unittest/pfs_instr_class-t.cc
+++ b/storage/perfschema/unittest/pfs_instr_class-t.cc
@@ -21,6 +21,8 @@
#include <pfs_global.h>
#include <tap.h>
+#include "stub_server_misc.h"
+
void test_no_registration()
{
int rc;
@@ -552,6 +554,8 @@ void test_instruments_reset()
void do_all_tests()
{
+ PFS_atomic::init();
+
test_no_registration();
test_mutex_registration();
test_rwlock_registration();
@@ -560,6 +564,8 @@ void do_all_tests()
test_file_registration();
test_table_registration();
test_instruments_reset();
+
+ PFS_atomic::cleanup();
}
int main(int, char **)
diff --git a/storage/perfschema/unittest/pfs_timer-t.cc b/storage/perfschema/unittest/pfs_timer-t.cc
index d8663c5ccda..69b554c7b31 100644
--- a/storage/perfschema/unittest/pfs_timer-t.cc
+++ b/storage/perfschema/unittest/pfs_timer-t.cc
@@ -105,7 +105,11 @@ void test_timers()
void do_all_tests()
{
+ PFS_atomic::init();
+
test_timers();
+
+ PFS_atomic::cleanup();
}
int main(int, char **)
diff --git a/storage/perfschema/unittest/stub_server_misc.h b/storage/perfschema/unittest/stub_server_misc.h
new file mode 100644
index 00000000000..17beadbb104
--- /dev/null
+++ b/storage/perfschema/unittest/stub_server_misc.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software 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 */
+
+/*
+ Minimal code to be able to link a unit test.
+*/
+
+volatile bool ready_to_exit= false;
+