summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMichael Widenius <monty@askmonty.org>2011-11-24 18:48:58 +0200
committerMichael Widenius <monty@askmonty.org>2011-11-24 18:48:58 +0200
commit69204571425ed3221e94c7eb1e030c00089bca26 (patch)
tree3d9cfbc44a057883c7db6bce267c8ebfd5fa9313 /storage
parente3e60a4102d6918e4231e402bef89b1a6b2a20cb (diff)
parentd26aefb0775048128495eaab151ee4118f8f7afd (diff)
downloadmariadb-git-69204571425ed3221e94c7eb1e030c00089bca26.tar.gz
Merge with MariaDB 5.1
Diffstat (limited to 'storage')
-rw-r--r--storage/Makefile.am3
-rwxr-xr-xstorage/archive/CMakeLists.txt3
-rw-r--r--storage/archive/Makefile.am2
-rw-r--r--storage/archive/archive_reader.c15
-rw-r--r--storage/archive/azio.c9
-rw-r--r--storage/archive/ha_archive.cc31
-rw-r--r--storage/blackhole/CMakeLists.txt3
-rw-r--r--storage/blackhole/Makefile.am2
-rw-r--r--storage/blackhole/ha_blackhole.cc7
-rw-r--r--storage/blackhole/ha_blackhole.h7
-rw-r--r--storage/csv/CMakeLists.txt3
-rw-r--r--storage/csv/Makefile.am2
-rw-r--r--storage/csv/ha_tina.cc6
-rw-r--r--storage/csv/ha_tina.h7
-rw-r--r--storage/csv/transparent_file.cc7
-rw-r--r--storage/csv/transparent_file.h7
-rw-r--r--storage/example/CMakeLists.txt3
-rw-r--r--storage/example/Makefile.am2
-rw-r--r--storage/example/ha_example.cc6
-rw-r--r--storage/example/ha_example.h6
-rwxr-xr-xstorage/federated/CMakeLists.txt3
-rw-r--r--storage/federated/Makefile.am4
-rw-r--r--storage/federated/ha_federated.cc4
-rw-r--r--storage/federated/ha_federated.h6
-rwxr-xr-xstorage/heap/CMakeLists.txt3
-rw-r--r--storage/heap/ha_heap.cc7
-rw-r--r--storage/heap/ha_heap.h6
-rw-r--r--storage/heap/hp_create.c1
-rw-r--r--storage/heap/hp_hash.c6
-rw-r--r--storage/heap/hp_info.c1
-rw-r--r--storage/heap/hp_test2.c6
-rw-r--r--storage/heap/hp_write.c7
-rw-r--r--storage/innobase/btr/btr0btr.c11
-rw-r--r--storage/innobase/btr/btr0cur.c35
-rw-r--r--storage/innobase/btr/btr0pcur.c27
-rw-r--r--storage/innobase/buf/buf0buf.c23
-rw-r--r--storage/innobase/dict/dict0load.c64
-rw-r--r--storage/innobase/fsp/fsp0fsp.c17
-rw-r--r--storage/innobase/handler/ha_innodb.cc164
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c8
-rw-r--r--storage/innobase/include/btr0pcur.h19
-rw-r--r--storage/innobase/include/btr0pcur.ic7
-rw-r--r--storage/innobase/include/btr0types.h5
-rw-r--r--storage/innobase/include/buf0buf.h28
-rw-r--r--storage/innobase/include/buf0buf.ic48
-rw-r--r--storage/innobase/include/fsp0fsp.h4
-rw-r--r--storage/innobase/include/mtr0mtr.h10
-rw-r--r--storage/innobase/include/rem0rec.h13
-rw-r--r--storage/innobase/include/rem0rec.ic37
-rw-r--r--storage/innobase/include/sync0rw.h3
-rw-r--r--storage/innobase/include/sync0rw.ic1
-rw-r--r--storage/innobase/include/sync0sync.h3
-rw-r--r--storage/innobase/include/trx0roll.h3
-rw-r--r--storage/innobase/include/trx0sys.h10
-rw-r--r--storage/innobase/include/trx0sys.ic21
-rw-r--r--storage/innobase/include/trx0trx.h5
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/include/ut0mem.h37
-rw-r--r--storage/innobase/include/ut0mem.ic21
-rw-r--r--storage/innobase/log/log0log.c9
-rw-r--r--storage/innobase/mtr/mtr0mtr.c34
-rw-r--r--storage/innobase/row/row0ins.c21
-rw-r--r--storage/innobase/row/row0purge.c14
-rw-r--r--storage/innobase/row/row0row.c25
-rw-r--r--storage/innobase/row/row0sel.c86
-rw-r--r--storage/innobase/row/row0vers.c16
-rw-r--r--storage/innobase/sync/sync0rw.c17
-rw-r--r--storage/innobase/sync/sync0sync.c10
-rw-r--r--storage/innobase/trx/trx0rec.c4
-rw-r--r--storage/innobase/trx/trx0trx.c11
-rw-r--r--storage/innobase/ut/ut0mem.c47
-rw-r--r--storage/innodb_plugin/ChangeLog156
-rw-r--r--storage/innodb_plugin/btr/btr0btr.c113
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c128
-rw-r--r--storage/innodb_plugin/btr/btr0pcur.c40
-rw-r--r--storage/innodb_plugin/btr/btr0sea.c257
-rw-r--r--storage/innodb_plugin/buf/buf0buddy.c411
-rw-r--r--storage/innodb_plugin/buf/buf0buf.c574
-rw-r--r--storage/innodb_plugin/buf/buf0flu.c4
-rw-r--r--storage/innodb_plugin/buf/buf0lru.c214
-rw-r--r--storage/innodb_plugin/buf/buf0rea.c170
-rw-r--r--storage/innodb_plugin/dict/dict0crea.c4
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c6
-rw-r--r--storage/innodb_plugin/dict/dict0load.c63
-rw-r--r--storage/innodb_plugin/fsp/fsp0fsp.c18
-rw-r--r--storage/innodb_plugin/ha/ha0ha.c69
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc194
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.h11
-rw-r--r--storage/innodb_plugin/handler/handler0alter.cc43
-rw-r--r--storage/innodb_plugin/ibuf/ibuf0ibuf.c37
-rw-r--r--storage/innodb_plugin/include/btr0btr.h34
-rw-r--r--storage/innodb_plugin/include/btr0btr.ic10
-rw-r--r--storage/innodb_plugin/include/btr0cur.h2
-rw-r--r--storage/innodb_plugin/include/btr0cur.ic2
-rw-r--r--storage/innodb_plugin/include/btr0pcur.h29
-rw-r--r--storage/innodb_plugin/include/btr0pcur.ic41
-rw-r--r--storage/innodb_plugin/include/btr0sea.h34
-rw-r--r--storage/innodb_plugin/include/btr0types.h25
-rw-r--r--storage/innodb_plugin/include/buf0buddy.h21
-rw-r--r--storage/innodb_plugin/include/buf0buddy.ic37
-rw-r--r--storage/innodb_plugin/include/buf0buf.h94
-rw-r--r--storage/innodb_plugin/include/buf0buf.ic61
-rw-r--r--storage/innodb_plugin/include/buf0lru.h23
-rw-r--r--storage/innodb_plugin/include/buf0types.h17
-rw-r--r--storage/innodb_plugin/include/fsp0fsp.h7
-rw-r--r--storage/innodb_plugin/include/ha0ha.h23
-rw-r--r--storage/innodb_plugin/include/ha0ha.ic54
-rw-r--r--storage/innodb_plugin/include/mtr0mtr.h12
-rw-r--r--storage/innodb_plugin/include/mtr0mtr.ic2
-rw-r--r--storage/innodb_plugin/include/page0cur.ic5
-rw-r--r--storage/innodb_plugin/include/page0page.h7
-rw-r--r--storage/innodb_plugin/include/page0page.ic2
-rw-r--r--storage/innodb_plugin/include/rem0rec.h14
-rw-r--r--storage/innodb_plugin/include/rem0rec.ic41
-rw-r--r--storage/innodb_plugin/include/row0row.h26
-rw-r--r--storage/innodb_plugin/include/row0row.ic45
-rw-r--r--storage/innodb_plugin/include/row0upd.ic10
-rw-r--r--storage/innodb_plugin/include/srv0srv.h2
-rw-r--r--storage/innodb_plugin/include/sync0rw.h3
-rw-r--r--storage/innodb_plugin/include/sync0rw.ic11
-rw-r--r--storage/innodb_plugin/include/sync0sync.h16
-rw-r--r--storage/innodb_plugin/include/trx0sys.h13
-rw-r--r--storage/innodb_plugin/include/trx0sys.ic24
-rw-r--r--storage/innodb_plugin/include/trx0trx.h11
-rw-r--r--storage/innodb_plugin/include/trx0undo.h55
-rw-r--r--storage/innodb_plugin/include/univ.i5
-rw-r--r--storage/innodb_plugin/include/ut0mem.h39
-rw-r--r--storage/innodb_plugin/include/ut0mem.ic23
-rw-r--r--storage/innodb_plugin/log/log0log.c9
-rw-r--r--storage/innodb_plugin/mtr/mtr0mtr.c36
-rw-r--r--storage/innodb_plugin/page/page0cur.c2
-rw-r--r--storage/innodb_plugin/page/page0page.c14
-rw-r--r--storage/innodb_plugin/page/page0zip.c186
-rw-r--r--storage/innodb_plugin/rem/rem0rec.c10
-rw-r--r--storage/innodb_plugin/row/row0ins.c27
-rw-r--r--storage/innodb_plugin/row/row0mysql.c32
-rw-r--r--storage/innodb_plugin/row/row0purge.c20
-rw-r--r--storage/innodb_plugin/row/row0row.c109
-rw-r--r--storage/innodb_plugin/row/row0sel.c112
-rw-r--r--storage/innodb_plugin/row/row0upd.c2
-rw-r--r--storage/innodb_plugin/row/row0vers.c18
-rw-r--r--storage/innodb_plugin/srv/srv0srv.c4
-rw-r--r--storage/innodb_plugin/sync/sync0rw.c11
-rw-r--r--storage/innodb_plugin/sync/sync0sync.c47
-rw-r--r--storage/innodb_plugin/trx/trx0rec.c75
-rw-r--r--storage/innodb_plugin/trx/trx0sys.c10
-rw-r--r--storage/innodb_plugin/trx/trx0trx.c70
-rw-r--r--storage/innodb_plugin/trx/trx0undo.c93
-rw-r--r--storage/innodb_plugin/ut/ut0mem.c49
-rw-r--r--storage/maria/ma_bitmap.c4
-rw-r--r--storage/maria/ma_blockrec.c11
-rw-r--r--storage/maria/ma_check.c14
-rw-r--r--storage/maria/ma_ft_boolean_search.c2
-rw-r--r--storage/maria/ma_ft_nlq_search.c2
-rw-r--r--storage/maria/ma_ft_update.c2
-rw-r--r--storage/maria/ma_key_recover.c3
-rw-r--r--storage/maria/ma_loghandler.c8
-rw-r--r--storage/maria/ma_open.c3
-rw-r--r--storage/maria/ma_rt_split.c2
-rw-r--r--storage/maria/ma_write.c10
-rw-r--r--storage/maria/maria_pack.c2
-rw-r--r--storage/myisam/CMakeLists.txt3
-rw-r--r--storage/myisam/ft_boolean_search.c9
-rw-r--r--storage/myisam/ft_nlq_search.c8
-rw-r--r--storage/myisam/ft_parser.c7
-rw-r--r--storage/myisam/ft_stopwords.c2
-rw-r--r--storage/myisam/ftdefs.h7
-rw-r--r--storage/myisam/fulltext.h6
-rw-r--r--storage/myisam/ha_myisam.cc22
-rw-r--r--storage/myisam/ha_myisam.h6
-rw-r--r--storage/myisam/mi_check.c28
-rw-r--r--storage/myisam/mi_close.c7
-rw-r--r--storage/myisam/mi_create.c6
-rw-r--r--storage/myisam/mi_dbug.c7
-rw-r--r--storage/myisam/mi_delete.c7
-rw-r--r--storage/myisam/mi_delete_all.c11
-rw-r--r--storage/myisam/mi_delete_table.c6
-rw-r--r--storage/myisam/mi_dynrec.c6
-rw-r--r--storage/myisam/mi_extra.c6
-rw-r--r--storage/myisam/mi_locking.c6
-rw-r--r--storage/myisam/mi_open.c6
-rw-r--r--storage/myisam/mi_packrec.c7
-rw-r--r--storage/myisam/mi_page.c6
-rw-r--r--storage/myisam/mi_preload.c7
-rw-r--r--storage/myisam/mi_range.c6
-rw-r--r--storage/myisam/mi_rnext.c6
-rw-r--r--storage/myisam/mi_search.c6
-rw-r--r--storage/myisam/mi_static.c7
-rw-r--r--storage/myisam/mi_test1.c6
-rw-r--r--storage/myisam/mi_test2.c6
-rw-r--r--storage/myisam/mi_unique.c6
-rw-r--r--storage/myisam/mi_update.c15
-rw-r--r--storage/myisam/mi_write.c10
-rw-r--r--storage/myisam/myisam_ftdump.c6
-rw-r--r--storage/myisam/myisamchk.c6
-rw-r--r--storage/myisam/myisamdef.h6
-rw-r--r--storage/myisam/myisamlog.c6
-rw-r--r--storage/myisam/myisampack.c5
-rw-r--r--storage/myisam/rt_split.c6
-rw-r--r--storage/myisam/sort.c6
-rw-r--r--storage/myisam/sp_test.c2
-rwxr-xr-xstorage/myisammrg/CMakeLists.txt3
-rw-r--r--storage/myisammrg/ha_myisammrg.cc5
-rw-r--r--storage/myisammrg/ha_myisammrg.h6
-rw-r--r--storage/myisammrg/myrg_create.c7
-rw-r--r--storage/myisammrg/myrg_info.c7
-rw-r--r--storage/myisammrg/myrg_open.c6
-rw-r--r--storage/myisammrg/myrg_rkey.c7
-rw-r--r--storage/mysql_storage_engine.cmake16
-rw-r--r--storage/ndb/MAINTAINERS2
-rw-r--r--storage/ndb/config/win-lib.am17
-rw-r--r--storage/ndb/config/win-prg.am17
-rw-r--r--storage/ndb/include/mgmapi/ndb_logevent.h5
-rw-r--r--storage/ndb/include/ndbapi/NdbEventOperation.hpp5
-rw-r--r--storage/ndb/include/ndbapi/NdbOperation.hpp5
-rw-r--r--storage/ndb/src/common/portlib/NdbMutex.c4
-rw-r--r--storage/ndb/src/common/util/Makefile.am2
-rw-r--r--storage/ndb/src/kernel/blocks/backup/read.cpp5
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp5
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp5
-rw-r--r--storage/ndb/src/kernel/blocks/lgman.cpp16
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp5
-rw-r--r--storage/ndb/src/kernel/blocks/suma/Suma.cpp5
-rw-r--r--storage/ndb/src/mgmsrv/InitConfigFileParser.cpp5
-rw-r--r--storage/ndb/src/mgmsrv/Makefile.am3
-rw-r--r--storage/ndb/src/ndbapi/DictCache.cpp4
-rw-r--r--storage/ndb/src/ndbapi/NdbEventOperation.cpp5
-rw-r--r--storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp5
-rw-r--r--storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp5
-rw-r--r--storage/ndb/test/run-test/Makefile.am3
-rw-r--r--storage/ndb/test/run-test/atrt.hpp5
-rw-r--r--storage/ndb/test/run-test/autotest-boot.sh17
-rw-r--r--storage/ndb/test/run-test/autotest-run.sh17
-rw-r--r--storage/ndb/test/run-test/files.cpp18
-rw-r--r--storage/ndb/test/run-test/setup.cpp18
-rw-r--r--storage/ndb/test/run-test/upgrade-boot.sh17
-rw-r--r--storage/ndb/test/sql/BANK.sql44
-rw-r--r--storage/ndb/test/sql/T1.sql9
-rw-r--r--storage/ndb/test/sql/test_create_drop.pl196
-rw-r--r--storage/ndb/test/sql/test_range_bounds.pl235
-rw-r--r--storage/ndb/test/tools/connect.cpp5
-rw-r--r--storage/ndb/test/tools/log_listner.cpp18
-rw-r--r--storage/ndb/tools/restore/consumer_restore.cpp5
-rw-r--r--storage/ndb/tools/restore/consumer_restorem.cpp5
-rw-r--r--storage/pbxt/src/database_xt.cc2
-rw-r--r--storage/pbxt/src/ha_pbxt.cc4
-rw-r--r--storage/pbxt/src/memory_xt.cc2
-rw-r--r--storage/pbxt/src/myxt_xt.cc15
-rw-r--r--storage/pbxt/src/restart_xt.cc29
-rw-r--r--storage/pbxt/src/tabcache_xt.cc5
-rw-r--r--storage/pbxt/src/table_xt.cc4
-rw-r--r--storage/pbxt/src/thread_xt.cc2
-rw-r--r--storage/pbxt/src/xactlog_xt.cc4
-rw-r--r--storage/xtradb/ChangeLog102
-rw-r--r--storage/xtradb/btr/btr0btr.c629
-rw-r--r--storage/xtradb/btr/btr0cur.c464
-rw-r--r--storage/xtradb/btr/btr0pcur.c29
-rw-r--r--storage/xtradb/btr/btr0sea.c4
-rw-r--r--storage/xtradb/buf/buf0buddy.c479
-rw-r--r--storage/xtradb/buf/buf0buf.c1060
-rw-r--r--storage/xtradb/buf/buf0flu.c11
-rw-r--r--storage/xtradb/buf/buf0lru.c350
-rw-r--r--storage/xtradb/buf/buf0rea.c179
-rw-r--r--storage/xtradb/dict/dict0dict.c7
-rw-r--r--storage/xtradb/dict/dict0load.c63
-rw-r--r--storage/xtradb/dict/dict0mem.c9
-rw-r--r--storage/xtradb/fil/fil0fil.c560
-rw-r--r--storage/xtradb/ha/hash0hash.c64
-rw-r--r--storage/xtradb/handler/ha_innodb.cc314
-rw-r--r--storage/xtradb/handler/ha_innodb.h11
-rw-r--r--storage/xtradb/handler/handler0alter.cc71
-rw-r--r--storage/xtradb/handler/i_s.cc430
-rw-r--r--storage/xtradb/handler/innodb_patch_info.h1
-rw-r--r--storage/xtradb/ibuf/ibuf0ibuf.c2
-rw-r--r--storage/xtradb/include/btr0btr.h170
-rw-r--r--storage/xtradb/include/btr0cur.h31
-rw-r--r--storage/xtradb/include/btr0cur.ic4
-rw-r--r--storage/xtradb/include/btr0pcur.h21
-rw-r--r--storage/xtradb/include/btr0pcur.ic9
-rw-r--r--storage/xtradb/include/btr0types.h125
-rw-r--r--storage/xtradb/include/buf0buddy.h21
-rw-r--r--storage/xtradb/include/buf0buddy.ic37
-rw-r--r--storage/xtradb/include/buf0buf.h81
-rw-r--r--storage/xtradb/include/buf0buf.ic74
-rw-r--r--storage/xtradb/include/buf0lru.h23
-rw-r--r--storage/xtradb/include/buf0types.h17
-rw-r--r--storage/xtradb/include/dict0mem.h7
-rw-r--r--storage/xtradb/include/fil0fil.h3
-rw-r--r--storage/xtradb/include/hash0hash.h49
-rw-r--r--storage/xtradb/include/mtr0mtr.h12
-rw-r--r--storage/xtradb/include/os0file.h3
-rw-r--r--storage/xtradb/include/os0proc.h28
-rw-r--r--storage/xtradb/include/page0cur.ic5
-rw-r--r--storage/xtradb/include/page0page.h39
-rw-r--r--storage/xtradb/include/page0page.ic32
-rw-r--r--storage/xtradb/include/page0zip.h2
-rw-r--r--storage/xtradb/include/rem0rec.h14
-rw-r--r--storage/xtradb/include/rem0rec.ic41
-rw-r--r--storage/xtradb/include/row0row.h26
-rw-r--r--storage/xtradb/include/row0row.ic45
-rw-r--r--storage/xtradb/include/row0upd.ic4
-rw-r--r--storage/xtradb/include/srv0srv.h10
-rw-r--r--storage/xtradb/include/sync0arr.h7
-rw-r--r--storage/xtradb/include/sync0rw.ic10
-rw-r--r--storage/xtradb/include/sync0sync.h6
-rw-r--r--storage/xtradb/include/trx0sys.h13
-rw-r--r--storage/xtradb/include/trx0sys.ic24
-rw-r--r--storage/xtradb/include/trx0trx.h14
-rw-r--r--storage/xtradb/include/trx0undo.h9
-rw-r--r--storage/xtradb/include/univ.i9
-rw-r--r--storage/xtradb/include/ut0lst.h43
-rw-r--r--storage/xtradb/include/ut0mem.h39
-rw-r--r--storage/xtradb/include/ut0mem.ic23
-rw-r--r--storage/xtradb/lock/lock0lock.c25
-rw-r--r--storage/xtradb/log/log0log.c17
-rw-r--r--storage/xtradb/log/log0recv.c5
-rw-r--r--storage/xtradb/mtr/mtr0mtr.c36
-rw-r--r--storage/xtradb/os/os0file.c91
-rw-r--r--storage/xtradb/os/os0proc.c170
-rw-r--r--storage/xtradb/page/page0cur.c27
-rw-r--r--storage/xtradb/page/page0page.c63
-rw-r--r--storage/xtradb/page/page0zip.c208
-rw-r--r--storage/xtradb/que/que0que.c6
-rw-r--r--storage/xtradb/rem/rem0rec.c10
-rw-r--r--storage/xtradb/row/row0ins.c73
-rw-r--r--storage/xtradb/row/row0mysql.c45
-rw-r--r--storage/xtradb/row/row0row.c109
-rw-r--r--storage/xtradb/row/row0sel.c99
-rw-r--r--storage/xtradb/row/row0upd.c86
-rw-r--r--storage/xtradb/row/row0vers.c18
-rw-r--r--storage/xtradb/srv/srv0srv.c66
-rw-r--r--storage/xtradb/srv/srv0start.c18
-rw-r--r--storage/xtradb/sync/sync0arr.c32
-rw-r--r--storage/xtradb/sync/sync0rw.c7
-rw-r--r--storage/xtradb/sync/sync0sync.c12
-rw-r--r--storage/xtradb/trx/trx0i_s.c2
-rw-r--r--storage/xtradb/trx/trx0rec.c6
-rw-r--r--storage/xtradb/trx/trx0sys.c10
-rw-r--r--storage/xtradb/trx/trx0trx.c75
-rw-r--r--storage/xtradb/trx/trx0undo.c25
-rw-r--r--storage/xtradb/ut/ut0mem.c49
341 files changed, 7607 insertions, 6406 deletions
diff --git a/storage/Makefile.am b/storage/Makefile.am
index e232547139d..c6d358a32f4 100644
--- a/storage/Makefile.am
+++ b/storage/Makefile.am
@@ -1,4 +1,5 @@
-# Copyright (C) 2005-2006 MySQL AB
+# Copyright (c) 2005, 2006 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/archive/CMakeLists.txt b/storage/archive/CMakeLists.txt
index 893a5dcf4f9..8c4d46fbbb8 100755
--- a/storage/archive/CMakeLists.txt
+++ b/storage/archive/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/archive/Makefile.am b/storage/archive/Makefile.am
index 83df8bae0db..c21242744ce 100644
--- a/storage/archive/Makefile.am
+++ b/storage/archive/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2006 MySQL AB
+# Copyright (c) 2005, 2010, Oracle and/or its affiliates
#
# 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/archive/archive_reader.c b/storage/archive/archive_reader.c
index 90220f26f6d..9bce82208fd 100644
--- a/storage/archive/archive_reader.c
+++ b/storage/archive/archive_reader.c
@@ -1,3 +1,18 @@
+/* Copyright (c) 2007, 2010, Oracle and/or its affiliates
+
+ 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 */
+
#include "azlib.h"
#include <string.h>
#include <assert.h>
diff --git a/storage/archive/azio.c b/storage/archive/azio.c
index fc54d98ab15..08c84c7c888 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 730d5b95abb..deee52749e0 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -1,17 +1,20 @@
-/* Copyright (C) 2003 MySQL AB
+/*
+ Copyright (c) 2004, 2011, Oracle and/or its affiliates
- 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
@@ -877,7 +880,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))
{
@@ -1125,7 +1128,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);
}
@@ -1626,6 +1629,8 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
azflush(&(share->archive_write), Z_SYNC_FLUSH);
pthread_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.
diff --git a/storage/blackhole/CMakeLists.txt b/storage/blackhole/CMakeLists.txt
index bed282ef21d..61be167994f 100644
--- a/storage/blackhole/CMakeLists.txt
+++ b/storage/blackhole/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/blackhole/Makefile.am b/storage/blackhole/Makefile.am
index 0ff5ebaa17a..fb8a4958cda 100644
--- a/storage/blackhole/Makefile.am
+++ b/storage/blackhole/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates
#
# 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/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 19651a370cc..5f4f954763a 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -1,4 +1,6 @@
-/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/*
+ Copyright (c) 2005-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
#ifdef USE_PRAGMA_IMPLEMENTATION
diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h
index 289e449be10..6ed7cbbc235 100644
--- a/storage/blackhole/ha_blackhole.h
+++ b/storage/blackhole/ha_blackhole.h
@@ -1,4 +1,6 @@
-/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/*
+ Copyright (c) 2005-2007 MySQL AB, 2008 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
diff --git a/storage/csv/CMakeLists.txt b/storage/csv/CMakeLists.txt
index 133425218e0..5fab7eef0c4 100644
--- a/storage/csv/CMakeLists.txt
+++ b/storage/csv/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/csv/Makefile.am b/storage/csv/Makefile.am
index 2965b0c87eb..e21dc9c5ede 100644
--- a/storage/csv/Makefile.am
+++ b/storage/csv/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2006 MySQL AB
+# Copyright (c) 2005, 2010, Oracle and/or its affiliates
#
# 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/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index 8ba425c86cb..f1b081be8d4 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/*
+ Copyright (c) 2004, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/*
Make sure to look at ha_tina.h for more details.
diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
index 06f23b029b4..8572a53a94d 100644
--- a/storage/csv/ha_tina.h
+++ b/storage/csv/ha_tina.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2003 MySQL AB
+/*
+ Copyright (c) 2004-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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 <sys/types.h>
#include <sys/stat.h>
diff --git a/storage/csv/transparent_file.cc b/storage/csv/transparent_file.cc
index 841c3efc476..3a7ebe55df6 100644
--- a/storage/csv/transparent_file.cc
+++ b/storage/csv/transparent_file.cc
@@ -1,4 +1,6 @@
-/* Copyright (C) 2003 MySQL AB
+/*
+ Copyright (c) 2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation // gcc: Class implementation
diff --git a/storage/csv/transparent_file.h b/storage/csv/transparent_file.h
index 0168e271e7d..575ae0b6f6b 100644
--- a/storage/csv/transparent_file.h
+++ b/storage/csv/transparent_file.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2003 MySQL AB
+/*
+ Copyright (c) 2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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 <sys/types.h>
#include <sys/stat.h>
diff --git a/storage/example/CMakeLists.txt b/storage/example/CMakeLists.txt
index f0b1343ab9c..51d8909e361 100644
--- a/storage/example/CMakeLists.txt
+++ b/storage/example/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/example/Makefile.am b/storage/example/Makefile.am
index f4ee8e3c276..1ef7d9fc86e 100644
--- a/storage/example/Makefile.am
+++ b/storage/example/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2006 MySQL AB
+# Copyright (c) 2005, 2010, Oracle and/or its affiliates
#
# 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/example/ha_example.cc b/storage/example/ha_example.cc
index 273b7039296..067bd00cdbf 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB, 2009 Sun Microsystems, Inc.
+/*
+ Copyright (c) 2004, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/**
@file ha_example.cc
diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h
index dc47fac1f17..79e1c422b95 100644
--- a/storage/example/ha_example.h
+++ b/storage/example/ha_example.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2003, 2010 Oracle and/or its affiliates. All rights reserved.
+/*
+ Copyright (c) 2004, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/** @file ha_example.h
diff --git a/storage/federated/CMakeLists.txt b/storage/federated/CMakeLists.txt
index 3f3201d351c..67dc978b9d5 100755
--- a/storage/federated/CMakeLists.txt
+++ b/storage/federated/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/federated/Makefile.am b/storage/federated/Makefile.am
index 48d86dded69..b4ee202cab3 100644
--- a/storage/federated/Makefile.am
+++ b/storage/federated/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates
#
# 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
@@ -41,7 +41,7 @@ ha_federated_la_SOURCES = ha_federated.cc $(top_srcdir)/mysys/string.c
noinst_LTLIBRARIES = @plugin_federated_static_target@ @plugin_federated_embedded_static_target@
libfederated_la_CXXFLAGS = $(AM_CXXFLAGS)
-libfederated_la_SOURCES= ha_federated.cc
+libfederated_la_SOURCES= ha_federated.cc $(top_srcdir)/mysys/string.c
libfederated_embedded_la_CXXFLAGS = $(AM_CXXFLAGS) @plugin_embedded_defs@
libfederated_embedded_la_CFLAGS = $(AM_CFLAGS) @plugin_embedded_defs@
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 34509e04799..40d33bde457 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004, 2010 Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2004, 2010, Oracle and/or its affiliates
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
@@ -11,7 +11,7 @@
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 */
/*
diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h
index 142e0e95e2b..7f0d72fa40a 100644
--- a/storage/federated/ha_federated.h
+++ b/storage/federated/ha_federated.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/*
+ Copyright (c) 2004, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/*
Please read ha_exmple.cc before reading this file.
diff --git a/storage/heap/CMakeLists.txt b/storage/heap/CMakeLists.txt
index 1e560b5e3b1..265bdb66f10 100755
--- a/storage/heap/CMakeLists.txt
+++ b/storage/heap/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/ha_heap.cc b/storage/heap/ha_heap.cc
index 7757d0a6210..a5d8679105a 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
#ifdef USE_PRAGMA_IMPLEMENTATION
@@ -380,6 +382,7 @@ int ha_heap::info(uint flag)
stats.index_file_length= hp_info.index_length;
stats.max_data_file_length= hp_info.max_records * hp_info.reclength;
stats.delete_length= hp_info.deleted * hp_info.reclength;
+ stats.create_time= (ulong) hp_info.create_time;
if (flag & HA_STATUS_AUTO)
stats.auto_increment_value= hp_info.auto_increment;
/*
diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h
index 69751101645..5402842413c 100644
--- a/storage/heap/ha_heap.h
+++ b/storage/heap/ha_heap.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
#ifdef USE_PRAGMA_INTERFACE
diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c
index bc8183bf777..f541d618c7b 100644
--- a/storage/heap/hp_create.c
+++ b/storage/heap/hp_create.c
@@ -180,6 +180,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
share->auto_key= create_info->auto_key;
share->auto_key_type= create_info->auto_key_type;
share->auto_increment= create_info->auto_increment;
+ share->create_time= (long) time((time_t*) 0);
/* Must be allocated separately for rename to work */
if (!(share->name= my_strdup(name,MYF(0))))
{
diff --git a/storage/heap/hp_hash.c b/storage/heap/hp_hash.c
index aaaa0fe833f..90694ca75b3 100644
--- a/storage/heap/hp_hash.c
+++ b/storage/heap/hp_hash.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* The hash functions used for saveing keys */
diff --git a/storage/heap/hp_info.c b/storage/heap/hp_info.c
index ea78c53fd40..c72dbaf2065 100644
--- a/storage/heap/hp_info.c
+++ b/storage/heap/hp_info.c
@@ -53,6 +53,7 @@ int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x, int flag )
x->index_length = info->s->index_length;
x->max_records = info->s->max_records;
x->errkey = info->errkey;
+ x->create_time = info->s->create_time;
if (flag & HA_STATUS_AUTO)
x->auto_increment= info->s->auto_increment + 1;
DBUG_RETURN(0);
diff --git a/storage/heap/hp_test2.c b/storage/heap/hp_test2.c
index 67471e93a7a..a3a20d9b236 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, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Test av isam-databas: stor test */
diff --git a/storage/heap/hp_write.c b/storage/heap/hp_write.c
index 4e8fa7e3580..5996d9b2682 100644
--- a/storage/heap/hp_write.c
+++ b/storage/heap/hp_write.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2002, 2004-2006 MySQL AB
+/*
+ Copyright (c) 2000-2002, 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Write a record to heap-databas */
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
index 9438277050d..5079757272a 100644
--- a/storage/innobase/btr/btr0btr.c
+++ b/storage/innobase/btr/btr0btr.c
@@ -464,6 +464,16 @@ btr_page_free_low(
page_no = buf_frame_get_page_no(page);
fseg_free_page(seg_header, space, page_no, mtr);
+
+ /* The page was marked free in the allocation bitmap, but it
+ should remain buffer-fixed until mtr_commit(mtr) or until it
+ is explicitly freed from the mini-transaction. */
+ ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
+ MTR_MEMO_PAGE_X_FIX));
+ /* TODO: Discard any operations on the page from the redo log
+ and remove the block from the flush list and the buffer pool.
+ This would free up buffer pool earlier and reduce writes to
+ both the tablespace and the redo log. */
}
/******************************************************************
@@ -479,6 +489,7 @@ btr_page_free(
{
ulint level;
+ ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
level = btr_page_get_level(page, mtr);
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 6c0497cbd41..3c12e28feb6 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -31,6 +31,7 @@ Created 10/16/1994 Heikki Tuuri
#include "btr0sea.h"
#include "row0upd.h"
#include "trx0rec.h"
+#include "trx0roll.h" /* trx_roll_crash_recv_trx */
#include "que0que.h"
#include "row0row.h"
#include "srv0srv.h"
@@ -73,6 +74,13 @@ this many index pages */
+ not_empty) \
/ (BTR_KEY_VAL_ESTIMATE_N_PAGES + ext_size))
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/* A BLOB field reference full of zero, for use in assertions and tests.
+Initially, BLOB field references are set to zero, in
+dtuple_convert_big_rec(). */
+const byte field_ref_zero[BTR_EXTERN_FIELD_REF_SIZE];
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
/***********************************************************************
Marks all extern fields in a record as owned by the record. This function
should be called if the delete mark of a record is removed: a not delete
@@ -1572,7 +1580,6 @@ btr_cur_optimistic_update(
ulint old_rec_size;
dtuple_t* new_entry;
dulint roll_ptr;
- trx_t* trx;
mem_heap_t* heap;
ibool reorganized = FALSE;
ulint i;
@@ -1585,6 +1592,10 @@ btr_cur_optimistic_update(
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(rec, offsets)
+ || thr_get_trx(thr) == trx_roll_crash_recv_trx);
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
@@ -1691,13 +1702,11 @@ btr_cur_optimistic_update(
page_cur_move_to_prev(page_cursor);
- trx = thr_get_trx(thr);
-
if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr);
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
- trx->id);
+ thr_get_trx(thr)->id);
}
rec = btr_cur_insert_if_possible(cursor, new_entry, &reorganized, mtr);
@@ -2850,7 +2859,6 @@ 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 */
@@ -2869,17 +2877,11 @@ btr_record_not_null_field_in_rec(
}
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 */
+ if (rec_offs_nth_sql_null(offsets, i)) {
break;
}
+
+ n_not_null[i]++;
}
}
@@ -2974,7 +2976,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- rec, n_cols, offsets_rec, n_not_null);
+ n_cols, offsets_rec, n_not_null);
}
}
@@ -3009,8 +3011,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- next_rec, n_cols, offsets_next_rec,
- n_not_null);
+ n_cols, offsets_next_rec, n_not_null);
}
total_external_size
diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c
index f73e82fb597..8d473794243 100644
--- a/storage/innobase/btr/btr0pcur.c
+++ b/storage/innobase/btr/btr0pcur.c
@@ -339,33 +339,6 @@ btr_pcur_restore_position(
return(FALSE);
}
-/******************************************************************
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-
-void
-btr_pcur_release_leaf(
-/*==================*/
- btr_pcur_t* cursor, /* in: persistent cursor */
- mtr_t* mtr) /* in: mtr */
-{
- page_t* page;
-
- ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
- ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
-
- page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
-
- btr_leaf_page_release(page, cursor->latch_mode, mtr);
-
- cursor->latch_mode = BTR_NO_LATCHES;
-
- cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
-}
-
/*************************************************************
Moves the persistent cursor to the first record on the next page. Releases the
latch on the current page, and bufferunfixes it. Note that there must not be
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index 08e033e7a63..78b39812cff 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -1009,29 +1009,6 @@ buf_page_peek_block(
}
/************************************************************************
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /* in: space id */
- ulint offset) /* in: page number */
-{
- buf_block_t* block;
-
- mutex_enter_fast(&(buf_pool->mutex));
-
- block = buf_page_hash_get(space, offset);
-
- if (block) {
- block->check_index_page_at_flush = FALSE;
- }
-
- mutex_exit(&(buf_pool->mutex));
-}
-
-/************************************************************************
Returns the current state of is_hashed of a page. FALSE if the page is
not in the pool. NOTE that this operation does not fix the page in the
pool if it is found there. */
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index c505bfbd6c4..7e820cfb08d 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/dict/dict0load.c
@@ -454,9 +454,11 @@ dict_load_report_deleted_index(
/************************************************************************
Loads definitions for index fields. */
static
-void
+ulint
dict_load_fields(
/*=============*/
+ /* out: DB_SUCCESS if ok, DB_CORRUPTION
+ if failed */
dict_table_t* table, /* in: table */
dict_index_t* index, /* in: index whose fields to load */
mem_heap_t* heap) /* in: memory heap for temporary storage */
@@ -474,6 +476,7 @@ dict_load_fields(
byte* buf;
ulint i;
mtr_t mtr;
+ ulint error = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -535,6 +538,26 @@ dict_load_fields(
field = rec_get_nth_field_old(rec, 4, &len);
+ if (prefix_len >= DICT_MAX_INDEX_COL_LEN) {
+ fprintf(stderr, "InnoDB: Error: load index"
+ " '%s' failed.\n"
+ "InnoDB: index field '%s' has a prefix"
+ " length of %lu bytes,\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, mem_heap_strdupl(
+ heap, (char*) field, len),
+ (ulong) prefix_len,
+ (ulong) (DICT_MAX_INDEX_COL_LEN - 1));
+ error = DB_CORRUPTION;
+ goto func_exit;
+ }
+
dict_mem_index_add_field(index,
mem_heap_strdupl(heap,
(char*) field, len),
@@ -543,8 +566,10 @@ dict_load_fields(
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
+func_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
+ return(error);
}
/************************************************************************
@@ -701,10 +726,28 @@ dict_load_indexes(
space, type, n_fields);
index->id = id;
- dict_load_fields(table, index, heap);
+ error = dict_load_fields(table, 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
+ && !(index->type & DICT_CLUSTERED)) {
+ error = DB_SUCCESS;
+ goto next_rec;
+ } else {
+ goto func_exit;
+ }
+ }
+
dict_index_add_to_cache(table, index, page_no);
}
-
+next_rec:
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
@@ -881,9 +924,18 @@ err_exit:
} 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;
+
+ /* 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
+ || !(index->type & DICT_CLUSTERED)) {
+ dict_table_remove_from_cache(table);
+ table = NULL;
+ }
}
#if 0
if (err != DB_SUCCESS && table != NULL) {
diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
index d228e683957..90e6ad34a9a 100644
--- a/storage/innobase/fsp/fsp0fsp.c
+++ b/storage/innobase/fsp/fsp0fsp.c
@@ -293,14 +293,14 @@ fseg_alloc_free_page_low(
/* out: the allocated page number, FIL_NULL
if no page could be allocated */
ulint space, /* in: space */
- fseg_inode_t* seg_inode, /* in: segment inode */
+ fseg_inode_t* seg_inode, /* in/out: segment inode */
ulint hint, /* in: hint of which page would be desirable */
byte direction, /* in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /* in: mtr handle */
+ mtr_t* mtr); /* in/out: mini-transaction */
/**************************************************************************
@@ -1381,7 +1381,7 @@ fsp_alloc_free_page(
be allocated */
ulint space, /* in: space id */
ulint hint, /* in: hint of which page would be desirable */
- mtr_t* mtr) /* in: mtr handle */
+ mtr_t* mtr) /* in/out: mini-transaction */
{
fsp_header_t* header;
fil_addr_t first;
@@ -1441,6 +1441,7 @@ fsp_alloc_free_page(
if (free == ULINT_UNDEFINED) {
ut_print_buf(stderr, ((byte*)descr) - 500, 1000);
+ putc('\n', stderr);
ut_error;
}
@@ -2331,14 +2332,14 @@ fseg_alloc_free_page_low(
/* out: the allocated page number, FIL_NULL
if no page could be allocated */
ulint space, /* in: space */
- fseg_inode_t* seg_inode, /* in: segment inode */
+ fseg_inode_t* seg_inode, /* in/out: segment inode */
ulint hint, /* in: hint of which page would be desirable */
byte direction, /* in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /* in: mtr handle */
+ mtr_t* mtr) /* in/out: mini-transaction */
{
fsp_header_t* space_header;
ulint space_size;
@@ -2554,8 +2555,6 @@ fseg_alloc_free_page_low(
fseg_mark_page_used(seg_inode, space, ret_page, mtr);
}
- buf_reset_check_index_page_at_flush(space, ret_page);
-
return(ret_page);
}
@@ -2569,7 +2568,7 @@ fseg_alloc_free_page_general(
/*=========================*/
/* out: allocated page offset, FIL_NULL if no
page could be allocated */
- fseg_header_t* seg_header,/* in: segment header */
+ fseg_header_t* seg_header,/* in/out: segment header */
ulint hint, /* in: hint of which page would be desirable */
byte direction,/* in: if the new page is needed because
of an index page split, and records are
@@ -2581,7 +2580,7 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr) /* in: mtr handle */
+ mtr_t* mtr) /* in/out: mini-transaction */
{
fseg_inode_t* inode;
ulint space;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 6f58fd70fbd..6709f790994 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -189,7 +189,7 @@ innobase_index_name_is_reserved(
/*============================*/
/* out: true if index name matches a
reserved name */
- const trx_t* trx, /* in: InnoDB transaction handle */
+ THD* thd, /* in/out: MySQL connection */
const TABLE* form, /* in: information on table
columns and indexes */
const char* norm_name); /* in: table name */
@@ -3082,25 +3082,6 @@ field_in_record_is_null(
return(0);
}
-/******************************************************************
-Sets a field in a record to SQL NULL. Uses the record format
-information in table to track the null bit in record. */
-inline
-void
-set_field_in_record_to_null(
-/*========================*/
- TABLE* table, /* in: MySQL table object */
- Field* field, /* in: MySQL field object */
- char* record) /* in: a row in MySQL format */
-{
- int null_offset;
-
- null_offset = (uint) ((char*) field->null_ptr
- - (char*) table->record[0]);
-
- record[null_offset] = record[null_offset] | field->null_bit;
-}
-
extern "C" {
/*****************************************************************
InnoDB uses this function to compare two data fields for which the data type
@@ -4106,8 +4087,7 @@ no_commit:
switch (sql_command) {
case SQLCOM_LOAD:
- if ((trx->duplicates
- & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
+ if (trx->duplicates) {
goto set_max_autoinc;
}
@@ -4283,14 +4263,16 @@ calc_row_difference(
/* The field has changed */
ufield = uvect->fields + n_changed;
+ UNIV_MEM_INVALID(ufield, sizeof *ufield);
/* Let us use a dummy dfield to make the conversion
from the MySQL column format to the InnoDB format */
- dict_col_copy_type_noninline(prebuilt->table->cols + i,
- &dfield.type);
-
if (n_len != UNIV_SQL_NULL) {
+ dict_col_copy_type_noninline(
+ prebuilt->table->cols + i,
+ &dfield.type);
+
buf = row_mysql_store_col_in_innobase_format(
&dfield,
(byte*)buf,
@@ -4301,11 +4283,13 @@ calc_row_difference(
prebuilt->table));
ufield->new_val.data = dfield.data;
ufield->new_val.len = dfield.len;
+ ufield->new_val.type = dfield.type;
} else {
ufield->new_val.data = NULL;
ufield->new_val.len = UNIV_SQL_NULL;
}
+ ufield->extern_storage = FALSE;
ufield->exp = NULL;
ufield->field_no = dict_col_get_clust_pos_noninline(
&prebuilt->table->cols[i], clust_index);
@@ -4383,8 +4367,7 @@ ha_innobase::update_row(
&& table->next_number_field
&& new_row == table->record[0]
&& thd_sql_command(user_thd) == SQLCOM_INSERT
- && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
- == TRX_DUP_IGNORE) {
+ && trx->duplicates) {
ulonglong auto_inc;
ulonglong col_max_value;
@@ -4732,6 +4715,7 @@ ha_innobase::index_read(
index,
(byte*) key_ptr,
(ulint) key_len, prebuilt->trx);
+ DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
} else {
/* We position the cursor to the last or the first entry
in the index */
@@ -5285,10 +5269,6 @@ 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);
- }
n_cols = form->s->fields;
@@ -5397,6 +5377,8 @@ err_col:
col_len);
}
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_create_table_for_mysql(table, trx);
innodb_check_for_record_too_big_error(flags & DICT_TF_COMPACT, error);
@@ -5642,6 +5624,35 @@ ha_innobase::create(
DBUG_RETURN(HA_ERR_TO_BIG_ROW);
}
+ strcpy(name2, name);
+
+ normalize_table_name(norm_name, name2);
+
+ /* Create the table definition in InnoDB */
+
+ flags = form->s->row_type != ROW_TYPE_REDUNDANT ? DICT_TF_COMPACT : 0;
+
+ /* Look for a primary key */
+
+ primary_key_no= (form->s->primary_key != MAX_KEY ?
+ (int) form->s->primary_key :
+ -1);
+
+ /* Our function row_get_mysql_key_number_for_index assumes
+ the primary key is always number 0, if it exists */
+
+ DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
+
+ /* Check for name conflicts (with reserved name) for
+ any user indices to be created. */
+ if (innobase_index_name_is_reserved(thd, form, norm_name)) {
+ DBUG_RETURN(-1);
+ }
+
+ if (IS_MAGIC_TABLE_AND_USER_DENIED_ACCESS(norm_name, thd)) {
+ DBUG_RETURN(HA_ERR_GENERIC);
+ }
+
/* Get the transaction associated with the current thd, or create one
if not yet created */
@@ -5665,48 +5676,12 @@ ha_innobase::create(
trx->check_unique_secondary = FALSE;
}
- 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;
-
- if (form->s->row_type != ROW_TYPE_REDUNDANT) {
- flags |= DICT_TF_COMPACT;
- }
-
- /* Look for a primary key */
-
- primary_key_no= (form->s->primary_key != MAX_KEY ?
- (int) form->s->primary_key :
- -1);
-
- /* Our function row_get_mysql_key_number_for_index assumes
- the primary key is always number 0, if it exists */
-
- DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
-
- /* Check for name conflicts (with reserved name) for
- any user indices to be created. */
- if (innobase_index_name_is_reserved(trx, form, norm_name)) {
- error = -1;
- goto cleanup;
- }
-
error = create_table_def(trx, form, norm_name,
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
flags);
@@ -5936,12 +5911,6 @@ ha_innobase::delete_table(
trx_search_latch_release_if_reserved(parent_trx);
- if (lower_case_table_names) {
- srv_lower_case_table_names = TRUE;
- } else {
- srv_lower_case_table_names = FALSE;
- }
-
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
@@ -5961,6 +5930,8 @@ ha_innobase::delete_table(
/* Drop the table in InnoDB */
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_drop_table_for_mysql(norm_name, trx,
thd_sql_command(thd)
== SQLCOM_DROP_DB);
@@ -6089,12 +6060,6 @@ ha_innobase::rename_table(
trx_search_latch_release_if_reserved(parent_trx);
- if (lower_case_table_names) {
- srv_lower_case_table_names = TRUE;
- } else {
- srv_lower_case_table_names = FALSE;
- }
-
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
INNOBASE_COPY_STMT(thd, trx);
@@ -6114,6 +6079,8 @@ ha_innobase::rename_table(
/* Rename the table in InnoDB */
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_rename_table_for_mysql(norm_from, norm_to, trx);
/* Flush the log to reduce probability that the .frm files and
@@ -6204,6 +6171,7 @@ ha_innobase::records_in_range(
void* heap2;
DBUG_ENTER("records_in_range");
+ DBUG_ASSERT(min_key || max_key);
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
@@ -6234,6 +6202,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (min_key ? min_key->length : 0),
prebuilt->trx);
+ DBUG_ASSERT(min_key
+ ? range_start->n_fields > 0
+ : range_start->n_fields == 0);
row_sel_convert_mysql_key_to_innobase(
range_end, (byte*) key_val_buff2,
@@ -6242,6 +6213,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (max_key ? max_key->length : 0),
prebuilt->trx);
+ DBUG_ASSERT(max_key
+ ? range_end->n_fields > 0
+ : range_end->n_fields == 0);
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
HA_READ_KEY_EXACT);
@@ -7127,6 +7101,7 @@ ha_innobase::extra(
break;
case HA_EXTRA_RESET_STATE:
reset_template(prebuilt);
+ thd_to_trx(ha_thd())->duplicates = 0;
break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
@@ -7144,19 +7119,18 @@ ha_innobase::extra(
parameters below. We must not invoke update_thd()
either, because the calling threads may change.
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
- case HA_EXTRA_IGNORE_DUP_KEY:
+ case HA_EXTRA_INSERT_WITH_UPDATE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
+ break;
case HA_EXTRA_WRITE_CAN_REPLACE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
break;
case HA_EXTRA_WRITE_CANNOT_REPLACE:
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
break;
- case HA_EXTRA_NO_IGNORE_DUP_KEY:
- thd_to_trx(ha_thd())->duplicates &=
- ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
- break;
default:/* Do nothing */
;
}
@@ -7342,10 +7316,18 @@ ha_innobase::external_lock(
reset_template(prebuilt);
- if (lock_type == F_WRLCK) {
+ if (lock_type == F_WRLCK
+ || (table->s->tmp_table
+ && thd_sql_command(thd) == SQLCOM_LOCK_TABLES)) {
/* If this is a SELECT, then it is in UPDATE TABLE ...
- or SELECT ... FOR UPDATE */
+ or SELECT ... FOR UPDATE
+
+ For temporary tables which are locked for READ by LOCK TABLES
+ updates are still allowed by SQL-layer. In order to accomodate
+ for such a situation we always request X-lock for such table
+ at LOCK TABLES time.
+ */
prebuilt->select_lock_type = LOCK_X;
prebuilt->stored_select_lock_type = LOCK_X;
}
@@ -8565,7 +8547,7 @@ innobase_commit_by_xid(
if (trx) {
innobase_commit_low(trx);
-
+ trx_free_for_background(trx);
return(XA_OK);
} else {
return(XAER_NOTA);
@@ -8588,7 +8570,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);
}
@@ -8824,7 +8808,7 @@ innobase_index_name_is_reserved(
/*============================*/
/* out: true if an index name
matches the reserved name */
- const trx_t* trx, /* in: InnoDB transaction handle */
+ THD* thd, /* in/out: MySQL connection */
const TABLE* form, /* in: information on table
columns and indexes */
const char* norm_name) /* in: table name */
@@ -8838,7 +8822,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_CANT_CREATE_TABLE,
"Cannot Create Index with name "
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index 71ecc7ec49f..1406b2de4e9 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -1683,16 +1683,16 @@ ibuf_add_free_page(
page = buf_page_get(space, page_no, RW_X_LATCH, &mtr);
-#ifdef UNIV_SYNC_DEBUG
- buf_page_dbg_add_level(page, SYNC_TREE_NODE_NEW);
-#endif /* UNIV_SYNC_DEBUG */
-
ibuf_enter();
mutex_enter(&ibuf_mutex);
root = ibuf_tree_root_get(ibuf_data, space, &mtr);
+#ifdef UNIV_SYNC_DEBUG
+ buf_page_dbg_add_level(page, SYNC_TREE_NODE_NEW);
+#endif /* UNIV_SYNC_DEBUG */
+
/* Add the page to the free list and update the ibuf size data */
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h
index ee40e905544..95564fd18ce 100644
--- a/storage/innobase/include/btr0pcur.h
+++ b/storage/innobase/include/btr0pcur.h
@@ -210,18 +210,6 @@ btr_pcur_restore_position(
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /* in: detached persistent cursor */
mtr_t* mtr); /* in: mtr */
-/******************************************************************
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-
-void
-btr_pcur_release_leaf(
-/*==================*/
- btr_pcur_t* cursor, /* in: persistent cursor */
- mtr_t* mtr); /* in: mtr */
/*************************************************************
Gets the rel_pos field for a cursor whose position has been stored. */
UNIV_INLINE
@@ -248,10 +236,9 @@ btr_pcur_get_mtr(
btr_pcur_t* cursor); /* in: persistent cursor */
/******************************************************************
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
-that is, the cursor becomes detached. If there have been modifications
-to the page where pcur is positioned, this can be used instead of
-btr_pcur_release_leaf. Function btr_pcur_store_position should be used
-before calling this, if restoration of cursor is wanted later. */
+that is, the cursor becomes detached.
+Function btr_pcur_store_position should be used before calling this,
+if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit(
diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic
index 66462530716..ddb37b51eef 100644
--- a/storage/innobase/include/btr0pcur.ic
+++ b/storage/innobase/include/btr0pcur.ic
@@ -376,10 +376,9 @@ btr_pcur_move_to_next(
/******************************************************************
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
-that is, the cursor becomes detached. If there have been modifications
-to the page where pcur is positioned, this can be used instead of
-btr_pcur_release_leaf. Function btr_pcur_store_position should be used
-before calling this, if restoration of cursor is wanted later. */
+that is, the cursor becomes detached.
+Function btr_pcur_store_position should be used before calling this,
+if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit(
diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h
index 8fa0bf0602d..eaa1f36e781 100644
--- a/storage/innobase/include/btr0types.h
+++ b/storage/innobase/include/btr0types.h
@@ -18,4 +18,9 @@ typedef struct btr_pcur_struct btr_pcur_t;
typedef struct btr_cur_struct btr_cur_t;
typedef struct btr_search_struct btr_search_t;
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+#define BTR_EXTERN_FIELD_REF_SIZE 20
+extern const byte field_ref_zero[BTR_EXTERN_FIELD_REF_SIZE];
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
#endif
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 3e8972d9182..0f7553a7043 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -176,25 +176,6 @@ buf_page_optimistic_get_func(
ulint line, /* in: line where called */
mtr_t* mtr); /* in: mini-transaction */
/************************************************************************
-Tries to get the page, but if file io is required, releases all latches
-in mtr down to the given savepoint. If io is required, this function
-retrieves the page to buffer buf_pool, but does not bufferfix it or latch
-it. */
-UNIV_INLINE
-buf_frame_t*
-buf_page_get_release_on_io(
-/*=======================*/
- /* out: pointer to the frame, or NULL
- if not in buffer buf_pool */
- ulint space, /* in: space id */
- ulint offset, /* in: offset of the page within space
- in units of a page */
- buf_frame_t* guess, /* in: guessed frame or NULL */
- ulint rw_latch, /* in: RW_X_LATCH, RW_S_LATCH,
- or RW_NO_LATCH */
- ulint savepoint, /* in: mtr savepoint */
- mtr_t* mtr); /* in: mtr */
-/************************************************************************
This is used to get access to a known database page, when no waiting can be
done. */
@@ -294,15 +275,6 @@ buf_page_peek_block(
ulint space, /* in: space id */
ulint offset);/* in: page number */
/************************************************************************
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /* in: space id */
- ulint offset);/* in: page number */
-/************************************************************************
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
debug version to check that it is not accessed any more unless
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 58c5fd9ef3d..2d42925faff 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -561,52 +561,6 @@ buf_page_hash_get(
}
/************************************************************************
-Tries to get the page, but if file io is required, releases all latches
-in mtr down to the given savepoint. If io is required, this function
-retrieves the page to buffer buf_pool, but does not bufferfix it or latch
-it. */
-UNIV_INLINE
-buf_frame_t*
-buf_page_get_release_on_io(
-/*=======================*/
- /* out: pointer to the frame, or NULL
- if not in buffer buf_pool */
- ulint space, /* in: space id */
- ulint offset, /* in: offset of the page within space
- in units of a page */
- buf_frame_t* guess, /* in: guessed frame or NULL */
- ulint rw_latch, /* in: RW_X_LATCH, RW_S_LATCH,
- or RW_NO_LATCH */
- ulint savepoint, /* in: mtr savepoint */
- mtr_t* mtr) /* in: mtr */
-{
- buf_frame_t* frame;
-
- frame = buf_page_get_gen(space, offset, rw_latch, guess,
- BUF_GET_IF_IN_POOL,
- __FILE__, __LINE__,
- mtr);
- if (frame != NULL) {
-
- return(frame);
- }
-
- /* The page was not in the buffer buf_pool: release the latches
- down to the savepoint */
-
- mtr_rollback_to_savepoint(mtr, savepoint);
-
- buf_page_get(space, offset, RW_S_LATCH, mtr);
-
- /* When we get here, the page is in buffer, but we release
- the latches again down to the savepoint, before returning */
-
- mtr_rollback_to_savepoint(mtr, savepoint);
-
- return(NULL);
-}
-
-/************************************************************************
Decrements the bufferfix count of a buffer control block and releases
a latch, if specified. */
UNIV_INLINE
@@ -660,6 +614,6 @@ buf_page_dbg_add_level(
ulint level __attribute__((unused))) /* in: latching order
level */
{
- sync_thread_add_level(&(buf_block_align(frame)->lock), level);
+ sync_thread_add_level(&(buf_block_align(frame)->lock), level, FALSE);
}
#endif /* UNIV_SYNC_DEBUG */
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index 17bfbeec2c1..b7322944189 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -167,7 +167,7 @@ fseg_alloc_free_page_general(
/*=========================*/
/* out: allocated page offset, FIL_NULL if no
page could be allocated */
- fseg_header_t* seg_header,/* in: segment header */
+ fseg_header_t* seg_header,/* in/out: segment header */
ulint hint, /* in: hint of which page would be desirable */
byte direction,/* in: if the new page is needed because
of an index page split, and records are
@@ -179,7 +179,7 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr); /* in: mtr handle */
+ mtr_t* mtr); /* in/out: mini-transaction */
/**************************************************************************
Reserves free pages from a tablespace. All mini-transactions which may
use several pages from the tablespace should call this function beforehand
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index a6e2976830b..2b41fa0059a 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -176,16 +176,6 @@ mtr_set_savepoint(
/* out: savepoint */
mtr_t* mtr); /* in: mtr */
/**************************************************************
-Releases the latches stored in an mtr memo down to a savepoint.
-NOTE! The mtr must not have made changes to buffer pages after the
-savepoint, as these can be handled only by mtr_commit. */
-
-void
-mtr_rollback_to_savepoint(
-/*======================*/
- mtr_t* mtr, /* in: mtr */
- ulint savepoint); /* in: savepoint */
-/**************************************************************
Releases the (index tree) s-latch stored in an mtr memo after a
savepoint. */
UNIV_INLINE
diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h
index 58762fc3111..67baeb7d8d2 100644
--- a/storage/innobase/include/rem0rec.h
+++ b/storage/innobase/include/rem0rec.h
@@ -339,6 +339,19 @@ rec_offs_any_extern(
/*================*/
/* out: TRUE if a field is stored externally */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/********************************************************
+Determine if the offsets are for a record containing null BLOB pointers. */
+UNIV_INLINE
+const byte*
+rec_offs_any_null_extern(
+/*=====================*/
+ /* out: first field containing
+ a null BLOB pointer,
+ or NULL if none found */
+ rec_t* rec, /*!< in: record */
+ const ulint* offsets); /*!< in: rec_get_offsets(rec) */
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/***************************************************************
Sets the value of the ith field extern storage bit. */
UNIV_INLINE
diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic
index df66bb13aeb..566c62e30f2 100644
--- a/storage/innobase/include/rem0rec.ic
+++ b/storage/innobase/include/rem0rec.ic
@@ -9,6 +9,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)
@@ -1020,6 +1021,42 @@ rec_offs_any_extern(
return(FALSE);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/********************************************************
+Determine if the offsets are for a record containing null BLOB pointers. */
+UNIV_INLINE
+const byte*
+rec_offs_any_null_extern(
+/*=====================*/
+ /* out: first field containing
+ a null BLOB pointer,
+ or NULL if none found */
+ rec_t* rec, /*!< in: record */
+ const ulint* offsets) /*!< in: rec_get_offsets(rec) */
+{
+ ulint i;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
+ 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_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
/***************************************************************
Sets the value of the ith field extern storage bit. */
UNIV_INLINE
diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
index dd898557d6e..6bd81623ad2 100644
--- a/storage/innobase/include/sync0rw.h
+++ b/storage/innobase/include/sync0rw.h
@@ -484,7 +484,8 @@ struct rw_lock_struct {
#define RW_LOCK_MAGIC_N 22643
#ifdef UNIV_SYNC_DEBUG
-/* The structure for storing debug info of an rw-lock */
+/** The structure for storing debug info of an rw-lock. All access to this
+structure must be protected by rw_lock_debug_mutex_enter(). */
struct rw_lock_debug_struct {
os_thread_id_t thread_id; /* The thread id of the thread which
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index eea639f26f4..2a674f00262 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -238,6 +238,7 @@ rw_lock_s_lock_func(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
mutex_enter(rw_lock_get_mutex(lock));
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index 9430d4cb723..595dca0da6d 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -198,8 +198,9 @@ void
sync_thread_add_level(
/*==================*/
void* latch, /* in: pointer to a mutex or an rw-lock */
- ulint level); /* in: level in the latching order; if
+ ulint level, /* in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
+ ibool relock);/* in: TRUE if re-entering an x-lock */
/**********************************************************************
Removes a latch from the thread level array if it is found there. */
diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h
index c1eca3d5753..4fabb83b025 100644
--- a/storage/innobase/include/trx0roll.h
+++ b/storage/innobase/include/trx0roll.h
@@ -15,6 +15,9 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.h"
#include "trx0sys.h"
+/* In crash recovery, the current trx to be rolled back */
+extern trx_t* trx_roll_crash_recv_trx;
+
#define trx_roll_free_all_savepoints(s) trx_roll_savepoints_free((s), NULL)
/***********************************************************************
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index bad3c9d570c..7ea981eb85c 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -256,6 +256,16 @@ trx_in_trx_list(
/*============*/
/* out: TRUE if is in */
trx_t* in_trx);/* in: trx */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/********************************************************
+Assert that a transaction is active. */
+UNIV_INLINE
+ibool
+trx_assert_active(
+/*==============*/
+ /* out: TRUE */
+ dulint trx_id); /* in: transaction identifier */
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/*********************************************************************
Updates the offset information about the end of the MySQL binlog entry
which corresponds to the transaction just being committed. In a MySQL
diff --git a/storage/innobase/include/trx0sys.ic b/storage/innobase/include/trx0sys.ic
index 1142fb60398..f5033c5778a 100644
--- a/storage/innobase/include/trx0sys.ic
+++ b/storage/innobase/include/trx0sys.ic
@@ -257,6 +257,27 @@ trx_get_on_id(
return(NULL);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/********************************************************
+Assert that a transaction is active. */
+UNIV_INLINE
+ibool
+trx_assert_active(
+/*==============*/
+ /* out: TRUE */
+ dulint trx_id) /* in: transaction identifier */
+{
+ trx_t* trx;
+
+ mutex_enter(&kernel_mutex);
+ trx = trx_get_on_id(trx_id);
+ ut_a(trx);
+ mutex_exit(&kernel_mutex);
+
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
/********************************************************************
Returns the minumum trx id in trx list. This is the smallest id for which
the trx can possibly be active. (But, you must look at the trx->conc_state to
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 4652f45892e..7cb16107746 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -19,7 +19,12 @@ Created 3/26/1996 Heikki Tuuri
#include "dict0types.h"
#include "trx0xa.h"
+/* 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. */
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index ce5d8a092bf..a67b1b3895e 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -88,6 +88,8 @@ memory is read outside the allocated blocks. */
#if 0
#define UNIV_DEBUG_VALGRIND /* Enable extra
Valgrind instrumentation */
+#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column
+ debugging without UNIV_DEBUG */
#define UNIV_DEBUG /* Enable ut_ad() assertions */
#define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */
#define UNIV_MEM_DEBUG /* detect memory leaks etc */
diff --git a/storage/innobase/include/ut0mem.h b/storage/innobase/include/ut0mem.h
index e56895bc142..cb369e85c39 100644
--- a/storage/innobase/include/ut0mem.h
+++ b/storage/innobase/include/ut0mem.h
@@ -145,43 +145,6 @@ ut_strlcpy_rev(
ulint size); /* in: size of destination buffer */
/**************************************************************************
-Compute strlen(ut_strcpyq(str, q)). */
-UNIV_INLINE
-ulint
-ut_strlenq(
-/*=======*/
- /* out: length of the string when quoted */
- const char* str, /* in: null-terminated string */
- char q); /* in: the quote character */
-
-/**************************************************************************
-Make a quoted copy of a NUL-terminated string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_memcpyq(). */
-
-char*
-ut_strcpyq(
-/*=======*/
- /* out: pointer to end of dest */
- char* dest, /* in: output buffer */
- char q, /* in: the quote character */
- const char* src); /* in: null-terminated string */
-
-/**************************************************************************
-Make a quoted copy of a fixed-length string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_strcpyq(). */
-
-char*
-ut_memcpyq(
-/*=======*/
- /* out: pointer to end of dest */
- char* dest, /* in: output buffer */
- char q, /* in: the quote character */
- const char* src, /* in: string to be quoted */
- ulint len); /* in: length of src */
-
-/**************************************************************************
Return the number of times s2 occurs in s1. Overlapping instances of s2
are only counted once. */
diff --git a/storage/innobase/include/ut0mem.ic b/storage/innobase/include/ut0mem.ic
index e0253ebf618..39713352a69 100644
--- a/storage/innobase/include/ut0mem.ic
+++ b/storage/innobase/include/ut0mem.ic
@@ -47,24 +47,3 @@ ut_strcmp(const void* str1, const void* str2)
{
return(strcmp((const char*)str1, (const char*)str2));
}
-
-/**************************************************************************
-Compute strlen(ut_strcpyq(str, q)). */
-UNIV_INLINE
-ulint
-ut_strlenq(
-/*=======*/
- /* out: length of the string when quoted */
- const char* str, /* in: null-terminated string */
- char q) /* in: the quote character */
-{
- ulint len;
-
- for (len = 0; *str; len++, str++) {
- if (*str == q) {
- len++;
- }
- }
-
- return(len);
-}
diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c
index 3300997112b..092e3bfe37f 100644
--- a/storage/innobase/log/log0log.c
+++ b/storage/innobase/log/log0log.c
@@ -3052,12 +3052,13 @@ loop:
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. */
+ /* 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. */
if (trx_n_mysql_transactions > 0
- || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
+ || UT_LIST_GET_LEN(trx_sys->trx_list) > trx_n_prepared) {
mutex_exit(&kernel_mutex);
diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c
index 365fa15878a..728c37ce564 100644
--- a/storage/innobase/mtr/mtr0mtr.c
+++ b/storage/innobase/mtr/mtr0mtr.c
@@ -201,40 +201,6 @@ mtr_commit(
dyn_array_free(&(mtr->log));
}
-/**************************************************************
-Releases the latches stored in an mtr memo down to a savepoint.
-NOTE! The mtr must not have made changes to buffer pages after the
-savepoint, as these can be handled only by mtr_commit. */
-
-void
-mtr_rollback_to_savepoint(
-/*======================*/
- mtr_t* mtr, /* in: mtr */
- ulint savepoint) /* in: savepoint */
-{
- mtr_memo_slot_t* slot;
- dyn_array_t* memo;
- ulint offset;
-
- ut_ad(mtr);
- ut_ad(mtr->magic_n == MTR_MAGIC_N);
- ut_ad(mtr->state == MTR_ACTIVE);
-
- memo = &(mtr->memo);
-
- offset = dyn_array_get_data_size(memo);
- ut_ad(offset >= savepoint);
-
- while (offset > savepoint) {
- offset -= sizeof(mtr_memo_slot_t);
-
- slot = dyn_array_get_element(memo, offset);
-
- ut_ad(slot->type != MTR_MEMO_MODIFY);
- mtr_memo_slot_release(mtr, slot);
- }
-}
-
/*******************************************************
Releases an object in the memo stack. */
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index 9786f90fd39..db134ca7a41 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -423,11 +423,9 @@ row_ins_cascade_calc_update_vec(
dict_table_t* table = foreign->foreign_table;
dict_index_t* index = foreign->foreign_index;
upd_t* update;
- upd_field_t* ufield;
dict_table_t* parent_table;
dict_index_t* parent_index;
upd_t* parent_update;
- upd_field_t* parent_ufield;
ulint n_fields_updated;
ulint parent_field_no;
ulint i;
@@ -463,12 +461,14 @@ row_ins_cascade_calc_update_vec(
dict_index_get_nth_col_no(parent_index, i));
for (j = 0; j < parent_update->n_fields; j++) {
- parent_ufield = parent_update->fields + j;
+ const upd_field_t* parent_ufield
+ = &parent_update->fields[j];
if (parent_ufield->field_no == parent_field_no) {
ulint min_size;
const dict_col_t* col;
+ upd_field_t* ufield;
col = dict_index_get_nth_col(index, i);
@@ -973,10 +973,9 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
- if ((node->is_delete
- && (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL))
- || (!node->is_delete
- && (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
+ if (node->is_delete
+ ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
+ : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) {
/* Build the appropriate update vector which sets
foreign->n_fields first fields in rec to SQL NULL */
@@ -985,6 +984,8 @@ row_ins_foreign_check_on_constraint(
update->info_bits = 0;
update->n_fields = foreign->n_fields;
+ UNIV_MEM_INVALID(update->fields,
+ update->n_fields * sizeof *update->fields);
for (i = 0; i < foreign->n_fields; i++) {
(update->fields + i)->field_no
@@ -1672,7 +1673,7 @@ row_ins_scan_sec_index_for_duplicate(
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
- allow_duplicates = thr_get_trx(thr)->duplicates & TRX_DUP_IGNORE;
+ allow_duplicates = thr_get_trx(thr)->duplicates;
/* Scan index records and check if there is a duplicate */
@@ -1812,7 +1813,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
- if (trx->duplicates & TRX_DUP_IGNORE) {
+ if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@@ -1854,7 +1855,7 @@ row_ins_duplicate_error_in_clust(
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
- if (trx->duplicates & TRX_DUP_IGNORE) {
+ if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c
index deec3b0a454..506d92f052e 100644
--- a/storage/innobase/row/row0purge.c
+++ b/storage/innobase/row/row0purge.c
@@ -379,7 +379,8 @@ row_purge_upd_exist_or_extern(
ut_ad(node);
- if (node->rec_type == TRX_UNDO_UPD_DEL_REC) {
+ if (node->rec_type == TRX_UNDO_UPD_DEL_REC
+ || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
goto skip_secondaries;
}
@@ -488,14 +489,14 @@ row_purge_parse_undo_rec(
dulint roll_ptr;
ulint info_bits;
ulint type;
- ulint cmpl_info;
ut_ad(node && thr);
trx = thr_get_trx(thr);
- ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
- updated_extern, &undo_no, &table_id);
+ ptr = trx_undo_rec_get_pars(
+ node->undo_rec, &type, &node->cmpl_info,
+ updated_extern, &undo_no, &table_id);
node->rec_type = type;
if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) {
@@ -508,7 +509,8 @@ row_purge_parse_undo_rec(
node->table = NULL;
if (type == TRX_UNDO_UPD_EXIST_REC
- && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) {
+ && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE
+ && !(*updated_extern)) {
/* Purge requires no changes to indexes: we may return */
@@ -563,7 +565,7 @@ row_purge_parse_undo_rec(
/* Read to the partial row the fields that occur in indexes */
- if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
+ if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
ptr = trx_undo_rec_get_partial_row(ptr, clust_index,
&(node->row), node->heap);
}
diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c
index 08e50817db9..171039e34ac 100644
--- a/storage/innobase/row/row0row.c
+++ b/storage/innobase/row/row0row.c
@@ -202,6 +202,7 @@ row_build(
ut_ad(index && rec && heap);
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(!mutex_own(&kernel_mutex));
if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_,
@@ -210,6 +211,26 @@ row_build(
ut_ad(rec_offs_validate(rec, index, offsets));
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* This condition can occur during crash recovery before
+ trx_rollback_or_clean_all_without_sess() has completed
+ execution.
+
+ This condition is possible if the server crashed
+ during an insert or update before
+ btr_store_big_rec_extern_fields() did mtr_commit() all
+ BLOB pointers to the clustered index record.
+
+ If the record contains a null BLOB pointer, look up the
+ transaction that holds the implicit lock on this record, and
+ assert that it is active. (In this version of InnoDB, we
+ cannot assert that it was recovered, because there is no
+ trx->is_recovered field.) */
+
+ ut_a(!rec_offs_any_null_extern(rec, offsets)
+ || trx_assert_active(row_get_rec_trx_id(rec, index, offsets)));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
@@ -302,6 +323,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);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ } else {
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}
rec_len = rec_offs_n_fields(offsets);
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index e03d3d79768..9ab6424a012 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -2468,6 +2468,8 @@ row_sel_field_store_in_mysql_format(
ut_ad(len != UNIV_SQL_NULL);
UNIV_MEM_ASSERT_RW(data, len);
+ UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
+ UNIV_MEM_INVALID(dest, templ->mysql_col_len);
if (templ->type == DATA_INT) {
/* Convert integer data from Innobase to a little-endian
@@ -2502,14 +2504,16 @@ row_sel_field_store_in_mysql_format(
dest = row_mysql_store_true_var_len(
dest, len, templ->mysql_length_bytes);
+ /* Copy the actual data. Leave the rest of the
+ buffer uninitialized. */
+ ut_memcpy(dest, data, len);
+ return;
}
/* Copy the actual data */
ut_memcpy(dest, data, len);
- /* Pad with trailing spaces. We pad with spaces also the
- unused end of a >= 5.0.3 true VARCHAR column, just in case
- MySQL expects its contents to be deterministic. */
+ /* Pad with trailing spaces. */
pad_ptr = dest + len;
@@ -3013,6 +3017,39 @@ sel_restore_position_for_mysql(
}
/************************************************************************
+Copies a cached field for MySQL from the fetch cache. */
+static
+void
+row_sel_copy_cached_field_for_mysql(
+/*================================*/
+ byte* buf, /* in/out: row buffer */
+ byte* cache, /* in: cached row */
+ const mysql_row_templ_t*templ) /* in: column template */
+{
+ ulint len;
+
+ buf += templ->mysql_col_offset;
+ cache += templ->mysql_col_offset;
+
+ UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len);
+
+ if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR
+ && templ->type != DATA_INT) {
+ /* Check for != DATA_INT to make sure we do
+ not treat MySQL ENUM or SET as a true VARCHAR!
+ Find the actual length of the true VARCHAR field. */
+ row_mysql_read_true_varchar(
+ &len, cache, templ->mysql_length_bytes);
+ len += templ->mysql_length_bytes;
+ UNIV_MEM_INVALID(buf, templ->mysql_col_len);
+ } else {
+ len = templ->mysql_col_len;
+ }
+
+ ut_memcpy(buf, cache, len);
+}
+
+/************************************************************************
Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE
void
@@ -3028,22 +3065,18 @@ row_sel_pop_cached_row_for_mysql(
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
+ UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len);
+
+ cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first];
+
if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) {
/* Copy cache record field by field, don't touch fields that
are not covered by current key */
- cached_rec = prebuilt->fetch_cache[
- prebuilt->fetch_cache_first];
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(cached_rec
- + templ->mysql_col_offset,
- templ->mysql_col_len);
-#endif
- ut_memcpy(buf + templ->mysql_col_offset,
- cached_rec + templ->mysql_col_offset,
- templ->mysql_col_len);
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, templ);
/* Copy NULL bit of the current field from cached_rec
to buf */
if (templ->mysql_null_bit_mask) {
@@ -3053,17 +3086,24 @@ row_sel_pop_cached_row_for_mysql(
& (byte)templ->mysql_null_bit_mask;
}
}
+ } else if (prebuilt->mysql_prefix_len > 63) {
+ /* The record is long. Copy it field by field, in case
+ there are some long VARCHAR column of which only a
+ small length is being used. */
+ UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len);
+
+ /* First copy the NULL bits. */
+ ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len);
+ /* Then copy the requested fields. */
+
+ for (i = 0; i < prebuilt->n_template; i++) {
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, prebuilt->mysql_template + i);
+ }
+ } else {
+ ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len);
}
- else {
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
- [prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
-#endif
- ut_memcpy(buf,
- prebuilt->fetch_cache[prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
- }
+
prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++;
diff --git a/storage/innobase/row/row0vers.c b/storage/innobase/row/row0vers.c
index 23aca8c3f2e..906b46fb51b 100644
--- a/storage/innobase/row/row0vers.c
+++ b/storage/innobase/row/row0vers.c
@@ -473,6 +473,11 @@ row_vers_build_for_consistent_read(
/* The view already sees this version: we can
copy it to in_heap and return */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(
+ version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
buf = mem_heap_alloc(in_heap,
rec_offs_size(*offsets));
*old_vers = rec_copy(buf, version, *offsets);
@@ -506,6 +511,10 @@ row_vers_build_for_consistent_read(
*offsets = rec_get_offsets(prev_version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(prev_version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
trx_id = row_get_rec_trx_id(prev_version, index, *offsets);
if (read_view_sees_trx_id(view, trx_id)) {
@@ -606,6 +615,10 @@ row_vers_build_for_semi_consistent_read(
/* We found a version that belongs to a
committed transaction: return it. */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (rec == version) {
*old_vers = rec;
err = DB_SUCCESS;
@@ -663,6 +676,9 @@ row_vers_build_for_semi_consistent_read(
version = prev_version;
*offsets = rec_get_offsets(version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}/* for (;;) */
if (heap) {
diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c
index ef4c07e8c26..05ea8ff0fe9 100644
--- a/storage/innobase/sync/sync0rw.c
+++ b/storage/innobase/sync/sync0rw.c
@@ -476,6 +476,9 @@ rw_lock_x_lock_func(
ulint i; /* spin round count */
ut_ad(rw_lock_validate(lock));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
lock_loop:
/* Acquire the mutex protecting the rw-lock fields */
@@ -663,7 +666,9 @@ rw_lock_add_debug_info(
rw_lock_debug_mutex_exit();
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
- sync_thread_add_level(lock, lock->level);
+ sync_thread_add_level(lock, lock->level,
+ lock_type == RW_LOCK_EX
+ && lock->writer_count > 1);
}
}
@@ -730,7 +735,7 @@ rw_lock_own(
ut_ad(lock);
ut_ad(rw_lock_validate(lock));
- mutex_enter(&(lock->mutex));
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
@@ -740,7 +745,7 @@ rw_lock_own(
&& (info->pass == 0)
&& (info->lock_type == lock_type)) {
- mutex_exit(&(lock->mutex));
+ rw_lock_debug_mutex_exit();
/* Found! */
return(TRUE);
@@ -748,7 +753,7 @@ rw_lock_own(
info = UT_LIST_GET_NEXT(list, info);
}
- mutex_exit(&(lock->mutex));
+ rw_lock_debug_mutex_exit();
return(FALSE);
}
@@ -828,11 +833,13 @@ rw_lock_list_print_info(
putc('\n', file);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
mutex_exit(&(lock->mutex));
@@ -868,11 +875,13 @@ rw_lock_print(
putc('\n', stderr);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
}
diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c
index 944fd2a97fc..1099dff798e 100644
--- a/storage/innobase/sync/sync0sync.c
+++ b/storage/innobase/sync/sync0sync.c
@@ -641,7 +641,7 @@ mutex_set_debug_info(
ut_ad(mutex);
ut_ad(file_name);
- sync_thread_add_level(mutex, mutex->level);
+ sync_thread_add_level(mutex, mutex->level, FALSE);
mutex->file_name = file_name;
mutex->line = line;
@@ -1011,8 +1011,9 @@ void
sync_thread_add_level(
/*==================*/
void* latch, /* in: pointer to a mutex or an rw-lock */
- ulint level) /* in: level in the latching order; if
+ ulint level, /* in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
+ ibool relock) /* in: TRUE if re-entering an x-lock */
{
sync_level_t* array;
sync_level_t* slot;
@@ -1060,6 +1061,10 @@ sync_thread_add_level(
array = thread_slot->levels;
+ if (relock) {
+ goto levels_ok;
+ }
+
/* NOTE that there is a problem with _NODE and _LEAF levels: if the
B-tree height changes, then a leaf can change to an internal node
or the other way around. We do not know at present if this can cause
@@ -1209,6 +1214,7 @@ sync_thread_add_level(
ut_error;
}
+levels_ok:
for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
slot = sync_thread_levels_get_nth(array, i);
diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c
index 38ad53fcfb0..730ac6a6f60 100644
--- a/storage/innobase/trx/trx0rec.c
+++ b/storage/innobase/trx/trx0rec.c
@@ -1397,6 +1397,10 @@ trx_undo_prev_version_build(
return(DB_ERROR);
}
+# if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+# endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint* ext_vect;
ulint n_ext_vect;
diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
index a82d7f452fc..d174f1e1b37 100644
--- a/storage/innobase/trx/trx0trx.c
+++ b/storage/innobase/trx/trx0trx.c
@@ -41,6 +41,9 @@ sess_t* trx_dummy_sess = NULL;
/* Number of transactions currently allocated for MySQL: protected by
the kernel mutex */
ulint trx_n_mysql_transactions = 0;
+/* Number of transactions currently in the XA PREPARED state: protected by
+the kernel mutex */
+ulint trx_n_prepared = 0;
/*****************************************************************
Starts the transaction if it is not yet started. */
@@ -480,6 +483,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"
@@ -558,6 +562,7 @@ trx_lists_init_at_db_start(void)
trx->conc_state
= TRX_PREPARED;
+ trx_n_prepared++;
} else {
fprintf(stderr,
"InnoDB: Since"
@@ -832,6 +837,11 @@ trx_commit_off_kernel(
|| 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
@@ -1882,6 +1892,7 @@ trx_prepare_off_kernel(
/*--------------------------------------*/
trx->conc_state = TRX_PREPARED;
+ trx_n_prepared++;
/*--------------------------------------*/
if (must_flush_log) {
diff --git a/storage/innobase/ut/ut0mem.c b/storage/innobase/ut/ut0mem.c
index b466a5f6872..2e0dd27edf4 100644
--- a/storage/innobase/ut/ut0mem.c
+++ b/storage/innobase/ut/ut0mem.c
@@ -408,53 +408,6 @@ ut_strlcpy_rev(
}
/**************************************************************************
-Make a quoted copy of a NUL-terminated string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_memcpyq(). */
-
-char*
-ut_strcpyq(
-/*=======*/
- /* out: pointer to end of dest */
- char* dest, /* in: output buffer */
- char q, /* in: the quote character */
- const char* src) /* in: null-terminated string */
-{
- while (*src) {
- if ((*dest++ = *src++) == q) {
- *dest++ = q;
- }
- }
-
- return(dest);
-}
-
-/**************************************************************************
-Make a quoted copy of a fixed-length string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_strcpyq(). */
-
-char*
-ut_memcpyq(
-/*=======*/
- /* out: pointer to end of dest */
- char* dest, /* in: output buffer */
- char q, /* in: the quote character */
- const char* src, /* in: string to be quoted */
- ulint len) /* in: length of src */
-{
- const char* srcend = src + len;
-
- while (src < srcend) {
- if ((*dest++ = *src++) == q) {
- *dest++ = q;
- }
- }
-
- return(dest);
-}
-
-/**************************************************************************
Return the number of times s2 occurs in s1. Overlapping instances of s2
are only counted once. */
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index 100cf3690ce..951a1bd9c3b 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,3 +1,159 @@
+2011-11-10 The InnoDB Team
+
+ * handler/ha_innodb.cc, row/row0ins.c, innodb_replace.test:
+ Fix Bug#11759688 52020: InnoDB can still deadlock
+ on just INSERT...ON DUPLICATE KEY a.k.a. the reintroduction of
+ Bug#7975 deadlock without any locking, simple select and update
+
+2011-11-08 The InnoDB Team
+
+ * btr/btr0pcur.c, include/btr0pcur.h, include/btr0pcur.ic:
+ Fix Bug#13358468 ASSERTION FAILURE IN BTR_PCUR_GET_BLOCK
+
+2011-10-27 The InnoDB Team
+
+ * row/row0mysql.c:
+ Fix Bug#12884631 62146: TABLES ARE LOST FOR DDL
+
+2011-10-20 The InnoDB Team
+
+ * btr/btr0cur.c:
+ Fix Bug#13116045 Compilation failure using GCC 4.6.1 in btr/btr0cur.c
+
+2011-10-12 The InnoDB Team
+
+ * btr/btr0cur.c, btr/btr0sea.c, buf/buf0buf.c, buf/buf0lru.c,
+ ha/ha0ha.c, handler/ha_innodb.cc, ibuf/ibuf0ibuf.c, include/btr0sea.h,
+ include/btr0types.h, include/buf0buf.h, include/ha0ha.h,
+ include/ha0ha.ic, include/row0upd.ic, include/sync0sync.h,
+ page/page0page.c, sync/sync0sync.c:
+ Fix Bug#13006367 62487: innodb takes 3 minutes to clean up
+ the adaptive hash index at shutdown
+
+2011-10-04 The InnoDB Team
+
+ * include/sync0rw.h, sync/sync0rw.c:
+ Fix Bug#13034534 RQG TESTS FAIL ON WINDOWS WITH CRASH NEAR
+ RW_LOCK_DEBUG_PRINT
+
+2011-09-20 The InnoDB Team
+
+ * row/row0purge.c:
+ Fix Bug#12963823 CRASH IN PURGE THREAD UNDER UNUSUAL CIRCUMSTANCES
+
+2011-09-12 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#12601439 CONSISTENT READ FAILURE IN COLUMN PREFIX INDEX
+
+2011-09-08 The InnoDB Team
+
+ * btr/btr0cur.c, include/page0page.h, include/row0upd.ic:
+ Fix Bug#12948130 UNNECESSARY X-LOCKING OF ADAPTIVE HASH INDEX
+
+2011-09-06 The InnoDB Team
+
+ * buf/buf0buddy.c:
+ Fix Bug#12950803 62294: BUF_BUDDY_RELOCATE CALLS GETTIMEOFDAY
+ WHILE HOLDING BUFFER POOL MUTEX
+
+2011-09-06 The InnoDB Team
+
+ * include/trx0undo.h, trx/trx0rec.c, trx/trx0undo.c:
+ Fix Bug#12547647 UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
+
+2011-08-29 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, fsp/fsp0fsp.c,
+ include/btr0btr.h, include/btr0cur.h, include/fsp0fsp.h,
+ include/mtr0mtr.h, include/mtr0mtr.ic, mtr/mtr0mtr.c,
+ row/row0ins.c, row/row0row.c, row/row0upd.c, trx/trx0undo.c:
+ Fix Bug#12704861 Corruption after a crash during BLOB update
+ and other regressions from the fix of Bug#12612184
+
+2011-08-15 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, btr/btr0pcur.c, btr/btr0sea.c,
+ dict/dict0crea.c, dict/dict0dict.c, ibuf/ibuf0ibuf.c,
+ include/btr0btr.h, include/btr0btr.ic, include/sync0sync.h,
+ sync/sync0sync.c:
+ Fix Bug#11766591 59733: Possible deadlock when buffered changes
+ are to be discarded in buf_page_create()
+
+2011-08-08 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#12835650 VARCHAR maximum length performance impact
+
+2011-08-08 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#12770537 I_S.TABLES.DATA_LENGTH DOES NOT SHOW ON-DISK SIZE
+ FOR COMPRESSED INNODB
+
+2011-07-19 The InnoDB Team
+
+ * buf/buf0buf.c, buf/buf0rea.c, handler/ha_innodb.cc,
+ include/buf0buf.h, include/buf0buf.ic, include/srv0srv.h,
+ srv/srv0srv.c:
+ Fix Bug#12356373 by reintroducing random readahead
+
+2011-06-30 The InnoDB Team
+
+ * row/row0row.c:
+ Fix Bug#12637786 Wrong secondary index entries on CHAR and VARCHAR
+ columns in ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED
+
+2011-06-16 The InnoDB Team
+
+ * btr/btr0cur.c, buf/buf0buddy.c, buf/buf0buf.c, buf/buf0lru.c,
+ include/buf0buddy.h, include/buf0buddy.ic, include/buf0buf.h,
+ include/buf0buf.ic, include/buf0lru.h, include/buf0types.h:
+ Fix Bug#61188 DROP TABLE extremely slow
+
+2011-06-16 The InnoDB Team
+
+ * buf/buf0buddy.c, buf/buf0buf.c, buf/buf0flu.c, buf/buf0lru.c,
+ include/buf0buf.h, include/buf0lru.h:
+ Fix Bug#61341 buf_LRU_insert_zip_clean can be O(N) on LRU length
+
+2011-06-16 The InnoDB Team
+
+ * page/page0zip.c, rem/rem0rec.c:
+ Fix Bug#61191 question about page_zip_available()
+
+2011-06-16 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, include/btr0btr.h, include/btr0cur.h,
+ include/btr0cur.ic, include/buf0buf.h, include/buf0buf.ic,
+ include/page0cur.ic, include/page0page.h, include/page0page.ic,
+ include/sync0rw.ic, include/sync0sync.h, page/page0cur.c,
+ page/page0page.c, row/row0ins.c, row/row0upd.c,
+ sync/sync0rw.c, sync/sync0sync.c:
+ Fix Bug#12612184 Race condition after btr_cur_pessimistic_update()
+
+2011-06-09 The InnoDB Team
+ * btr/btr0cur.c, include/rem0rec.h, include/rem0rec.ic,
+ * row/row0row.c, row/row0vers.c, trx/trx0rec.c:
+ Instrumentation for Bug#12612184 Race condition in row_upd_clust_rec()
+
+2011-05-19 The InnoDB Team
+
+ * row/row0row.c:
+ Fix Bug#12429576 Assertion failure on purge of column prefix index
+
+2011-04-07 The InnoDB Team
+
+ * handler/ha_innodb.cc, handler/ha_innodb.h, handler/handler0alter.cc:
+ Fix Bug #52409 Assertion failure: long semaphore wait
+
+2011-04-07 The InnoDB Team
+
+ * handler/ha_innodb.cc, include/trx0trx.h, include/trx0undo.h,
+ log/log0log.c, trx/trx0sys.c, trx/trx0trx.c, trx/trx0undo.c:
+ Fix Bug #59641 Prepared XA transaction in system after hard crash
+ causes future shutdown hang
+
2011-03-30 The InnoDB Team
* srv/srv0srv.c, sync/sync0arr.h, sync/sync0arr.c:
diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c
index 46810c011c4..23729c12c1a 100644
--- a/storage/innodb_plugin/btr/btr0btr.c
+++ b/storage/innodb_plugin/btr/btr0btr.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.
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
@@ -690,7 +690,8 @@ btr_root_block_get(
zip_size = dict_table_zip_size(index->table);
root_page_no = dict_index_get_page(index);
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
+ index, mtr);
ut_a((ibool)!!page_is_comp(buf_block_get_frame(block))
== dict_table_is_comp(index->table));
#ifdef UNIV_BTR_DEBUG
@@ -891,7 +892,7 @@ btr_page_alloc_for_ibuf(
dict_table_zip_size(index->table),
node_addr.page, RW_X_LATCH, mtr);
new_page = buf_block_get_frame(new_block);
- buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ buf_block_dbg_add_level(new_block, SYNC_IBUF_TREE_NODE_NEW);
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
@@ -1064,6 +1065,15 @@ btr_page_free_low(
fseg_free_page(seg_header,
buf_block_get_space(block),
buf_block_get_page_no(block), mtr);
+
+ /* The page was marked free in the allocation bitmap, but it
+ should remain buffer-fixed until mtr_commit(mtr) or until it
+ is explicitly freed from the mini-transaction. */
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ /* TODO: Discard any operations on the page from the redo log
+ and remove the block from the flush list and the buffer pool.
+ This would free up buffer pool earlier and reduce writes to
+ both the tablespace and the redo log. */
}
/**************************************************************//**
@@ -1139,7 +1149,7 @@ btr_node_ptr_get_child(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
return(btr_block_get(space, dict_table_zip_size(index->table),
- page_no, RW_X_LATCH, mtr));
+ page_no, RW_X_LATCH, index, mtr));
}
/************************************************************//**
@@ -1311,7 +1321,8 @@ btr_create(
space, 0,
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
- buf_block_dbg_add_level(ibuf_hdr_block, SYNC_TREE_NODE_NEW);
+ buf_block_dbg_add_level(
+ ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(buf_block_get_page_no(ibuf_hdr_block)
== IBUF_HEADER_PAGE_NO);
@@ -1348,10 +1359,9 @@ btr_create(
page_no = buf_block_get_page_no(block);
frame = buf_block_get_frame(block);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
-
if (type & DICT_IBUF) {
/* It is an insert buffer tree: initialize the free list */
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
@@ -1359,6 +1369,8 @@ btr_create(
} else {
/* It is a non-ibuf tree: create a file segment for leaf
pages */
+ buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
+
if (!fseg_create(space, page_no,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
@@ -1430,7 +1442,8 @@ btr_free_but_not_root(
leaf_loop:
mtr_start(&mtr);
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
+ root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, &mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
+ root, space));
@@ -1452,7 +1465,8 @@ leaf_loop:
top_loop:
mtr_start(&mtr);
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
+ root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, &mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
+ root, space));
@@ -1478,13 +1492,13 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
- mtr_t* mtr) /*!< in: a mini-transaction which has already
- been started */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fseg_header_t* header;
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, mtr);
btr_search_drop_page_hash_index(block);
@@ -2272,7 +2286,7 @@ btr_attach_half_pages(
/*==================*/
dict_index_t* index, /*!< in: the index tree */
buf_block_t* block, /*!< in/out: page to be split */
- rec_t* split_rec, /*!< in: first record on upper
+ const rec_t* split_rec, /*!< in: first record on upper
half page */
buf_block_t* new_block, /*!< in/out: the new half page */
ulint direction, /*!< in: FSP_UP or FSP_DOWN */
@@ -2362,9 +2376,8 @@ btr_attach_half_pages(
/* Update page links of the level */
if (prev_page_no != FIL_NULL) {
- buf_block_t* prev_block = btr_block_get(space, zip_size,
- prev_page_no,
- RW_X_LATCH, mtr);
+ buf_block_t* prev_block = btr_block_get(
+ space, zip_size, prev_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
ut_a(btr_page_get_next(prev_block->frame, mtr)
@@ -2377,9 +2390,8 @@ btr_attach_half_pages(
}
if (next_page_no != FIL_NULL) {
- buf_block_t* next_block = btr_block_get(space, zip_size,
- next_page_no,
- RW_X_LATCH, mtr);
+ buf_block_t* next_block = btr_block_get(
+ space, zip_size, next_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
ut_a(btr_page_get_prev(next_block->frame, mtr)
@@ -2801,17 +2813,42 @@ func_exit:
return(rec);
}
+#ifdef UNIV_SYNC_DEBUG
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,index,mtr)
+#else /* UNIV_SYNC_DEBUG */
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,mtr)
+#endif /* UNIV_SYNC_DEBUG */
+
/*************************************************************//**
Removes a page from the level list of pages. */
-static
+static __attribute__((nonnull))
void
-btr_level_list_remove(
-/*==================*/
- ulint space, /*!< in: space where removed */
- ulint zip_size,/*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- page_t* page, /*!< in: page to remove */
- mtr_t* mtr) /*!< in: mtr */
+btr_level_list_remove_func(
+/*=======================*/
+ ulint space, /*!< in: space where removed */
+ ulint zip_size,/*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ page_t* page, /*!< in/out: page to remove */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree */
+#endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint prev_page_no;
ulint next_page_no;
@@ -2829,7 +2866,7 @@ btr_level_list_remove(
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block
= btr_block_get(space, zip_size, prev_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
page_t* prev_page
= buf_block_get_frame(prev_block);
#ifdef UNIV_BTR_DEBUG
@@ -2846,7 +2883,7 @@ btr_level_list_remove(
if (next_page_no != FIL_NULL) {
buf_block_t* next_block
= btr_block_get(space, zip_size, next_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
page_t* next_page
= buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
@@ -3161,7 +3198,7 @@ btr_compress(
if (is_left) {
merge_block = btr_block_get(space, zip_size, left_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@@ -3170,7 +3207,7 @@ btr_compress(
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@@ -3259,7 +3296,7 @@ err_exit:
btr_search_drop_page_hash_index(block);
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
btr_node_ptr_delete(index, block, mtr);
lock_update_merge_left(merge_block, orig_pred, block);
@@ -3312,7 +3349,7 @@ err_exit:
#endif /* UNIV_BTR_DEBUG */
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
/* Replace the address of the old child node (= page) with the
address of the merge page to the right */
@@ -3495,7 +3532,7 @@ btr_discard_page(
if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, left_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@@ -3503,7 +3540,7 @@ btr_discard_page(
#endif /* UNIV_BTR_DEBUG */
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@@ -3538,7 +3575,7 @@ btr_discard_page(
btr_node_ptr_delete(index, block, mtr);
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
#ifdef UNIV_ZIP_DEBUG
{
page_zip_des_t* merge_page_zip
@@ -4056,7 +4093,7 @@ loop:
if (right_page_no != FIL_NULL) {
const rec_t* right_rec;
right_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, &mtr);
+ RW_X_LATCH, index, &mtr);
right_page = buf_block_get_frame(right_block);
if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
!= page_get_page_no(page))) {
@@ -4282,7 +4319,7 @@ node_ptr_fails:
mtr_start(&mtr);
block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, &mtr);
+ RW_X_LATCH, index, &mtr);
page = buf_block_get_frame(block);
goto loop;
diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index d7b5ed0d135..9f4be053a43 100644
--- a/storage/innodb_plugin/btr/btr0cur.c
+++ b/storage/innodb_plugin/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
@@ -238,7 +238,8 @@ btr_cur_latch_leaves(
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
- get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no, mode, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@@ -249,9 +250,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- left_page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, left_page_no,
+ RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
== page_is_comp(page));
@@ -261,8 +262,9 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
- get_block = btr_block_get(space, zip_size, page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no,
+ RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@@ -271,9 +273,9 @@ btr_cur_latch_leaves(
right_page_no = btr_page_get_next(page, mtr);
if (right_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- right_page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, right_page_no,
+ RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
== page_is_comp(page));
@@ -292,8 +294,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- left_page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size,
+ left_page_no, mode, cursor->index, mtr);
cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
@@ -304,7 +307,8 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
- get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no, mode, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@@ -572,7 +576,9 @@ retry_page_get:
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ block, dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
ut_ad(0 == ut_dulint_cmp(index->id,
@@ -630,8 +636,8 @@ retry_page_get:
if (level > 0) {
/* x-latch the page */
- page = btr_page_get(space, zip_size,
- page_no, RW_X_LATCH, mtr);
+ page = btr_page_get(space, zip_size, page_no,
+ RW_X_LATCH, index, mtr);
ut_a((ibool)!!page_is_comp(page)
== dict_table_is_comp(index->table));
}
@@ -1721,6 +1727,7 @@ btr_cur_update_in_place(
roll_ptr_t roll_ptr = ut_dulint_zero;
trx_t* trx;
ulint was_delete_marked;
+ ibool is_hashed;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -1762,7 +1769,21 @@ btr_cur_update_in_place(
return(err);
}
- if (block->is_hashed) {
+ if (!(flags & BTR_KEEP_SYS_FLAG)) {
+ row_upd_rec_sys_fields(rec, NULL,
+ index, offsets, trx, roll_ptr);
+ }
+
+ was_delete_marked = rec_get_deleted_flag(
+ rec, page_is_comp(buf_block_get_frame(block)));
+
+ is_hashed = (block->index != NULL);
+
+ if (is_hashed) {
+ /* TO DO: Can we skip this if none of the fields
+ index->search_info->curr_n_fields
+ are being updated? */
+
/* The function row_upd_changes_ord_field_binary works only
if the update vector was built for a clustered index, we must
NOT call it if index is secondary */
@@ -1778,17 +1799,9 @@ btr_cur_update_in_place(
rw_lock_x_lock(&btr_search_latch);
}
- if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields(rec, NULL,
- index, offsets, trx, roll_ptr);
- }
-
- was_delete_marked = rec_get_deleted_flag(
- rec, page_is_comp(buf_block_get_frame(block)));
-
row_upd_rec_in_place(rec, index, offsets, update, page_zip);
- if (block->is_hashed) {
+ if (is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
}
@@ -1854,7 +1867,6 @@ btr_cur_optimistic_update(
ulint old_rec_size;
dtuple_t* new_entry;
roll_ptr_t roll_ptr;
- trx_t* trx;
mem_heap_t* heap;
ulint i;
ulint n_ext;
@@ -1871,6 +1883,10 @@ btr_cur_optimistic_update(
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(rec, offsets)
+ || trx_is_recv(thr_get_trx(thr)));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
@@ -1993,13 +2009,11 @@ any_extern:
page_cur_move_to_prev(page_cursor);
- trx = thr_get_trx(thr);
-
if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr);
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
- trx->id);
+ thr_get_trx(thr)->id);
}
/* There are no externally stored columns in new_entry */
@@ -2486,7 +2500,8 @@ btr_cur_parse_del_mark_set_clust_rec(
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
- it. */
+ it. Besides, these fields are being updated in place
+ and the adaptive hash index does not depend on them. */
btr_rec_set_deleted_flag(rec, page_zip, val);
@@ -2566,9 +2581,9 @@ btr_cur_del_mark_set_clust_rec(
return(err);
}
- if (block->is_hashed) {
- rw_lock_x_lock(&btr_search_latch);
- }
+ /* The btr_search_latch is not needed here, because
+ the adaptive hash index does not depend on the delete-mark
+ and the delete-mark is being updated in place. */
page_zip = buf_block_get_page_zip(block);
@@ -2582,10 +2597,6 @@ btr_cur_del_mark_set_clust_rec(
index, offsets, trx, roll_ptr);
}
- if (block->is_hashed) {
- rw_lock_x_unlock(&btr_search_latch);
- }
-
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
@@ -2661,7 +2672,8 @@ btr_cur_parse_del_mark_set_sec_rec(
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
- it. */
+ it. Besides, the delete-mark flag is being updated in place
+ and the adaptive hash index does not depend on it. */
btr_rec_set_deleted_flag(rec, page_zip, val);
}
@@ -2709,16 +2721,11 @@ btr_cur_del_mark_set_sec_rec(
ut_ad(!!page_rec_is_comp(rec)
== dict_table_is_comp(cursor->index->table));
- if (block->is_hashed) {
- rw_lock_x_lock(&btr_search_latch);
- }
-
+ /* We do not need to reserve btr_search_latch, as the
+ delete-mark flag is being updated in place and the adaptive
+ hash index does not depend on it. */
btr_rec_set_deleted_flag(rec, buf_block_get_page_zip(block), val);
- if (block->is_hashed) {
- rw_lock_x_unlock(&btr_search_latch);
- }
-
btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
return(DB_SUCCESS);
@@ -2738,8 +2745,11 @@ btr_cur_del_unmark_for_ibuf(
uncompressed */
mtr_t* mtr) /*!< in: mtr */
{
- /* We do not need to reserve btr_search_latch, as the page has just
- been read to the buffer pool and there cannot be a hash index to it. */
+ /* We do not need to reserve btr_search_latch, as the page
+ has just been read to the buffer pool and there cannot be
+ a hash index to it. Besides, the delete-mark flag is being
+ updated in place and the adaptive hash index does not depend
+ on it. */
btr_rec_set_deleted_flag(rec, page_zip, FALSE);
@@ -3222,7 +3232,6 @@ 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 */
@@ -3241,17 +3250,11 @@ btr_record_not_null_field_in_rec(
}
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 */
+ if (rec_offs_nth_sql_null(offsets, i)) {
break;
}
+
+ n_not_null[i]++;
}
}
@@ -3359,7 +3362,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- rec, n_cols, offsets_rec, n_not_null);
+ n_cols, offsets_rec, n_not_null);
}
}
@@ -3394,8 +3397,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- next_rec, n_cols, offsets_next_rec,
- n_not_null);
+ n_cols, offsets_next_rec, n_not_null);
}
total_external_size
@@ -3801,7 +3803,7 @@ 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) != BUF_LRU_FREED
+ if (!buf_LRU_free_block(&block->page, all)
&& all && block->page.zip.data) {
/* Attempt to deallocate the uncompressed page
if the whole block cannot be deallocted. */
diff --git a/storage/innodb_plugin/btr/btr0pcur.c b/storage/innodb_plugin/btr/btr0pcur.c
index 056896c7927..57d9752649f 100644
--- a/storage/innodb_plugin/btr/btr0pcur.c
+++ b/storage/innodb_plugin/btr/btr0pcur.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
@@ -247,6 +247,8 @@ btr_pcur_restore_position_func(
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
+ cursor->latch_mode = latch_mode;
+ cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->block_when_stored = btr_pcur_get_block(cursor);
return(FALSE);
@@ -266,8 +268,10 @@ btr_pcur_restore_position_func(
file, line, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
- buf_block_dbg_add_level(btr_pcur_get_block(cursor),
- SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ btr_pcur_get_block(cursor),
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
if (cursor->rel_pos == BTR_PCUR_ON) {
#ifdef UNIV_DEBUG
@@ -356,33 +360,6 @@ btr_pcur_restore_position_func(
return(FALSE);
}
-/**************************************************************//**
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-UNIV_INTERN
-void
-btr_pcur_release_leaf(
-/*==================*/
- btr_pcur_t* cursor, /*!< in: persistent cursor */
- mtr_t* mtr) /*!< in: mtr */
-{
- buf_block_t* block;
-
- ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
- ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
-
- block = btr_pcur_get_block(cursor);
-
- btr_leaf_page_release(block, cursor->latch_mode, mtr);
-
- cursor->latch_mode = BTR_NO_LATCHES;
-
- cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
-}
-
/*********************************************************//**
Moves the persistent cursor to the first record on the next page. Releases the
latch on the current page, and bufferunfixes it. Note that there must not be
@@ -417,7 +394,8 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_block = btr_block_get(space, zip_size, next_page_no,
- cursor->latch_mode, mtr);
+ cursor->latch_mode,
+ btr_pcur_get_btr_cur(cursor)->index, mtr);
next_page = buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_page) == page_is_comp(page));
diff --git a/storage/innodb_plugin/btr/btr0sea.c b/storage/innodb_plugin/btr/btr0sea.c
index cd0eadbb1b8..3dd30cbc0f3 100644
--- a/storage/innodb_plugin/btr/btr0sea.c
+++ b/storage/innodb_plugin/btr/btr0sea.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -44,12 +44,8 @@ Created 2/17/1996 Heikki Tuuri
#include "ha0ha.h"
/** Flag: has the search system been enabled?
-Protected by btr_search_latch and btr_search_enabled_mutex. */
+Protected by btr_search_latch. */
UNIV_INTERN char btr_search_enabled = TRUE;
-UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
-
-/** Mutex protecting btr_search_enabled */
-static mutex_t btr_search_enabled_mutex;
/** A dummy variable to fool the compiler */
UNIV_INTERN ulint btr_search_this_is_zero = 0;
@@ -169,7 +165,6 @@ btr_search_sys_create(
btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
rw_lock_create(&btr_search_latch, SYNC_SEARCH_SYS);
- mutex_create(&btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
@@ -199,27 +194,37 @@ void
btr_search_disable(void)
/*====================*/
{
- mutex_enter(&btr_search_enabled_mutex);
+ dict_table_t* table;
+
+ mutex_enter(&dict_sys->mutex);
rw_lock_x_lock(&btr_search_latch);
- /* Disable access to hash index, also tell ha_insert_for_fold()
- stop adding new nodes to hash index, but still allow updating
- existing nodes */
btr_search_enabled = FALSE;
- /* Clear all block->is_hashed flags and remove all entries
- from btr_search_sys->hash_index. */
- buf_pool_drop_hash_index();
+ /* Clear the index->search_info->ref_count of every index in
+ the data dictionary cache. */
+ for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
+ table = UT_LIST_GET_NEXT(table_LRU, table)) {
+
+ dict_index_t* index;
+
+ for (index = dict_table_get_first_index(table); index;
+ index = dict_table_get_next_index(index)) {
+
+ index->search_info->ref_count = 0;
+ }
+ }
+
+ mutex_exit(&dict_sys->mutex);
- /* hash index has been cleaned up, disallow any operation to
- the hash index */
- btr_search_fully_disabled = TRUE;
+ /* Set all block->index = NULL. */
+ buf_pool_clear_hash_index();
- /* btr_search_enabled_mutex should guarantee this. */
- ut_ad(!btr_search_enabled);
+ /* Clear the adaptive hash index. */
+ hash_table_clear(btr_search_sys->hash_index);
+ mem_heap_empty(btr_search_sys->hash_index->heap);
rw_lock_x_unlock(&btr_search_latch);
- mutex_exit(&btr_search_enabled_mutex);
}
/********************************************************************//**
@@ -229,14 +234,11 @@ void
btr_search_enable(void)
/*====================*/
{
- mutex_enter(&btr_search_enabled_mutex);
rw_lock_x_lock(&btr_search_latch);
btr_search_enabled = TRUE;
- btr_search_fully_disabled = FALSE;
rw_lock_x_unlock(&btr_search_latch);
- mutex_exit(&btr_search_enabled_mutex);
}
/*****************************************************************//**
@@ -459,7 +461,7 @@ btr_search_update_block_hash_info(
&& (block->n_bytes == info->n_bytes)
&& (block->left_side == info->left_side)) {
- if ((block->is_hashed)
+ if ((block->index)
&& (block->curr_n_fields == info->n_fields)
&& (block->curr_n_bytes == info->n_bytes)
&& (block->curr_left_side == info->left_side)) {
@@ -488,7 +490,7 @@ btr_search_update_block_hash_info(
/ BTR_SEARCH_PAGE_BUILD_LIMIT)
&& (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) {
- if ((!block->is_hashed)
+ if ((!block->index)
|| (block->n_hash_helps
> 2 * page_get_n_recs(block->frame))
|| (block->n_fields != block->curr_n_fields)
@@ -520,9 +522,9 @@ btr_search_update_hash_ref(
buf_block_t* block, /*!< in: buffer block where cursor positioned */
btr_cur_t* cursor) /*!< in: cursor */
{
- ulint fold;
- rec_t* rec;
- dulint index_id;
+ dict_index_t* index;
+ ulint fold;
+ const rec_t* rec;
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
#ifdef UNIV_SYNC_DEBUG
@@ -533,13 +535,15 @@ btr_search_update_hash_ref(
ut_ad(page_align(btr_cur_get_rec(cursor))
== buf_block_get_frame(block));
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(index == cursor->index);
+ ut_a(!dict_index_is_ibuf(index));
if ((info->n_hash_potential > 0)
&& (block->curr_n_fields == info->n_fields)
@@ -556,12 +560,11 @@ btr_search_update_hash_ref(
return;
}
- index_id = cursor->index->id;
fold = rec_fold(rec,
- rec_get_offsets(rec, cursor->index, offsets_,
+ rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
block->curr_n_fields,
- block->curr_n_bytes, index_id);
+ block->curr_n_bytes, index->id);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -824,7 +827,7 @@ btr_search_guess_on_hash(
mtr_t* mtr) /*!< in: mtr */
{
buf_block_t* block;
- rec_t* rec;
+ const rec_t* rec;
ulint fold;
dulint index_id;
#ifdef notdefined
@@ -832,6 +835,7 @@ btr_search_guess_on_hash(
btr_pcur_t pcur;
#endif
ut_ad(index && info && tuple && cursor && mtr);
+ ut_ad(!dict_index_is_ibuf(index));
ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF));
@@ -909,7 +913,7 @@ btr_search_guess_on_hash(
ut_ad(page_rec_is_user_rec(rec));
- btr_cur_position(index, rec, block, cursor);
+ btr_cur_position(index, (rec_t*) rec, block, cursor);
/* Check the validity of the guess within the page */
@@ -1040,15 +1044,16 @@ btr_search_drop_page_hash_index(
retry:
rw_lock_s_lock(&btr_search_latch);
- page = block->frame;
+ index = block->index;
- if (UNIV_LIKELY(!block->is_hashed)) {
+ if (UNIV_LIKELY(!index)) {
rw_lock_s_unlock(&btr_search_latch);
return;
}
+ ut_a(!dict_index_is_ibuf(index));
table = btr_search_sys->hash_index;
#ifdef UNIV_SYNC_DEBUG
@@ -1059,8 +1064,6 @@ retry:
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
- index = block->index;
- ut_a(!dict_index_is_ibuf(index));
/* NOTE: The fields of block must not be accessed after
releasing btr_search_latch, as the index page might only
@@ -1070,6 +1073,7 @@ retry:
ut_a(n_fields + n_bytes > 0);
+ page = block->frame;
n_recs = page_get_n_recs(page);
/* Calculate and cache fold values into an array for fast deletion
@@ -1118,7 +1122,7 @@ next_rec:
rw_lock_x_lock(&btr_search_latch);
- if (UNIV_UNLIKELY(!block->is_hashed)) {
+ if (UNIV_UNLIKELY(!block->index)) {
/* Someone else has meanwhile dropped the hash index */
goto cleanup;
@@ -1146,9 +1150,8 @@ next_rec:
ut_a(index->search_info->ref_count > 0);
index->search_info->ref_count--;
- block->is_hashed = FALSE;
block->index = NULL;
-
+
cleanup:
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (UNIV_UNLIKELY(block->n_pointers)) {
@@ -1174,8 +1177,8 @@ cleanup:
}
/********************************************************************//**
-Drops a page hash index when a page is freed from a fseg to the file system.
-Drops possible hash index if the page happens to be in the buffer pool. */
+Drops a possible page hash index when a page is evicted from the buffer pool
+or freed in a file segment. */
UNIV_INTERN
void
btr_search_drop_page_hash_when_freed(
@@ -1188,28 +1191,19 @@ btr_search_drop_page_hash_when_freed(
buf_block_t* block;
mtr_t mtr;
- if (!buf_page_peek_if_search_hashed(space, page_no)) {
-
- return;
- }
-
mtr_start(&mtr);
- /* We assume that if the caller has a latch on the page, then the
- caller has already dropped the hash index for the page, and we never
- get here. Therefore we can acquire the s-latch to the page without
- having to fear a deadlock. */
+ /* If the caller has a latch on the page, then the caller must
+ have a x-latch on the page and it must have already dropped
+ the hash index for the page. Because of the x-latch that we
+ are possibly holding, we cannot s-latch the page, but must
+ (recursively) x-latch it, even though we are only reading. */
- block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
+ block = buf_page_get_gen(space, zip_size, page_no, RW_X_LATCH, NULL,
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
- before buf_page_get_gen() got a chance to acquire the buffer
- pool mutex again. Thus, we must check for a NULL return. */
- if (UNIV_LIKELY(block != NULL)) {
+ if (block && block->index) {
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
@@ -1241,7 +1235,6 @@ btr_search_build_page_hash_index(
rec_t* next_rec;
ulint fold;
ulint next_fold;
- dulint index_id;
ulint n_cached;
ulint n_recs;
ulint* folds;
@@ -1255,9 +1248,6 @@ btr_search_build_page_hash_index(
ut_ad(index);
ut_a(!dict_index_is_ibuf(index));
- table = btr_search_sys->hash_index;
- page = buf_block_get_frame(block);
-
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
@@ -1266,9 +1256,17 @@ btr_search_build_page_hash_index(
rw_lock_s_lock(&btr_search_latch);
- if (block->is_hashed && ((block->curr_n_fields != n_fields)
- || (block->curr_n_bytes != n_bytes)
- || (block->curr_left_side != left_side))) {
+ if (!btr_search_enabled) {
+ rw_lock_s_unlock(&btr_search_latch);
+ return;
+ }
+
+ table = btr_search_sys->hash_index;
+ page = buf_block_get_frame(block);
+
+ if (block->index && ((block->curr_n_fields != n_fields)
+ || (block->curr_n_bytes != n_bytes)
+ || (block->curr_left_side != left_side))) {
rw_lock_s_unlock(&btr_search_latch);
@@ -1305,7 +1303,7 @@ btr_search_build_page_hash_index(
n_cached = 0;
- index_id = btr_page_get_index_id(page);
+ ut_a(UT_DULINT_EQ(index->id, btr_page_get_index_id(page)));
rec = page_rec_get_next(page_get_infimum_rec(page));
@@ -1320,7 +1318,7 @@ btr_search_build_page_hash_index(
}
}
- fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
if (left_side) {
@@ -1347,7 +1345,7 @@ btr_search_build_page_hash_index(
offsets = rec_get_offsets(next_rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
- n_bytes, index_id);
+ n_bytes, index->id);
if (fold != next_fold) {
/* Insert an entry into the hash index */
@@ -1372,13 +1370,13 @@ btr_search_build_page_hash_index(
rw_lock_x_lock(&btr_search_latch);
- if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
+ if (UNIV_UNLIKELY(!btr_search_enabled)) {
goto exit_func;
}
- if (block->is_hashed && ((block->curr_n_fields != n_fields)
- || (block->curr_n_bytes != n_bytes)
- || (block->curr_left_side != left_side))) {
+ if (block->index && ((block->curr_n_fields != n_fields)
+ || (block->curr_n_bytes != n_bytes)
+ || (block->curr_left_side != left_side))) {
goto exit_func;
}
@@ -1387,11 +1385,10 @@ btr_search_build_page_hash_index(
rebuild hash index for a page that is already hashed, we
have to take care not to increment the counter in that
case. */
- if (!block->is_hashed) {
+ if (!block->index) {
index->search_info->ref_count++;
}
- block->is_hashed = TRUE;
block->n_hash_helps = 0;
block->curr_n_fields = n_fields;
@@ -1439,14 +1436,15 @@ btr_search_move_or_delete_hash_entries(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(!new_block->is_hashed || new_block->index == index);
- ut_a(!block->is_hashed || block->index == index);
- ut_a(!(new_block->is_hashed || block->is_hashed)
- || !dict_index_is_ibuf(index));
rw_lock_s_lock(&btr_search_latch);
- if (new_block->is_hashed) {
+ ut_a(!new_block->index || new_block->index == index);
+ ut_a(!block->index || block->index == index);
+ ut_a(!(new_block->index || block->index)
+ || !dict_index_is_ibuf(index));
+
+ if (new_block->index) {
rw_lock_s_unlock(&btr_search_latch);
@@ -1455,7 +1453,7 @@ btr_search_move_or_delete_hash_entries(
return;
}
- if (block->is_hashed) {
+ if (block->index) {
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@@ -1492,42 +1490,48 @@ btr_search_update_hash_on_delete(
{
hash_table_t* table;
buf_block_t* block;
- rec_t* rec;
+ const rec_t* rec;
ulint fold;
- dulint index_id;
+ dict_index_t* index;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
mem_heap_t* heap = NULL;
rec_offs_init(offsets_);
- rec = btr_cur_get_rec(cursor);
-
block = btr_cur_get_block(cursor);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
+ ut_a(index == cursor->index);
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(!dict_index_is_ibuf(index));
table = btr_search_sys->hash_index;
- index_id = cursor->index->id;
- fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
+ rec = btr_cur_get_rec(cursor);
+
+ fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- block->curr_n_fields, block->curr_n_bytes, index_id);
+ block->curr_n_fields, block->curr_n_bytes, index->id);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
+
rw_lock_x_lock(&btr_search_latch);
- ha_search_and_delete_if_found(table, fold, rec);
+ if (block->index) {
+ ut_a(block->index == index);
+
+ ha_search_and_delete_if_found(table, fold, rec);
+ }
rw_lock_x_unlock(&btr_search_latch);
}
@@ -1545,6 +1549,7 @@ btr_search_update_hash_node_on_insert(
{
hash_table_t* table;
buf_block_t* block;
+ dict_index_t* index;
rec_t* rec;
rec = btr_cur_get_rec(cursor);
@@ -1555,16 +1560,25 @@ btr_search_update_hash_node_on_insert(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(cursor->index == index);
+ ut_a(!dict_index_is_ibuf(index));
rw_lock_x_lock(&btr_search_latch);
+ if (!block->index) {
+
+ goto func_exit;
+ }
+
+ ut_a(block->index == index);
+
if ((cursor->flag == BTR_CUR_HASH)
&& (cursor->n_fields == block->curr_n_fields)
&& (cursor->n_bytes == block->curr_n_bytes)
@@ -1575,6 +1589,7 @@ btr_search_update_hash_node_on_insert(
ha_search_and_update_if_found(table, cursor->fold, rec,
block, page_rec_get_next(rec));
+func_exit:
rw_lock_x_unlock(&btr_search_latch);
} else {
rw_lock_x_unlock(&btr_search_latch);
@@ -1596,10 +1611,10 @@ btr_search_update_hash_on_insert(
{
hash_table_t* table;
buf_block_t* block;
+ dict_index_t* index;
rec_t* rec;
rec_t* ins_rec;
rec_t* next_rec;
- dulint index_id;
ulint fold;
ulint ins_fold;
ulint next_fold = 0; /* remove warning (??? bug ???) */
@@ -1624,15 +1639,15 @@ btr_search_update_hash_on_insert(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
-
- index_id = cursor->index->id;
+ ut_a(index == cursor->index);
+ ut_a(!dict_index_is_ibuf(index));
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@@ -1641,21 +1656,21 @@ btr_search_update_hash_on_insert(
ins_rec = page_rec_get_next(rec);
next_rec = page_rec_get_next(ins_rec);
- offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
+ offsets = rec_get_offsets(ins_rec, index, offsets,
ULINT_UNDEFINED, &heap);
- ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id);
+ ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id);
if (!page_rec_is_supremum(next_rec)) {
- offsets = rec_get_offsets(next_rec, cursor->index, offsets,
+ offsets = rec_get_offsets(next_rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
- n_bytes, index_id);
+ n_bytes, index->id);
}
if (!page_rec_is_infimum(rec)) {
- offsets = rec_get_offsets(rec, cursor->index, offsets,
+ offsets = rec_get_offsets(rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
- fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
} else {
if (left_side) {
@@ -1663,6 +1678,10 @@ btr_search_update_hash_on_insert(
locked = TRUE;
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
+
ha_insert_for_fold(table, ins_fold, block, ins_rec);
}
@@ -1676,6 +1695,10 @@ btr_search_update_hash_on_insert(
rw_lock_x_lock(&btr_search_latch);
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
if (!left_side) {
@@ -1694,6 +1717,10 @@ check_next_rec:
rw_lock_x_lock(&btr_search_latch);
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
ha_insert_for_fold(table, ins_fold, block, ins_rec);
@@ -1709,6 +1736,10 @@ check_next_rec:
rw_lock_x_lock(&btr_search_latch);
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
if (!left_side) {
@@ -1716,7 +1747,7 @@ check_next_rec:
ha_insert_for_fold(table, ins_fold, block, ins_rec);
/*
fputs("Hash insert for ", stderr);
- dict_index_name_print(stderr, cursor->index);
+ dict_index_name_print(stderr, index);
fprintf(stderr, " fold %lu\n", ins_fold);
*/
} else {
@@ -1820,7 +1851,7 @@ btr_search_validate(void)
+ (block->curr_n_bytes > 0),
&heap);
- if (!block->is_hashed || node->fold
+ if (!block->index || node->fold
!= rec_fold((rec_t*)(node->data),
offsets,
block->curr_n_fields,
@@ -1855,10 +1886,10 @@ btr_search_validate(void)
rec_print_new(stderr, (rec_t*)node->data,
offsets);
fprintf(stderr, "\nInnoDB: on that page."
- " Page mem address %p, is hashed %lu,"
+ " Page mem address %p, is hashed %p,"
" n fields %lu, n bytes %lu\n"
"InnoDB: side %lu\n",
- (void*) page, (ulong) block->is_hashed,
+ (void*) page, (void*) block->index,
(ulong) block->curr_n_fields,
(ulong) block->curr_n_bytes,
(ulong) block->curr_left_side);
diff --git a/storage/innodb_plugin/buf/buf0buddy.c b/storage/innodb_plugin/buf/buf0buddy.c
index 63c99571510..efc4fd46e90 100644
--- a/storage/innodb_plugin/buf/buf0buddy.c
+++ b/storage/innodb_plugin/buf/buf0buddy.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2010, Innobase Oy. 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 the Free Software
@@ -45,6 +45,14 @@ static ulint buf_buddy_n_frames;
Protected by buf_pool_mutex. */
UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
+/** Validate a given zip_free list. */
+#define BUF_BUDDY_LIST_VALIDATE(i) \
+ UT_LIST_VALIDATE(list, buf_page_t, \
+ buf_pool->zip_free[i], \
+ ut_ad(buf_page_get_state( \
+ ut_list_node_313) \
+ == BUF_BLOCK_ZIP_FREE))
+
/**********************************************************************//**
Get the offset of the buddy of a compressed page frame.
@return the buddy relative of page */
@@ -76,21 +84,10 @@ buf_buddy_add_to_free(
buf_page_t* bpage, /*!< in,own: block to be freed */
ulint i) /*!< in: index of buf_pool->zip_free[] */
{
-#ifdef UNIV_DEBUG_VALGRIND
- buf_page_t* b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
-
- if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
-
ut_ad(buf_pool_mutex_own());
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
ut_ad(buf_pool->zip_free[i].start != bpage);
UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
-
-#ifdef UNIV_DEBUG_VALGRIND
- if (b) UNIV_MEM_FREE(b, BUF_BUDDY_LOW << i);
- UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
}
/**********************************************************************//**
@@ -102,25 +99,17 @@ buf_buddy_remove_from_free(
buf_page_t* bpage, /*!< in: block to be removed */
ulint i) /*!< in: index of buf_pool->zip_free[] */
{
-#ifdef UNIV_DEBUG_VALGRIND
+#ifdef UNIV_DEBUG
buf_page_t* prev = UT_LIST_GET_PREV(list, bpage);
buf_page_t* next = UT_LIST_GET_NEXT(list, bpage);
- if (prev) UNIV_MEM_VALID(prev, BUF_BUDDY_LOW << i);
- if (next) UNIV_MEM_VALID(next, BUF_BUDDY_LOW << i);
-
ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE);
ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* UNIV_DEBUG */
ut_ad(buf_pool_mutex_own());
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
-
-#ifdef UNIV_DEBUG_VALGRIND
- if (prev) UNIV_MEM_FREE(prev, BUF_BUDDY_LOW << i);
- if (next) UNIV_MEM_FREE(next, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
}
/**********************************************************************//**
@@ -136,17 +125,13 @@ buf_buddy_alloc_zip(
ut_ad(buf_pool_mutex_own());
ut_a(i < BUF_BUDDY_SIZES);
+ ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
+
+ ut_d(BUF_BUDDY_LIST_VALIDATE(i));
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* !UNIV_DEBUG_VALGRIND */
bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
if (bpage) {
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
buf_buddy_remove_from_free(bpage, i);
@@ -165,13 +150,10 @@ buf_buddy_alloc_zip(
}
}
-#ifdef UNIV_DEBUG
if (bpage) {
- memset(bpage, ~i, BUF_BUDDY_LOW << i);
+ ut_d(memset(bpage, ~i, BUF_BUDDY_LOW << i));
+ UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
}
-#endif /* UNIV_DEBUG */
-
- UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
return(bpage);
}
@@ -255,6 +237,7 @@ buf_buddy_alloc_from(
{
ulint offs = BUF_BUDDY_LOW << j;
ut_ad(j <= BUF_BUDDY_SIZES);
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
ut_ad(j >= i);
ut_ad(!ut_align_offset(buf, offs));
@@ -268,13 +251,7 @@ buf_buddy_alloc_from(
bpage = (buf_page_t*) ((byte*) buf + offs);
ut_d(memset(bpage, j, BUF_BUDDY_LOW << j));
bpage->state = BUF_BLOCK_ZIP_FREE;
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(
- ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* !UNIV_DEBUG_VALGRIND */
+ ut_d(BUF_BUDDY_LIST_VALIDATE(i));
buf_buddy_add_to_free(bpage, j);
}
@@ -284,8 +261,8 @@ 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.
-The buf_pool_mutex may only be released and reacquired if lru != NULL.
-@return allocated block, possibly NULL if lru==NULL */
+The buf_pool_mutex may be released and reacquired.
+@return allocated block, never NULL */
UNIV_INTERN
void*
buf_buddy_alloc_low(
@@ -294,13 +271,14 @@ buf_buddy_alloc_low(
or BUF_BUDDY_SIZES */
ibool* lru) /*!< in: pointer to a variable that will be assigned
TRUE if storage was allocated from the LRU list
- and buf_pool_mutex was temporarily released,
- or NULL if the LRU list should not be used */
+ and buf_pool_mutex was temporarily released */
{
buf_block_t* block;
+ ut_ad(lru);
ut_ad(buf_pool_mutex_own());
ut_ad(!mutex_own(&buf_pool_zip_mutex));
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
if (i < BUF_BUDDY_SIZES) {
/* Try to allocate from the buddy system. */
@@ -320,11 +298,6 @@ buf_buddy_alloc_low(
goto alloc_big;
}
- if (!lru) {
-
- return(NULL);
- }
-
/* Try replacing an uncompressed page in the buffer pool. */
buf_pool_mutex_exit();
block = buf_LRU_get_free_block();
@@ -342,62 +315,6 @@ func_exit:
}
/**********************************************************************//**
-Try to relocate the control block of a compressed page.
-@return TRUE if relocated */
-static
-ibool
-buf_buddy_relocate_block(
-/*=====================*/
- buf_page_t* bpage, /*!< in: block to relocate */
- buf_page_t* dpage) /*!< in: free block to relocate to */
-{
- buf_page_t* b;
-
- ut_ad(buf_pool_mutex_own());
-
- switch (buf_page_get_state(bpage)) {
- case BUF_BLOCK_ZIP_FREE:
- case BUF_BLOCK_NOT_USED:
- case BUF_BLOCK_READY_FOR_USE:
- case BUF_BLOCK_FILE_PAGE:
- case BUF_BLOCK_MEMORY:
- case BUF_BLOCK_REMOVE_HASH:
- ut_error;
- case BUF_BLOCK_ZIP_DIRTY:
- /* Cannot relocate dirty pages. */
- return(FALSE);
-
- case BUF_BLOCK_ZIP_PAGE:
- break;
- }
-
- mutex_enter(&buf_pool_zip_mutex);
-
- if (!buf_page_can_relocate(bpage)) {
- mutex_exit(&buf_pool_zip_mutex);
- return(FALSE);
- }
-
- buf_relocate(bpage, dpage);
- ut_d(bpage->state = BUF_BLOCK_ZIP_FREE);
-
- /* relocate buf_pool->zip_clean */
- b = UT_LIST_GET_PREV(list, dpage);
- UT_LIST_REMOVE(list, buf_pool->zip_clean, dpage);
-
- if (b) {
- UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, dpage);
- } else {
- UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, dpage);
- }
-
- UNIV_MEM_INVALID(bpage, sizeof *bpage);
-
- mutex_exit(&buf_pool_zip_mutex);
- return(TRUE);
-}
-
-/**********************************************************************//**
Try to relocate a block.
@return TRUE if relocated */
static
@@ -410,107 +327,90 @@ buf_buddy_relocate(
{
buf_page_t* bpage;
const ulint size = BUF_BUDDY_LOW << i;
- ullint usec = ut_time_us(NULL);
+ mutex_t* mutex;
+ ulint space;
+ ulint page_no;
ut_ad(buf_pool_mutex_own());
ut_ad(!mutex_own(&buf_pool_zip_mutex));
ut_ad(!ut_align_offset(src, size));
ut_ad(!ut_align_offset(dst, size));
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
UNIV_MEM_ASSERT_W(dst, size);
/* We assume that all memory from buf_buddy_alloc()
- is used for either compressed pages or buf_page_t
- objects covering compressed pages. */
+ is used for compressed page frames. */
/* We look inside the allocated objects returned by
- buf_buddy_alloc() and assume that anything of
- PAGE_ZIP_MIN_SIZE or larger is a compressed page that contains
- a valid space_id and page_no in the page header. Should the
- fields be invalid, we will be unable to relocate the block.
- We also assume that anything that fits sizeof(buf_page_t)
- actually is a properly initialized buf_page_t object. */
-
- if (size >= PAGE_ZIP_MIN_SIZE) {
- /* This is a compressed page. */
- mutex_t* mutex;
-
- /* The src block may be split into smaller blocks,
- some of which may be free. Thus, the
- mach_read_from_4() calls below may attempt to read
- from free memory. The memory is "owned" by the buddy
- allocator (and it has been allocated from the buffer
- pool), so there is nothing wrong about this. The
- mach_read_from_4() calls here will only trigger bogus
- Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
- ulint space = mach_read_from_4(
- (const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- ulint page_no = mach_read_from_4(
- (const byte*) src + FIL_PAGE_OFFSET);
- /* Suppress Valgrind warnings about conditional jump
- on uninitialized value. */
- UNIV_MEM_VALID(&space, sizeof space);
- UNIV_MEM_VALID(&page_no, sizeof page_no);
- bpage = buf_page_hash_get(space, page_no);
-
- if (!bpage || bpage->zip.data != src) {
- /* The block has probably been freshly
- allocated by buf_LRU_get_free_block() but not
- added to buf_pool->page_hash yet. Obviously,
- it cannot be relocated. */
-
- return(FALSE);
- }
+ buf_buddy_alloc() and assume that each block is a compressed
+ page that contains a valid space_id and page_no in the page
+ header. Should the fields be invalid, we will be unable to
+ relocate the block. */
+
+ /* The src block may be split into smaller blocks,
+ some of which may be free. Thus, the
+ mach_read_from_4() calls below may attempt to read
+ from free memory. The memory is "owned" by the buddy
+ allocator (and it has been allocated from the buffer
+ pool), so there is nothing wrong about this. The
+ mach_read_from_4() calls here will only trigger bogus
+ Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
+ space = mach_read_from_4((const byte *) src
+ + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+ page_no = mach_read_from_4((const byte *) src
+ + FIL_PAGE_OFFSET);
+ /* Suppress Valgrind warnings about conditional jump
+ on uninitialized value. */
+ UNIV_MEM_VALID(&space, sizeof space);
+ UNIV_MEM_VALID(&page_no, sizeof page_no);
+ bpage = buf_page_hash_get(space, page_no);
+
+ if (!bpage || bpage->zip.data != src) {
+ /* The block has probably been freshly
+ allocated by buf_LRU_get_free_block() but not
+ added to buf_pool->page_hash yet. Obviously,
+ it cannot be relocated. */
- if (page_zip_get_size(&bpage->zip) != size) {
- /* The block is of different size. We would
- have to relocate all blocks covered by src.
- For the sake of simplicity, give up. */
- ut_ad(page_zip_get_size(&bpage->zip) < size);
+ return(FALSE);
+ }
- return(FALSE);
- }
+ if (page_zip_get_size(&bpage->zip) != size) {
+ /* The block is of different size. We would
+ have to relocate all blocks covered by src.
+ For the sake of simplicity, give up. */
+ ut_ad(page_zip_get_size(&bpage->zip) < size);
- /* The block must have been allocated, but it may
- contain uninitialized data. */
- UNIV_MEM_ASSERT_W(src, size);
-
- mutex = buf_page_get_mutex(bpage);
-
- mutex_enter(mutex);
-
- if (buf_page_can_relocate(bpage)) {
- /* Relocate the compressed page. */
- ut_a(bpage->zip.data == src);
- memcpy(dst, src, size);
- bpage->zip.data = dst;
- mutex_exit(mutex);
-success:
- UNIV_MEM_INVALID(src, size);
- {
- buf_buddy_stat_t* buddy_stat
- = &buf_buddy_stat[i];
- buddy_stat->relocated++;
- buddy_stat->relocated_usec
- += ut_time_us(NULL) - usec;
- }
- return(TRUE);
- }
+ return(FALSE);
+ }
- mutex_exit(mutex);
- } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
- /* This must be a buf_page_t object. */
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in
- buf_page_t. On other systems, Valgrind could complain
- about uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(src, size);
-#endif
- if (buf_buddy_relocate_block(src, dst)) {
+ /* The block must have been allocated, but it may
+ contain uninitialized data. */
+ UNIV_MEM_ASSERT_W(src, size);
+
+ mutex = buf_page_get_mutex(bpage);
+
+ mutex_enter(mutex);
- goto success;
+ if (buf_page_can_relocate(bpage)) {
+ /* Relocate the compressed page. */
+ ullint usec = ut_time_us(NULL);
+ ut_a(bpage->zip.data == src);
+ memcpy(dst, src, size);
+ bpage->zip.data = dst;
+ mutex_exit(mutex);
+ UNIV_MEM_INVALID(src, size);
+ {
+ buf_buddy_stat_t* buddy_stat
+ = &buf_buddy_stat[i];
+ buddy_stat->relocated++;
+ buddy_stat->relocated_usec
+ += ut_time_us(NULL) - usec;
}
+ return(TRUE);
}
+ mutex_exit(mutex);
+
return(FALSE);
}
@@ -531,12 +431,14 @@ buf_buddy_free_low(
ut_ad(buf_pool_mutex_own());
ut_ad(!mutex_own(&buf_pool_zip_mutex));
ut_ad(i <= BUF_BUDDY_SIZES);
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
ut_ad(buf_buddy_stat[i].used > 0);
buf_buddy_stat[i].used--;
+
recombine:
UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
- ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
+ ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE;
if (i == BUF_BUDDY_SIZES) {
buf_buddy_block_free(buf);
@@ -547,32 +449,36 @@ recombine:
ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
ut_ad(!buf_pool_contains_zip(buf));
- /* Try to combine adjacent blocks. */
+ /* Do not recombine blocks if there are few free blocks.
+ We may waste up to 15360*max_len bytes to free blocks
+ (1024 + 2048 + 4096 + 8192 = 15360) */
+ if (UT_LIST_GET_LEN(buf_pool->zip_free[i]) < 16) {
+ goto func_exit;
+ }
+ /* Try to combine adjacent blocks. */
buddy = (buf_page_t*) buf_buddy_get(((byte*) buf), BUF_BUDDY_LOW << i);
#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
+ /* When Valgrind instrumentation is not enabled, we can read
+ buddy->state to quickly determine that a block is not free.
+ When the block is not free, buddy->state belongs to a compressed
+ page frame that may be flagged uninitialized in our Valgrind
+ instrumentation. */
if (buddy->state != BUF_BLOCK_ZIP_FREE) {
goto buddy_nonfree;
}
-
- /* The field buddy->state can only be trusted for free blocks.
- If buddy->state == BUF_BLOCK_ZIP_FREE, the block is free if
- it is in the free list. */
#endif /* !UNIV_DEBUG_VALGRIND */
for (bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); bpage; ) {
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
if (bpage == buddy) {
-buddy_free:
/* The buddy is free: recombine */
buf_buddy_remove_from_free(bpage, i);
-buddy_free2:
+buddy_is_free:
ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
ut_ad(!buf_pool_contains_zip(buddy));
i++;
@@ -582,122 +488,43 @@ buddy_free2:
}
ut_a(bpage != buf);
-
- {
- buf_page_t* next = UT_LIST_GET_NEXT(list, bpage);
- UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
- bpage = next;
- }
+ UNIV_MEM_ASSERT_W(bpage, BUF_BUDDY_LOW << i);
+ bpage = UT_LIST_GET_NEXT(list, bpage);
}
#ifndef UNIV_DEBUG_VALGRIND
buddy_nonfree:
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* !UNIV_DEBUG_VALGRIND */
+
+ ut_d(BUF_BUDDY_LIST_VALIDATE(i));
/* The buddy is not free. Is there a free block of this size? */
bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
if (bpage) {
+
/* Remove the block from the free list, because a successful
buf_buddy_relocate() will overwrite bpage->list. */
-
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
buf_buddy_remove_from_free(bpage, i);
/* Try to relocate the buddy of buf to the free block. */
if (buf_buddy_relocate(buddy, bpage, i)) {
- ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
- goto buddy_free2;
+ buddy->state = BUF_BLOCK_ZIP_FREE;
+ goto buddy_is_free;
}
buf_buddy_add_to_free(bpage, i);
-
- /* Try to relocate the buddy of the free block to buf. */
- buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
- BUF_BUDDY_LOW << i);
-
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
-
- /* The buddy must not be (completely) free, because we
- always recombine adjacent free blocks.
-
- (Parts of the buddy can be free in
- buf_pool->zip_free[j] with j < i.) */
- ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(
- ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE
- && ut_list_node_313 != buddy)));
-#endif /* !UNIV_DEBUG_VALGRIND */
-
- if (buf_buddy_relocate(buddy, buf, i)) {
-
- buf = bpage;
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
- ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
- goto buddy_free;
- }
}
+func_exit:
/* Free the block to the buddy list. */
bpage = buf;
-#ifdef UNIV_DEBUG
- if (i < buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)) {
- /* This area has most likely been allocated for at
- least one compressed-only block descriptor. Check
- that there are no live objects in the area. This is
- not a complete check: it may yield false positives as
- well as false negatives. Also, due to buddy blocks
- being recombined, it is possible (although unlikely)
- that this branch is never reached. */
-
- char* c;
-
-# ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing
- uninitialized memory. Besides, Valgrind performs a
- more exhaustive check, at every memory access. */
- const buf_page_t* b = buf;
- const buf_page_t* const b_end = (buf_page_t*)
- ((char*) b + (BUF_BUDDY_LOW << i));
-
- for (; b < b_end; b++) {
- /* Avoid false positives (and cause false
- negatives) by checking for b->space < 1000. */
-
- if ((b->state == BUF_BLOCK_ZIP_PAGE
- || b->state == BUF_BLOCK_ZIP_DIRTY)
- && b->space > 0 && b->space < 1000) {
- fprintf(stderr,
- "buddy dirty %p %u (%u,%u) %p,%lu\n",
- (void*) b,
- b->state, b->space, b->offset,
- buf, i);
- }
- }
-# endif /* !UNIV_DEBUG_VALGRIND */
-
- /* Scramble the block. This should make any pointers
- invalid and trigger a segmentation violation. Because
- the scrambling can be reversed, it may be possible to
- track down the object pointing to the freed data by
- dereferencing the unscrambled bpage->LRU or
- bpage->list pointers. */
- for (c = (char*) buf + (BUF_BUDDY_LOW << i);
- c-- > (char*) buf; ) {
- *c = ~*c ^ i;
- }
- } else {
- /* Fill large blocks with a constant pattern. */
- memset(bpage, i, BUF_BUDDY_LOW << i);
- }
-#endif /* UNIV_DEBUG */
+
+ /* Fill large blocks with a constant pattern. */
+ ut_d(memset(bpage, i, BUF_BUDDY_LOW << i));
+ UNIV_MEM_INVALID(bpage, BUF_BUDDY_LOW << i);
+
bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_add_to_free(bpage, i);
}
diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
index 14ec7b75911..d88860b807b 100644
--- a/storage/innodb_plugin/buf/buf0buf.c
+++ b/storage/innodb_plugin/buf/buf0buf.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, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -873,72 +873,6 @@ buf_chunk_not_freed(
return(NULL);
}
-/*********************************************************************//**
-Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state.
-@return TRUE if all freed */
-static
-ibool
-buf_chunk_all_free(
-/*===============*/
- const buf_chunk_t* chunk) /*!< in: chunk being checked */
-{
- const buf_block_t* block;
- ulint i;
-
- ut_ad(buf_pool);
- ut_ad(buf_pool_mutex_own());
-
- block = chunk->blocks;
-
- for (i = chunk->size; i--; block++) {
-
- if (buf_block_get_state(block) != BUF_BLOCK_NOT_USED) {
-
- return(FALSE);
- }
- }
-
- return(TRUE);
-}
-
-/********************************************************************//**
-Frees a chunk of buffer frames. */
-static
-void
-buf_chunk_free(
-/*===========*/
- buf_chunk_t* chunk) /*!< out: chunk of buffers */
-{
- buf_block_t* block;
- const buf_block_t* block_end;
-
- ut_ad(buf_pool_mutex_own());
-
- block_end = chunk->blocks + chunk->size;
-
- for (block = chunk->blocks; block < block_end; block++) {
- ut_a(buf_block_get_state(block) == BUF_BLOCK_NOT_USED);
- ut_a(!block->page.zip.data);
-
- ut_ad(!block->page.in_LRU_list);
- ut_ad(!block->in_unzip_LRU_list);
- ut_ad(!block->page.in_flush_list);
- /* Remove the block from the free list. */
- ut_ad(block->page.in_free_list);
- UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
-
- /* Free the latches. */
- mutex_free(&block->mutex);
- rw_lock_free(&block->lock);
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_free(&block->debug_latch);
-#endif /* UNIV_SYNC_DEBUG */
- UNIV_MEM_UNDESC(block);
- }
-
- os_mem_free_large(chunk->mem, chunk->mem_size);
-}
-
/********************************************************************//**
Creates the buffer pool.
@return own: buf_pool object, NULL if not enough memory or error */
@@ -1012,13 +946,29 @@ buf_pool_free(void)
{
buf_chunk_t* chunk;
buf_chunk_t* chunks;
+ buf_page_t* bpage;
+
+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
+ while (bpage != NULL) {
+ buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
+ enum buf_page_state state = buf_page_get_state(bpage);
+
+ ut_ad(buf_page_in_file(bpage));
+ ut_ad(bpage->in_LRU_list);
+
+ if (state != BUF_BLOCK_FILE_PAGE) {
+ /* We must not have any dirty block. */
+ ut_ad(state == BUF_BLOCK_ZIP_PAGE);
+ buf_page_free_descriptor(bpage);
+ }
+
+ bpage = prev_bpage;
+ }
chunks = buf_pool->chunks;
chunk = chunks + buf_pool->n_chunks;
while (--chunk >= chunks) {
- /* Bypass the checks of buf_chunk_free(), since they
- would fail at shutdown. */
os_mem_free_large(chunk->mem, chunk->mem_size);
}
@@ -1030,86 +980,42 @@ buf_pool_free(void)
}
/********************************************************************//**
-Drops the adaptive hash index. To prevent a livelock, this function
-is only to be called while holding btr_search_latch and while
-btr_search_enabled == FALSE. */
+Clears the adaptive hash index on all pages in the buffer pool. */
UNIV_INTERN
void
-buf_pool_drop_hash_index(void)
-/*==========================*/
+buf_pool_clear_hash_index(void)
+/*===========================*/
{
- ibool released_search_latch;
+ buf_chunk_t* chunks = buf_pool->chunks;
+ buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!btr_search_enabled);
- do {
- buf_chunk_t* chunks = buf_pool->chunks;
- buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
-
- released_search_latch = FALSE;
-
- while (--chunk >= chunks) {
- buf_block_t* block = chunk->blocks;
- ulint i = chunk->size;
+ while (--chunk >= chunks) {
+ buf_block_t* block = chunk->blocks;
+ ulint i = chunk->size;
- for (; i--; block++) {
- /* block->is_hashed cannot be modified
- when we have an x-latch on btr_search_latch;
- see the comment in buf0buf.h */
+ for (; i--; block++) {
+ dict_index_t* index = block->index;
- if (buf_block_get_state(block)
- != BUF_BLOCK_FILE_PAGE
- || !block->is_hashed) {
- continue;
- }
+ /* We can set block->index = NULL
+ when we have an x-latch on btr_search_latch;
+ see the comment in buf0buf.h */
- /* To follow the latching order, we
- have to release btr_search_latch
- before acquiring block->latch. */
- rw_lock_x_unlock(&btr_search_latch);
- /* When we release the search latch,
- 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
- allocated for some other use after
- btr_search_latch was released above.
- We do not care which file page the
- 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
- btr_search_drop_page_hash_index() will
- 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);
+ if (!index) {
+ /* Not hashed */
+ continue;
}
+
+ block->index = NULL;
+# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ block->n_pointers = 0;
+# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
}
- } while (released_search_latch);
+ }
}
/********************************************************************//**
@@ -1194,311 +1100,6 @@ buf_relocate(
}
/********************************************************************//**
-Shrinks the buffer pool. */
-static
-void
-buf_pool_shrink(
-/*============*/
- ulint chunk_size) /*!< in: number of pages to remove */
-{
- buf_chunk_t* chunks;
- buf_chunk_t* chunk;
- ulint max_size;
- ulint max_free_size;
- buf_chunk_t* max_chunk;
- buf_chunk_t* max_free_chunk;
-
- ut_ad(!buf_pool_mutex_own());
-
-try_again:
- btr_search_disable(); /* Empty the adaptive hash index again */
- buf_pool_mutex_enter();
-
-shrink_again:
- if (buf_pool->n_chunks <= 1) {
-
- /* Cannot shrink if there is only one chunk */
- goto func_done;
- }
-
- /* Search for the largest free chunk
- not larger than the size difference */
- chunks = buf_pool->chunks;
- chunk = chunks + buf_pool->n_chunks;
- max_size = max_free_size = 0;
- max_chunk = max_free_chunk = NULL;
-
- while (--chunk >= chunks) {
- if (chunk->size <= chunk_size
- && chunk->size > max_free_size) {
- if (chunk->size > max_size) {
- max_size = chunk->size;
- max_chunk = chunk;
- }
-
- if (buf_chunk_all_free(chunk)) {
- max_free_size = chunk->size;
- max_free_chunk = chunk;
- }
- }
- }
-
- if (!max_free_size) {
-
- ulint dirty = 0;
- ulint nonfree = 0;
- buf_block_t* block;
- buf_block_t* bend;
-
- /* Cannot shrink: try again later
- (do not assign srv_buf_pool_old_size) */
- if (!max_chunk) {
-
- goto func_exit;
- }
-
- block = max_chunk->blocks;
- bend = block + max_chunk->size;
-
- /* Move the blocks of chunk to the end of the
- LRU list and try to flush them. */
- for (; block < bend; block++) {
- switch (buf_block_get_state(block)) {
- case BUF_BLOCK_NOT_USED:
- continue;
- case BUF_BLOCK_FILE_PAGE:
- break;
- default:
- nonfree++;
- continue;
- }
-
- mutex_enter(&block->mutex);
- /* The following calls will temporarily
- release block->mutex and buf_pool_mutex.
- Therefore, we have to always retry,
- even if !dirty && !nonfree. */
-
- if (!buf_flush_ready_for_replace(&block->page)) {
-
- buf_LRU_make_block_old(&block->page);
- dirty++;
- } else if (buf_LRU_free_block(&block->page, TRUE)
- != BUF_LRU_FREED) {
- nonfree++;
- }
-
- mutex_exit(&block->mutex);
- }
-
- buf_pool_mutex_exit();
-
- /* Request for a flush of the chunk if it helps.
- Do not flush if there are non-free blocks, since
- flushing will not make the chunk freeable. */
- if (nonfree) {
- /* Avoid busy-waiting. */
- os_thread_sleep(100000);
- } else if (dirty
- && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
- == ULINT_UNDEFINED) {
-
- buf_flush_wait_batch_end(BUF_FLUSH_LRU);
- }
-
- goto try_again;
- }
-
- max_size = max_free_size;
- max_chunk = max_free_chunk;
-
- srv_buf_pool_old_size = srv_buf_pool_size;
-
- /* Rewrite buf_pool->chunks. Copy everything but max_chunk. */
- chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
- memcpy(chunks, buf_pool->chunks,
- (max_chunk - buf_pool->chunks) * sizeof *chunks);
- memcpy(chunks + (max_chunk - buf_pool->chunks),
- max_chunk + 1,
- buf_pool->chunks + buf_pool->n_chunks
- - (max_chunk + 1));
- ut_a(buf_pool->curr_size > max_chunk->size);
- buf_pool->curr_size -= max_chunk->size;
- srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
- chunk_size -= max_chunk->size;
- buf_chunk_free(max_chunk);
- mem_free(buf_pool->chunks);
- buf_pool->chunks = chunks;
- buf_pool->n_chunks--;
-
- /* Allow a slack of one megabyte. */
- if (chunk_size > 1048576 / UNIV_PAGE_SIZE) {
-
- goto shrink_again;
- }
-
-func_done:
- srv_buf_pool_old_size = srv_buf_pool_size;
-func_exit:
- buf_pool_mutex_exit();
- btr_search_enable();
-}
-
-/********************************************************************//**
-Rebuild buf_pool->page_hash. */
-static
-void
-buf_pool_page_hash_rebuild(void)
-/*============================*/
-{
- ulint i;
- ulint n_chunks;
- buf_chunk_t* chunk;
- hash_table_t* page_hash;
- hash_table_t* zip_hash;
- buf_page_t* b;
-
- buf_pool_mutex_enter();
-
- /* Free, create, and populate the hash table. */
- hash_table_free(buf_pool->page_hash);
- buf_pool->page_hash = page_hash = hash_create(2 * buf_pool->curr_size);
- zip_hash = hash_create(2 * buf_pool->curr_size);
-
- HASH_MIGRATE(buf_pool->zip_hash, zip_hash, buf_page_t, hash,
- BUF_POOL_ZIP_FOLD_BPAGE);
-
- hash_table_free(buf_pool->zip_hash);
- buf_pool->zip_hash = zip_hash;
-
- /* Insert the uncompressed file pages to buf_pool->page_hash. */
-
- chunk = buf_pool->chunks;
- n_chunks = buf_pool->n_chunks;
-
- for (i = 0; i < n_chunks; i++, chunk++) {
- ulint j;
- buf_block_t* block = chunk->blocks;
-
- for (j = 0; j < chunk->size; j++, block++) {
- if (buf_block_get_state(block)
- == BUF_BLOCK_FILE_PAGE) {
- ut_ad(!block->page.in_zip_hash);
- ut_ad(block->page.in_page_hash);
-
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(
- block->page.space,
- block->page.offset),
- &block->page);
- }
- }
- }
-
- /* Insert the compressed-only pages to buf_pool->page_hash.
- All such blocks are either in buf_pool->zip_clean or
- in buf_pool->flush_list. */
-
- for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
- b = UT_LIST_GET_NEXT(list, b)) {
- ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
- ut_ad(!b->in_flush_list);
- ut_ad(b->in_LRU_list);
- ut_ad(b->in_page_hash);
- ut_ad(!b->in_zip_hash);
-
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(b->space, b->offset), b);
- }
-
- for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
- b = UT_LIST_GET_NEXT(list, b)) {
- ut_ad(b->in_flush_list);
- ut_ad(b->in_LRU_list);
- ut_ad(b->in_page_hash);
- ut_ad(!b->in_zip_hash);
-
- switch (buf_page_get_state(b)) {
- case BUF_BLOCK_ZIP_DIRTY:
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(b->space,
- b->offset), b);
- break;
- case BUF_BLOCK_FILE_PAGE:
- /* uncompressed page */
- break;
- case BUF_BLOCK_ZIP_FREE:
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_NOT_USED:
- case BUF_BLOCK_READY_FOR_USE:
- case BUF_BLOCK_MEMORY:
- case BUF_BLOCK_REMOVE_HASH:
- ut_error;
- break;
- }
- }
-
- buf_pool_mutex_exit();
-}
-
-/********************************************************************//**
-Resizes the buffer pool. */
-UNIV_INTERN
-void
-buf_pool_resize(void)
-/*=================*/
-{
- buf_pool_mutex_enter();
-
- if (srv_buf_pool_old_size == srv_buf_pool_size) {
-
- buf_pool_mutex_exit();
- return;
- }
-
- if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
-
- buf_pool_mutex_exit();
-
- /* Disable adaptive hash indexes and empty the index
- in order to free up memory in the buffer pool chunks. */
- buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
- / UNIV_PAGE_SIZE);
- } else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
-
- /* Enlarge the buffer pool by at least one megabyte */
-
- ulint mem_size
- = srv_buf_pool_size - srv_buf_pool_curr_size;
- buf_chunk_t* chunks;
- buf_chunk_t* chunk;
-
- chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
-
- memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
- * sizeof *chunks);
-
- chunk = &chunks[buf_pool->n_chunks];
-
- if (!buf_chunk_init(chunk, mem_size)) {
- mem_free(chunks);
- } else {
- buf_pool->curr_size += chunk->size;
- srv_buf_pool_curr_size = buf_pool->curr_size
- * UNIV_PAGE_SIZE;
- mem_free(buf_pool->chunks);
- buf_pool->chunks = chunks;
- buf_pool->n_chunks++;
- }
-
- srv_buf_pool_old_size = srv_buf_pool_size;
- buf_pool_mutex_exit();
- }
-
- buf_pool_page_hash_rebuild();
-}
-
-/********************************************************************//**
Moves a page to the start of the buffer pool LRU list. This high-level
function can be used to prevent an important page from slipping out of
the buffer pool. */
@@ -1547,59 +1148,6 @@ buf_page_set_accessed_make_young(
}
}
-/********************************************************************//**
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-UNIV_INTERN
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /*!< in: space id */
- ulint offset) /*!< in: page number */
-{
- buf_block_t* block;
-
- buf_pool_mutex_enter();
-
- block = (buf_block_t*) buf_page_hash_get(space, offset);
-
- if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
- block->check_index_page_at_flush = FALSE;
- }
-
- buf_pool_mutex_exit();
-}
-
-/********************************************************************//**
-Returns the current state of is_hashed of a page. FALSE if the page is
-not in the pool. NOTE that this operation does not fix the page in the
-pool if it is found there.
-@return TRUE if page hash index is built in search system */
-UNIV_INTERN
-ibool
-buf_page_peek_if_search_hashed(
-/*===========================*/
- ulint space, /*!< in: space id */
- ulint offset) /*!< in: page number */
-{
- buf_block_t* block;
- ibool is_hashed;
-
- buf_pool_mutex_enter();
-
- block = (buf_block_t*) buf_page_hash_get(space, offset);
-
- if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
- is_hashed = FALSE;
- } else {
- is_hashed = block->is_hashed;
- }
-
- buf_pool_mutex_exit();
-
- return(is_hashed);
-}
-
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
@@ -1731,7 +1279,7 @@ err_exit:
mutex_enter(block_mutex);
/* Discard the uncompressed page frame if possible. */
- if (buf_LRU_free_block(bpage, FALSE) == BUF_LRU_FREED) {
+ if (buf_LRU_free_block(bpage, FALSE)) {
mutex_exit(block_mutex);
goto lookup;
@@ -1804,7 +1352,6 @@ buf_block_init_low(
block->index = NULL;
block->n_hash_helps = 0;
- block->is_hashed = FALSE;
block->n_fields = 1;
block->n_bytes = 0;
block->left_side = TRUE;
@@ -2072,13 +1619,8 @@ loop:
if (block) {
/* If the guess is a compressed page descriptor that
- has been allocated by buf_buddy_alloc(), it may have
- been invalidated by buf_buddy_relocate(). In that
- case, block could point to something that happens to
- contain the expected bits in block->page. Similarly,
- the guess may be pointing to a buffer pool chunk that
- has been released when resizing the buffer pool. */
-
+ has been allocated by buf_page_alloc_descriptor(),
+ it may have been freed by buf_relocate(). */
if (!buf_block_is_uncompressed(block)
|| offset != block->page.offset
|| space != block->page.space
@@ -2233,8 +1775,10 @@ wait_until_unfixed:
if (buf_page_get_state(&block->page)
== BUF_BLOCK_ZIP_PAGE) {
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(list, buf_pool->zip_clean,
&block->page);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
ut_ad(!block->page.in_flush_list);
} else {
/* Relocate buf_pool->flush_list. */
@@ -2260,11 +1804,10 @@ wait_until_unfixed:
mutex_exit(&buf_pool_zip_mutex);
buf_pool->n_pend_unzip++;
- bpage->state = BUF_BLOCK_ZIP_FREE;
- buf_buddy_free(bpage, sizeof *bpage);
-
buf_pool_mutex_exit();
+ buf_page_free_descriptor(bpage);
+
/* Decompress the page and apply buffered operations
while not holding buf_pool_mutex or block->mutex. */
success = buf_zip_decompress(block, srv_use_checksums);
@@ -2308,7 +1851,7 @@ wait_until_unfixed:
/* Try to evict the block from the buffer pool, to use the
insert buffer as much as possible. */
- if (buf_LRU_free_block(&block->page, TRUE) == BUF_LRU_FREED) {
+ if (buf_LRU_free_block(&block->page, TRUE)) {
buf_pool_mutex_exit();
mutex_exit(&block->mutex);
fprintf(stderr,
@@ -2922,17 +2465,12 @@ err_exit:
mutex_exit(&block->mutex);
} else {
- /* Defer buf_buddy_alloc() until after the block has
- been found not to exist. The buf_buddy_alloc() and
- buf_buddy_free() calls may be expensive because of
- buf_buddy_relocate(). */
/* The compressed page must be allocated before the
control block (bpage), in order to avoid the
invocation of buf_buddy_relocate_block() on
uninitialized data. */
data = buf_buddy_alloc(zip_size, &lru);
- bpage = buf_buddy_alloc(sizeof *bpage, &lru);
/* If buf_buddy_alloc() allocated storage from the LRU list,
it released and reacquired buf_pool_mutex. Thus, we must
@@ -2940,15 +2478,13 @@ err_exit:
if (UNIV_UNLIKELY(lru)
&& UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
- /* The block was added by some other thread. */
- bpage->state = BUF_BLOCK_ZIP_FREE;
- buf_buddy_free(bpage, sizeof *bpage);
buf_buddy_free(data, zip_size);
-
bpage = NULL;
goto func_exit;
}
+ bpage = buf_page_alloc_descriptor();
+
page_zip_des_init(&bpage->zip);
page_zip_set_size(&bpage->zip, zip_size);
bpage->zip.data = data;
@@ -2975,7 +2511,9 @@ err_exit:
/* The block must be put to the LRU list, to the old blocks */
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
buf_LRU_insert_zip_clean(bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
buf_page_set_io_fix(bpage, BUF_IO_READ);
@@ -3972,12 +3510,16 @@ buf_print_io(
/* Statistics about read ahead algorithm */
fprintf(file, "Pages read ahead %.2f/s,"
- " evicted without access %.2f/s\n",
+ " evicted without access %.2f/s,"
+ " Random read ahead %.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,
+ (buf_pool->stat.n_ra_pages_read_rnd
+ - buf_pool->old_stat.n_ra_pages_read_rnd)
/ time_elapsed);
/* Print some values to help us with visualizing what is
diff --git a/storage/innodb_plugin/buf/buf0flu.c b/storage/innodb_plugin/buf/buf0flu.c
index 3a9975ce4b7..60cf8d58bc7 100644
--- a/storage/innodb_plugin/buf/buf0flu.c
+++ b/storage/innodb_plugin/buf/buf0flu.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.
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
@@ -435,7 +435,9 @@ buf_flush_remove(
case BUF_BLOCK_ZIP_DIRTY:
buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE);
UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
buf_LRU_insert_zip_clean(bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
break;
case BUF_BLOCK_FILE_PAGE:
UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
diff --git a/storage/innodb_plugin/buf/buf0lru.c b/storage/innodb_plugin/buf/buf0lru.c
index a69b2658c51..5124787eba1 100644
--- a/storage/innodb_plugin/buf/buf0lru.c
+++ b/storage/innodb_plugin/buf/buf0lru.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.
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
@@ -272,7 +272,7 @@ next_page:
mutex_enter(&((buf_block_t*) bpage)->mutex);
is_fixed = bpage->buf_fix_count > 0
- || !((buf_block_t*) bpage)->is_hashed;
+ || !((buf_block_t*) bpage)->index;
mutex_exit(&((buf_block_t*) bpage)->mutex);
if (is_fixed) {
@@ -355,7 +355,7 @@ scan_again:
while (bpage != NULL) {
buf_page_t* prev_bpage;
- ibool prev_bpage_buf_fix = FALSE;
+ mutex_t* block_mutex = NULL;
ut_a(buf_page_in_file(bpage));
@@ -368,18 +368,21 @@ scan_again:
if (buf_page_get_space(bpage) != id) {
/* Skip this block, as it does not belong to
the space that is being invalidated. */
+ goto next_page;
} else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
/* We cannot remove this page during this scan
yet; maybe the system is currently reading it
in, or flushing the modifications to the file */
all_freed = FALSE;
+ goto next_page;
} else {
- mutex_t* block_mutex = buf_page_get_mutex(bpage);
+ block_mutex = buf_page_get_mutex(bpage);
mutex_enter(block_mutex);
if (bpage->buf_fix_count > 0) {
+ mutex_exit(block_mutex);
/* We cannot remove this page during
this scan yet; maybe the system is
currently reading it in, or flushing
@@ -389,106 +392,59 @@ scan_again:
goto next_page;
}
+ }
+
+ ut_ad(mutex_own(block_mutex));
#ifdef UNIV_DEBUG
- if (buf_debug_prints) {
- fprintf(stderr,
- "Dropping space %lu page %lu\n",
- (ulong) buf_page_get_space(bpage),
- (ulong) buf_page_get_page_no(bpage));
- }
+ if (buf_debug_prints) {
+ fprintf(stderr,
+ "Dropping space %lu page %lu\n",
+ (ulong) buf_page_get_space(bpage),
+ (ulong) buf_page_get_page_no(bpage));
+ }
#endif
- if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
- /* This is a compressed-only block
- descriptor. Ensure that prev_bpage
- cannot be relocated when bpage is freed. */
- if (UNIV_LIKELY(prev_bpage != NULL)) {
- switch (buf_page_get_state(
- prev_bpage)) {
- case BUF_BLOCK_FILE_PAGE:
- /* Descriptors of uncompressed
- blocks will not be relocated,
- because we are holding the
- buf_pool_mutex. */
- break;
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_ZIP_DIRTY:
- /* Descriptors of compressed-
- only blocks can be relocated,
- unless they are buffer-fixed.
- Because both bpage and
- prev_bpage are protected by
- buf_pool_zip_mutex, it is
- not necessary to acquire
- further mutexes. */
- ut_ad(&buf_pool_zip_mutex
- == block_mutex);
- ut_ad(mutex_own(block_mutex));
- prev_bpage_buf_fix = TRUE;
- prev_bpage->buf_fix_count++;
- break;
- default:
- ut_error;
- }
- }
- } else if (((buf_block_t*) bpage)->is_hashed) {
- ulint page_no;
- ulint zip_size;
+ if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
+ /* This is a compressed-only block
+ descriptor. Do nothing. */
+ } else if (((buf_block_t*) bpage)->index) {
+ ulint page_no;
+ ulint zip_size;
- buf_pool_mutex_exit();
+ buf_pool_mutex_exit();
- zip_size = buf_page_get_zip_size(bpage);
- page_no = buf_page_get_page_no(bpage);
+ zip_size = buf_page_get_zip_size(bpage);
+ page_no = buf_page_get_page_no(bpage);
- mutex_exit(block_mutex);
+ mutex_exit(block_mutex);
- /* Note that the following call will acquire
- an S-latch on the page */
+ /* Note that the following call will acquire
+ and release an X-latch on the page. */
- btr_search_drop_page_hash_when_freed(
- id, zip_size, page_no);
- goto scan_again;
- }
-
- if (bpage->oldest_modification != 0) {
+ btr_search_drop_page_hash_when_freed(
+ id, zip_size, page_no);
+ goto scan_again;
+ }
- buf_flush_remove(bpage);
- }
+ if (bpage->oldest_modification != 0) {
- /* Remove from the LRU list. */
+ buf_flush_remove(bpage);
+ }
- if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
- != BUF_BLOCK_ZIP_FREE) {
- buf_LRU_block_free_hashed_page((buf_block_t*)
- bpage);
- } else {
- /* The block_mutex should have been
- released by buf_LRU_block_remove_hashed_page()
- when it returns BUF_BLOCK_ZIP_FREE. */
- ut_ad(block_mutex == &buf_pool_zip_mutex);
- ut_ad(!mutex_own(block_mutex));
-
- if (prev_bpage_buf_fix) {
- /* We temporarily buffer-fixed
- prev_bpage, so that
- buf_buddy_free() could not
- relocate it, in case it was a
- compressed-only block
- descriptor. */
-
- mutex_enter(block_mutex);
- ut_ad(prev_bpage->buf_fix_count > 0);
- prev_bpage->buf_fix_count--;
- mutex_exit(block_mutex);
- }
+ /* Remove from the LRU list. */
- goto next_page_no_mutex;
- }
-next_page:
+ if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
+ != BUF_BLOCK_ZIP_FREE) {
+ buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
mutex_exit(block_mutex);
+ } else {
+ /* The block_mutex should have been released
+ by buf_LRU_block_remove_hashed_page() when it
+ returns BUF_BLOCK_ZIP_FREE. */
+ ut_ad(block_mutex == &buf_pool_zip_mutex);
+ ut_ad(!mutex_own(block_mutex));
}
-
-next_page_no_mutex:
+next_page:
bpage = prev_bpage;
}
@@ -501,6 +457,7 @@ next_page_no_mutex:
}
}
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/********************************************************************//**
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
UNIV_INTERN
@@ -532,6 +489,7 @@ buf_LRU_insert_zip_clean(
UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, bpage);
}
}
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//**
Try to free an uncompressed page of a compressed block from the unzip
@@ -572,7 +530,7 @@ buf_LRU_free_from_unzip_LRU_list(
UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
- enum buf_lru_free_block_status freed;
+ ibool freed;
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(block->in_unzip_LRU_list);
@@ -582,24 +540,9 @@ buf_LRU_free_from_unzip_LRU_list(
freed = buf_LRU_free_block(&block->page, FALSE);
mutex_exit(&block->mutex);
- switch (freed) {
- case BUF_LRU_FREED:
+ if (freed) {
return(TRUE);
-
- case BUF_LRU_CANNOT_RELOCATE:
- /* If we failed to relocate, try
- regular LRU eviction. */
- return(FALSE);
-
- case BUF_LRU_NOT_FREED:
- /* The block was buffer-fixed or I/O-fixed.
- Keep looking. */
- continue;
}
-
- /* inappropriate return value from
- buf_LRU_free_block() */
- ut_error;
}
return(FALSE);
@@ -630,10 +573,9 @@ buf_LRU_free_from_common_LRU_list(
UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
- enum buf_lru_free_block_status freed;
- unsigned accessed;
- mutex_t* block_mutex
- = buf_page_get_mutex(bpage);
+ ibool freed;
+ unsigned accessed;
+ mutex_t* block_mutex = buf_page_get_mutex(bpage);
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
@@ -643,8 +585,7 @@ buf_LRU_free_from_common_LRU_list(
freed = buf_LRU_free_block(bpage, TRUE);
mutex_exit(block_mutex);
- switch (freed) {
- case BUF_LRU_FREED:
+ if (freed) {
/* Keep track of pages that are evicted without
ever being accessed. This gives us a measure of
the effectiveness of readahead */
@@ -652,21 +593,7 @@ buf_LRU_free_from_common_LRU_list(
++buf_pool->stat.n_ra_pages_evicted;
}
return(TRUE);
-
- case BUF_LRU_NOT_FREED:
- /* The block was dirty, buffer-fixed, or I/O-fixed.
- Keep looking. */
- continue;
-
- case BUF_LRU_CANNOT_RELOCATE:
- /* This should never occur, because we
- want to discard the compressed page too. */
- break;
}
-
- /* inappropriate return value from
- buf_LRU_free_block() */
- ut_error;
}
return(FALSE);
@@ -1348,17 +1275,16 @@ buf_LRU_make_block_old(
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
+NOTE: If this function returns TRUE, it will temporarily
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
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
-BUF_LRU_NOT_FREED otherwise. */
+@return TRUE if freed, FALSE otherwise. */
UNIV_INTERN
-enum buf_lru_free_block_status
+ibool
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
@@ -1383,7 +1309,7 @@ buf_LRU_free_block(
if (!buf_page_can_relocate(bpage)) {
/* Do not free buffer-fixed or I/O-fixed blocks. */
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
#ifdef UNIV_IBUF_COUNT_DEBUG
@@ -1395,7 +1321,7 @@ buf_LRU_free_block(
/* Do not completely free dirty blocks. */
if (bpage->oldest_modification) {
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
} else if (bpage->oldest_modification) {
/* Do not completely free dirty blocks. */
@@ -1403,7 +1329,7 @@ buf_LRU_free_block(
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
ut_ad(buf_page_get_state(bpage)
== BUF_BLOCK_ZIP_DIRTY);
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
goto alloc;
@@ -1412,14 +1338,8 @@ buf_LRU_free_block(
If it cannot be allocated (without freeing a block
from the LRU list), refuse to free bpage. */
alloc:
- buf_pool_mutex_exit_forbid();
- b = buf_buddy_alloc(sizeof *b, NULL);
- buf_pool_mutex_exit_allow();
-
- if (UNIV_UNLIKELY(!b)) {
- return(BUF_LRU_CANNOT_RELOCATE);
- }
-
+ b = buf_page_alloc_descriptor();
+ ut_a(b);
memcpy(b, bpage, sizeof *b);
}
@@ -1518,7 +1438,9 @@ alloc:
}
if (b->state == BUF_BLOCK_ZIP_PAGE) {
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
buf_LRU_insert_zip_clean(b);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
} else {
/* Relocate on buf_pool->flush_list. */
buf_flush_relocate_on_flush_list(bpage, b);
@@ -1585,7 +1507,7 @@ alloc:
mutex_enter(block_mutex);
}
- return(BUF_LRU_FREED);
+ return(TRUE);
}
/******************************************************************//**
@@ -1797,16 +1719,16 @@ buf_LRU_block_remove_hashed_page(
ut_a(bpage->zip.data);
ut_a(buf_page_get_zip_size(bpage));
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
mutex_exit(&buf_pool_zip_mutex);
buf_pool_mutex_exit_forbid();
buf_buddy_free(bpage->zip.data,
page_zip_get_size(&bpage->zip));
- bpage->state = BUF_BLOCK_ZIP_FREE;
- buf_buddy_free(bpage, sizeof(*bpage));
buf_pool_mutex_exit_allow();
- UNIV_MEM_UNDESC(bpage);
+ buf_page_free_descriptor(bpage);
return(BUF_BLOCK_ZIP_FREE);
case BUF_BLOCK_FILE_PAGE:
diff --git a/storage/innodb_plugin/buf/buf0rea.c b/storage/innodb_plugin/buf/buf0rea.c
index 81f788baac2..0b36eeb5cd3 100644
--- a/storage/innodb_plugin/buf/buf0rea.c
+++ b/storage/innodb_plugin/buf/buf0rea.c
@@ -38,6 +38,14 @@ Created 11/5/1995 Heikki Tuuri
#include "srv0start.h"
#include "srv0srv.h"
+/** The size in blocks of the area where the random read-ahead algorithm counts
+the accessed pages when deciding whether to read-ahead */
+#define BUF_READ_AHEAD_RANDOM_AREA BUF_READ_AHEAD_AREA
+
+/** There must be at least this many pages in buf_pool in the area to start
+a random read-ahead */
+#define BUF_READ_AHEAD_RANDOM_THRESHOLD (5 + BUF_READ_AHEAD_RANDOM_AREA / 8)
+
/** The linear read-ahead area size */
#define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA
@@ -158,6 +166,165 @@ buf_read_page_low(
}
/********************************************************************//**
+Applies a random read-ahead in buf_pool if there are at least a threshold
+value of accessed pages from the random read-ahead area. Does not read any
+page, not even the one at the position (space, offset), if the read-ahead
+mechanism is not activated. NOTE 1: the calling thread may own latches on
+pages: to avoid deadlocks this function must be written such that it cannot
+end up waiting for these latches! NOTE 2: the calling thread must want
+access to the page given: this rule is set to prevent unintended read-aheads
+performed by ibuf routines, a situation which could result in a deadlock if
+the OS does not support asynchronous i/o.
+@return number of page read requests issued; NOTE that if we read ibuf
+pages, it may happen that the page at the given page number does not
+get read even if we return a positive value! */
+static
+ulint
+buf_read_ahead_random(
+/*==================*/
+ ulint space, /*!< in: space id */
+ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
+ ulint offset) /*!< in: page number of a page which the current thread
+ wants to access */
+{
+ ib_int64_t tablespace_version;
+ ulint recent_blocks = 0;
+ ulint count;
+ ulint ibuf_mode;
+ ulint low, high;
+ ulint err;
+ ulint i;
+ ulint buf_read_ahead_random_area;
+
+ if (!srv_random_read_ahead) {
+ /* Disabled by user */
+ return(0);
+ }
+
+ if (srv_startup_is_before_trx_rollback_phase) {
+ /* No read-ahead to avoid thread deadlocks */
+ return(0);
+ }
+
+ if (ibuf_bitmap_page(zip_size, offset)
+ || trx_sys_hdr_page(space, offset)) {
+
+ /* If it is an ibuf bitmap page or trx sys hdr, we do
+ no read-ahead, as that could break the ibuf page access
+ order */
+
+ return(0);
+ }
+
+ /* Remember the tablespace version before we ask the tablespace size
+ below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
+ do not try to read outside the bounds of the tablespace! */
+
+ tablespace_version = fil_space_get_version(space);
+
+ buf_read_ahead_random_area = BUF_READ_AHEAD_RANDOM_AREA;
+
+ low = (offset / buf_read_ahead_random_area)
+ * buf_read_ahead_random_area;
+ high = (offset / buf_read_ahead_random_area + 1)
+ * buf_read_ahead_random_area;
+ if (high > fil_space_get_size(space)) {
+
+ high = fil_space_get_size(space);
+ }
+
+ buf_pool_mutex_enter();
+
+ if (buf_pool->n_pend_reads
+ > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
+ buf_pool_mutex_exit();
+
+ return(0);
+ }
+
+ /* Count how many blocks in the area have been recently accessed,
+ that is, reside near the start of the LRU list. */
+
+ for (i = low; i < high; i++) {
+ const buf_page_t* bpage = buf_page_hash_get(space, i);
+
+ if (bpage
+ && buf_page_is_accessed(bpage)
+ && buf_page_peek_if_young(bpage)) {
+
+ recent_blocks++;
+
+ if (recent_blocks >= BUF_READ_AHEAD_RANDOM_THRESHOLD) {
+
+ buf_pool_mutex_exit();
+ goto read_ahead;
+ }
+ }
+ }
+
+ buf_pool_mutex_exit();
+ /* Do nothing */
+ return(0);
+
+read_ahead:
+ /* Read all the suitable blocks within the area */
+
+ if (ibuf_inside()) {
+ ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
+ } else {
+ ibuf_mode = BUF_READ_ANY_PAGE;
+ }
+
+ count = 0;
+
+ for (i = low; i < high; i++) {
+ /* It is only sensible to do read-ahead in the non-sync aio
+ mode: hence FALSE as the first parameter */
+
+ if (!ibuf_bitmap_page(zip_size, i)) {
+ count += buf_read_page_low(
+ &err, FALSE,
+ ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
+ space, zip_size, FALSE,
+ tablespace_version, i);
+ if (err == DB_TABLESPACE_DELETED) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Warning: in random"
+ " readahead trying to access\n"
+ "InnoDB: tablespace %lu page %lu,\n"
+ "InnoDB: but the tablespace does not"
+ " exist or is just being dropped.\n",
+ (ulong) space, (ulong) i);
+ }
+ }
+ }
+
+ /* In simulated aio we wake the aio handler threads only after
+ queuing all aio requests, in native aio the following call does
+ nothing: */
+
+ os_aio_simulated_wake_handler_threads();
+
+#ifdef UNIV_DEBUG
+ if (buf_debug_prints && (count > 0)) {
+ fprintf(stderr,
+ "Random read-ahead space %lu offset %lu pages %lu\n",
+ (ulong) space, (ulong) offset,
+ (ulong) count);
+ }
+#endif /* UNIV_DEBUG */
+
+ /* Read ahead is considered one I/O operation for the purpose of
+ LRU policy decision. */
+ buf_LRU_stat_inc_io();
+
+ buf_pool->stat.n_ra_pages_read_rnd += count;
+ return(count);
+}
+
+
+/********************************************************************//**
High-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
@@ -175,6 +342,9 @@ buf_read_page(
ulint count;
ulint err;
+ count = buf_read_ahead_random(space, zip_size, offset);
+ srv_buf_pool_reads += count;
+
tablespace_version = fil_space_get_version(space);
/* We do the i/o in the synchronous aio mode to save thread
diff --git a/storage/innodb_plugin/dict/dict0crea.c b/storage/innodb_plugin/dict/dict0crea.c
index 7d6cbc8c1c8..a57b2eca9e2 100644
--- a/storage/innodb_plugin/dict/dict0crea.c
+++ b/storage/innodb_plugin/dict/dict0crea.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
@@ -828,7 +828,7 @@ dict_truncate_index_tree(
appropriate field in the SYS_INDEXES record: this mini-transaction
marks the B-tree totally truncated */
- btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, mtr);
btr_free_root(space, zip_size, root_page_no, mtr);
create:
diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index a8787bbda61..2d2262acf87 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/dict/dict0dict.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
@@ -1661,7 +1661,9 @@ undo_size_ok:
new_index->stat_n_leaf_pages = 1;
new_index->page = page_no;
- rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
+ rw_lock_create(&new_index->lock,
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
diff --git a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c
index c3825902536..7a0b6edcb08 100644
--- a/storage/innodb_plugin/dict/dict0load.c
+++ b/storage/innodb_plugin/dict/dict0load.c
@@ -553,9 +553,10 @@ dict_load_columns(
}
/********************************************************************//**
-Loads definitions for index fields. */
+Loads definitions for index fields.
+@return DB_SUCCESS if ok, DB_CORRUPTION if failed */
static
-void
+ulint
dict_load_fields(
/*=============*/
dict_index_t* index, /*!< in: index whose fields to load */
@@ -574,6 +575,7 @@ dict_load_fields(
byte* buf;
ulint i;
mtr_t mtr;
+ ulint error = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -640,6 +642,26 @@ dict_load_fields(
field = rec_get_nth_field_old(rec, 4, &len);
+ if (prefix_len >= DICT_MAX_INDEX_COL_LEN) {
+ fprintf(stderr, "InnoDB: Error: load index"
+ " '%s' failed.\n"
+ "InnoDB: index field '%s' has a prefix"
+ " length of %lu bytes,\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, mem_heap_strdupl(
+ heap, (char*) field, len),
+ (ulong) prefix_len,
+ (ulong) (DICT_MAX_INDEX_COL_LEN - 1));
+ error = DB_CORRUPTION;
+ goto func_exit;
+ }
+
dict_mem_index_add_field(index,
mem_heap_strdupl(heap,
(char*) field, len),
@@ -649,8 +671,10 @@ next_rec:
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
+func_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
+ return(error);
}
/********************************************************************//**
@@ -801,7 +825,25 @@ dict_load_indexes(
space, type, n_fields);
index->id = id;
- 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
+ && !(index->type & DICT_CLUSTERED)) {
+ error = DB_SUCCESS;
+ goto next_rec;
+ } else {
+ goto func_exit;
+ }
+ }
+
error = dict_index_add_to_cache(table, index, page_no,
FALSE);
/* The data dictionary tables should never contain
@@ -1027,9 +1069,18 @@ err_exit:
} 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;
+
+ /* 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
+ || !(index->type & DICT_CLUSTERED)) {
+ dict_table_remove_from_cache(table);
+ table = NULL;
+ }
}
#if 0
if (err != DB_SUCCESS && table != NULL) {
diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
index d091a14c474..fee7fde2e5c 100644
--- a/storage/innodb_plugin/fsp/fsp0fsp.c
+++ b/storage/innodb_plugin/fsp/fsp0fsp.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.
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
@@ -326,14 +326,14 @@ fseg_alloc_free_page_low(
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
- fseg_inode_t* seg_inode, /*!< in: segment inode */
+ fseg_inode_t* seg_inode, /*!< in/out: segment inode */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /*!< in: mtr handle */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
@@ -1548,7 +1548,7 @@ fsp_alloc_free_page(
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint hint, /*!< in: hint of which page would be desirable */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
fsp_header_t* header;
fil_addr_t first;
@@ -2572,14 +2572,14 @@ fseg_alloc_free_page_low(
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
- fseg_inode_t* seg_inode, /*!< in: segment inode */
+ fseg_inode_t* seg_inode, /*!< in/out: segment inode */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
fsp_header_t* space_header;
ulint space_size;
@@ -2803,8 +2803,6 @@ fseg_alloc_free_page_low(
fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
}
- buf_reset_check_index_page_at_flush(space, ret_page);
-
return(ret_page);
}
@@ -2817,7 +2815,7 @@ UNIV_INTERN
ulint
fseg_alloc_free_page_general(
/*=========================*/
- fseg_header_t* seg_header,/*!< in: segment header */
+ fseg_header_t* seg_header,/*!< in/out: segment header */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
@@ -2829,7 +2827,7 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
fseg_inode_t* inode;
ulint space;
diff --git a/storage/innodb_plugin/ha/ha0ha.c b/storage/innodb_plugin/ha/ha0ha.c
index 7f11917de0a..65046138275 100644
--- a/storage/innodb_plugin/ha/ha0ha.c
+++ b/storage/innodb_plugin/ha/ha0ha.c
@@ -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
@@ -89,40 +89,6 @@ ha_create_func(
}
/*************************************************************//**
-Empties a hash table and frees the memory heaps. */
-UNIV_INTERN
-void
-ha_clear(
-/*=====*/
- hash_table_t* table) /*!< in, own: hash table */
-{
- ulint i;
- ulint n;
-
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
-#endif /* UNIV_SYNC_DEBUG */
-
-#ifndef UNIV_HOTBACKUP
- /* Free the memory heaps. */
- n = table->n_mutexes;
-
- for (i = 0; i < n; i++) {
- mem_heap_free(table->heaps[i]);
- }
-#endif /* !UNIV_HOTBACKUP */
-
- /* Clear the hash table. */
- n = hash_get_n_cells(table);
-
- for (i = 0; i < n; i++) {
- hash_get_nth_cell(table, i)->node = NULL;
- }
-}
-
-/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
is inserted. If btr_search_enabled is set to FALSE, we will only allow
@@ -140,7 +106,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data) /*!< in: data, must not be NULL */
+ const rec_t* data) /*!< in: data, must not be NULL */
{
hash_cell_t* cell;
ha_node_t* node;
@@ -153,7 +119,11 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(block->frame == page_align(data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ASSERT_HASH_MUTEX_OWN(table, fold);
+ ut_ad(btr_search_enabled);
hash = hash_calc_hash(fold, table);
@@ -173,7 +143,6 @@ ha_insert_for_fold_func(
prev_block->n_pointers--;
block->n_pointers++;
}
- ut_ad(!btr_search_fully_disabled);
# endif /* !UNIV_HOTBACKUP */
prev_node->block = block;
@@ -186,13 +155,6 @@ ha_insert_for_fold_func(
prev_node = prev_node->next;
}
- /* We are in the process of disabling hash index, do not add
- new chain node */
- if (!btr_search_enabled) {
- ut_ad(!btr_search_fully_disabled);
- return(TRUE);
- }
-
/* We have to allocate a new chain node */
node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t));
@@ -250,6 +212,10 @@ ha_delete_hash_node(
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
@@ -272,11 +238,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data, /*!< in: pointer to the data */
+ const rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* new_data)/*!< in: new pointer to the data */
+ const rec_t* new_data)/*!< in: new pointer to the data */
{
ha_node_t* node;
@@ -286,6 +252,13 @@ ha_search_and_update_if_found_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(new_block->frame == page_align(new_data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ if (!btr_search_enabled) {
+ return;
+ }
node = ha_search_with_data(table, fold, data);
@@ -322,6 +295,10 @@ ha_remove_all_nodes_to_page(
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index a9b81116a90..f3804d5e944 100644
--- a/storage/innodb_plugin/handler/ha_innodb.cc
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -501,6 +501,8 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
{"buffer_pool_pages_total",
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
+ {"buffer_pool_read_ahead_rnd",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
{"buffer_pool_read_ahead",
(char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
{"buffer_pool_read_ahead_evicted",
@@ -2302,7 +2304,6 @@ innobase_change_buffering_inited_ok:
/* Get the current high water mark format. */
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
- btr_search_fully_disabled = (!btr_search_enabled);
DBUG_RETURN(FALSE);
error:
DBUG_RETURN(TRUE);
@@ -3790,25 +3791,6 @@ field_in_record_is_null(
return(0);
}
-/**************************************************************//**
-Sets a field in a record to SQL NULL. Uses the record format
-information in table to track the null bit in record. */
-static inline
-void
-set_field_in_record_to_null(
-/*========================*/
- TABLE* table, /*!< in: MySQL table object */
- Field* field, /*!< in: MySQL field object */
- char* record) /*!< in: a row in MySQL format */
-{
- int null_offset;
-
- null_offset = (uint) ((char*) field->null_ptr
- - (char*) table->record[0]);
-
- record[null_offset] = record[null_offset] | field->null_bit;
-}
-
/*************************************************************//**
InnoDB uses this function to compare two data fields for which the data type
is such that we must use MySQL code to compare them. NOTE that the prototype
@@ -4811,8 +4793,7 @@ no_commit:
switch (sql_command) {
case SQLCOM_LOAD:
- if ((trx->duplicates
- & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
+ if (trx->duplicates) {
goto set_max_autoinc;
}
@@ -4989,14 +4970,15 @@ calc_row_difference(
/* The field has changed */
ufield = uvect->fields + n_changed;
+ UNIV_MEM_INVALID(ufield, sizeof *ufield);
/* Let us use a dummy dfield to make the conversion
from the MySQL column format to the InnoDB format */
- dict_col_copy_type(prebuilt->table->cols + i,
- dfield_get_type(&dfield));
-
if (n_len != UNIV_SQL_NULL) {
+ dict_col_copy_type(prebuilt->table->cols + i,
+ dfield_get_type(&dfield));
+
buf = row_mysql_store_col_in_innobase_format(
&dfield,
(byte*)buf,
@@ -5004,7 +4986,7 @@ calc_row_difference(
new_mysql_row_col,
col_pack_len,
dict_table_is_comp(prebuilt->table));
- dfield_copy_data(&ufield->new_val, &dfield);
+ dfield_copy(&ufield->new_val, &dfield);
} else {
dfield_set_null(&ufield->new_val);
}
@@ -5087,8 +5069,7 @@ ha_innobase::update_row(
&& table->next_number_field
&& new_row == table->record[0]
&& thd_sql_command(user_thd) == SQLCOM_INSERT
- && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
- == TRX_DUP_IGNORE) {
+ && trx->duplicates) {
ulonglong auto_inc;
ulonglong col_max_value;
@@ -5446,6 +5427,7 @@ ha_innobase::index_read(
(byte*) key_ptr,
(ulint) key_len,
prebuilt->trx);
+ DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
} else {
/* We position the cursor to the last or the first entry
in the index */
@@ -6024,10 +6006,6 @@ 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 */
@@ -6147,6 +6125,8 @@ err_col:
col_len);
}
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_create_table_for_mysql(table, trx);
if (error == DB_DUPLICATE_KEY) {
@@ -6563,42 +6543,17 @@ 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) {
@@ -6740,16 +6695,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);
@@ -6993,18 +6969,14 @@ 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);
/* Drop the table in InnoDB */
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_drop_table_for_mysql(norm_name, trx,
thd_sql_command(thd)
== SQLCOM_DROP_DB);
@@ -7120,12 +7092,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));
@@ -7140,6 +7106,8 @@ innobase_rename_table(
row_mysql_lock_data_dictionary(trx);
}
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_rename_table_for_mysql(
norm_from, norm_to, trx, lock_and_commit);
@@ -7259,6 +7227,7 @@ ha_innobase::records_in_range(
mem_heap_t* heap;
DBUG_ENTER("records_in_range");
+ DBUG_ASSERT(min_key || max_key);
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
@@ -7304,6 +7273,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (min_key ? min_key->length : 0),
prebuilt->trx);
+ DBUG_ASSERT(min_key
+ ? range_start->n_fields > 0
+ : range_start->n_fields == 0);
row_sel_convert_mysql_key_to_innobase(
range_end, (byte*) key_val_buff2,
@@ -7312,6 +7284,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (max_key ? max_key->length : 0),
prebuilt->trx);
+ DBUG_ASSERT(max_key
+ ? range_end->n_fields > 0
+ : range_end->n_fields == 0);
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
HA_READ_KEY_EXACT);
@@ -7665,6 +7640,8 @@ ha_innobase::info_low(
if (flag & HA_STATUS_VARIABLE) {
+ ulint page_size;
+
dict_table_stats_lock(ib_table, RW_S_LATCH);
n_rows = ib_table->stat_n_rows;
@@ -7707,14 +7684,19 @@ ha_innobase::info_low(
prebuilt->autoinc_last_value = 0;
}
+ page_size = dict_table_zip_size(ib_table);
+ if (page_size == 0) {
+ page_size = UNIV_PAGE_SIZE;
+ }
+
stats.records = (ha_rows)n_rows;
stats.deleted = 0;
- stats.data_file_length = ((ulonglong)
- ib_table->stat_clustered_index_size)
- * UNIV_PAGE_SIZE;
- stats.index_file_length = ((ulonglong)
- ib_table->stat_sum_of_other_index_sizes)
- * UNIV_PAGE_SIZE;
+ stats.data_file_length
+ = ((ulonglong) ib_table->stat_clustered_index_size)
+ * page_size;
+ stats.index_file_length =
+ ((ulonglong) ib_table->stat_sum_of_other_index_sizes)
+ * page_size;
dict_table_stats_unlock(ib_table, RW_S_LATCH);
@@ -8441,6 +8423,7 @@ ha_innobase::extra(
break;
case HA_EXTRA_RESET_STATE:
reset_template(prebuilt);
+ thd_to_trx(ha_thd())->duplicates = 0;
break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
@@ -8458,19 +8441,18 @@ ha_innobase::extra(
parameters below. We must not invoke update_thd()
either, because the calling threads may change.
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
- case HA_EXTRA_IGNORE_DUP_KEY:
+ case HA_EXTRA_INSERT_WITH_UPDATE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
+ break;
case HA_EXTRA_WRITE_CAN_REPLACE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
break;
case HA_EXTRA_WRITE_CANNOT_REPLACE:
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
break;
- case HA_EXTRA_NO_IGNORE_DUP_KEY:
- thd_to_trx(ha_thd())->duplicates &=
- ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
- break;
default:/* Do nothing */
;
}
@@ -8657,10 +8639,18 @@ ha_innobase::external_lock(
reset_template(prebuilt);
- if (lock_type == F_WRLCK) {
+ if (lock_type == F_WRLCK
+ || (table->s->tmp_table
+ && thd_sql_command(thd) == SQLCOM_LOCK_TABLES)) {
/* If this is a SELECT, then it is in UPDATE TABLE ...
- or SELECT ... FOR UPDATE */
+ or SELECT ... FOR UPDATE
+
+ For temporary tables which are locked for READ by LOCK TABLES
+ updates are still allowed by SQL-layer. In order to accomodate
+ for such a situation we always request X-lock for such table
+ at LOCK TABLES time.
+ */
prebuilt->select_lock_type = LOCK_X;
prebuilt->stored_select_lock_type = LOCK_X;
}
@@ -9999,7 +9989,7 @@ innobase_commit_by_xid(
if (trx) {
innobase_commit_low(trx);
-
+ trx_free_for_background(trx);
return(XA_OK);
} else {
return(XAER_NOTA);
@@ -10025,7 +10015,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);
}
@@ -10699,19 +10691,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;
@@ -10723,7 +10715,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 "
@@ -11032,6 +11024,11 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
NULL, NULL, 0, 0, 1, 0);
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead,
+ PLUGIN_VAR_NOCMDARG,
+ "Whether to use read ahead for random access within an extent.",
+ NULL, NULL, FALSE);
+
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 "
@@ -11096,6 +11093,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
MYSQL_SYSVAR(change_buffering_debug),
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+ MYSQL_SYSVAR(random_read_ahead),
MYSQL_SYSVAR(read_ahead_threshold),
MYSQL_SYSVAR(io_capacity),
NULL
diff --git a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h
index 7a8f29853de..f7a5456b1a7 100644
--- a/storage/innodb_plugin/handler/ha_innodb.h
+++ b/storage/innodb_plugin/handler/ha_innodb.h
@@ -317,15 +317,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/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc
index dc1317d5c5a..485e03737e3 100644
--- a/storage/innodb_plugin/handler/handler0alter.cc
+++ b/storage/innodb_plugin/handler/handler0alter.cc
@@ -649,44 +649,37 @@ ha_innobase::add_index(
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);
if (UNIV_UNLIKELY(!innodb_table)) {
- error = HA_ERR_NO_SUCH_TABLE;
- goto err_exit;
+ 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);
- }
+ /* Check that index keys are sensible */
+ error = innobase_check_index_keys(key_info, num_of_keys, innodb_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);
}
+ 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. */
@@ -758,8 +751,12 @@ err_exit:
ut_d(dict_table_check_for_dup_indexes(innodb_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;
diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
index 23981ac388e..a22de3b0e70 100644
--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c
+++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.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
@@ -356,7 +356,7 @@ ibuf_tree_root_get(
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
return(buf_block_get_frame(block));
}
@@ -496,7 +496,7 @@ ibuf_init_at_db_start(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
root = buf_block_get_frame(block);
}
@@ -1766,17 +1766,16 @@ ibuf_add_free_page(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
-
+ ibuf_enter();
- page = buf_block_get_frame(block);
- }
+ mutex_enter(&ibuf_mutex);
- ibuf_enter();
+ root = ibuf_tree_root_get(&mtr);
- mutex_enter(&ibuf_mutex);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
- root = ibuf_tree_root_get(&mtr);
+ page = buf_block_get_frame(block);
+ }
/* Add the page to the free list and update the ibuf size data */
@@ -1897,8 +1896,7 @@ ibuf_remove_free_page(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
-
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
page = buf_block_get_frame(block);
}
@@ -2408,7 +2406,7 @@ ibuf_get_volume_buffered(
block = buf_page_get(
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
@@ -2482,7 +2480,7 @@ count_later:
block = buf_page_get(
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
next_page = buf_block_get_frame(block);
@@ -2973,7 +2971,7 @@ ibuf_insert_to_index_page(
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
- ut_ad(!buf_block_align(page)->is_hashed);
+ ut_ad(!buf_block_align(page)->index);
if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
!= (ibool)!!page_is_comp(page))) {
@@ -3248,6 +3246,7 @@ ibuf_merge_or_delete_for_page(
ut_ad(!block || buf_block_get_space(block) == space);
ut_ad(!block || buf_block_get_page_no(block) == page_no);
ut_ad(!block || buf_block_get_zip_size(block) == zip_size);
+ ut_ad(!block || buf_block_get_io_fix(block) == BUF_IO_READ);
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE
|| trx_sys_hdr_page(space, page_no)) {
@@ -3403,7 +3402,13 @@ loop:
ut_a(success);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ /* This is a user page (secondary index leaf page),
+ but we pretend that it is a change buffer page in
+ order to obey the latching order. This should be OK,
+ because buffered changes are applied immediately while
+ the block is io-fixed. Other threads must not try to
+ latch an io-fixed block. */
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
}
/* Position pcur in the insert buffer at the first entry for this
diff --git a/storage/innodb_plugin/include/btr0btr.h b/storage/innodb_plugin/include/btr0btr.h
index 5aa02694e0e..e32da9e4c86 100644
--- a/storage/innodb_plugin/include/btr0btr.h
+++ b/storage/innodb_plugin/include/btr0btr.h
@@ -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.
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
@@ -188,26 +188,45 @@ btr_block_get_func(
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));
+# ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree, may be NULL
+ if it is not an insert buffer tree */
+# endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
+# ifdef UNIV_SYNC_DEBUG
+/** 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 index index tree, may be NULL if not the insert buffer tree
+@param mtr mini-transaction handle
+@return the block descriptor */
+# define btr_block_get(space,zip_size,page_no,mode,index,mtr) \
+ btr_block_get_func(space,zip_size,page_no,mode, \
+ __FILE__,__LINE__,index,mtr)
+# else /* UNIV_SYNC_DEBUG */
/** 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 idx index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the block descriptor */
-# define btr_block_get(space,zip_size,page_no,mode,mtr) \
+# define btr_block_get(space,zip_size,page_no,mode,idx,mtr) \
btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
+# endif /* UNIV_SYNC_DEBUG */
/** 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 idx index tree, may be NULL if not the insert buffer tree
@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))
+# define btr_page_get(space,zip_size,page_no,mode,idx,mtr) \
+ buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,idx,mtr))
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
Gets the index id field of a page.
@@ -333,8 +352,7 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
- mtr_t* mtr); /*!< in: a mini-transaction which has already
- been started */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
/*************************************************************//**
Makes tree one level higher by splitting the root, and inserts
the tuple. It is assumed that mtr contains an x-latch on the tree.
diff --git a/storage/innodb_plugin/include/btr0btr.ic b/storage/innodb_plugin/include/btr0btr.ic
index 83eb3627abb..1837d091ccf 100644
--- a/storage/innodb_plugin/include/btr0btr.ic
+++ b/storage/innodb_plugin/include/btr0btr.ic
@@ -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.
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
@@ -48,6 +48,10 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree, may be NULL
+ if it is not an insert buffer tree */
+#endif /* UNIV_SYNC_DEBUG */
mtr_t* mtr) /*!< in/out: mtr */
{
buf_block_t* block;
@@ -57,7 +61,9 @@ btr_block_get_func(
if (mode != RW_NO_LATCH) {
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ block, index != NULL && dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
return(block);
diff --git a/storage/innodb_plugin/include/btr0cur.h b/storage/innodb_plugin/include/btr0cur.h
index ece3621fa97..3669ce28f02 100644
--- a/storage/innodb_plugin/include/btr0cur.h
+++ b/storage/innodb_plugin/include/btr0cur.h
@@ -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.
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
diff --git a/storage/innodb_plugin/include/btr0cur.ic b/storage/innodb_plugin/include/btr0cur.ic
index 280583f6ccf..cd3a5d895bb 100644
--- a/storage/innodb_plugin/include/btr0cur.ic
+++ b/storage/innodb_plugin/include/btr0cur.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
diff --git a/storage/innodb_plugin/include/btr0pcur.h b/storage/innodb_plugin/include/btr0pcur.h
index 2334a266280..40ecc77dcd1 100644
--- a/storage/innodb_plugin/include/btr0pcur.h
+++ b/storage/innodb_plugin/include/btr0pcur.h
@@ -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
@@ -244,18 +244,6 @@ btr_pcur_restore_position_func(
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_restore_position(l,cur,mtr) \
btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr)
-/**************************************************************//**
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-UNIV_INTERN
-void
-btr_pcur_release_leaf(
-/*==================*/
- btr_pcur_t* cursor, /*!< in: persistent cursor */
- mtr_t* mtr); /*!< in: mtr */
/*********************************************************//**
Gets the rel_pos field for a cursor whose position has been stored.
@return BTR_PCUR_ON, ... */
@@ -282,24 +270,15 @@ 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
-to the page where pcur is positioned, this can be used instead of
-btr_pcur_release_leaf. Function btr_pcur_store_position should be used
-before calling this, if restoration of cursor is wanted later. */
+that is, the cursor becomes detached.
+Function btr_pcur_store_position should be used before calling this,
+if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit_specify_mtr(
/*========================*/
btr_pcur_t* pcur, /*!< in: persistent cursor */
mtr_t* mtr); /*!< in: mtr to commit */
-/**************************************************************//**
-Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
-@return TRUE if detached */
-UNIV_INLINE
-ibool
-btr_pcur_is_detached(
-/*=================*/
- btr_pcur_t* pcur); /*!< in: persistent cursor */
/*********************************************************//**
Moves the persistent cursor to the next record in the tree. If no records are
left, the cursor stays 'after last in tree'.
diff --git a/storage/innodb_plugin/include/btr0pcur.ic b/storage/innodb_plugin/include/btr0pcur.ic
index 0c38797e6c5..f49e155f97e 100644
--- a/storage/innodb_plugin/include/btr0pcur.ic
+++ b/storage/innodb_plugin/include/btr0pcur.ic
@@ -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
@@ -396,10 +396,9 @@ btr_pcur_move_to_next(
/**************************************************************//**
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
-that is, the cursor becomes detached. If there have been modifications
-to the page where pcur is positioned, this can be used instead of
-btr_pcur_release_leaf. Function btr_pcur_store_position should be used
-before calling this, if restoration of cursor is wanted later. */
+that is, the cursor becomes detached.
+Function btr_pcur_store_position should be used before calling this,
+if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit_specify_mtr(
@@ -417,38 +416,6 @@ btr_pcur_commit_specify_mtr(
}
/**************************************************************//**
-Sets the pcur latch mode to BTR_NO_LATCHES. */
-UNIV_INLINE
-void
-btr_pcur_detach(
-/*============*/
- btr_pcur_t* pcur) /*!< in: persistent cursor */
-{
- ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
-
- pcur->latch_mode = BTR_NO_LATCHES;
-
- pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
-}
-
-/**************************************************************//**
-Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
-@return TRUE if detached */
-UNIV_INLINE
-ibool
-btr_pcur_is_detached(
-/*=================*/
- btr_pcur_t* pcur) /*!< in: persistent cursor */
-{
- if (pcur->latch_mode == BTR_NO_LATCHES) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/**************************************************************//**
Sets the old_rec_buf field to NULL. */
UNIV_INLINE
void
diff --git a/storage/innodb_plugin/include/btr0sea.h b/storage/innodb_plugin/include/btr0sea.h
index 6493689a969..1f920471f7d 100644
--- a/storage/innodb_plugin/include/btr0sea.h
+++ b/storage/innodb_plugin/include/btr0sea.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -141,8 +141,8 @@ btr_search_drop_page_hash_index(
for which we know that
block->buf_fix_count == 0 */
/********************************************************************//**
-Drops a page hash index when a page is freed from a fseg to the file system.
-Drops possible hash index if the page happens to be in the buffer pool. */
+Drops a possible page hash index when a page is evicted from the buffer pool
+or freed in a file segment. */
UNIV_INTERN
void
btr_search_drop_page_hash_when_freed(
@@ -192,16 +192,6 @@ btr_search_validate(void);
# define btr_search_validate() TRUE
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
-/** Flag: has the search system been enabled?
-Protected by btr_search_latch and btr_search_enabled_mutex. */
-extern char btr_search_enabled;
-
-/** Flag: whether the search system has completed its disabling process,
-It is set to TRUE right after buf_pool_drop_hash_index() in
-btr_search_disable(), indicating hash index entries are cleaned up.
-Protected by btr_search_latch and btr_search_enabled_mutex. */
-extern ibool btr_search_fully_disabled;
-
/** The search info struct in an index */
struct btr_search_struct{
ulint ref_count; /*!< Number of blocks in this index tree
@@ -270,24 +260,6 @@ struct btr_search_sys_struct{
/** The adaptive hash index */
extern btr_search_sys_t* btr_search_sys;
-/** @brief The latch protecting the adaptive search system
-
-This latch protects the
-(1) hash index;
-(2) columns of a record to which we have a pointer in the hash index;
-
-but does NOT protect:
-
-(3) next record offset field in a record;
-(4) next or previous records on the same page.
-
-Bear in mind (3) and (4) when using the hash index.
-*/
-extern rw_lock_t* btr_search_latch_temp;
-
-/** The latch protecting the adaptive search system */
-#define btr_search_latch (*btr_search_latch_temp)
-
#ifdef UNIV_SEARCH_PERF_STAT
/** Number of successful adaptive hash index lookups */
extern ulint btr_search_n_succ;
diff --git a/storage/innodb_plugin/include/btr0types.h b/storage/innodb_plugin/include/btr0types.h
index 07c06fb18d7..5adc858b931 100644
--- a/storage/innodb_plugin/include/btr0types.h
+++ b/storage/innodb_plugin/include/btr0types.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -30,6 +30,7 @@ Created 2/17/1996 Heikki Tuuri
#include "rem0types.h"
#include "page0types.h"
+#include "sync0rw.h"
/** Persistent cursor */
typedef struct btr_pcur_struct btr_pcur_t;
@@ -38,6 +39,28 @@ 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;
+/** @brief The latch protecting the adaptive search system
+
+This latch protects the
+(1) hash index;
+(2) columns of a record to which we have a pointer in the hash index;
+
+but does NOT protect:
+
+(3) next record offset field in a record;
+(4) next or previous records on the same page.
+
+Bear in mind (3) and (4) when using the hash index.
+*/
+extern rw_lock_t* btr_search_latch_temp;
+
+/** The latch protecting the adaptive search system */
+#define btr_search_latch (*btr_search_latch_temp)
+
+/** Flag: has the search system been enabled?
+Protected by btr_search_latch. */
+extern char btr_search_enabled;
+
#ifdef UNIV_BLOB_DEBUG
# include "buf0types.h"
/** An index->blobs entry for keeping track of off-page column references */
diff --git a/storage/innodb_plugin/include/buf0buddy.h b/storage/innodb_plugin/include/buf0buddy.h
index 7648950d5d1..d218a7112f1 100644
--- a/storage/innodb_plugin/include/buf0buddy.h
+++ b/storage/innodb_plugin/include/buf0buddy.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2009, Innobase Oy. 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 the Free Software
@@ -37,24 +37,19 @@ 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. 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
-control blocks must be properly initialized immediately after
-buf_buddy_alloc() has returned the memory, before releasing
-buf_pool_mutex.
-@return allocated block, possibly NULL if lru == NULL */
+block->mutex. The buf_pool_mutex may be released and reacquired.
+This function should only be used for allocating compressed page frames.
+@return allocated block, never NULL */
UNIV_INLINE
void*
buf_buddy_alloc(
/*============*/
- ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */
+ ulint size, /*!< in: compressed page size
+ (between PAGE_ZIP_MIN_SIZE and UNIV_PAGE_SIZE) */
ibool* lru) /*!< in: pointer to a variable that will be assigned
TRUE if storage was allocated from the LRU list
- and buf_pool_mutex was temporarily released,
- or NULL if the LRU list should not be used */
- __attribute__((malloc));
-
+ and buf_pool_mutex was temporarily released */
+ __attribute__((malloc, nonnull));
/**********************************************************************//**
Release a block. */
UNIV_INLINE
diff --git a/storage/innodb_plugin/include/buf0buddy.ic b/storage/innodb_plugin/include/buf0buddy.ic
index c419a2374d9..1087b45ee61 100644
--- a/storage/innodb_plugin/include/buf0buddy.ic
+++ b/storage/innodb_plugin/include/buf0buddy.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2009, Innobase Oy. 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 the Free Software
@@ -36,8 +36,8 @@ 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.
-The buf_pool_mutex may only be released and reacquired if lru != NULL.
-@return allocated block, possibly NULL if lru==NULL */
+The buf_pool_mutex may be released and reacquired.
+@return allocated block, never NULL */
UNIV_INTERN
void*
buf_buddy_alloc_low(
@@ -46,9 +46,8 @@ buf_buddy_alloc_low(
or BUF_BUDDY_SIZES */
ibool* lru) /*!< in: pointer to a variable that will be assigned
TRUE if storage was allocated from the LRU list
- and buf_pool_mutex was temporarily released,
- or NULL if the LRU list should not be used */
- __attribute__((malloc));
+ and buf_pool_mutex was temporarily released */
+ __attribute__((malloc, nonnull));
/**********************************************************************//**
Deallocate a block. */
@@ -74,6 +73,8 @@ buf_buddy_get_slot(
ulint i;
ulint s;
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+
for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) {
}
@@ -84,26 +85,25 @@ 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
-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
-control blocks must be properly initialized immediately after
-buf_buddy_alloc() has returned the memory, before releasing
-buf_pool_mutex.
-@return allocated block, possibly NULL if lru == NULL */
+block->mutex. The buf_pool_mutex may be released and reacquired.
+This function should only be used for allocating compressed page frames.
+@return allocated block, never NULL */
UNIV_INLINE
void*
buf_buddy_alloc(
/*============*/
- ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */
+ ulint size, /*!< in: compressed page size
+ (between PAGE_ZIP_MIN_SIZE and UNIV_PAGE_SIZE) */
ibool* lru) /*!< in: pointer to a variable that will be assigned
TRUE if storage was allocated from the LRU list
- and buf_pool_mutex was temporarily released,
- or NULL if the LRU list should not be used */
+ and buf_pool_mutex was temporarily released */
{
ut_ad(buf_pool_mutex_own());
+ ut_ad(ut_is_2pow(size));
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+ ut_ad(size <= UNIV_PAGE_SIZE);
- return(buf_buddy_alloc_low(buf_buddy_get_slot(size), lru));
+ return((byte*) buf_buddy_alloc_low(buf_buddy_get_slot(size), lru));
}
/**********************************************************************//**
@@ -117,6 +117,9 @@ buf_buddy_free(
ulint size) /*!< in: block size, up to UNIV_PAGE_SIZE */
{
ut_ad(buf_pool_mutex_own());
+ ut_ad(ut_is_2pow(size));
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+ ut_ad(size <= UNIV_PAGE_SIZE);
buf_buddy_free_low(buf, buf_buddy_get_slot(size));
}
diff --git a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h
index 05dead5ac9e..489d1bec5b6 100644
--- a/storage/innodb_plugin/include/buf0buf.h
+++ b/storage/innodb_plugin/include/buf0buf.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.
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
@@ -120,13 +120,11 @@ buf_pool_free(void);
/*===============*/
/********************************************************************//**
-Drops the adaptive hash index. To prevent a livelock, this function
-is only to be called while holding btr_search_latch and while
-btr_search_enabled == FALSE. */
+Clears the adaptive hash index on all pages in the buffer pool. */
UNIV_INTERN
void
-buf_pool_drop_hash_index(void);
-/*==========================*/
+buf_pool_clear_hash_index(void);
+/*===========================*/
/********************************************************************//**
Relocate a buffer control block. Relocates the block on the LRU list
@@ -141,12 +139,6 @@ buf_relocate(
BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
buf_page_t* dpage) /*!< in/out: destination control block */
__attribute__((nonnull));
-/********************************************************************//**
-Resizes the buffer pool. */
-UNIV_INTERN
-void
-buf_pool_resize(void);
-/*=================*/
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
@@ -163,6 +155,23 @@ ib_uint64_t
buf_pool_get_oldest_modification(void);
/*==================================*/
/********************************************************************//**
+Allocates a buf_page_t descriptor. This function must succeed. In case
+of failure we assert in this function. */
+UNIV_INLINE
+buf_page_t*
+buf_page_alloc_descriptor(void)
+/*===========================*/
+ __attribute__((malloc));
+/********************************************************************//**
+Free a buf_page_t descriptor. */
+UNIV_INLINE
+void
+buf_page_free_descriptor(
+/*=====================*/
+ buf_page_t* bpage) /*!< in: bpage descriptor to free. */
+ __attribute__((nonnull));
+
+/********************************************************************//**
Allocates a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
UNIV_INLINE
@@ -361,15 +370,6 @@ buf_page_peek(
/*==========*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */
-/********************************************************************//**
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-UNIV_INTERN
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /*!< in: space id */
- ulint offset);/*!< in: page number */
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
@@ -416,6 +416,18 @@ buf_block_get_freed_page_clock(
__attribute__((pure));
/********************************************************************//**
+Tells if a block is still close enough to the MRU end of the LRU list
+meaning that it is not in danger of getting evicted and also implying
+that it has been accessed recently.
+Note that this is for heuristics only and does not reserve buffer pool
+mutex.
+@return TRUE if block is close to MRU end of LRU */
+UNIV_INLINE
+ibool
+buf_page_peek_if_young(
+/*===================*/
+ const buf_page_t* bpage); /*!< in: block */
+/********************************************************************//**
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex.
@@ -426,17 +438,6 @@ buf_page_peek_if_too_old(
/*=====================*/
const buf_page_t* bpage); /*!< in: block to make younger */
/********************************************************************//**
-Returns the current state of is_hashed of a page. FALSE if the page is
-not in the pool. NOTE that this operation does not fix the page in the
-pool if it is found there.
-@return TRUE if page hash index is built in search system */
-UNIV_INTERN
-ibool
-buf_page_peek_if_search_hashed(
-/*===========================*/
- ulint space, /*!< in: space id */
- ulint offset);/*!< in: page number */
-/********************************************************************//**
Gets the youngest modification log sequence number for a frame.
Returns zero if not file page or no modification occurred yet.
@return newest modification to page */
@@ -1228,13 +1229,16 @@ struct buf_block_struct{
/* @} */
/** @name Hash search fields
- These 6 fields may only be modified when we have
+ These 5 fields may only be modified when we have
an x-latch on btr_search_latch AND
- we are holding an s-latch or x-latch on buf_block_struct::lock or
- we know that buf_block_struct::buf_fix_count == 0.
An exception to this is when we init or create a page
- in the buffer pool in buf0buf.c. */
+ in the buffer pool in buf0buf.c.
+
+ Another exception is that assigning block->index = NULL
+ is allowed whenever holding an x-latch on btr_search_latch. */
/* @{ */
@@ -1243,20 +1247,20 @@ struct buf_block_struct{
pointers in the adaptive hash index
pointing to this frame */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- unsigned is_hashed:1; /*!< TRUE if hash index has
- already been built on this
- page; note that it does not
- guarantee that the index is
- complete, though: there may
- have been hash collisions,
- record deletions, etc. */
unsigned curr_n_fields:10;/*!< prefix length for hash indexing:
number of full fields */
unsigned curr_n_bytes:15;/*!< number of bytes in hash
indexing */
unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
- dict_index_t* index; /*!< Index for which the adaptive
- hash index has been created. */
+ dict_index_t* index; /*!< Index for which the
+ adaptive hash index has been
+ created, or NULL if the page
+ does not exist in the
+ index. Note that it does not
+ guarantee that the index is
+ complete, though: there may
+ have been hash collisions,
+ record deletions, etc. */
/* @} */
# ifdef UNIV_SYNC_DEBUG
/** @name Debug fields */
@@ -1298,6 +1302,8 @@ struct buf_pool_stat_struct{
ulint n_pages_written;/*!< number write operations */
ulint n_pages_created;/*!< number of pages created
in the pool with no read */
+ ulint n_ra_pages_read_rnd;/*!< number of pages read in
+ as part of random read ahead */
ulint n_ra_pages_read;/*!< number of pages read in
as part of read ahead */
ulint n_ra_pages_evicted;/*!< number of read ahead
@@ -1421,8 +1427,10 @@ struct buf_pool_struct{
frames and buf_page_t descriptors of blocks that exist
in the buffer pool only in compressed form. */
/* @{ */
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_BASE_NODE_T(buf_page_t) zip_clean;
/*!< unmodified compressed pages */
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES];
/*!< buddy free lists */
#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
diff --git a/storage/innodb_plugin/include/buf0buf.ic b/storage/innodb_plugin/include/buf0buf.ic
index 0025bef5aac..0fe1dbc2da5 100644
--- a/storage/innodb_plugin/include/buf0buf.ic
+++ b/storage/innodb_plugin/include/buf0buf.ic
@@ -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
@@ -62,6 +62,27 @@ buf_block_get_freed_page_clock(
}
/********************************************************************//**
+Tells if a block is still close enough to the MRU end of the LRU list
+meaning that it is not in danger of getting evicted and also implying
+that it has been accessed recently.
+Note that this is for heuristics only and does not reserve buffer pool
+mutex.
+@return TRUE if block is close to MRU end of LRU */
+UNIV_INLINE
+ibool
+buf_page_peek_if_young(
+/*===================*/
+ const buf_page_t* bpage) /*!< in: block */
+{
+ /* FIXME: bpage->freed_page_clock is 31 bits */
+ return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
+ < ((ulint) bpage->freed_page_clock
+ + (buf_pool->curr_size
+ * (BUF_LRU_OLD_RATIO_DIV - buf_LRU_old_ratio)
+ / (BUF_LRU_OLD_RATIO_DIV * 4))));
+}
+
+/********************************************************************//**
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex.
@@ -89,12 +110,7 @@ buf_page_peek_if_too_old(
buf_pool->stat.n_pages_not_made_young++;
return(FALSE);
} else {
- /* FIXME: bpage->freed_page_clock is 31 bits */
- return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
- > ((ulint) bpage->freed_page_clock
- + (buf_pool->curr_size
- * (BUF_LRU_OLD_RATIO_DIV - buf_LRU_old_ratio)
- / (BUF_LRU_OLD_RATIO_DIV * 4))));
+ return(!buf_page_peek_if_young(bpage));
}
}
@@ -715,6 +731,35 @@ buf_block_get_lock_hash_val(
}
/********************************************************************//**
+Allocates a buf_page_t descriptor. This function must succeed. In case
+of failure we assert in this function.
+@return: the allocated descriptor. */
+UNIV_INLINE
+buf_page_t*
+buf_page_alloc_descriptor(void)
+/*===========================*/
+{
+ buf_page_t* bpage;
+
+ bpage = (buf_page_t*) ut_malloc(sizeof *bpage);
+ ut_d(memset(bpage, 0, sizeof *bpage));
+ UNIV_MEM_ALLOC(bpage, sizeof *bpage);
+
+ return(bpage);
+}
+
+/********************************************************************//**
+Free a buf_page_t descriptor. */
+UNIV_INLINE
+void
+buf_page_free_descriptor(
+/*=====================*/
+ buf_page_t* bpage) /*!< in: bpage descriptor to free. */
+{
+ ut_free(bpage);
+}
+
+/********************************************************************//**
Allocates a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
UNIV_INLINE
@@ -1071,7 +1116,7 @@ buf_block_dbg_add_level(
where we have acquired latch */
ulint level) /*!< in: latching order level */
{
- sync_thread_add_level(&block->lock, level);
+ sync_thread_add_level(&block->lock, level, FALSE);
}
#endif /* UNIV_SYNC_DEBUG */
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innodb_plugin/include/buf0lru.h b/storage/innodb_plugin/include/buf0lru.h
index d543bce53cd..0c2102b9549 100644
--- a/storage/innodb_plugin/include/buf0lru.h
+++ b/storage/innodb_plugin/include/buf0lru.h
@@ -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.
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
@@ -30,18 +30,6 @@ Created 11/5/1995 Heikki Tuuri
#include "ut0byte.h"
#include "buf0types.h"
-/** The return type of buf_LRU_free_block() */
-enum buf_lru_free_block_status {
- /** freed */
- BUF_LRU_FREED = 0,
- /** not freed because the caller asked to remove the
- uncompressed frame but the control block cannot be
- relocated */
- BUF_LRU_CANNOT_RELOCATE,
- /** not freed because of some other reason */
- BUF_LRU_NOT_FREED
-};
-
/******************************************************************//**
Tries to remove LRU flushed blocks from the end of the LRU list and put them
to the free list. This is beneficial for the efficiency of the insert buffer
@@ -84,6 +72,7 @@ void
buf_LRU_invalidate_tablespace(
/*==========================*/
ulint id); /*!< in: space id */
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/********************************************************************//**
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
UNIV_INTERN
@@ -91,22 +80,22 @@ void
buf_LRU_insert_zip_clean(
/*=====================*/
buf_page_t* bpage); /*!< in: pointer to the block in question */
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//**
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
+NOTE: If this function returns TRUE, it will temporarily
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
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
-BUF_LRU_NOT_FREED otherwise. */
+@return TRUE if freed, FALSE otherwise. */
UNIV_INTERN
-enum buf_lru_free_block_status
+ibool
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
diff --git a/storage/innodb_plugin/include/buf0types.h b/storage/innodb_plugin/include/buf0types.h
index bfae6477135..4fe0b4483c8 100644
--- a/storage/innodb_plugin/include/buf0types.h
+++ b/storage/innodb_plugin/include/buf0types.h
@@ -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
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,8 @@ Created 11/17/1995 Heikki Tuuri
#ifndef buf0types_h
#define buf0types_h
+#include "page0types.h"
+
/** Buffer page (uncompressed or compressed) */
typedef struct buf_page_struct buf_page_t;
/** Buffer block for which an uncompressed page exists */
@@ -58,17 +60,10 @@ enum buf_io_fix {
/** Parameters of binary buddy system for compressed pages (buf0buddy.h) */
/* @{ */
-#if UNIV_WORD_SIZE <= 4 /* 32-bit system */
-/** Base-2 logarithm of the smallest buddy block size */
-# define BUF_BUDDY_LOW_SHIFT 6
-#else /* 64-bit system */
-/** Base-2 logarithm of the smallest buddy block size */
-# define BUF_BUDDY_LOW_SHIFT 7
-#endif
+#define BUF_BUDDY_LOW_SHIFT PAGE_ZIP_MIN_SIZE_SHIFT
+
#define BUF_BUDDY_LOW (1 << BUF_BUDDY_LOW_SHIFT)
- /*!< minimum block size in the binary
- buddy system; must be at least
- sizeof(buf_page_t) */
+
#define BUF_BUDDY_SIZES (UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT)
/*!< number of buddy sizes */
diff --git a/storage/innodb_plugin/include/fsp0fsp.h b/storage/innodb_plugin/include/fsp0fsp.h
index 7abd3914eda..403e1d404a8 100644
--- a/storage/innodb_plugin/include/fsp0fsp.h
+++ b/storage/innodb_plugin/include/fsp0fsp.h
@@ -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.
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
@@ -198,7 +198,7 @@ UNIV_INTERN
ulint
fseg_alloc_free_page_general(
/*=========================*/
- fseg_header_t* seg_header,/*!< in: segment header */
+ fseg_header_t* seg_header,/*!< in/out: segment header */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
@@ -210,7 +210,8 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr); /*!< in: mtr handle */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((warn_unused_result, nonnull(1,5)));
/**********************************************************************//**
Reserves free pages from a tablespace. All mini-transactions which may
use several pages from the tablespace should call this function beforehand
diff --git a/storage/innodb_plugin/include/ha0ha.h b/storage/innodb_plugin/include/ha0ha.h
index 3299000bf3c..8bba564d153 100644
--- a/storage/innodb_plugin/include/ha0ha.h
+++ b/storage/innodb_plugin/include/ha0ha.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
@@ -31,13 +31,14 @@ Created 8/18/1994 Heikki Tuuri
#include "hash0hash.h"
#include "page0types.h"
#include "buf0types.h"
+#include "rem0types.h"
/*************************************************************//**
Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
-void*
+const rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@@ -51,11 +52,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data, /*!< in: pointer to the data */
+ const rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* new_data);/*!< in: new pointer to the data */
+ const rec_t* new_data);/*!< in: new pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/** Looks for an element when we know the pointer to the data and
@@ -114,14 +115,6 @@ chosen to be a slightly bigger prime number.
#endif /* UNIV_SYNC_DEBUG */
/*************************************************************//**
-Empties a hash table and frees the memory heaps. */
-UNIV_INTERN
-void
-ha_clear(
-/*=====*/
- hash_table_t* table); /*!< in, own: hash table */
-
-/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
is inserted.
@@ -138,7 +131,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data); /*!< in: data, must not be NULL */
+ const rec_t* data); /*!< in: data, must not be NULL */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/**
@@ -174,7 +167,7 @@ ha_search_and_delete_if_found(
/*==========================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data); /*!< in: pointer to the data */
+ const rec_t* data); /*!< in: pointer to the data */
#ifndef UNIV_HOTBACKUP
/*****************************************************************//**
Removes from the chain determined by fold all nodes whose data pointer
@@ -217,7 +210,7 @@ struct ha_node_struct {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block; /*!< buffer block containing the data, or NULL */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data; /*!< pointer to the data */
+ const rec_t* data; /*!< pointer to the data */
ulint fold; /*!< fold value for the data */
};
diff --git a/storage/innodb_plugin/include/ha0ha.ic b/storage/innodb_plugin/include/ha0ha.ic
index 734403c4cd9..5656e9b7eba 100644
--- a/storage/innodb_plugin/include/ha0ha.ic
+++ b/storage/innodb_plugin/include/ha0ha.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
@@ -25,6 +25,7 @@ Created 8/18/1994 Heikki Tuuri
#include "ut0rnd.h"
#include "mem0mem.h"
+#include "btr0types.h"
/***********************************************************//**
Deletes a hash node. */
@@ -39,10 +40,10 @@ ha_delete_hash_node(
Gets a hash node data.
@return pointer to the data */
UNIV_INLINE
-void*
+const rec_t*
ha_node_get_data(
/*=============*/
- ha_node_t* node) /*!< in: hash chain node */
+ const ha_node_t* node) /*!< in: hash chain node */
{
return(node->data);
}
@@ -57,7 +58,7 @@ ha_node_set_data_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
node->block = block;
@@ -107,39 +108,10 @@ ha_chain_get_first(
/*************************************************************//**
Looks for an element in a hash table.
-@return pointer to the first hash table node in chain having the fold
-number, NULL if not found */
-UNIV_INLINE
-ha_node_t*
-ha_search(
-/*======*/
- hash_table_t* table, /*!< in: hash table */
- ulint fold) /*!< in: folded value of the searched data */
-{
- ha_node_t* node;
-
- ASSERT_HASH_MUTEX_OWN(table, fold);
-
- node = ha_chain_get_first(table, fold);
-
- while (node) {
- if (node->fold == fold) {
-
- return(node);
- }
-
- node = ha_chain_get_next(node);
- }
-
- return(NULL);
-}
-
-/*************************************************************//**
-Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
-void*
+const rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@@ -148,6 +120,10 @@ ha_search_and_get_data(
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);
@@ -172,12 +148,14 @@ ha_search_with_data(
/*================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+ ut_ad(btr_search_enabled);
+
node = ha_chain_get_first(table, fold);
while (node) {
@@ -202,11 +180,15 @@ ha_search_and_delete_if_found(
/*==========================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_search_with_data(table, fold, data);
diff --git a/storage/innodb_plugin/include/mtr0mtr.h b/storage/innodb_plugin/include/mtr0mtr.h
index bc3f1951be9..8a9ec8ea7f0 100644
--- a/storage/innodb_plugin/include/mtr0mtr.h
+++ b/storage/innodb_plugin/include/mtr0mtr.h
@@ -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.
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
@@ -213,16 +213,6 @@ ulint
mtr_set_savepoint(
/*==============*/
mtr_t* mtr); /*!< in: mtr */
-/**********************************************************//**
-Releases the latches stored in an mtr memo down to a savepoint.
-NOTE! The mtr must not have made changes to buffer pages after the
-savepoint, as these can be handled only by mtr_commit. */
-UNIV_INTERN
-void
-mtr_rollback_to_savepoint(
-/*======================*/
- mtr_t* mtr, /*!< in: mtr */
- ulint savepoint); /*!< in: savepoint */
#ifndef UNIV_HOTBACKUP
/**********************************************************//**
Releases the (index tree) s-latch stored in an mtr memo after a
diff --git a/storage/innodb_plugin/include/mtr0mtr.ic b/storage/innodb_plugin/include/mtr0mtr.ic
index 18f8e87b3cf..9f92d2b06a1 100644
--- a/storage/innodb_plugin/include/mtr0mtr.ic
+++ b/storage/innodb_plugin/include/mtr0mtr.ic
@@ -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.
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
diff --git a/storage/innodb_plugin/include/page0cur.ic b/storage/innodb_plugin/include/page0cur.ic
index 3520677dfb3..81474fa35f5 100644
--- a/storage/innodb_plugin/include/page0cur.ic
+++ b/storage/innodb_plugin/include/page0cur.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
@@ -27,6 +27,8 @@ Created 10/4/1994 Heikki Tuuri
#include "buf0types.h"
#ifdef UNIV_DEBUG
+# include "rem0cmp.h"
+
/*********************************************************//**
Gets pointer to the page frame where the cursor is positioned.
@return page */
@@ -268,6 +270,7 @@ page_cur_tuple_insert(
index, rec, offsets, mtr);
}
+ ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, offsets));
mem_heap_free(heap);
return(rec);
}
diff --git a/storage/innodb_plugin/include/page0page.h b/storage/innodb_plugin/include/page0page.h
index 3899499fb6a..12c4fed75d2 100644
--- a/storage/innodb_plugin/include/page0page.h
+++ b/storage/innodb_plugin/include/page0page.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
@@ -68,10 +68,7 @@ typedef byte page_header_t;
#define PAGE_MAX_TRX_ID 18 /* highest id of a trx which may have modified
a record on the page; a dulint; defined only
in secondary indexes and in the insert buffer
- tree; NOTE: this may be modified only
- when the thread has an x-latch to the page,
- and ALSO an x-latch to btr_search_latch
- if there is a hash index to the page! */
+ tree */
#define PAGE_HEADER_PRIV_END 26 /* end of private data structure of the page
header which are set in a page create */
/*----*/
diff --git a/storage/innodb_plugin/include/page0page.ic b/storage/innodb_plugin/include/page0page.ic
index 8f794410f20..b096a5ba321 100644
--- a/storage/innodb_plugin/include/page0page.ic
+++ b/storage/innodb_plugin/include/page0page.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
diff --git a/storage/innodb_plugin/include/rem0rec.h b/storage/innodb_plugin/include/rem0rec.h
index 17d08afabb9..06de23be757 100644
--- a/storage/innodb_plugin/include/rem0rec.h
+++ b/storage/innodb_plugin/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() */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_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_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec.
@return nonzero if externally stored */
diff --git a/storage/innodb_plugin/include/rem0rec.ic b/storage/innodb_plugin/include/rem0rec.ic
index 8e5bd9a7fcd..7cff36fee6c 100644
--- a/storage/innodb_plugin/include/rem0rec.ic
+++ b/storage/innodb_plugin/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));
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_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_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
/******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec.
@return nonzero if externally stored */
diff --git a/storage/innodb_plugin/include/row0row.h b/storage/innodb_plugin/include/row0row.h
index 723b7b53395..36fb26482ce 100644
--- a/storage/innodb_plugin/include/row0row.h
+++ b/storage/innodb_plugin/include/row0row.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -38,16 +38,16 @@ Created 4/20/1996 Heikki Tuuri
#include "btr0types.h"
/*********************************************************************//**
-Gets the offset of the trx id field, in bytes relative to the origin of
+Gets the offset of the DB_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) */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: record offsets */
+ __attribute__((nonnull, warn_unused_result));
/*********************************************************************//**
Reads the trx id field from a clustered index record.
@return value of the field */
@@ -55,9 +55,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 */
@@ -65,9 +66,10 @@ UNIV_INLINE
roll_ptr_t
row_get_rec_roll_ptr(
/*=================*/
- 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));
/*****************************************************************//**
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.
diff --git a/storage/innodb_plugin/include/row0row.ic b/storage/innodb_plugin/include/row0row.ic
index 05c007641af..0b9ca982af8 100644
--- a/storage/innodb_plugin/include/row0row.ic
+++ b/storage/innodb_plugin/include/row0row.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -28,15 +28,42 @@ Created 4/20/1996 Heikki Tuuri
#include "trx0undo.h"
/*********************************************************************//**
+Gets the offset of the DB_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(
+/*==================*/
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: record offsets */
+{
+ ulint pos;
+ ulint offset;
+ ulint len;
+
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(rec_offs_validate(NULL, 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;
@@ -46,7 +73,7 @@ row_get_rec_trx_id(
offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
return(trx_read_trx_id(rec + offset));
@@ -59,9 +86,9 @@ UNIV_INLINE
roll_ptr_t
row_get_rec_roll_ptr(
/*=================*/
- 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;
@@ -71,7 +98,7 @@ row_get_rec_roll_ptr(
offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
diff --git a/storage/innodb_plugin/include/row0upd.ic b/storage/innodb_plugin/include/row0upd.ic
index 18e22f1eca9..10646241125 100644
--- a/storage/innodb_plugin/include/row0upd.ic
+++ b/storage/innodb_plugin/include/row0upd.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -28,7 +28,6 @@ Created 12/27/1996 Heikki Tuuri
# include "trx0trx.h"
# include "trx0undo.h"
# include "row0row.h"
-# include "btr0sea.h"
#endif /* !UNIV_HOTBACKUP */
#include "page0zip.h"
@@ -157,11 +156,6 @@ row_upd_rec_sys_fields(
{
ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(rec, index, offsets));
-#ifdef UNIV_SYNC_DEBUG
- if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) {
- ut_ad(!buf_block_align(rec)->is_hashed);
- }
-#endif /* UNIV_SYNC_DEBUG */
if (UNIV_LIKELY_NULL(page_zip)) {
ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
@@ -171,7 +165,7 @@ row_upd_rec_sys_fields(
ulint offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
#if DATA_TRX_ID + 1 != DATA_ROLL_PTR
diff --git a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
index 91ae895040c..7c63a5f0d45 100644
--- a/storage/innodb_plugin/include/srv0srv.h
+++ b/storage/innodb_plugin/include/srv0srv.h
@@ -143,6 +143,7 @@ extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
extern ulint srv_n_file_io_threads;
+extern my_bool srv_random_read_ahead;
extern ulong srv_read_ahead_threshold;
extern ulint srv_n_read_io_threads;
extern ulint srv_n_write_io_threads;
@@ -618,6 +619,7 @@ struct export_var_struct{
ulint innodb_buffer_pool_wait_free; /*!< srv_buf_pool_wait_free */
ulint innodb_buffer_pool_pages_flushed; /*!< srv_buf_pool_flushed */
ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
+ ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */
ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */
ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
ulint innodb_dblwr_pages_written; /*!< srv_dblwr_pages_written */
diff --git a/storage/innodb_plugin/include/sync0rw.h b/storage/innodb_plugin/include/sync0rw.h
index 47f7dbfe0eb..40be1396a4c 100644
--- a/storage/innodb_plugin/include/sync0rw.h
+++ b/storage/innodb_plugin/include/sync0rw.h
@@ -564,7 +564,8 @@ struct rw_lock_struct {
};
#ifdef UNIV_SYNC_DEBUG
-/** The structure for storing debug info of an rw-lock */
+/** The structure for storing debug info of an rw-lock. All access to this
+structure must be protected by rw_lock_debug_mutex_enter(). */
struct rw_lock_debug_struct {
os_thread_id_t thread_id; /*!< The thread id of the thread which
diff --git a/storage/innodb_plugin/include/sync0rw.ic b/storage/innodb_plugin/include/sync0rw.ic
index 7116f1b7c9b..5eb3d017eca 100644
--- a/storage/innodb_plugin/include/sync0rw.ic
+++ b/storage/innodb_plugin/include/sync0rw.ic
@@ -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
@@ -406,6 +406,7 @@ rw_lock_s_lock_func(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
/* TODO: study performance of UNIV_LIKELY branch prediction hints. */
@@ -603,16 +604,16 @@ rw_lock_x_unlock_direct(
ut_ad((lock->lock_word % X_LOCK_DECR) == 0);
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
-#endif
-
if (lock->lock_word == 0) {
lock->recursive = FALSE;
UNIV_MEM_INVALID(&lock->writer_thread,
sizeof lock->writer_thread);
}
+#ifdef UNIV_SYNC_DEBUG
+ rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
+#endif
+
lock->lock_word += X_LOCK_DECR;
ut_ad(!lock->waiters);
diff --git a/storage/innodb_plugin/include/sync0sync.h b/storage/innodb_plugin/include/sync0sync.h
index 71c9920a10b..63bad29a9c8 100644
--- a/storage/innodb_plugin/include/sync0sync.h
+++ b/storage/innodb_plugin/include/sync0sync.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
@@ -219,8 +219,10 @@ void
sync_thread_add_level(
/*==================*/
void* latch, /*!< in: pointer to a mutex or an rw-lock */
- ulint level); /*!< in: level in the latching order; if
+ ulint level, /*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
+ ibool relock) /*!< in: TRUE if re-entering an x-lock */
+ __attribute__((nonnull));
/******************************************************************//**
Removes a latch from the thread level array if it is found there.
@return TRUE if found in the array; it is no error if the latch is
@@ -446,10 +448,6 @@ or row lock! */
#define SYNC_DICT_HEADER 995
#define SYNC_IBUF_HEADER 914
#define SYNC_IBUF_PESS_INSERT_MUTEX 912
-#define SYNC_IBUF_MUTEX 910 /* ibuf mutex is really below
- SYNC_FSP_PAGE: we assign a value this
- high only to make the program to pass
- the debug checks */
/*-------------------------------*/
#define SYNC_INDEX_TREE 900
#define SYNC_TREE_NODE_NEW 892
@@ -466,8 +464,11 @@ or row lock! */
#define SYNC_FSP 400
#define SYNC_FSP_PAGE 395
/*------------------------------------- Insert buffer headers */
-/*------------------------------------- ibuf_mutex */
+#define SYNC_IBUF_MUTEX 370 /* ibuf_mutex */
/*------------------------------------- Insert buffer tree */
+#define SYNC_IBUF_INDEX_TREE 360
+#define SYNC_IBUF_TREE_NODE_NEW 359
+#define SYNC_IBUF_TREE_NODE 358
#define SYNC_IBUF_BITMAP_MUTEX 351
#define SYNC_IBUF_BITMAP 350
/*------------------------------------- MySQL query cache mutex */
@@ -480,7 +481,6 @@ or row lock! */
#define SYNC_LOG 170
#define SYNC_RECV 168
#define SYNC_WORK_QUEUE 162
-#define SYNC_SEARCH_SYS_CONF 161 /* for assigning btr_search_enabled */
#define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
heap that can be extended to the
buffer pool, its logical level is
diff --git a/storage/innodb_plugin/include/trx0sys.h b/storage/innodb_plugin/include/trx0sys.h
index cbb89689748..78bb6fc349b 100644
--- a/storage/innodb_plugin/include/trx0sys.h
+++ b/storage/innodb_plugin/include/trx0sys.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -284,6 +284,17 @@ ibool
trx_in_trx_list(
/*============*/
trx_t* in_trx);/*!< in: trx */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/***********************************************************//**
+Assert that a transaction has been recovered.
+@return TRUE */
+UNIV_INLINE
+ibool
+trx_assert_recovered(
+/*=================*/
+ trx_id_t trx_id) /*!< in: transaction identifier */
+ __attribute__((warn_unused_result));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/*****************************************************************//**
Updates the offset information about the end of the MySQL binlog entry
which corresponds to the transaction just being committed. In a MySQL
diff --git a/storage/innodb_plugin/include/trx0sys.ic b/storage/innodb_plugin/include/trx0sys.ic
index 820d31d0692..6246debac0a 100644
--- a/storage/innodb_plugin/include/trx0sys.ic
+++ b/storage/innodb_plugin/include/trx0sys.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -277,6 +277,28 @@ trx_get_on_id(
return(NULL);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/***********************************************************//**
+Assert that a transaction has been recovered.
+@return TRUE */
+UNIV_INLINE
+ibool
+trx_assert_recovered(
+/*=================*/
+ trx_id_t trx_id) /*!< in: transaction identifier */
+{
+ trx_t* trx;
+
+ mutex_enter(&kernel_mutex);
+ trx = trx_get_on_id(trx_id);
+ ut_a(trx);
+ ut_a(trx->is_recovered);
+ mutex_exit(&kernel_mutex);
+
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
/****************************************************************//**
Returns the minumum trx id in trx list. This is the smallest id for which
the trx can possibly be active. (But, you must look at the trx->conc_state to
diff --git a/storage/innodb_plugin/include/trx0trx.h b/storage/innodb_plugin/include/trx0trx.h
index 833bae4a4ff..4bf3e75a5ee 100644
--- a/storage/innodb_plugin/include/trx0trx.h
+++ b/storage/innodb_plugin/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 */
+ __attribute__((nonnull));
+/********************************************************************//**
Frees a transaction object for MySQL. */
UNIV_INTERN
void
diff --git a/storage/innodb_plugin/include/trx0undo.h b/storage/innodb_plugin/include/trx0undo.h
index a084f2394b5..c95f99d6417 100644
--- a/storage/innodb_plugin/include/trx0undo.h
+++ b/storage/innodb_plugin/include/trx0undo.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -204,17 +204,51 @@ trx_undo_add_page(
mtr_t* mtr); /*!< in: mtr which does not have a latch to any
undo log page; the caller must have reserved
the rollback segment mutex */
+/********************************************************************//**
+Frees the last undo log page.
+The caller must hold the rollback segment mutex. */
+UNIV_INTERN
+void
+trx_undo_free_last_page_func(
+/*==========================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log memory copy */
+ mtr_t* mtr) /*!< in/out: mini-transaction which does not
+ have a latch to any undo log page or which
+ has allocated the undo log page */
+ __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+# define trx_undo_free_last_page(trx,undo,mtr) \
+ trx_undo_free_last_page_func(trx,undo,mtr)
+#else /* UNIV_DEBUG */
+# define trx_undo_free_last_page(trx,undo,mtr) \
+ trx_undo_free_last_page_func(undo,mtr)
+#endif /* UNIV_DEBUG */
+
/***********************************************************************//**
Truncates an undo log from the end. This function is used during a rollback
to free space from an undo log. */
UNIV_INTERN
void
-trx_undo_truncate_end(
-/*==================*/
- trx_t* trx, /*!< in: transaction whose undo log it is */
- trx_undo_t* undo, /*!< in: undo log */
- undo_no_t limit); /*!< in: all undo records with undo number
+trx_undo_truncate_end_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction whose undo log it is */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log */
+ undo_no_t limit) /*!< in: all undo records with undo number
>= this value should be truncated */
+ __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+# define trx_undo_truncate_end(trx,undo,limit) \
+ trx_undo_truncate_end_func(trx,undo,limit)
+#else /* UNIV_DEBUG */
+# define trx_undo_truncate_end(trx,undo,limit) \
+ trx_undo_truncate_end_func(undo,limit)
+#endif /* UNIV_DEBUG */
+
/***********************************************************************//**
Truncates an undo log from the start. This function is used during a purge
operation. */
@@ -298,6 +332,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 */
+ __attribute__((nonnull));
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
Parses the redo log entry of an undo log page initialization.
diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i
index 319db93d137..8a4d8a55370 100644
--- a/storage/innodb_plugin/include/univ.i
+++ b/storage/innodb_plugin/include/univ.i
@@ -1,8 +1,7 @@
/*****************************************************************************
-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.
-Copyright (c) 2009, Sun Microsystems, Inc.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -46,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 1
#define INNODB_VERSION_MINOR 0
-#define INNODB_VERSION_BUGFIX 16
+#define INNODB_VERSION_BUGFIX 17
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
diff --git a/storage/innodb_plugin/include/ut0mem.h b/storage/innodb_plugin/include/ut0mem.h
index f14606be966..9c6ee9049ec 100644
--- a/storage/innodb_plugin/include/ut0mem.h
+++ b/storage/innodb_plugin/include/ut0mem.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
@@ -210,43 +210,6 @@ ut_strlcpy_rev(
ulint size); /*!< in: size of destination buffer */
/**********************************************************************//**
-Compute strlen(ut_strcpyq(str, q)).
-@return length of the string when quoted */
-UNIV_INLINE
-ulint
-ut_strlenq(
-/*=======*/
- const char* str, /*!< in: null-terminated string */
- char q); /*!< in: the quote character */
-
-/**********************************************************************//**
-Make a quoted copy of a NUL-terminated string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_memcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_strcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src); /*!< in: null-terminated string */
-
-/**********************************************************************//**
-Make a quoted copy of a fixed-length string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_strcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_memcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src, /*!< in: string to be quoted */
- ulint len); /*!< in: length of src */
-
-/**********************************************************************//**
Return the number of times s2 occurs in s1. Overlapping instances of s2
are only counted once.
@return the number of times s2 occurs in s1 */
diff --git a/storage/innodb_plugin/include/ut0mem.ic b/storage/innodb_plugin/include/ut0mem.ic
index f36c28f1989..c06e2b3ae81 100644
--- a/storage/innodb_plugin/include/ut0mem.ic
+++ b/storage/innodb_plugin/include/ut0mem.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
@@ -99,27 +99,6 @@ ut_strcmp(const char* str1, const char* str2)
}
/**********************************************************************//**
-Compute strlen(ut_strcpyq(str, q)).
-@return length of the string when quoted */
-UNIV_INLINE
-ulint
-ut_strlenq(
-/*=======*/
- const char* str, /*!< in: null-terminated string */
- char q) /*!< in: the quote character */
-{
- ulint len;
-
- for (len = 0; *str; len++, str++) {
- if (*str == q) {
- len++;
- }
- }
-
- return(len);
-}
-
-/**********************************************************************//**
Converts a raw binary data to a NUL-terminated hex string. The output is
truncated if there is not enough space in "hex", make sure "hex_size" is at
least (2 * raw_size + 1) if you do not want this to happen. Returns the
diff --git a/storage/innodb_plugin/log/log0log.c b/storage/innodb_plugin/log/log0log.c
index 183c24d2147..4bb9abdc1a4 100644
--- a/storage/innodb_plugin/log/log0log.c
+++ b/storage/innodb_plugin/log/log0log.c
@@ -3085,12 +3085,13 @@ loop:
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. */
+ /* 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. */
if (trx_n_mysql_transactions > 0
- || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
+ || UT_LIST_GET_LEN(trx_sys->trx_list) > trx_n_prepared) {
mutex_exit(&kernel_mutex);
diff --git a/storage/innodb_plugin/mtr/mtr0mtr.c b/storage/innodb_plugin/mtr/mtr0mtr.c
index 417e97732bb..5fad61b2922 100644
--- a/storage/innodb_plugin/mtr/mtr0mtr.c
+++ b/storage/innodb_plugin/mtr/mtr0mtr.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.
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
@@ -211,40 +211,6 @@ mtr_commit(
}
#ifndef UNIV_HOTBACKUP
-/**********************************************************//**
-Releases the latches stored in an mtr memo down to a savepoint.
-NOTE! The mtr must not have made changes to buffer pages after the
-savepoint, as these can be handled only by mtr_commit. */
-UNIV_INTERN
-void
-mtr_rollback_to_savepoint(
-/*======================*/
- mtr_t* mtr, /*!< in: mtr */
- ulint savepoint) /*!< in: savepoint */
-{
- mtr_memo_slot_t* slot;
- dyn_array_t* memo;
- ulint offset;
-
- ut_ad(mtr);
- ut_ad(mtr->magic_n == MTR_MAGIC_N);
- ut_ad(mtr->state == MTR_ACTIVE);
-
- memo = &(mtr->memo);
-
- offset = dyn_array_get_data_size(memo);
- ut_ad(offset >= savepoint);
-
- while (offset > savepoint) {
- offset -= sizeof(mtr_memo_slot_t);
-
- slot = dyn_array_get_element(memo, offset);
-
- ut_ad(slot->type != MTR_MEMO_MODIFY);
- mtr_memo_slot_release(mtr, slot);
- }
-}
-
/***************************************************//**
Releases an object in the memo stack. */
UNIV_INTERN
diff --git a/storage/innodb_plugin/page/page0cur.c b/storage/innodb_plugin/page/page0cur.c
index 936762b986a..ab5aa257338 100644
--- a/storage/innodb_plugin/page/page0cur.c
+++ b/storage/innodb_plugin/page/page0cur.c
@@ -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
diff --git a/storage/innodb_plugin/page/page0page.c b/storage/innodb_plugin/page/page0page.c
index 6cae03e8829..93869e997b5 100644
--- a/storage/innodb_plugin/page/page0page.c
+++ b/storage/innodb_plugin/page/page0page.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.
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
@@ -215,12 +215,6 @@ page_set_max_trx_id(
{
page_t* page = buf_block_get_frame(block);
#ifndef UNIV_HOTBACKUP
- const ibool is_hashed = block->is_hashed;
-
- if (is_hashed) {
- rw_lock_x_lock(&btr_search_latch);
- }
-
ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#endif /* !UNIV_HOTBACKUP */
@@ -241,12 +235,6 @@ page_set_max_trx_id(
} else {
mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
}
-
-#ifndef UNIV_HOTBACKUP
- if (is_hashed) {
- rw_lock_x_unlock(&btr_search_latch);
- }
-#endif /* !UNIV_HOTBACKUP */
}
/************************************************************//**
diff --git a/storage/innodb_plugin/page/page0zip.c b/storage/innodb_plugin/page/page0zip.c
index 6e866b3f016..9f00fb4d1e0 100644
--- a/storage/innodb_plugin/page/page0zip.c
+++ b/storage/innodb_plugin/page/page0zip.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 2005, 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
@@ -151,6 +151,20 @@ page_zip_empty_size(
#endif /* !UNIV_HOTBACKUP */
/*************************************************************//**
+Gets the number of elements in the dense page directory,
+including deleted records (the free list).
+@return number of elements in the dense page directory */
+UNIV_INLINE
+ulint
+page_zip_dir_elems(
+/*===============*/
+ const page_zip_des_t* page_zip) /*!< in: compressed page */
+{
+ /* Exclude the page infimum and supremum from the record count. */
+ return(page_dir_get_n_heap(page_zip->data) - PAGE_HEAP_NO_USER_LOW);
+}
+
+/*************************************************************//**
Gets the size of the compressed page trailer (the dense page directory),
including deleted records (the free list).
@return length of dense page directory, in bytes */
@@ -160,14 +174,42 @@ page_zip_dir_size(
/*==============*/
const page_zip_des_t* page_zip) /*!< in: compressed page */
{
- /* Exclude the page infimum and supremum from the record count. */
- ulint size = PAGE_ZIP_DIR_SLOT_SIZE
- * (page_dir_get_n_heap(page_zip->data)
- - PAGE_HEAP_NO_USER_LOW);
- return(size);
+ return(PAGE_ZIP_DIR_SLOT_SIZE * page_zip_dir_elems(page_zip));
+}
+
+/*************************************************************//**
+Gets an offset to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@return offset of the dense page directory */
+UNIV_INLINE
+ulint
+page_zip_dir_start_offs(
+/*====================*/
+ const page_zip_des_t* page_zip, /*!< in: compressed page */
+ ulint n_dense) /*!< in: directory size */
+{
+ ut_ad(n_dense * PAGE_ZIP_DIR_SLOT_SIZE < page_zip_get_size(page_zip));
+
+ return(page_zip_get_size(page_zip) - n_dense * PAGE_ZIP_DIR_SLOT_SIZE);
}
/*************************************************************//**
+Gets a pointer to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@param[in] page_zip compressed page
+@param[in] n_dense number of entries in the directory
+@return pointer to the dense page directory */
+#define page_zip_dir_start_low(page_zip, n_dense) \
+ ((page_zip)->data + page_zip_dir_start_offs(page_zip, n_dense))
+/*************************************************************//**
+Gets a pointer to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@param[in] page_zip compressed page
+@return pointer to the dense page directory */
+#define page_zip_dir_start(page_zip) \
+ page_zip_dir_start_low(page_zip, page_zip_dir_elems(page_zip))
+
+/*************************************************************//**
Gets the size of the compressed page trailer (the dense page directory),
only including user records (excluding the free list).
@return length of dense page directory comprising existing records, in bytes */
@@ -2242,8 +2284,7 @@ zlib_done:
}
/* Restore the uncompressed columns in heap_no order. */
- storage = page_zip->data + page_zip_get_size(page_zip)
- - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start_low(page_zip, n_dense);
for (slot = 0; slot < n_dense; slot++) {
rec_t* rec = recs[slot];
@@ -2728,8 +2769,7 @@ zlib_done:
return(FALSE);
}
- storage = page_zip->data + page_zip_get_size(page_zip)
- - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start_low(page_zip, n_dense);
externs = storage - n_dense
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
@@ -3457,9 +3497,7 @@ page_zip_write_rec(
}
/* Write the data bytes. Store the uncompressed bytes separately. */
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start(page_zip);
if (page_is_leaf(page)) {
ulint len;
@@ -3755,9 +3793,7 @@ corrupt:
field = page + offset;
storage = page_zip->data + z_offset;
- storage_end = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage_end = page_zip_dir_start(page_zip);
heap_no = 1 + (storage_end - storage) / REC_NODE_PTR_SIZE;
@@ -3793,7 +3829,9 @@ page_zip_write_node_ptr(
{
byte* field;
byte* storage;
+#ifdef UNIV_DEBUG
page_t* page = page_align(rec);
+#endif /* UNIV_DEBUG */
ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
ut_ad(page_simple_validate_new(page));
@@ -3810,9 +3848,7 @@ page_zip_write_node_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
UNIV_MEM_ASSERT_RW(rec, size);
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE
+ storage = page_zip_dir_start(page_zip)
- (rec_get_heap_no_new(rec) - 1) * REC_NODE_PTR_SIZE;
field = rec + size - REC_NODE_PTR_SIZE;
@@ -3861,7 +3897,9 @@ page_zip_write_trx_id_and_roll_ptr(
{
byte* field;
byte* storage;
+#ifdef UNIV_DEBUG
page_t* page = page_align(rec);
+#endif /* UNIV_DEBUG */
ulint len;
ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
@@ -3879,9 +3917,7 @@ page_zip_write_trx_id_and_roll_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE
+ storage = page_zip_dir_start(page_zip)
- (rec_get_heap_no_new(rec) - 1)
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
@@ -3912,17 +3948,9 @@ page_zip_write_trx_id_and_roll_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
}
-#ifdef UNIV_ZIP_DEBUG
-/** Set this variable in a debugger to disable page_zip_clear_rec().
-The only observable effect should be the compression ratio due to
-deleted records not being zeroed out. In rare cases, there can be
-page_zip_validate() failures on the node_ptr, trx_id and roll_ptr
-columns if the space is reallocated for a smaller record. */
-UNIV_INTERN ibool page_zip_clear_rec_disable;
-#endif /* UNIV_ZIP_DEBUG */
-
/**********************************************************************//**
-Clear an area on the uncompressed and compressed page, if possible. */
+Clear an area on the uncompressed and compressed page.
+Do not clear the data payload, as that would grow the modification log. */
static
void
page_zip_clear_rec(
@@ -3934,6 +3962,9 @@ page_zip_clear_rec(
{
ulint heap_no;
page_t* page = page_align(rec);
+ byte* storage;
+ byte* field;
+ ulint len;
/* page_zip_validate() would fail here if a record
containing externally stored columns is being deleted. */
ut_ad(rec_offs_validate(rec, index, offsets));
@@ -3949,60 +3980,38 @@ page_zip_clear_rec(
UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
rec_offs_extra_size(offsets));
- if (
-#ifdef UNIV_ZIP_DEBUG
- !page_zip_clear_rec_disable &&
-#endif /* UNIV_ZIP_DEBUG */
- page_zip->m_end
- + 1 + ((heap_no - 1) >= 64)/* size of the log entry */
- + page_zip_get_trailer_len(page_zip,
- dict_index_is_clust(index), NULL)
- < page_zip_get_size(page_zip)) {
- byte* data;
-
- /* Clear only the data bytes, because the allocator and
- the decompressor depend on the extra bytes. */
- memset(rec, 0, rec_offs_data_size(offsets));
-
- if (!page_is_leaf(page)) {
- /* Clear node_ptr on the compressed page. */
- byte* storage = page_zip->data
- + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page)
- - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
-
- memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
- 0, REC_NODE_PTR_SIZE);
- } else if (dict_index_is_clust(index)) {
- /* Clear trx_id and roll_ptr on the compressed page. */
- byte* storage = page_zip->data
- + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page)
- - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
-
- memset(storage - (heap_no - 1)
- * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
- 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
- }
+ if (!page_is_leaf(page)) {
+ /* Clear node_ptr. On the compressed page,
+ there is an array of node_ptr immediately before the
+ dense page directory, at the very end of the page. */
+ storage = page_zip_dir_start(page_zip);
+ ut_ad(dict_index_get_n_unique_in_tree(index) ==
+ rec_offs_n_fields(offsets) - 1);
+ field = rec_get_nth_field(rec, offsets,
+ rec_offs_n_fields(offsets) - 1,
+ &len);
+ ut_ad(len == REC_NODE_PTR_SIZE);
- /* Log that the data was zeroed out. */
- data = page_zip->data + page_zip->m_end;
- ut_ad(!*data);
- if (UNIV_UNLIKELY(heap_no - 1 >= 64)) {
- *data++ = (byte) (0x80 | (heap_no - 1) >> 7);
- ut_ad(!*data);
- }
- *data++ = (byte) ((heap_no - 1) << 1 | 1);
- ut_ad(!*data);
- ut_ad((ulint) (data - page_zip->data)
- < page_zip_get_size(page_zip));
- page_zip->m_end = data - page_zip->data;
- page_zip->m_nonempty = TRUE;
- } else if (page_is_leaf(page) && dict_index_is_clust(index)) {
- /* Do not clear the record, because there is not enough space
- to log the operation. */
+ ut_ad(!rec_offs_any_extern(offsets));
+ memset(field, 0, REC_NODE_PTR_SIZE);
+ memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
+ 0, REC_NODE_PTR_SIZE);
+ } else if (dict_index_is_clust(index)) {
+ /* Clear trx_id and roll_ptr. On the compressed page,
+ there is an array of these fields immediately before the
+ dense page directory, at the very end of the page. */
+ const ulint trx_id_pos
+ = dict_col_get_clust_pos(
+ dict_table_get_sys_col(
+ index->table, DATA_TRX_ID), index);
+ storage = page_zip_dir_start(page_zip);
+ field = rec_get_nth_field(rec, offsets, trx_id_pos, &len);
+ ut_ad(len == DATA_TRX_ID_LEN);
+
+ memset(field, 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
+ memset(storage - (heap_no - 1)
+ * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
+ 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
if (rec_offs_any_extern(offsets)) {
ulint i;
@@ -4011,15 +4020,18 @@ page_zip_clear_rec(
/* Clear all BLOB pointers in order to make
page_zip_validate() pass. */
if (rec_offs_nth_extern(offsets, i)) {
- ulint len;
- byte* field = rec_get_nth_field(
+ field = rec_get_nth_field(
rec, offsets, i, &len);
+ ut_ad(len
+ == BTR_EXTERN_FIELD_REF_SIZE);
memset(field + len
- BTR_EXTERN_FIELD_REF_SIZE,
0, BTR_EXTERN_FIELD_REF_SIZE);
}
}
}
+ } else {
+ ut_ad(!rec_offs_any_extern(offsets));
}
#ifdef UNIV_ZIP_DEBUG
diff --git a/storage/innodb_plugin/rem/rem0rec.c b/storage/innodb_plugin/rem/rem0rec.c
index 37ba8ca2ffe..9f90d2940dd 100644
--- a/storage/innodb_plugin/rem/rem0rec.c
+++ b/storage/innodb_plugin/rem/rem0rec.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.
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
@@ -408,7 +408,7 @@ rec_init_offsets(
do {
ulint len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
- len = offs += 4;
+ len = offs += REC_NODE_PTR_SIZE;
goto resolved;
}
@@ -640,7 +640,7 @@ rec_get_offsets_reverse(
do {
ulint len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
- len = offs += 4;
+ len = offs += REC_NODE_PTR_SIZE;
goto resolved;
}
@@ -1131,9 +1131,9 @@ rec_convert_dtuple_to_rec_comp(
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
- ut_ad(len == 4);
+ ut_ad(len == REC_NODE_PTR_SIZE);
memcpy(end, dfield_get_data(field), len);
- end += 4;
+ end += REC_NODE_PTR_SIZE;
break;
}
diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
index 8050c099751..2cbe1e13edc 100644
--- a/storage/innodb_plugin/row/row0ins.c
+++ b/storage/innodb_plugin/row/row0ins.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
@@ -434,11 +434,9 @@ row_ins_cascade_calc_update_vec(
dict_table_t* table = foreign->foreign_table;
dict_index_t* index = foreign->foreign_index;
upd_t* update;
- upd_field_t* ufield;
dict_table_t* parent_table;
dict_index_t* parent_index;
upd_t* parent_update;
- upd_field_t* parent_ufield;
ulint n_fields_updated;
ulint parent_field_no;
ulint i;
@@ -474,13 +472,15 @@ row_ins_cascade_calc_update_vec(
dict_index_get_nth_col_no(parent_index, i));
for (j = 0; j < parent_update->n_fields; j++) {
- parent_ufield = parent_update->fields + j;
+ const upd_field_t* parent_ufield
+ = &parent_update->fields[j];
if (parent_ufield->field_no == parent_field_no) {
ulint min_size;
const dict_col_t* col;
ulint ufield_len;
+ upd_field_t* ufield;
col = dict_index_get_nth_col(index, i);
@@ -493,6 +493,8 @@ row_ins_cascade_calc_update_vec(
ufield->field_no
= dict_table_get_nth_col_pos(
table, dict_col_get_no(col));
+
+ ufield->orig_len = 0;
ufield->exp = NULL;
ufield->new_val = parent_ufield->new_val;
@@ -993,10 +995,9 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
- if ((node->is_delete
- && (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL))
- || (!node->is_delete
- && (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
+ if (node->is_delete
+ ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
+ : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) {
/* Build the appropriate update vector which sets
foreign->n_fields first fields in rec to SQL NULL */
@@ -1005,6 +1006,8 @@ row_ins_foreign_check_on_constraint(
update->info_bits = 0;
update->n_fields = foreign->n_fields;
+ UNIV_MEM_INVALID(update->fields,
+ update->n_fields * sizeof *update->fields);
for (i = 0; i < foreign->n_fields; i++) {
upd_field_t* ufield = &update->fields[i];
@@ -1662,7 +1665,7 @@ row_ins_scan_sec_index_for_duplicate(
ulint n_fields_cmp;
btr_pcur_t pcur;
ulint err = DB_SUCCESS;
- unsigned allow_duplicates;
+ ulint allow_duplicates;
mtr_t mtr;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
@@ -1693,7 +1696,7 @@ row_ins_scan_sec_index_for_duplicate(
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
- allow_duplicates = thr_get_trx(thr)->duplicates & TRX_DUP_IGNORE;
+ allow_duplicates = thr_get_trx(thr)->duplicates;
/* Scan index records and check if there is a duplicate */
@@ -1827,7 +1830,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
- if (trx->duplicates & TRX_DUP_IGNORE) {
+ if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@@ -1871,7 +1874,7 @@ row_ins_duplicate_error_in_clust(
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
- if (trx->duplicates & TRX_DUP_IGNORE) {
+ if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
index c4911400cee..6f689f9909d 100644
--- a/storage/innodb_plugin/row/row0mysql.c
+++ b/storage/innodb_plugin/row/row0mysql.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved.
+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 the Free Software
@@ -3221,6 +3221,19 @@ check_next_foreign:
"index_id CHAR;\n"
"foreign_id CHAR;\n"
"found INT;\n"
+
+ "DECLARE CURSOR cur_fk IS\n"
+ "SELECT ID FROM SYS_FOREIGN\n"
+ "WHERE FOR_NAME = :table_name\n"
+ "AND TO_BINARY(FOR_NAME)\n"
+ " = TO_BINARY(:table_name)\n"
+ "LOCK IN SHARE MODE;\n"
+
+ "DECLARE CURSOR cur_idx IS\n"
+ "SELECT ID FROM SYS_INDEXES\n"
+ "WHERE TABLE_ID = table_id\n"
+ "LOCK IN SHARE MODE;\n"
+
"BEGIN\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
@@ -3243,13 +3256,9 @@ check_next_foreign:
"IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
" found := 0;\n"
"END IF;\n"
+ "OPEN cur_fk;\n"
"WHILE found = 1 LOOP\n"
- " SELECT ID INTO foreign_id\n"
- " FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = :table_name\n"
- " AND TO_BINARY(FOR_NAME)\n"
- " = TO_BINARY(:table_name)\n"
- " LOCK IN SHARE MODE;\n"
+ " FETCH cur_fk INTO foreign_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -3259,12 +3268,11 @@ check_next_foreign:
" WHERE ID = foreign_id;\n"
" END IF;\n"
"END LOOP;\n"
+ "CLOSE cur_fk;\n"
"found := 1;\n"
+ "OPEN cur_idx;\n"
"WHILE found = 1 LOOP\n"
- " SELECT ID INTO index_id\n"
- " FROM SYS_INDEXES\n"
- " WHERE TABLE_ID = table_id\n"
- " LOCK IN SHARE MODE;\n"
+ " FETCH cur_idx INTO index_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -3275,6 +3283,7 @@ check_next_foreign:
" AND TABLE_ID = table_id;\n"
" END IF;\n"
"END LOOP;\n"
+ "CLOSE cur_idx;\n"
"DELETE FROM SYS_COLUMNS\n"
"WHERE TABLE_ID = table_id;\n"
"DELETE FROM SYS_TABLES\n"
@@ -3962,6 +3971,7 @@ end:
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, NULL);
trx->error_state = DB_SUCCESS;
+ err = DB_ERROR;
goto funct_exit;
}
diff --git a/storage/innodb_plugin/row/row0purge.c b/storage/innodb_plugin/row/row0purge.c
index 752a2ec9e83..4d4c1afc458 100644
--- a/storage/innodb_plugin/row/row0purge.c
+++ b/storage/innodb_plugin/row/row0purge.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
@@ -11,8 +11,8 @@ 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; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -406,7 +406,8 @@ row_purge_upd_exist_or_extern_func(
ut_ad(node);
- if (node->rec_type == TRX_UNDO_UPD_DEL_REC) {
+ if (node->rec_type == TRX_UNDO_UPD_DEL_REC
+ || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
goto skip_secondaries;
}
@@ -530,14 +531,14 @@ row_purge_parse_undo_rec(
roll_ptr_t roll_ptr;
ulint info_bits;
ulint type;
- ulint cmpl_info;
ut_ad(node && thr);
trx = thr_get_trx(thr);
- ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
- updated_extern, &undo_no, &table_id);
+ ptr = trx_undo_rec_get_pars(
+ node->undo_rec, &type, &node->cmpl_info,
+ updated_extern, &undo_no, &table_id);
node->rec_type = type;
if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) {
@@ -550,7 +551,8 @@ row_purge_parse_undo_rec(
node->table = NULL;
if (type == TRX_UNDO_UPD_EXIST_REC
- && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) {
+ && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE
+ && !(*updated_extern)) {
/* Purge requires no changes to indexes: we may return */
@@ -600,7 +602,7 @@ err_exit:
/* Read to the partial row the fields that occur in indexes */
- if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
+ if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
ptr = trx_undo_rec_get_partial_row(
ptr, clust_index, &node->row,
type == TRX_UNDO_UPD_DEL_REC,
diff --git a/storage/innodb_plugin/row/row0row.c b/storage/innodb_plugin/row/row0row.c
index 8e806a14a98..9cdbbe76e04 100644
--- a/storage/innodb_plugin/row/row0row.c
+++ b/storage/innodb_plugin/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.
@@ -130,12 +101,27 @@ row_build_index_entry(
dfield_copy(dfield, dfield2);
- if (dfield_is_null(dfield) || ind_field->prefix_len == 0) {
+ if (dfield_is_null(dfield)) {
+ continue;
+ }
+
+ if (ind_field->prefix_len == 0
+ && (!dfield_is_ext(dfield)
+ || dict_index_is_clust(index))) {
+ /* The dfield_copy() above suffices for
+ columns that are stored in-page, or for
+ clustered index record columns that are not
+ part of a column prefix in the PRIMARY KEY. */
continue;
}
- /* If a column prefix index, take only the prefix.
- Prefix-indexed columns may be externally stored. */
+ /* If the column is stored externally (off-page) in
+ the clustered index, it must be an ordering field in
+ the secondary index. In the Antelope format, only
+ prefix-indexed columns may be stored off-page in the
+ clustered index record. In the Barracuda format, also
+ fully indexed long CHAR or VARCHAR columns may be
+ stored off-page. */
ut_ad(col->ord_part);
if (UNIV_LIKELY_NULL(ext)) {
@@ -148,17 +134,41 @@ row_build_index_entry(
}
dfield_set_data(dfield, buf, len);
}
+
+ if (ind_field->prefix_len == 0) {
+ /* In the Barracuda format
+ (ROW_FORMAT=DYNAMIC or
+ ROW_FORMAT=COMPRESSED), we can have a
+ secondary index on an entire column
+ that is stored off-page in the
+ clustered index. As this is not a
+ prefix index (prefix_len == 0),
+ include the entire off-page column in
+ the secondary index record. */
+ continue;
+ }
} else if (dfield_is_ext(dfield)) {
+ /* This table is either in Antelope format
+ (ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT)
+ or a purge record where the ordered part of
+ the field is not external.
+ In Antelope, the maximum column prefix
+ index length is 767 bytes, and the clustered
+ index record contains a 768-byte prefix of
+ each off-page column. */
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));
+ dfield_set_len(dfield, len);
}
- len = dtype_get_at_most_n_mbchars(
- col->prtype, col->mbminlen, col->mbmaxlen,
- ind_field->prefix_len, len, dfield_get_data(dfield));
- dfield_set_len(dfield, len);
+ /* If a column prefix index, take only the prefix. */
+ if (ind_field->prefix_len) {
+ len = dtype_get_at_most_n_mbchars(
+ col->prtype, col->mbminlen, col->mbmaxlen,
+ ind_field->prefix_len, len,
+ dfield_get_data(dfield));
+ dfield_set_len(dfield, len);
+ }
}
ut_ad(dtuple_check_typed(entry));
@@ -223,6 +233,7 @@ row_build(
ut_ad(index && rec && heap);
ut_ad(dict_index_is_clust(index));
+ ut_ad(!mutex_own(&kernel_mutex));
if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_,
@@ -231,6 +242,22 @@ row_build(
ut_ad(rec_offs_validate(rec, index, offsets));
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* This condition can occur during crash recovery before
+ trx_rollback_active() has completed execution.
+
+ This condition is possible if the server crashed
+ during an insert or update before
+ btr_store_big_rec_extern_fields() did mtr_commit() all
+ BLOB pointers to the clustered index record.
+
+ If the record contains a null BLOB pointer, look up the
+ transaction that holds the implicit lock on this record, and
+ assert that it was recovered (and will soon be rolled back). */
+ ut_a(!rec_offs_any_null_extern(rec, offsets)
+ || trx_assert_recovered(row_get_rec_trx_id(rec, index, offsets)));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
@@ -415,6 +442,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);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ } else {
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}
entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);
diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c
index 423ddfade22..32f21dbe198 100644
--- a/storage/innodb_plugin/row/row0sel.c
+++ b/storage/innodb_plugin/row/row0sel.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -101,12 +101,17 @@ 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 prefix_len, /*!< in: index column prefix length
+ in bytes */
ulint zip_size) /*!< in: compressed page size, or 0 */
{
ulint len;
byte buf[DICT_MAX_INDEX_COL_LEN];
ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
+ ut_ad(prefix_len >= sec_len);
+ ut_ad(prefix_len > 0);
+ ut_a(prefix_len <= sizeof buf);
if (UNIV_UNLIKELY
(!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
@@ -118,7 +123,7 @@ row_sel_sec_rec_is_for_blob(
return(FALSE);
}
- len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
+ len = btr_copy_externally_stored_field_prefix(buf, prefix_len,
zip_size,
clust_field, clust_len);
@@ -132,7 +137,7 @@ row_sel_sec_rec_is_for_blob(
}
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
- sec_len, len, (const char*) buf);
+ prefix_len, len, (const char*) buf);
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
}
@@ -219,11 +224,20 @@ row_sel_sec_rec_is_for_clust_rec(
if (rec_offs_nth_extern(clust_offs, clust_pos)
&& len < sec_len) {
+ /* This function should never be
+ invoked on an Antelope format table,
+ because they should always contain
+ enough prefix in the clustered index
+ record. */
+ ut_ad(dict_table_get_format(clust_index->table)
+ >= DICT_TF_FORMAT_ZIP);
+
if (!row_sel_sec_rec_is_for_blob(
col->mtype, col->prtype,
col->mbminlen, col->mbmaxlen,
clust_field, clust_len,
sec_field, sec_len,
+ ifield->prefix_len,
dict_table_zip_size(
clust_index->table))) {
goto inequal;
@@ -494,7 +508,7 @@ sel_col_prefetch_buf_alloc(
sel_buf = column->prefetch_buf + i;
sel_buf->data = NULL;
-
+ sel_buf->len = 0;
sel_buf->val_buf_size = 0;
}
}
@@ -519,6 +533,8 @@ sel_col_prefetch_buf_free(
mem_free(sel_buf->data);
}
}
+
+ mem_free(prefetch_buf);
}
/*********************************************************************//**
@@ -2544,6 +2560,8 @@ row_sel_field_store_in_mysql_format(
ut_ad(len != UNIV_SQL_NULL);
UNIV_MEM_ASSERT_RW(data, len);
+ UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
+ UNIV_MEM_INVALID(dest, templ->mysql_col_len);
switch (templ->type) {
case DATA_INT:
@@ -2580,14 +2598,16 @@ row_sel_field_store_in_mysql_format(
dest = row_mysql_store_true_var_len(
dest, len, templ->mysql_length_bytes);
+ /* Copy the actual data. Leave the rest of the
+ buffer uninitialized. */
+ memcpy(dest, data, len);
+ break;
}
/* Copy the actual data */
ut_memcpy(dest, data, len);
- /* Pad with trailing spaces. We pad with spaces also the
- unused end of a >= 5.0.3 true VARCHAR column, just in case
- MySQL expects its contents to be deterministic. */
+ /* Pad with trailing spaces. */
pad_ptr = dest + len;
@@ -3120,6 +3140,39 @@ sel_restore_position_for_mysql(
}
/********************************************************************//**
+Copies a cached field for MySQL from the fetch cache. */
+static
+void
+row_sel_copy_cached_field_for_mysql(
+/*================================*/
+ byte* buf, /*!< in/out: row buffer */
+ const byte* cache, /*!< in: cached row */
+ const mysql_row_templ_t*templ) /*!< in: column template */
+{
+ ulint len;
+
+ buf += templ->mysql_col_offset;
+ cache += templ->mysql_col_offset;
+
+ UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len);
+
+ if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR
+ && templ->type != DATA_INT) {
+ /* Check for != DATA_INT to make sure we do
+ not treat MySQL ENUM or SET as a true VARCHAR!
+ Find the actual length of the true VARCHAR field. */
+ row_mysql_read_true_varchar(
+ &len, cache, templ->mysql_length_bytes);
+ len += templ->mysql_length_bytes;
+ UNIV_MEM_INVALID(buf, templ->mysql_col_len);
+ } else {
+ len = templ->mysql_col_len;
+ }
+
+ ut_memcpy(buf, cache, len);
+}
+
+/********************************************************************//**
Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE
void
@@ -3131,26 +3184,22 @@ row_sel_pop_cached_row_for_mysql(
{
ulint i;
const mysql_row_templ_t*templ;
- byte* cached_rec;
+ const byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
+ UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len);
+
+ cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first];
+
if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) {
/* Copy cache record field by field, don't touch fields that
are not covered by current key */
- cached_rec = prebuilt->fetch_cache[
- prebuilt->fetch_cache_first];
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(cached_rec
- + templ->mysql_col_offset,
- templ->mysql_col_len);
-#endif
- ut_memcpy(buf + templ->mysql_col_offset,
- cached_rec + templ->mysql_col_offset,
- templ->mysql_col_len);
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, templ);
/* Copy NULL bit of the current field from cached_rec
to buf */
if (templ->mysql_null_bit_mask) {
@@ -3160,17 +3209,24 @@ row_sel_pop_cached_row_for_mysql(
& (byte)templ->mysql_null_bit_mask;
}
}
+ } else if (prebuilt->mysql_prefix_len > 63) {
+ /* The record is long. Copy it field by field, in case
+ there are some long VARCHAR column of which only a
+ small length is being used. */
+ UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len);
+
+ /* First copy the NULL bits. */
+ ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len);
+ /* Then copy the requested fields. */
+
+ for (i = 0; i < prebuilt->n_template; i++) {
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, prebuilt->mysql_template + i);
+ }
+ } else {
+ ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len);
}
- else {
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
- [prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
-#endif
- ut_memcpy(buf,
- prebuilt->fetch_cache[prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
- }
+
prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++;
diff --git a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c
index 13134afd1aa..aec3dc19b86 100644
--- a/storage/innodb_plugin/row/row0upd.c
+++ b/storage/innodb_plugin/row/row0upd.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
diff --git a/storage/innodb_plugin/row/row0vers.c b/storage/innodb_plugin/row/row0vers.c
index d4fde0b939b..8a7bb842293 100644
--- a/storage/innodb_plugin/row/row0vers.c
+++ b/storage/innodb_plugin/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 */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(
+ version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_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);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(prev_version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
trx_id = row_get_rec_trx_id(prev_version, index, *offsets);
if (read_view_sees_trx_id(view, trx_id)) {
@@ -682,6 +691,10 @@ row_vers_build_for_semi_consistent_read(
/* We found a version that belongs to a
committed transaction: return it. */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (rec == version) {
*old_vers = rec;
err = DB_SUCCESS;
@@ -739,6 +752,9 @@ row_vers_build_for_semi_consistent_read(
version = prev_version;
*offsets = rec_get_offsets(version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}/* for (;;) */
if (heap) {
diff --git a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
index b1fc1ac67fd..8ad4c02e322 100644
--- a/storage/innodb_plugin/srv/srv0srv.c
+++ b/storage/innodb_plugin/srv/srv0srv.c
@@ -203,6 +203,8 @@ UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX;
+/* Switch to enable random read ahead. */
+UNIV_INTERN my_bool srv_random_read_ahead = FALSE;
/* User settable value of the number of pages that must be present
in the buffer cache and accessed sequentially for InnoDB to trigger a
readahead request. */
@@ -1906,6 +1908,8 @@ srv_export_innodb_status(void)
export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free;
export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
+ export_vars.innodb_buffer_pool_read_ahead_rnd
+ = buf_pool->stat.n_ra_pages_read_rnd;
export_vars.innodb_buffer_pool_read_ahead
= buf_pool->stat.n_ra_pages_read;
export_vars.innodb_buffer_pool_read_ahead_evicted
diff --git a/storage/innodb_plugin/sync/sync0rw.c b/storage/innodb_plugin/sync/sync0rw.c
index a5da606ad80..bc060319246 100644
--- a/storage/innodb_plugin/sync/sync0rw.c
+++ b/storage/innodb_plugin/sync/sync0rw.c
@@ -612,6 +612,9 @@ rw_lock_x_lock_func(
ibool spinning = FALSE;
ut_ad(rw_lock_validate(lock));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
i = 0;
@@ -766,7 +769,9 @@ rw_lock_add_debug_info(
rw_lock_debug_mutex_exit();
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
- sync_thread_add_level(lock, lock->level);
+ sync_thread_add_level(lock, lock->level,
+ lock_type == RW_LOCK_EX
+ && lock->lock_word < 0);
}
}
@@ -926,11 +931,13 @@ rw_lock_list_print_info(
putc('\n', file);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_exit(&(lock->mutex));
@@ -974,11 +981,13 @@ rw_lock_print(
putc('\n', stderr);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
}
diff --git a/storage/innodb_plugin/sync/sync0sync.c b/storage/innodb_plugin/sync/sync0sync.c
index 2be9d667705..3e66aaafef2 100644
--- a/storage/innodb_plugin/sync/sync0sync.c
+++ b/storage/innodb_plugin/sync/sync0sync.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, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -656,7 +656,7 @@ mutex_set_debug_info(
ut_ad(mutex);
ut_ad(file_name);
- sync_thread_add_level(mutex, mutex->level);
+ sync_thread_add_level(mutex, mutex->level, FALSE);
mutex->file_name = file_name;
mutex->line = line;
@@ -1083,8 +1083,9 @@ void
sync_thread_add_level(
/*==================*/
void* latch, /*!< in: pointer to a mutex or an rw-lock */
- ulint level) /*!< in: level in the latching order; if
+ ulint level, /*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
+ ibool relock) /*!< in: TRUE if re-entering an x-lock */
{
sync_level_t* array;
sync_level_t* slot;
@@ -1132,6 +1133,10 @@ sync_thread_add_level(
array = thread_slot->levels;
+ if (relock) {
+ goto levels_ok;
+ }
+
/* NOTE that there is a problem with _NODE and _LEAF levels: if the
B-tree height changes, then a leaf can change to an internal node
or the other way around. We do not know at present if this can cause
@@ -1155,7 +1160,6 @@ sync_thread_add_level(
case SYNC_DOUBLEWRITE:
case SYNC_BUF_POOL:
case SYNC_SEARCH_SYS:
- case SYNC_SEARCH_SYS_CONF:
case SYNC_TRX_LOCK_HEAP:
case SYNC_KERNEL:
case SYNC_IBUF_BITMAP_MUTEX:
@@ -1168,6 +1172,7 @@ sync_thread_add_level(
case SYNC_DICT_HEADER:
case SYNC_TRX_I_S_RWLOCK:
case SYNC_TRX_I_S_LAST_READ:
+ case SYNC_IBUF_MUTEX:
if (!sync_thread_levels_g(array, level, TRUE)) {
fprintf(stderr,
"InnoDB: sync_thread_levels_g(array, %lu)"
@@ -1231,22 +1236,33 @@ sync_thread_add_level(
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
break;
case SYNC_TREE_NODE_NEW:
- ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE)
- || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
+ ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE));
break;
case SYNC_INDEX_TREE:
- if (sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
- && sync_thread_levels_contain(array, SYNC_FSP)) {
- ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1,
- TRUE));
+ ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
+ break;
+ case SYNC_IBUF_TREE_NODE:
+ ut_a(sync_thread_levels_contain(array, SYNC_IBUF_INDEX_TREE)
+ || sync_thread_levels_g(array, SYNC_IBUF_TREE_NODE - 1,
+ TRUE));
+ break;
+ case SYNC_IBUF_TREE_NODE_NEW:
+ /* ibuf_add_free_page() allocates new pages for the
+ change buffer while only holding the tablespace
+ x-latch. These pre-allocated new pages may only be
+ taken in use while holding ibuf_mutex, in
+ btr_page_alloc_for_ibuf(). */
+ ut_a(sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
+ || sync_thread_levels_contain(array, SYNC_FSP));
+ break;
+ case SYNC_IBUF_INDEX_TREE:
+ if (sync_thread_levels_contain(array, SYNC_FSP)) {
+ ut_a(sync_thread_levels_g(array, level - 1, TRUE));
} else {
- ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1,
- TRUE));
+ ut_a(sync_thread_levels_g(
+ array, SYNC_IBUF_TREE_NODE - 1, TRUE));
}
break;
- case SYNC_IBUF_MUTEX:
- ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, TRUE));
- break;
case SYNC_IBUF_PESS_INSERT_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
@@ -1269,6 +1285,7 @@ sync_thread_add_level(
ut_error;
}
+levels_ok:
for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
slot = sync_thread_levels_get_nth(array, i);
diff --git a/storage/innodb_plugin/trx/trx0rec.c b/storage/innodb_plugin/trx/trx0rec.c
index f50e10ed756..2db98e029df 100644
--- a/storage/innodb_plugin/trx/trx0rec.c
+++ b/storage/innodb_plugin/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
@@ -1097,13 +1097,14 @@ trx_undo_rec_get_partial_row(
#endif /* !UNIV_HOTBACKUP */
/***********************************************************************//**
-Erases the unused undo log page end. */
-static
-void
+Erases the unused undo log page end.
+@return TRUE if the page contained something, FALSE if it was empty */
+static __attribute__((nonnull))
+ibool
trx_undo_erase_page_end(
/*====================*/
- page_t* undo_page, /*!< in: undo page whose end to erase */
- mtr_t* mtr) /*!< in: mtr */
+ page_t* undo_page, /*!< in/out: undo page whose end to erase */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint first_free;
@@ -1113,6 +1114,7 @@ trx_undo_erase_page_end(
(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free);
mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr);
+ return(first_free != TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
}
/***********************************************************//**
@@ -1180,6 +1182,9 @@ trx_undo_report_row_operation(
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
+#ifdef UNIV_DEBUG
+ int loop_count = 0;
+#endif /* UNIV_DEBUG */
rec_offs_init(offsets_);
ut_a(dict_index_is_clust(index));
@@ -1242,7 +1247,7 @@ trx_undo_report_row_operation(
mtr_start(&mtr);
- for (;;) {
+ do {
buf_block_t* undo_block;
page_t* undo_page;
ulint offset;
@@ -1271,7 +1276,31 @@ trx_undo_report_row_operation(
version the replicate page constructed using the log
records stays identical to the original page */
- trx_undo_erase_page_end(undo_page, &mtr);
+ if (!trx_undo_erase_page_end(undo_page, &mtr)) {
+ /* The record did not fit on an empty
+ undo page. Discard the freshly allocated
+ page and return an error. */
+
+ /* When we remove a page from an undo
+ log, this is analogous to a
+ pessimistic insert in a B-tree, and we
+ must reserve the counterpart of the
+ tree latch, which is the rseg
+ mutex. We must commit the mini-transaction
+ first, because it may be holding lower-level
+ latches, such as SYNC_FSP and SYNC_FSP_PAGE. */
+
+ mtr_commit(&mtr);
+ mtr_start(&mtr);
+
+ mutex_enter(&rseg->mutex);
+ trx_undo_free_last_page(trx, undo, &mtr);
+ mutex_exit(&rseg->mutex);
+
+ err = DB_TOO_BIG_RECORD;
+ goto err_exit;
+ }
+
mtr_commit(&mtr);
} else {
/* Success */
@@ -1291,16 +1320,15 @@ trx_undo_report_row_operation(
*roll_ptr = trx_undo_build_roll_ptr(
op_type == TRX_UNDO_INSERT_OP,
rseg->id, page_no, offset);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+ goto func_exit;
}
ut_ad(page_no == undo->last_page_no);
/* We have to extend the undo log by one page */
+ ut_ad(++loop_count < 2);
mtr_start(&mtr);
/* When we add a page to an undo log, this is analogous to
@@ -1312,18 +1340,19 @@ trx_undo_report_row_operation(
page_no = trx_undo_add_page(trx, undo, &mtr);
mutex_exit(&(rseg->mutex));
+ } while (UNIV_LIKELY(page_no != FIL_NULL));
- if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
- /* Did not succeed: out of space */
+ /* Did not succeed: out of space */
+ err = DB_OUT_OF_FILE_SPACE;
- mutex_exit(&(trx->undo_mutex));
- mtr_commit(&mtr);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(DB_OUT_OF_FILE_SPACE);
- }
+err_exit:
+ mutex_exit(&trx->undo_mutex);
+ mtr_commit(&mtr);
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
+ return(err);
}
/*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
@@ -1577,6 +1606,10 @@ trx_undo_prev_version_build(
return(DB_ERROR);
}
+# if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+# endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint n_ext;
diff --git a/storage/innodb_plugin/trx/trx0sys.c b/storage/innodb_plugin/trx/trx0sys.c
index 48963bc7e45..2aadcca2dae 100644
--- a/storage/innodb_plugin/trx/trx0sys.c
+++ b/storage/innodb_plugin/trx/trx0sys.c
@@ -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 "os0file.h"
@@ -1548,10 +1549,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. */
@@ -1583,6 +1586,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/innodb_plugin/trx/trx0trx.c b/storage/innodb_plugin/trx/trx0trx.c
index f0bbf220815..7f3a3fcb4bf 100644
--- a/storage/innodb_plugin/trx/trx0trx.c
+++ b/storage/innodb_plugin/trx/trx0trx.c
@@ -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;
/*************************************************************//**
Set detailed error message for the transaction. */
@@ -334,6 +337,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
@@ -463,6 +520,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"
@@ -541,6 +599,7 @@ trx_lists_init_at_db_start(void)
trx->conc_state
= TRX_PREPARED;
+ trx_n_prepared++;
} else {
fprintf(stderr,
"InnoDB: Since"
@@ -820,6 +879,11 @@ trx_commit_off_kernel(
|| 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
@@ -1857,6 +1921,7 @@ trx_prepare_off_kernel(
/*--------------------------------------*/
trx->conc_state = TRX_PREPARED;
+ trx_n_prepared++;
/*--------------------------------------*/
if (lsn) {
@@ -2031,10 +2096,11 @@ trx_get_trx_by_xid(
while (trx) {
/* Compare two X/Open XA transaction id's: their
length should be the same and binary comparison
- of gtrid_lenght+bqual_length bytes should be
+ of gtrid_length+bqual_length bytes should be
the same */
- if (trx->conc_state == TRX_PREPARED
+ 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,
diff --git a/storage/innodb_plugin/trx/trx0undo.c b/storage/innodb_plugin/trx/trx0undo.c
index 76e88948e41..746f0808643 100644
--- a/storage/innodb_plugin/trx/trx0undo.c
+++ b/storage/innodb_plugin/trx/trx0undo.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -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"
@@ -997,29 +998,28 @@ trx_undo_free_page(
}
/********************************************************************//**
-Frees an undo log page when there is also the memory object for the undo
-log. */
-static
+Frees the last undo log page.
+The caller must hold the rollback segment mutex. */
+UNIV_INTERN
void
-trx_undo_free_page_in_rollback(
-/*===========================*/
- trx_t* trx __attribute__((unused)), /*!< in: transaction */
- trx_undo_t* undo, /*!< in: undo log memory copy */
- ulint page_no,/*!< in: page number to free: must not be the
- header page */
- mtr_t* mtr) /*!< in: mtr which does not have a latch to any
- undo log page; the caller must have reserved
- the rollback segment mutex */
+trx_undo_free_last_page_func(
+/*==========================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log memory copy */
+ mtr_t* mtr) /*!< in/out: mini-transaction which does not
+ have a latch to any undo log page or which
+ has allocated the undo log page */
{
- ulint last_page_no;
-
- ut_ad(undo->hdr_page_no != page_no);
- ut_ad(mutex_own(&(trx->undo_mutex)));
+ ut_ad(mutex_own(&trx->undo_mutex));
+ ut_ad(undo->hdr_page_no != undo->last_page_no);
+ ut_ad(undo->size > 0);
- last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
- undo->hdr_page_no, page_no, mtr);
+ undo->last_page_no = trx_undo_free_page(
+ undo->rseg, FALSE, undo->space,
+ undo->hdr_page_no, undo->last_page_no, mtr);
- undo->last_page_no = last_page_no;
undo->size--;
}
@@ -1055,9 +1055,11 @@ Truncates an undo log from the end. This function is used during a rollback
to free space from an undo log. */
UNIV_INTERN
void
-trx_undo_truncate_end(
-/*==================*/
- trx_t* trx, /*!< in: transaction whose undo log it is */
+trx_undo_truncate_end_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction whose undo log it is */
+#endif /* UNIV_DEBUG */
trx_undo_t* undo, /*!< in: undo log */
undo_no_t limit) /*!< in: all undo records with undo number
>= this value should be truncated */
@@ -1083,18 +1085,7 @@ trx_undo_truncate_end(
rec = trx_undo_page_get_last_rec(undo_page, undo->hdr_page_no,
undo->hdr_offset);
- for (;;) {
- if (rec == NULL) {
- if (last_page_no == undo->hdr_page_no) {
-
- goto function_exit;
- }
-
- trx_undo_free_page_in_rollback(
- trx, undo, last_page_no, &mtr);
- break;
- }
-
+ while (rec) {
if (ut_dulint_cmp(trx_undo_rec_get_undo_no(rec), limit)
>= 0) {
/* Truncate at least this record off, maybe
@@ -1109,6 +1100,14 @@ trx_undo_truncate_end(
undo->hdr_offset);
}
+ if (last_page_no == undo->hdr_page_no) {
+
+ goto function_exit;
+ }
+
+ ut_ad(last_page_no == undo->last_page_no);
+ trx_undo_free_last_page(trx, undo, &mtr);
+
mtr_commit(&mtr);
}
@@ -1976,4 +1975,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/innodb_plugin/ut/ut0mem.c b/storage/innodb_plugin/ut/ut0mem.c
index bf55e4273b6..95fb2187b79 100644
--- a/storage/innodb_plugin/ut/ut0mem.c
+++ b/storage/innodb_plugin/ut/ut0mem.c
@@ -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
@@ -489,53 +489,6 @@ ut_strlcpy_rev(
return(src_size);
}
-/**********************************************************************//**
-Make a quoted copy of a NUL-terminated string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_memcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_strcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src) /*!< in: null-terminated string */
-{
- while (*src) {
- if ((*dest++ = *src++) == q) {
- *dest++ = q;
- }
- }
-
- return(dest);
-}
-
-/**********************************************************************//**
-Make a quoted copy of a fixed-length string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_strcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_memcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src, /*!< in: string to be quoted */
- ulint len) /*!< in: length of src */
-{
- const char* srcend = src + len;
-
- while (src < srcend) {
- if ((*dest++ = *src++) == q) {
- *dest++ = q;
- }
- }
-
- return(dest);
-}
-
#ifndef UNIV_HOTBACKUP
/**********************************************************************//**
Return the number of times s2 occurs in s1. Overlapping instances of s2
diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c
index 39c3cd27d33..18ea1fc3997 100644
--- a/storage/maria/ma_bitmap.c
+++ b/storage/maria/ma_bitmap.c
@@ -1413,7 +1413,7 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap,
uchar *page_end= data + bitmap->total_size;
uchar *best_data= 0;
uint min_size;
- uint best_area_size, best_prefix_area_size, best_suffix_area_size;
+ uint best_area_size, best_prefix_area_size;
uint page, size;
ulonglong best_prefix_bits;
DBUG_ENTER("allocate_full_pages");
@@ -1422,7 +1422,6 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap,
/* Following variables are only used if best_data is set */
LINT_INIT(best_prefix_bits);
LINT_INIT(best_prefix_area_size);
- LINT_INIT(best_suffix_area_size);
min_size= pages_needed;
if (!full_page && min_size > BLOB_SEGMENT_MIN_SIZE)
@@ -1494,7 +1493,6 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap,
best_area_size= area_size;
best_prefix_bits= prefix_bits;
best_prefix_area_size= prefix_area_size;
- best_suffix_area_size= suffix_area_size;
/* Prefer to put data in biggest possible area */
if (area_size <= pages_needed)
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
index ad5ec3fe2b9..6165e211566 100644
--- a/storage/maria/ma_blockrec.c
+++ b/storage/maria/ma_blockrec.c
@@ -5014,7 +5014,8 @@ static my_bool read_row_extent_info(MARIA_HA *info, uchar *buff,
MARIA_EXTENT_CURSOR extent;
MARIA_RECORD_POS *tail_pos;
uchar *data, *end_of_data;
- uint flag, row_extents, row_extents_size, field_lengths;
+ uint flag, row_extents, row_extents_size;
+ uint field_lengths __attribute__ ((unused));
uchar *extents, *end;
DBUG_ENTER("read_row_extent_info");
@@ -5049,6 +5050,10 @@ static my_bool read_row_extent_info(MARIA_HA *info, uchar *buff,
}
info->cur_row.extents_count= row_extents;
+ /*
+ field_lengths looks unused but get_key_length will
+ increment data, which is required as data it's used later.
+ */
if (share->base.max_field_lengths)
get_key_length(field_lengths, data);
@@ -6749,11 +6754,11 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info,
uint i;
uint res;
uint page_range;
- pgcache_page_no_t page, start_page;
+ pgcache_page_no_t page;
uchar *buff;
uint data_on_page= data_size;
- start_page= page= page_korr(header);
+ page= page_korr(header);
header+= PAGE_STORE_SIZE;
page_range= pagerange_korr(header);
header+= PAGERANGE_STORE_SIZE;
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index f4470f846f5..ef6484adbe9 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -5525,7 +5525,7 @@ static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param,
SORT_KEY_BLOCKS *key_block= sort_info->key_block;
MARIA_SHARE *share= sort_info->info->s;
- val_len=HA_FT_WLEN+share->base.rec_reflength;
+ val_len=HA_FT_WLEN+share->rec_reflength;
get_key_full_length_rdonly(a_len, a);
if (!ft_buf)
@@ -5535,7 +5535,7 @@ static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param,
and row format is NOT static - for _ma_dpointer not to garble offsets
*/
if ((share->base.key_reflength <=
- share->base.rec_reflength) &&
+ share->rec_reflength) &&
(share->options &
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
ft_buf= (SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length +
@@ -5627,7 +5627,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
my_off_t prev_block)
{
uint a_length,t_length,nod_flag;
- my_off_t filepos,key_file_length;
+ my_off_t filepos;
uchar *anc_buff,*lastkey;
MARIA_KEY_PARAM s_temp;
MARIA_KEYDEF *keyinfo=sort_param->keyinfo;
@@ -5673,8 +5673,8 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
tmp_key.keyinfo= keyinfo;
tmp_key.data= (uchar*) key;
- tmp_key.data_length= _ma_keylength(keyinfo, key) - share->base.rec_reflength;
- tmp_key.ref_length= share->base.rec_reflength;
+ tmp_key.data_length= _ma_keylength(keyinfo, key) - share->rec_reflength;
+ tmp_key.ref_length= share->rec_reflength;
t_length= (*keyinfo->pack_key)(&tmp_key, nod_flag,
(uchar*) 0, lastkey, lastkey, &s_temp);
@@ -5695,7 +5695,6 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
_ma_store_page_used(share, anc_buff, key_block->last_length);
bzero(anc_buff+key_block->last_length,
keyinfo->block_length- key_block->last_length);
- key_file_length=share->state.state.key_file_length;
if ((filepos= _ma_new(info, DFLT_INIT_HITS, &page_link)) == HA_OFFSET_ERROR)
DBUG_RETURN(1);
_ma_fast_unlock_key_del(info);
@@ -5806,7 +5805,7 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param)
int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param)
{
uint nod_flag,length;
- my_off_t filepos,key_file_length;
+ my_off_t filepos;
SORT_KEY_BLOCKS *key_block;
MARIA_SORT_INFO *sort_info= sort_param->sort_info;
myf myf_rw=sort_info->param->myf_rw;
@@ -5823,7 +5822,6 @@ int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param)
length= _ma_get_page_used(info->s, key_block->buff);
if (nod_flag)
_ma_kpointer(info,key_block->end_pos,filepos);
- key_file_length= info->s->state.state.key_file_length;
bzero(key_block->buff+length, keyinfo->block_length-length);
if ((filepos= _ma_new(info, DFLT_INIT_HITS, &page_link)) ==
HA_OFFSET_ERROR)
diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c
index 35a34d32713..208b39f3b32 100644
--- a/storage/maria/ma_ft_boolean_search.c
+++ b/storage/maria/ma_ft_boolean_search.c
@@ -344,7 +344,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
int subkeys=1;
my_bool can_go_down;
MARIA_HA *info=ftb->info;
- uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ uint off, extra=HA_FT_WLEN+info->s->rec_reflength;
uchar *lastkey_buf= ftbw->word+ftbw->off;
MARIA_KEY key;
LINT_INIT(off);
diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c
index 927f34f8b72..e0e1e2ce0d3 100644
--- a/storage/maria/ma_ft_nlq_search.c
+++ b/storage/maria/ma_ft_nlq_search.c
@@ -74,7 +74,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
uchar *keybuff= aio->keybuff;
MARIA_KEYDEF *keyinfo= info->s->keyinfo+aio->keynr;
my_off_t key_root=info->s->state.key_root[aio->keynr];
- uint extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ uint extra=HA_FT_WLEN+info->s->rec_reflength;
MARIA_KEY key;
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
float tmp_weight;
diff --git a/storage/maria/ma_ft_update.c b/storage/maria/ma_ft_update.c
index f38990efab9..e99366033b4 100644
--- a/storage/maria/ma_ft_update.c
+++ b/storage/maria/ma_ft_update.c
@@ -364,7 +364,7 @@ my_bool _ma_ft_convert_to_ft2(MARIA_HA *info, MARIA_KEY *key)
for (key_ptr+=length; key_ptr < end; key_ptr+=keyinfo->keylength)
{
tmp_key.data= key_ptr;
- if (_ma_ck_real_write_btree(info, key, &root, SEARCH_SAME))
+ if (_ma_ck_real_write_btree(info, &tmp_key, &root, SEARCH_SAME))
DBUG_RETURN(1);
}
diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c
index 71af3a011e3..48bb9cb13d0 100644
--- a/storage/maria/ma_key_recover.c
+++ b/storage/maria/ma_key_recover.c
@@ -944,7 +944,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
uchar *buff;
const uchar *header_end= header + head_length;
uint page_offset= 0, org_page_length;
- uint nod_flag, page_length, keypage_header, keynr;
+ uint page_length, keypage_header, keynr;
uint max_page_size= share->max_index_block_size;
int result;
MARIA_PAGE page;
@@ -972,7 +972,6 @@ uint _ma_apply_redo_index(MARIA_HA *info,
keynr= _ma_get_keynr(share, buff);
_ma_page_setup(&page, info, share->keyinfo + keynr, page_pos, buff);
- nod_flag= page.node;
org_page_length= page_length= page.size;
keypage_header= share->keypage_header;
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index a01e0949b68..6f70fdf34cf 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -2608,14 +2608,14 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer)
i < buffer->size;
i+= TRANSLOG_PAGE_SIZE, pg++)
{
+#ifndef DBUG_OFF
TRANSLOG_ADDRESS addr= (buffer->offset + i);
- TRANSLOG_VALIDATOR_DATA data;
+#endif
DBUG_PRINT("info", ("send log form %lu till %lu address: (%lu,0x%lx) "
"page #: %lu buffer size: %lu buffer: 0x%lx",
(ulong) i, (ulong) (i + TRANSLOG_PAGE_SIZE),
LSN_IN_PARTS(addr), (ulong) pg, (ulong) buffer->size,
(ulong) buffer));
- data.addr= &addr;
DBUG_ASSERT(log_descriptor.pagecache->block_size == TRANSLOG_PAGE_SIZE);
DBUG_ASSERT(i + TRANSLOG_PAGE_SIZE <= buffer->size);
if (translog_status != TRANSLOG_OK && translog_status != TRANSLOG_SHUTDOWN)
@@ -6557,16 +6557,12 @@ my_bool translog_scanner_init(LSN lsn,
TRANSLOG_SCANNER_DATA *scanner,
my_bool use_direct)
{
- TRANSLOG_VALIDATOR_DATA data;
DBUG_ENTER("translog_scanner_init");
DBUG_PRINT("enter", ("Scanner: 0x%lx LSN: (%lu,0x%lx)",
(ulong) scanner, LSN_IN_PARTS(lsn)));
DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY);
- data.addr= &scanner->page_addr;
- data.was_recovered= 0;
-
scanner->page_offset= LSN_OFFSET(lsn) % TRANSLOG_PAGE_SIZE;
scanner->fixed_horizon= fixed_horizon;
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index 498904f89a7..3f15749ced5 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -1834,8 +1834,7 @@ int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share, const char *org_name,
}
info->dfile.file= share->bitmap.file.file=
- my_open(share->data_file_name.str, share->mode | O_SHARE,
- MYF(MY_WME));
+ my_open(data_name, share->mode | O_SHARE, MYF(MY_WME));
return info->dfile.file >= 0 ? 0 : 1;
}
diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c
index 6f32a60c073..ea90b60ce12 100644
--- a/storage/maria/ma_rt_split.c
+++ b/storage/maria/ma_rt_split.c
@@ -380,7 +380,6 @@ int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page,
SplitStruct *stop;
double *coord_buf;
double *next_coord;
- double *old_coord;
int n_dim;
uchar *source_cur, *cur1, *cur2;
uchar *new_page_buff, *log_internal_copy, *log_internal_copy_ptr,
@@ -426,7 +425,6 @@ int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page,
maria_rtree_d_mbr(keyinfo->seg, key->data, key_data_length, cur->coords);
cur->key= key->data;
- old_coord= next_coord;
if (split_maria_rtree_node(task, max_keys + 1,
page->size + full_length + 2,
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c
index 629e07b872d..322bc4fcf20 100644
--- a/storage/maria/ma_write.c
+++ b/storage/maria/ma_write.c
@@ -364,9 +364,11 @@ err:
else
{
MARIA_KEY key;
- if (_ma_ck_delete(info,
- (*keyinfo->make_key)(info, &key, i, buff, record,
- filepos, info->trn->trid)))
+ if (keyinfo->ck_delete(info,
+ (*keyinfo->make_key)(info, &key, i, buff,
+ record,
+ filepos,
+ info->trn->trid)))
{
if (local_lock_tree)
rw_unlock(&keyinfo->root_lock);
@@ -834,7 +836,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key,
{
if (share->max_index_block_size - a_length < 32 &&
(keyinfo->flag & HA_FULLTEXT) && key_pos == endpos &&
- share->base.key_reflength <= share->base.rec_reflength &&
+ share->base.key_reflength <= share->rec_reflength &&
share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
{
/*
diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c
index 983a38e69e7..c87ecfa7776 100644
--- a/storage/maria/maria_pack.c
+++ b/storage/maria/maria_pack.c
@@ -3070,7 +3070,6 @@ static int mrg_rrnd(PACK_MRG_INFO *info,uchar *buf)
{
int error;
MARIA_HA *isam_info;
- my_off_t filepos;
if (!info->current)
{
@@ -3095,7 +3094,6 @@ static int mrg_rrnd(PACK_MRG_INFO *info,uchar *buf)
return(HA_ERR_END_OF_FILE);
info->current++;
isam_info= *info->current;
- filepos=isam_info->s->pack.header_length;
maria_reset(isam_info);
maria_extra(isam_info,HA_EXTRA_CACHE, 0);
if ((error= maria_scan_init(isam_info)))
diff --git a/storage/myisam/CMakeLists.txt b/storage/myisam/CMakeLists.txt
index ce27c209418..5185aee4ed6 100644
--- a/storage/myisam/CMakeLists.txt
+++ b/storage/myisam/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index 3a6368f338d..65d5c5ca44c 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2001-2005 MySQL AB
+/*
+ Copyright (c) 2001-2007 MySQL AB, 2008-2010 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
@@ -358,7 +361,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
int subkeys=1;
my_bool can_go_down;
MI_INFO *info=ftb->info;
- uint UNINIT_VAR(off), extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ uint UNINIT_VAR(off), extra= HA_FT_WLEN + info->s->rec_reflength;
uchar *lastkey_buf=ftbw->word+ftbw->off;
if (ftbw->flags & FTB_FLAG_TRUNC)
diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c
index a00fa8e840c..5f2334d20a1 100644
--- a/storage/myisam/ft_nlq_search.c
+++ b/storage/myisam/ft_nlq_search.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2001-2005 MySQL AB
+/*
+ Copyright (c) 2001, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
@@ -73,7 +75,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
uchar *keybuff=aio->keybuff;
MI_KEYDEF *keyinfo=info->s->keyinfo+aio->keynr;
my_off_t key_root=info->s->state.key_root[aio->keynr];
- uint extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ uint extra= HA_FT_WLEN + info->s->rec_reflength;
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
float tmp_weight;
#else
diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c
index 0609157f1a0..545ccaabaf8 100644
--- a/storage/myisam/ft_parser.c
+++ b/storage/myisam/ft_parser.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2005 MySQL AB
+/*
+ Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c
index 5bfbf7e6c61..ffbf521f28a 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
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/ftdefs.h b/storage/myisam/ftdefs.h
index b26fa523b42..a87430969a3 100644
--- a/storage/myisam/ftdefs.h
+++ b/storage/myisam/ftdefs.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2005 MySQL AB
+/*
+ Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
diff --git a/storage/myisam/fulltext.h b/storage/myisam/fulltext.h
index 9aef2d0d002..626742215f2 100644
--- a/storage/myisam/fulltext.h
+++ b/storage/myisam/fulltext.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Written by Sergei A. Golubchik, who has a shared copyright to this code */
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 13d59b63527..f0a6eb3ea39 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
#ifdef USE_PRAGMA_IMPLEMENTATION
@@ -1168,6 +1170,18 @@ int ha_myisam::repair(THD *thd, HA_CHECK &param, bool do_optimize)
mi_get_mask_all_keys_active(share->base.keys) :
share->state.key_map);
ulonglong testflag= param.testflag;
+#ifdef HAVE_MMAP
+ bool remap= test(share->file_map);
+ /*
+ mi_repair*() functions family use file I/O even if memory
+ mapping is available.
+
+ Since mixing mmap I/O and file I/O may cause various artifacts,
+ memory mapping must be disabled.
+ */
+ if (remap)
+ mi_munmap_file(file);
+#endif
if (mi_test_if_sort_rep(file,file->state->records,key_map,0) &&
(local_testflag & T_REP_BY_SORT))
{
@@ -1200,6 +1214,10 @@ int ha_myisam::repair(THD *thd, HA_CHECK &param, bool do_optimize)
test(param.testflag & T_QUICK));
}
param.testflag= testflag | (param.testflag & T_RETRY_WITHOUT_QUICK);
+#ifdef HAVE_MMAP
+ if (remap)
+ mi_dynmap_file(file, file->state->data_file_length);
+#endif
optimize_done=1;
}
if (!error)
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index e6ad6b03476..3a3b5536a30 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
#ifdef USE_PRAGMA_INTERFACE
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 0e5da184f58..36c79b3d12f 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Describe, check and repair of MyISAM tables */
@@ -941,7 +943,7 @@ static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend)
{
int error,got_error,flag;
- uint key,UNINIT_VAR(left_length),b_type,field;
+ uint key, UNINIT_VAR(left_length), b_type;
ha_rows records,del_blocks;
my_off_t used,empty,pos,splits,UNINIT_VAR(start_recpos),
del_length,link_used,start_block;
@@ -949,7 +951,6 @@ int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend)
char llbuff[22],llbuff2[22],llbuff3[22];
ha_checksum intern_record_checksum;
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
- my_bool static_row_size;
MI_KEYDEF *keyinfo;
MI_BLOCK_INFO block_info;
DBUG_ENTER("chk_data_link");
@@ -973,21 +974,6 @@ int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend)
got_error=error=0;
empty=info->s->pack.header_length;
- /* Check how to calculate checksum of rows */
- static_row_size=1;
- if (info->s->data_file_type == COMPRESSED_RECORD)
- {
- for (field=0 ; field < info->s->base.fields ; field++)
- {
- if (info->s->rec[field].base_type == FIELD_BLOB ||
- info->s->rec[field].base_type == FIELD_VARCHAR)
- {
- static_row_size=0;
- break;
- }
- }
- }
-
pos=my_b_tell(&param->read_cache);
bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0]));
while (pos < info->state->data_file_length)
@@ -3943,7 +3929,7 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
SORT_FT_BUF *ft_buf=sort_info->ft_buf;
SORT_KEY_BLOCKS *key_block=sort_info->key_block;
- val_len=HA_FT_WLEN+sort_info->info->s->base.rec_reflength;
+ val_len= HA_FT_WLEN + sort_info->info->s->rec_reflength;
get_key_full_length_rdonly(a_len, (uchar *)a);
if (!ft_buf)
@@ -3953,7 +3939,7 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
and row format is NOT static - for _mi_dpointer not to garble offsets
*/
if ((sort_info->info->s->base.key_reflength <=
- sort_info->info->s->base.rec_reflength) &&
+ sort_info->info->s->rec_reflength) &&
(sort_info->info->s->options &
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
ft_buf=(SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length +
diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c
index 6173f8b3bff..c6e6289ffe1 100644
--- a/storage/myisam/mi_close.c
+++ b/storage/myisam/mi_close.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2004 MySQL AB
+/*
+ Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* close a isam-database */
/*
diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c
index f40f1bad710..21b683d0d4d 100644
--- a/storage/myisam/mi_create.c
+++ b/storage/myisam/mi_create.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Create a MyISAM table */
diff --git a/storage/myisam/mi_dbug.c b/storage/myisam/mi_dbug.c
index ab85ece07ab..c942d17218d 100644
--- a/storage/myisam/mi_dbug.c
+++ b/storage/myisam/mi_dbug.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2005 MySQL AB
+/*
+ Copyright (c) 2000-2006 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Support rutiner with are using with dbug */
diff --git a/storage/myisam/mi_delete.c b/storage/myisam/mi_delete.c
index 3bc0c2296ee..97456037c38 100644
--- a/storage/myisam/mi_delete.c
+++ b/storage/myisam/mi_delete.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Remove a row from a MyISAM table */
diff --git a/storage/myisam/mi_delete_all.c b/storage/myisam/mi_delete_all.c
index f1c654b0396..3c5e0638334 100644
--- a/storage/myisam/mi_delete_all.c
+++ b/storage/myisam/mi_delete_all.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2003, 2005 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Remove all rows from a MyISAM table */
/* This clears the status information and truncates files */
@@ -62,11 +64,6 @@ int mi_delete_all_rows(MI_INFO *info)
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err;
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
-#ifdef HAVE_MMAP
- /* Map again */
- if (share->file_map)
- mi_dynmap_file(info, (my_off_t) 0);
-#endif
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
diff --git a/storage/myisam/mi_delete_table.c b/storage/myisam/mi_delete_table.c
index c4797187bec..1b533cffb68 100644
--- a/storage/myisam/mi_delete_table.c
+++ b/storage/myisam/mi_delete_table.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2001, 2004, 2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/*
deletes a table
diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c
index f08e9f32a3f..417a542f33d 100644
--- a/storage/myisam/mi_dynrec.c
+++ b/storage/myisam/mi_dynrec.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/*
Functions to handle space-packed-records and blobs
diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c
index 7b8f5249b3e..d6dddeb9ed7 100644
--- a/storage/myisam/mi_extra.c
+++ b/storage/myisam/mi_extra.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2005 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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 "myisamdef.h"
#ifdef HAVE_SYS_MMAN_H
diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c
index 97011831af8..06eed31847b 100644
--- a/storage/myisam/mi_locking.c
+++ b/storage/myisam/mi_locking.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/*
locking of isam-tables.
diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c
index 9d69f8622e8..d3ecdf7239a 100644
--- a/storage/myisam/mi_open.c
+++ b/storage/myisam/mi_open.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* open a isam-database */
diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c
index a3c700794f9..7b90ba8276b 100644
--- a/storage/myisam/mi_packrec.c
+++ b/storage/myisam/mi_packrec.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Functions to compressed records */
diff --git a/storage/myisam/mi_page.c b/storage/myisam/mi_page.c
index 82acb801c90..d458437337c 100644
--- a/storage/myisam/mi_page.c
+++ b/storage/myisam/mi_page.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2004, 2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Read and write key blocks */
diff --git a/storage/myisam/mi_preload.c b/storage/myisam/mi_preload.c
index 115f0f0c70c..a2d751a709c 100644
--- a/storage/myisam/mi_preload.c
+++ b/storage/myisam/mi_preload.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2003, 2005 MySQL AB
+/*
+ Copyright (c) 2003, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/*
Preload indexes into key cache
diff --git a/storage/myisam/mi_range.c b/storage/myisam/mi_range.c
index 60d51637591..dde337c27e5 100644
--- a/storage/myisam/mi_range.c
+++ b/storage/myisam/mi_range.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2004, 2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/*
Gives a approximated number of how many records there is between two keys.
diff --git a/storage/myisam/mi_rnext.c b/storage/myisam/mi_rnext.c
index b9bbda3cacb..6c23bee92ee 100644
--- a/storage/myisam/mi_rnext.c
+++ b/storage/myisam/mi_rnext.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2004 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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 "myisamdef.h"
diff --git a/storage/myisam/mi_search.c b/storage/myisam/mi_search.c
index 1f8399f25ca..153064cb360 100644
--- a/storage/myisam/mi_search.c
+++ b/storage/myisam/mi_search.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* key handling functions */
diff --git a/storage/myisam/mi_static.c b/storage/myisam/mi_static.c
index 27485e101ff..67588791886 100644
--- a/storage/myisam/mi_static.c
+++ b/storage/myisam/mi_static.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2002, 2004-2005 MySQL AB
+/*
+ Copyright (c) 2000-2002, 2004-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/*
Static variables for MyISAM library. All definied here for easy making of
diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c
index 8cde271282e..c93cdc6fe21 100644
--- a/storage/myisam/mi_test1.c
+++ b/storage/myisam/mi_test1.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2005 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Testing of the basic functions of a MyISAM table */
diff --git a/storage/myisam/mi_test2.c b/storage/myisam/mi_test2.c
index 444d1970913..24fbdc57bbb 100644
--- a/storage/myisam/mi_test2.c
+++ b/storage/myisam/mi_test2.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Test av isam-databas: stor test */
diff --git a/storage/myisam/mi_unique.c b/storage/myisam/mi_unique.c
index fdba84a2e67..0725f6f9354 100644
--- a/storage/myisam/mi_unique.c
+++ b/storage/myisam/mi_unique.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Functions to check if a row is unique */
diff --git a/storage/myisam/mi_update.c b/storage/myisam/mi_update.c
index 7a7c37c546d..3f0eca95101 100644
--- a/storage/myisam/mi_update.c
+++ b/storage/myisam/mi_update.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Update an old row in a MyISAM table */
@@ -193,8 +195,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 +214,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;
}
}
diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c
index 8229dfef9a5..e344105774c 100644
--- a/storage/myisam/mi_write.c
+++ b/storage/myisam/mi_write.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Write a row to a MyISAM table */
@@ -211,7 +213,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)
rw_unlock(&share->key_root_lock[i]);
@@ -526,7 +528,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
if (keyinfo->block_length - a_length < 32 &&
keyinfo->flag & HA_FULLTEXT && key_pos == endpos &&
- info->s->base.key_reflength <= info->s->base.rec_reflength &&
+ info->s->base.key_reflength <= info->s->rec_reflength &&
info->s->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
{
/*
diff --git a/storage/myisam/myisam_ftdump.c b/storage/myisam/myisam_ftdump.c
index 4436d06e36b..039d04058e4 100644
--- a/storage/myisam/myisam_ftdump.c
+++ b/storage/myisam/myisam_ftdump.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2001-2006 MySQL AB
+/*
+ Copyright (c) 2001, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Written by Sergei A. Golubchik, who has a shared copyright to this code
added support for long options (my_getopt) 22.5.2002 by Jani Tolonen */
diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c
index 83a106c7941..6277bd1b7de 100644
--- a/storage/myisam/myisamchk.c
+++ b/storage/myisam/myisamchk.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* Describe, check and repair of MyISAM tables */
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index f6f58236423..84d133566f9 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* This file is included by all internal myisam files */
diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c
index c441acf6c3f..095a0347753 100644
--- a/storage/myisam/myisamlog.c
+++ b/storage/myisam/myisamlog.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* write whats in isam.log */
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index f1b9e04c474..eaf78b38c02 100644
--- a/storage/myisam/myisampack.c
+++ b/storage/myisam/myisampack.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2007 MySQL AB
+/* Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +11,8 @@
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
+*/
/* Pack MyISAM file */
diff --git a/storage/myisam/rt_split.c b/storage/myisam/rt_split.c
index 0b7cc43e062..ffd100fe5d4 100644
--- a/storage/myisam/rt_split.c
+++ b/storage/myisam/rt_split.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2002-2005 MySQL AB & Alexey Botchkov
+/*
+ Copyright (c) 2002, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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 "myisamdef.h"
diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c
index 5274d8da5ca..b67f77654ad 100644
--- a/storage/myisam/sort.c
+++ b/storage/myisam/sort.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/*
Creates a index for a database by reading keys, sorting them and outputing
diff --git a/storage/myisam/sp_test.c b/storage/myisam/sp_test.c
index 7a30a742fd6..20733df2fe3 100644
--- a/storage/myisam/sp_test.c
+++ b/storage/myisam/sp_test.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2004 MySQL AB
+/* Copyright (c) 2002, 2011, Oracle and/or its affiliates
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/myisammrg/CMakeLists.txt b/storage/myisammrg/CMakeLists.txt
index c545d04a780..172e0e8afc5 100755
--- a/storage/myisammrg/CMakeLists.txt
+++ b/storage/myisammrg/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Copyright (C) 2006 MySQL AB
+# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# 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/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index a168decd6c8..274ba2fcd81 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +11,8 @@
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
+*/
/*
diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h
index aa8f8d3e2be..c0334c35c66 100644
--- a/storage/myisammrg/ha_myisammrg.h
+++ b/storage/myisammrg/ha_myisammrg.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2011, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
#ifdef USE_PRAGMA_INTERFACE
diff --git a/storage/myisammrg/myrg_create.c b/storage/myisammrg/myrg_create.c
index eaed470daec..2720aeae894 100644
--- a/storage/myisammrg/myrg_create.c
+++ b/storage/myisammrg/myrg_create.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2001, 2005 MySQL AB
+/*
+ Copyright (c) 2000, 2001, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Create a MYMERGE_-file */
diff --git a/storage/myisammrg/myrg_info.c b/storage/myisammrg/myrg_info.c
index 1930351ec8f..67a403e7643 100644
--- a/storage/myisammrg/myrg_info.c
+++ b/storage/myisammrg/myrg_info.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2002 MySQL AB
+/*
+ Copyright (c) 2000-2002, 2005, 2006 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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 "myrg_def.h"
diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c
index ba452854808..2a74e56a8ae 100644
--- a/storage/myisammrg/myrg_open.c
+++ b/storage/myisammrg/myrg_open.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/*
+ Copyright (c) 2000, 2010, Oracle and/or its affiliates
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
@@ -11,7 +12,8 @@
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
+*/
/* open a MyISAM MERGE table */
diff --git a/storage/myisammrg/myrg_rkey.c b/storage/myisammrg/myrg_rkey.c
index c00ca79056f..3b14e8ce3b6 100644
--- a/storage/myisammrg/myrg_rkey.c
+++ b/storage/myisammrg/myrg_rkey.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000-2003, 2005 MySQL AB
+/*
+ Copyright (c) 2000-2003, 2005-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +13,8 @@
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
+*/
/* Read record based on a key */
diff --git a/storage/mysql_storage_engine.cmake b/storage/mysql_storage_engine.cmake
index b29ba961179..cbe9a310d67 100644
--- a/storage/mysql_storage_engine.cmake
+++ b/storage/mysql_storage_engine.cmake
@@ -1,3 +1,19 @@
+# Copyright (c) 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
+#
+# 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
+
# MYSQL_STORAGE_ENGINE Macro creates a project to build storage engine
# library.
#
diff --git a/storage/ndb/MAINTAINERS b/storage/ndb/MAINTAINERS
index d1547d48234..38f504cd1a1 100644
--- a/storage/ndb/MAINTAINERS
+++ b/storage/ndb/MAINTAINERS
@@ -1,3 +1,5 @@
+Copyright (c) 2007 MySQL AB
+
MySQL Cluster MAINTAINERS
-------------------------
diff --git a/storage/ndb/config/win-lib.am b/storage/ndb/config/win-lib.am
index 05ac1ec8a40..1b3d772cf17 100644
--- a/storage/ndb/config/win-lib.am
+++ b/storage/ndb/config/win-lib.am
@@ -1,5 +1,22 @@
# Microsoft Developer Studio Project File - Name="@name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
+
+# Copyright (c) 2004, 2005 MySQL AB
+# Use is subject to license terms.
+#
+# 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
+
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
diff --git a/storage/ndb/config/win-prg.am b/storage/ndb/config/win-prg.am
index 70c19a70c6d..e234f74abc7 100644
--- a/storage/ndb/config/win-prg.am
+++ b/storage/ndb/config/win-prg.am
@@ -1,5 +1,22 @@
# Microsoft Developer Studio Project File - Name="mysqld" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
+
+# Copyright (c) 2004, 2006 MySQL AB
+# Use is subject to license terms.
+#
+# 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
+
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
diff --git a/storage/ndb/include/mgmapi/ndb_logevent.h b/storage/ndb/include/mgmapi/ndb_logevent.h
index 519c13b2ca9..d491275df01 100644
--- a/storage/ndb/include/mgmapi/ndb_logevent.h
+++ b/storage/ndb/include/mgmapi/ndb_logevent.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 */
#ifndef NDB_LOGEVENT_H
#define NDB_LOGEVENT_H
diff --git a/storage/ndb/include/ndbapi/NdbEventOperation.hpp b/storage/ndb/include/ndbapi/NdbEventOperation.hpp
index 0f98a4debef..3e7601e4f50 100644
--- a/storage/ndb/include/ndbapi/NdbEventOperation.hpp
+++ b/storage/ndb/include/ndbapi/NdbEventOperation.hpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2007 MySQL AB, 2010 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 */
#ifndef NdbEventOperation_H
#define NdbEventOperation_H
diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp
index 713c29f028d..65cb308000b 100644
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2007 MySQL AB, 2010 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 */
#ifndef NdbOperation_H
#define NdbOperation_H
diff --git a/storage/ndb/src/common/portlib/NdbMutex.c b/storage/ndb/src/common/portlib/NdbMutex.c
index 5595baba7c4..6edab9f23ea 100644
--- a/storage/ndb/src/common/portlib/NdbMutex.c
+++ b/storage/ndb/src/common/portlib/NdbMutex.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003, 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
@@ -11,7 +11,7 @@
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 <ndb_global.h>
diff --git a/storage/ndb/src/common/util/Makefile.am b/storage/ndb/src/common/util/Makefile.am
index 4a69924192e..87ec96fe1e3 100644
--- a/storage/ndb/src/common/util/Makefile.am
+++ b/storage/ndb/src/common/util/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2004-2005 MySQL AB
+# Copyright (c) 2004, 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/ndb/src/kernel/blocks/backup/read.cpp b/storage/ndb/src/kernel/blocks/backup/read.cpp
index 78f6f2f1b50..ebe769ede24 100644
--- a/storage/ndb/src/kernel/blocks/backup/read.cpp
+++ b/storage/ndb/src/kernel/blocks/backup/read.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2006 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <ndb_global.h>
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 8f8d4aad9ab..b42e16cd6a3 100644
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <ndb_global.h>
#include <my_sys.h>
diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 11e8c1cc191..09cc1c9f162 100644
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 */
#define DBLQH_C
#include "Dblqh.hpp"
diff --git a/storage/ndb/src/kernel/blocks/lgman.cpp b/storage/ndb/src/kernel/blocks/lgman.cpp
index 53cb1e113e1..84333889e42 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) 2005, 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/kernel/blocks/ndbfs/AsyncFile.cpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index c107baca39f..841ed49e36f 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <ndb_global.h>
#include <my_sys.h>
diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.cpp b/storage/ndb/src/kernel/blocks/suma/Suma.cpp
index 9179cf7fbbd..bfcb74cbd04 100644
--- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp
+++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <my_config.h>
#include "Suma.hpp"
diff --git a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
index 560a9559999..42ce36221d7 100644
--- a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
+++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <ndb_global.h>
diff --git a/storage/ndb/src/mgmsrv/Makefile.am b/storage/ndb/src/mgmsrv/Makefile.am
index 3ae70155554..593e9e3d292 100644
--- a/storage/ndb/src/mgmsrv/Makefile.am
+++ b/storage/ndb/src/mgmsrv/Makefile.am
@@ -1,4 +1,5 @@
-# Copyright (C) 2004-2006 MySQL AB
+# Copyright (c) 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/storage/ndb/src/ndbapi/DictCache.cpp b/storage/ndb/src/ndbapi/DictCache.cpp
index 9c66b2be9d2..13bf8b63cee 100644
--- a/storage/ndb/src/ndbapi/DictCache.cpp
+++ b/storage/ndb/src/ndbapi/DictCache.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003, 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
@@ -11,7 +11,7 @@
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 <ndb_global.h>
#include "DictCache.hpp"
diff --git a/storage/ndb/src/ndbapi/NdbEventOperation.cpp b/storage/ndb/src/ndbapi/NdbEventOperation.cpp
index 1353ca40e95..308a91808ca 100644
--- a/storage/ndb/src/ndbapi/NdbEventOperation.cpp
+++ b/storage/ndb/src/ndbapi/NdbEventOperation.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2007 MySQL AB, 2010 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <Ndb.hpp>
diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
index ed60650e33e..004e28c43a5 100644
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2007 MySQL AB, 2010 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <ndb_global.h>
diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
index c027226584c..2f4bb18ba8e 100644
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2007 MySQL AB, 2010 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 */
#ifndef NdbEventOperationImpl_H
#define NdbEventOperationImpl_H
diff --git a/storage/ndb/test/run-test/Makefile.am b/storage/ndb/test/run-test/Makefile.am
index e1bc71fb4a9..78be2471d90 100644
--- a/storage/ndb/test/run-test/Makefile.am
+++ b/storage/ndb/test/run-test/Makefile.am
@@ -1,4 +1,5 @@
-# Copyright (C) 2004-2006 MySQL AB
+# Copyright (c) 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+# Use is subject to license terms.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/storage/ndb/test/run-test/atrt.hpp b/storage/ndb/test/run-test/atrt.hpp
index db26bd9bfc0..39f7e1a7bf2 100644
--- a/storage/ndb/test/run-test/atrt.hpp
+++ b/storage/ndb/test/run-test/atrt.hpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2003-2007 MySQL AB, 2008 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 */
#ifndef atrt_config_hpp
#define atrt_config_hpp
diff --git a/storage/ndb/test/run-test/autotest-boot.sh b/storage/ndb/test/run-test/autotest-boot.sh
index 1df3a26cc8a..f1f8aea2519 100644
--- a/storage/ndb/test/run-test/autotest-boot.sh
+++ b/storage/ndb/test/run-test/autotest-boot.sh
@@ -1,4 +1,21 @@
#!/bin/sh
+
+# Copyright (c) 2007 MySQL AB
+# Use is subject to license terms.
+#
+# 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
+
#############################################################
# 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/autotest-run.sh b/storage/ndb/test/run-test/autotest-run.sh
index b543cd1efb9..0c9c6aee215 100644
--- a/storage/ndb/test/run-test/autotest-run.sh
+++ b/storage/ndb/test/run-test/autotest-run.sh
@@ -1,4 +1,21 @@
#!/bin/sh
+
+# Copyright (c) 2007 MySQL AB
+# Use is subject to license terms.
+#
+# 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
+
#############################################################
# 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/files.cpp b/storage/ndb/test/run-test/files.cpp
index c6a29350b91..294d0aca56e 100644
--- a/storage/ndb/test/run-test/files.cpp
+++ b/storage/ndb/test/run-test/files.cpp
@@ -1,3 +1,21 @@
+/*
+ Copyright (c) 2007 MySQL AB
+ Use is subject to license terms.
+
+ 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
+*/
+
#include "atrt.hpp"
#include <sys/types.h>
#include <dirent.h>
diff --git a/storage/ndb/test/run-test/setup.cpp b/storage/ndb/test/run-test/setup.cpp
index cbb7a34f171..b52f9bbda76 100644
--- a/storage/ndb/test/run-test/setup.cpp
+++ b/storage/ndb/test/run-test/setup.cpp
@@ -1,3 +1,21 @@
+/*
+ Copyright (c) 2007 MySQL AB
+ Use is subject to license terms.
+
+ 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
+*/
+
#include "atrt.hpp"
#include <ndb_global.h>
#include <my_sys.h>
diff --git a/storage/ndb/test/run-test/upgrade-boot.sh b/storage/ndb/test/run-test/upgrade-boot.sh
index d3542166551..745418dbb7c 100644
--- a/storage/ndb/test/run-test/upgrade-boot.sh
+++ b/storage/ndb/test/run-test/upgrade-boot.sh
@@ -1,4 +1,21 @@
#!/bin/sh
+
+# Copyright (c) 2007 MySQL AB
+# Use is subject to license terms.
+#
+# 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
+
#############################################################
# This script created by Jonas does the following #
# Cleans up clones and pevious builds, pulls new clones, #
diff --git a/storage/ndb/test/sql/BANK.sql b/storage/ndb/test/sql/BANK.sql
deleted file mode 100644
index 055761621e3..00000000000
--- a/storage/ndb/test/sql/BANK.sql
+++ /dev/null
@@ -1,44 +0,0 @@
-CREATE DATABASE IF NOT EXISTS BANK default charset=latin1 default collate=latin1_bin;
-USE BANK;
-DROP TABLE IF EXISTS GL;
-CREATE TABLE GL ( TIME BIGINT UNSIGNED NOT NULL,
- ACCOUNT_TYPE INT UNSIGNED NOT NULL,
- BALANCE INT UNSIGNED NOT NULL,
- DEPOSIT_COUNT INT UNSIGNED NOT NULL,
- DEPOSIT_SUM INT UNSIGNED NOT NULL,
- WITHDRAWAL_COUNT INT UNSIGNED NOT NULL,
- WITHDRAWAL_SUM INT UNSIGNED NOT NULL,
- PURGED INT UNSIGNED NOT NULL,
- PRIMARY KEY USING HASH (TIME,ACCOUNT_TYPE))
- ENGINE = NDB;
-
-DROP TABLE IF EXISTS ACCOUNT;
-CREATE TABLE ACCOUNT ( ACCOUNT_ID INT UNSIGNED NOT NULL,
- OWNER INT UNSIGNED NOT NULL,
- BALANCE INT UNSIGNED NOT NULL,
- ACCOUNT_TYPE INT UNSIGNED NOT NULL,
- PRIMARY KEY USING HASH (ACCOUNT_ID))
- ENGINE = NDB;
-
-DROP TABLE IF EXISTS TRANSACTION;
-CREATE TABLE TRANSACTION ( TRANSACTION_ID BIGINT UNSIGNED NOT NULL,
- ACCOUNT INT UNSIGNED NOT NULL,
- ACCOUNT_TYPE INT UNSIGNED NOT NULL,
- OTHER_ACCOUNT INT UNSIGNED NOT NULL,
- TRANSACTION_TYPE INT UNSIGNED NOT NULL,
- TIME BIGINT UNSIGNED NOT NULL,
- AMOUNT INT UNSIGNED NOT NULL,
- PRIMARY KEY USING HASH (TRANSACTION_ID,ACCOUNT))
- ENGINE = NDB;
-
-DROP TABLE IF EXISTS SYSTEM_VALUES;
-CREATE TABLE SYSTEM_VALUES ( SYSTEM_VALUES_ID INT UNSIGNED NOT NULL,
- VALUE BIGINT UNSIGNED NOT NULL,
- PRIMARY KEY USING HASH (SYSTEM_VALUES_ID))
- ENGINE = NDB;
-
-DROP TABLE IF EXISTS ACCOUNT_TYPE;
-CREATE TABLE ACCOUNT_TYPE ( ACCOUNT_TYPE_ID INT UNSIGNED NOT NULL,
- DESCRIPTION CHAR(64) NOT NULL,
- PRIMARY KEY USING HASH (ACCOUNT_TYPE_ID))
- ENGINE = NDB;
diff --git a/storage/ndb/test/sql/T1.sql b/storage/ndb/test/sql/T1.sql
deleted file mode 100644
index 754211c4eac..00000000000
--- a/storage/ndb/test/sql/T1.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-create database if not exists TEST_DB;
-use TEST_DB;
-drop table if exists T1;
-create table T1 (KOL1 int unsigned not null,
- KOL2 int unsigned not null,
- KOL3 int unsigned not null,
- KOL4 int unsigned not null,
- KOL5 int unsigned not null,
- primary key using hash(KOL1)) engine=ndb;
diff --git a/storage/ndb/test/sql/test_create_drop.pl b/storage/ndb/test/sql/test_create_drop.pl
deleted file mode 100644
index eb9d5e31dc8..00000000000
--- a/storage/ndb/test/sql/test_create_drop.pl
+++ /dev/null
@@ -1,196 +0,0 @@
-# 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;
-
-# mgm info
-my $mgmhost = "localhost";
-my $mgmport = 38101;
-
-# location of ndb_x_fs
-my $datadir = "c2";
-my @schemafiles = <$datadir/ndb_*_fs/D[12]/DBDICT/P0.SchemaLog>;
-@schemafiles or die "no schemafiles in $datadir";
-
-my $dsn;
-$dsn = "dbi:mysql:test:localhost;port=38100";
-
-# this works better for me
-my $cnf = $ENV{MYSQL_HOME} . "/var/my.cnf";
-$dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$cnf";
-
-my $dbh;
-$dbh = DBI->connect($dsn, 'root', undef, { RaiseError => 0, PrintError => 0 });
-$dbh or die $DBI::errstr;
-
-# mgm commands
-
-my $mgm = undef;
-
-sub mgmconnect {
- $mgm = IO::Socket::INET->new(
- Proto => "tcp",
- PeerHost => $mgmhost,
- PeerPort => $mgmport);
- $mgm or die "connect to mgm failed: $!";
- $mgm->autoflush(1);
-};
-
-mgmconnect();
-warn "connected to mgm $mgmhost $mgmport\n";
-
-my $nodeinfo = {};
-
-sub getnodeinfo {
- $nodeinfo = {};
- $mgm->print("get status\n");
- $mgm->print("\n");
- while (defined($_ = $mgm->getline)) {
- /^node\s+status/ && last;
- }
- while (defined($_ = $mgm->getline)) {
- /^\s*$/ && last;
- /^node\.(\d+)\.(\w+):\s*(\S+)/ && ($nodeinfo->{$1}{$2} = $3);
- }
-}
-
-getnodeinfo();
-
-my @dbnode = ();
-for my $n (keys %$nodeinfo) {
- my $p = $nodeinfo->{$n};
- ($p->{type} eq 'NDB') && push(@dbnode, $n);
-}
-@dbnode = sort { $a <=> $b } @dbnode;
-@dbnode or die "mgm error, found no db nodes";
-warn "db nodes: @dbnode\n";
-
-sub restartnode {
- my($n, $initialstart) = @_;
- warn "restart node $n initialstart=$initialstart\n";
- $mgm->print("restart node\n");
- $mgm->print("node: $n\n");
- $mgm->print("initialstart: $initialstart\n");
- $mgm->print("\n");
- while (1) {
- sleep 5;
- getnodeinfo();
- my $status = $nodeinfo->{$n}{status};
- my $sp = $nodeinfo->{$n}{startphase};
- warn "node $n status: $status sp: $sp\n";
- last if $status eq 'STARTED';
- }
-}
-
-sub restartall {
- warn "restart all\n";
- $mgm->print("restart all\n");
- $mgm->print("\n");
- while (1) {
- sleep 5;
- getnodeinfo();
- my $ok = 1;
- for my $n (@dbnode) {
- my $status = $nodeinfo->{$n}{status};
- my $sp = $nodeinfo->{$n}{startphase};
- warn "node $n status: $status sp: $sp\n";
- $ok = 0 if $status ne 'STARTED';
- }
- last if $ok;
- }
-}
-
-# the sql stuff
-
-my $maxtab = 300;
-my @tab = ();
-
-sub create {
- my($n) = @_;
- my $sql = "create table t$n (a int primary key, b varchar(20), key (b)) engine=ndb";
- warn "create t$n\n";
- $dbh->do($sql) or die "$sql\n$DBI::errstr";
-}
-
-sub drop {
- my($n) = @_;
- my $sql = "drop table t$n";
- warn "drop t$n\n";
- $dbh->do($sql) or die "$sql\n$DBI::errstr";
-}
-
-sub dropall {
- for my $n (0..($maxtab-1)) {
- my $sql = "drop table if exists t$n";
- $dbh->do($sql) or die "$sql\n$DBI::errstr";
- }
-}
-
-sub createdrop {
- my $n = int(rand($maxtab));
- if (! $tab[$n]) {
- create($n);
- $tab[$n] = 1;
- } else {
- drop($n);
- $tab[$n] = 0;
- }
-}
-
-sub checkschemafiles {
- system("printSchemaFile -ce @schemafiles");
- $? == 0 or die "schemafiles check failed";
-}
-
-sub randomrestart {
- my($k) = @_;
- my $s = int(rand(500));
- if ($s < 2) {
- my $i = $k % scalar(@dbnode);
- my $n = $dbnode[$i];
- my $initialstart = ($s < 1 ? 0 : 1);
- restartnode($n, $initialstart);
- return 1;
- }
- if ($s < 3) {
- restartall();
- return 1;
- }
- return 0;
-}
-
-# deterministic
-srand(1);
-
-warn "drop any old tables\n";
-dropall();
-
-my $loop = 1000000;
-for my $k (0..($loop-1)) {
- warn "$k\n";
- createdrop();
- checkschemafiles();
- if (randomrestart($k)) {
- checkschemafiles();
- }
-}
-
-$dbh->disconnect or die $DBI::errstr;
-
-# vim: set sw=2:
diff --git a/storage/ndb/test/sql/test_range_bounds.pl b/storage/ndb/test/sql/test_range_bounds.pl
deleted file mode 100644
index 964847044de..00000000000
--- a/storage/ndb/test/sql/test_range_bounds.pl
+++ /dev/null
@@ -1,235 +0,0 @@
-# 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
-# set MYSQL_HOME to installation top
-#
-
-use strict;
-use integer;
-use Getopt::Long;
-use DBI;
-
-my $opt_all = 0;
-my $opt_cnt = 5;
-my $opt_verbose = 0;
-GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt, "verbose" => \$opt_verbose)
- or die "options are: --all --cnt=N --verbose";
-
-my $mysql_home = $ENV{MYSQL_HOME};
-defined($mysql_home) or die "no MYSQL_HOME";
-my $dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$mysql_home/var/my.cnf";
-my $opts = { RaiseError => 0, PrintError => 0, AutoCommit => 1, };
-
-my $dbh;
-my $sth;
-my $sql;
-
-$dbh = DBI->connect($dsn, "root", undef, $opts) or die $DBI::errstr;
-
-my $table = 't';
-
-$sql = "drop table if exists $table";
-$dbh->do($sql) or die $DBI::errstr;
-
-sub cut ($$$) {
- my($op, $key, $val) = @_;
- $op = '==' if $op eq '=';
- my(@w) = @$val;
- eval "\@w = grep(\$_ $op $key, \@w)";
- $@ and die $@;
- return [ @w ];
-}
-
-sub mkdummy ($) {
- my ($val) = @_;
- return {
- 'dummy' => 1,
- 'exp' => '9 = 9',
- 'res' => $val,
- };
-}
-
-sub mkone ($$$$) {
- my($col, $op, $key, $val) = @_;
- my $res = cut($op, $key, $val);
- return {
- 'exp' => "$col $op $key",
- 'res' => $res,
- };
-}
-
-sub mktwo ($$$$$$) {
- my($col, $op1, $key1, $op2, $key2, $val) = @_;
- my $res = cut($op2, $key2, cut($op1, $key1, $val));
- return {
- 'exp' => "$col $op1 $key1 and $col $op2 $key2",
- 'res' => $res,
- };
-}
-
-sub mkall ($$$$) {
- my($col, $key1, $key2, $val) = @_;
- my @a = ();
- my $p = mkdummy($val);
- push(@a, $p) if $opt_all;
- my @ops = qw(< <= = >= >);
- for my $op (@ops) {
- my $p = mkone($col, $op, $key1, $val);
- push(@a, $p) if $opt_all || @{$p->{res}} != 0;
- }
- my @ops1 = $opt_all ? @ops : qw(= >= >);
- my @ops2 = $opt_all ? @ops : qw(<= <);
- for my $op1 (@ops1) {
- for my $op2 (@ops2) {
- my $p = mktwo($col, $op1, $key1, $op2, $key2, $val);
- push(@a, $p) if $opt_all || @{$p->{res}} != 0;
- }
- }
- warn scalar(@a)." cases\n" if $opt_verbose;
- return \@a;
-}
-
-my $casecnt = 0;
-
-sub verify ($$$) {
- my($sql, $ord, $res) = @_;
- warn "$sql\n" if $opt_verbose;
- $sth = $dbh->prepare($sql) or die "prepare: $sql: $DBI::errstr";
- $sth->execute() or die "execute: $sql: $DBI::errstr";
- #
- # BUG: execute can return success on error so check again
- #
- $sth->err and die "execute: $sql: $DBI::errstr";
- my @out = ();
- for my $b (@{$res->[0]}) {
- for my $c (@{$res->[1]}) {
- for my $d (@{$res->[2]}) {
- push(@out, [$b, $c, $d]);
- }
- }
- }
- if ($ord) {
- @out = sort {
- $ord * ($a->[0] - $b->[0]) ||
- $ord * ($a->[1] - $b->[1]) ||
- $ord * ($a->[2] - $b->[2]) ||
- 0
- } @out;
- }
- my $cnt = scalar @out;
- my $n = 0;
- while (1) {
- my $row = $sth->fetchrow_arrayref;
- $row || last;
- @$row == 3 or die "bad row: $sql: @$row";
- for my $v (@$row) {
- $v =~ s/^\s+|\s+$//g;
- $v =~ /^\d+$/ or die "bad value: $sql: $v";
- }
- if ($ord) {
- my $out = $out[$n];
- $row->[0] == $out->[0] &&
- $row->[1] == $out->[1] &&
- $row->[2] == $out->[2] or
- die "$sql: row $n: got row @$row != @$out";
- }
- $n++;
- }
- $sth->err and die "fetch: $sql: $DBI::errstr";
- $n == $cnt or die "verify: $sql: got row count $n != $cnt";
- $casecnt++;
-}
-
-for my $nn ("bcd", "") {
- my %nn;
- for my $x (qw(b c d)) {
- $nn{$x} = $nn =~ /$x/ ? "not null" : "null";
- }
- warn "create table\n";
- $sql = <<EOF;
-create table $table (
- a int primary key,
- b int $nn{b},
- c int $nn{c},
- d int $nn{d},
- index (b, c, d)
-) engine=ndb
-EOF
- $dbh->do($sql) or die $DBI::errstr;
- warn "insert\n";
- $sql = "insert into $table values(?, ?, ?, ?)";
- $sth = $dbh->prepare($sql) or die $DBI::errstr;
- my @val = (0..($opt_cnt-1));
- my $v0 = 0;
- for my $v1 (@val) {
- for my $v2 (@val) {
- for my $v3 (@val) {
- $sth->bind_param(1, $v0) or die $DBI::errstr;
- $sth->bind_param(2, $v1) or die $DBI::errstr;
- $sth->bind_param(3, $v2) or die $DBI::errstr;
- $sth->bind_param(4, $v3) or die $DBI::errstr;
- $sth->execute or die $DBI::errstr;
- $v0++;
- }
- }
- }
- warn "generate cases\n";
- my $key1 = 1;
- my $key2 = 3;
- my $a1 = mkall('b', $key1, $key2, \@val);
- my $a2 = mkall('c', $key1, $key2, \@val);
- my $a3 = mkall('d', $key1, $key2, \@val);
- warn "select\n";
- for my $ord (0, +1, -1) {
- my $orderby =
- $ord == 0 ? "" :
- $ord == +1 ? " order by b, c, d" :
- $ord == -1 ? " order by b desc, c desc, d desc" : die "not here";
- for my $p1 (@$a1) {
- my $res = [ $p1->{res}, \@val, \@val ];
- $sql = "select b, c, d from $table" .
- " where $p1->{exp}" .
- $orderby;
- verify($sql, $ord, $res);
- for my $p2 (@$a2) {
- my $res = [ $p1->{res}, $p2->{res}, \@val ];
- $sql = "select b, c, d from $table" .
- " where $p1->{exp} and $p2->{exp}" .
- $orderby;
- verify($sql, $ord, $res);
- for my $p3 (@$a3) {
- my $res = [ $p1->{res}, $p2->{res}, $p3->{res} ];
- $sql = "select b, c, d from $table" .
- " where $p1->{exp} and $p2->{exp} and $p3->{exp}" .
- $orderby;
- verify($sql, $ord, $res);
- }
- }
- }
- }
- warn "drop table\n";
- $sql = "drop table $table";
- $dbh->do($sql) or die $DBI::errstr;
-}
-
-warn "verified $casecnt cases\n";
-warn "done\n";
-
-# vim: set sw=2:
diff --git a/storage/ndb/test/tools/connect.cpp b/storage/ndb/test/tools/connect.cpp
index 278dbe833ea..14d9b238102 100644
--- a/storage/ndb/test/tools/connect.cpp
+++ b/storage/ndb/test/tools/connect.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2007 MySQL AB, 2008 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <ndb_global.h>
#include <ndb_opts.h>
diff --git a/storage/ndb/test/tools/log_listner.cpp b/storage/ndb/test/tools/log_listner.cpp
index c5125ef7414..a0a03f1319a 100644
--- a/storage/ndb/test/tools/log_listner.cpp
+++ b/storage/ndb/test/tools/log_listner.cpp
@@ -1,3 +1,21 @@
+/*
+ Copyright (c) 2007 MySQL AB
+ Use is subject to license terms.
+
+ 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
+*/
+
#include <mgmapi.h>
#include <ndb_global.h>
#include <ndb_opts.h>
diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp
index e8e8d584f09..fe8d4edd5f1 100644
--- a/storage/ndb/tools/restore/consumer_restore.cpp
+++ b/storage/ndb/tools/restore/consumer_restore.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 <NDBT_ReturnCodes.h>
#include "consumer_restore.hpp"
diff --git a/storage/ndb/tools/restore/consumer_restorem.cpp b/storage/ndb/tools/restore/consumer_restorem.cpp
index 233f8d5fe98..1f921ae02a3 100644
--- a/storage/ndb/tools/restore/consumer_restorem.cpp
+++ b/storage/ndb/tools/restore/consumer_restorem.cpp
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (c) 2004-2006 MySQL AB, 2009 Sun Microsystems, Inc.
+ Use is subject to license terms.
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
@@ -11,7 +12,7 @@
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 "consumer_restore.hpp"
#include <NdbSleep.h>
diff --git a/storage/pbxt/src/database_xt.cc b/storage/pbxt/src/database_xt.cc
index 8d1b4e46da9..635cb63224a 100644
--- a/storage/pbxt/src/database_xt.cc
+++ b/storage/pbxt/src/database_xt.cc
@@ -87,7 +87,7 @@ xtPublic void xt_lock_installation(XTThreadPtr self, char *installation_path)
char file_path[PATH_MAX];
char buffer[101];
size_t red_size;
- llong pid;
+ llong pid __attribute__ ((unused));
xtBool cd = pbxt_crash_debug;
xt_strcpy(PATH_MAX, file_path, installation_path);
diff --git a/storage/pbxt/src/ha_pbxt.cc b/storage/pbxt/src/ha_pbxt.cc
index 8640c079a37..584d188a2cd 100644
--- a/storage/pbxt/src/ha_pbxt.cc
+++ b/storage/pbxt/src/ha_pbxt.cc
@@ -1559,7 +1559,7 @@ static int pbxt_rollback(handlerton *hton, THD *thd, bool all)
if (!all)
self->st_stat_trans = FALSE;
}
- return 0;
+ return err;
}
#ifdef DRIZZLED
@@ -2863,11 +2863,9 @@ int ha_pbxt::update_row(const byte * old_data, byte * new_data)
* insert into t1 (val) values (1);
*/
if (table->found_next_number_field && new_data == table->record[0]) {
- MX_LONGLONG_T nr;
my_bitmap_map *old_map;
old_map = mx_tmp_use_all_columns(table, table->read_set);
- nr = table->found_next_number_field->val_int();
ha_set_auto_increment(pb_open_tab, table->found_next_number_field);
mx_tmp_restore_column_map(table, old_map);
}
diff --git a/storage/pbxt/src/memory_xt.cc b/storage/pbxt/src/memory_xt.cc
index b2f6c248b3c..d498336e814 100644
--- a/storage/pbxt/src/memory_xt.cc
+++ b/storage/pbxt/src/memory_xt.cc
@@ -558,7 +558,7 @@ static size_t mm_checkmem(XTThreadPtr self, MissingMemoryPtr mm_ptr, void *p, xt
unsigned char *ptr = (unsigned char *) p - MEM_DEBUG_HDR_SIZE;
MemoryDebugPtr debug_ptr = (MemoryDebugPtr) ptr;
size_t size = debug_ptr->size;
- long a_value; /* Added to simplfy debugging. */
+ long a_value __attribute__ ((unused)); /* Added to simplfy debugging. */
if (!ASSERT(p))
return(0);
diff --git a/storage/pbxt/src/myxt_xt.cc b/storage/pbxt/src/myxt_xt.cc
index 410bf2d2f3c..b7b81823383 100644
--- a/storage/pbxt/src/myxt_xt.cc
+++ b/storage/pbxt/src/myxt_xt.cc
@@ -830,7 +830,10 @@ xtPublic xtBool myxt_create_row_from_key(XTOpenTablePtr XT_UNUSED(ot), XTIndexPt
{
byte *record = (byte *) dest_buff;
register byte *key;
- byte *pos,*key_end;
+ byte *pos;
+#ifdef CHECK_KEYS
+ byte *key_end;
+#endif
register XTIndexSegRec *keyseg = ind->mi_seg;
/* GOTCHA: When selecting from multiple
@@ -843,7 +846,9 @@ xtPublic xtBool myxt_create_row_from_key(XTOpenTablePtr XT_UNUSED(ot), XTIndexPt
memset(dest_buff, 0xFF, table->s->null_bytes);
*/
key = (byte *) b_value;
+#ifdef CHECK_KEYS
key_end = key + key_len;
+#endif
for (u_int i=0; i<ind->mi_seg_count; i++, keyseg++) {
if (keyseg->null_bit) {
if (!*key++)
@@ -1021,7 +1026,8 @@ xtPublic u_int myxt_get_key_length(XTIndexPtr ind, xtWord1 *key_buf)
register XTIndexSegRec *keyseg = ind->mi_seg;
register uchar *key_data = (uchar *) key_buf;
uint seg_len;
- uint pack_len;
+ uint pack_len
+ __attribute__ ((unused));
for (u_int i=0; i<ind->mi_seg_count; i++, keyseg++) {
/* Handle NULL part */
@@ -1506,7 +1512,7 @@ xtPublic u_int myxt_key_seg_length(XTIndexSegRec *keyseg, u_int key_offset, xtWo
xtPublic xtWord4 myxt_store_row_length(XTOpenTablePtr ot, char *rec_buff)
{
TABLE *table = ot->ot_table->tab_dic.dic_my_table;
- char *sdata;
+ char *sdata __attribute__ ((unused));
xtWord4 dlen;
xtWord4 item_size;
xtWord4 row_size = 0;
@@ -1886,7 +1892,8 @@ xtPublic void myxt_print_key(XTIndexPtr ind, xtWord1 *key_value)
register XTIndexSegRec *keyseg = ind->mi_seg;
register uchar *b = (uchar *) key_value;
uint b_length;
- uint pack_len;
+ uint pack_len
+ __attribute__ ((unused));
for (u_int i = 0; i < ind->mi_seg_count; i++, keyseg++) {
if (i!=0)
diff --git a/storage/pbxt/src/restart_xt.cc b/storage/pbxt/src/restart_xt.cc
index 93720f2b113..868c97de020 100644
--- a/storage/pbxt/src/restart_xt.cc
+++ b/storage/pbxt/src/restart_xt.cc
@@ -94,17 +94,21 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re
xtBool xn_set = FALSE;
xtXactID xn_id = 0;
char buffer[200];
+#ifdef TRACE_RECORD_DATA
XTTabRecExtDPtr rec_buf;
- XTTabRecExtDPtr ext_rec;
XTTabRecFixDPtr fix_rec;
u_int rec_len;
+#endif
+ XTTabRecExtDPtr ext_rec;
xtLogID log_id = 0;
xtLogOffset log_offset = 0;
+#ifdef TRACE_RECORD_DATA
rec_buf = NULL;
- ext_rec = NULL;
fix_rec = NULL;
rec_len = 0;
+#endif
+ ext_rec = NULL;
switch (record->xl.xl_status_1) {
case XT_LOG_ENT_REC_MODIFIED:
case XT_LOG_ENT_UPDATE:
@@ -118,10 +122,12 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re
rec_id = XT_GET_DISK_4(record->xu.xu_rec_id_4);
xn_id = XT_GET_DISK_4(record->xu.xu_xact_id_4);
row_id = XT_GET_DISK_4(record->xu.xu_row_id_4);
- rec_len = XT_GET_DISK_2(record->xu.xu_size_2);
xn_set = TRUE;
type="rec";
+#ifdef TRACE_RECORD_DATA
+ rec_len = XT_GET_DISK_2(record->xu.xu_size_2);
rec_buf = (XTTabRecExtDPtr) &record->xu.xu_rec_type_1;
+#endif
ext_rec = (XTTabRecExtDPtr) &record->xu.xu_rec_type_1;
if (XT_REC_IS_EXT_DLOG(ext_rec->tr_rec_type_1)) {
log_id = XT_GET_DISK_2(ext_rec->re_log_id_2);
@@ -129,7 +135,9 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re
}
else {
ext_rec = NULL;
+#ifdef TRACE_RECORD_DATA
fix_rec = (XTTabRecFixDPtr) &record->xu.xu_rec_type_1;
+#endif
}
break;
case XT_LOG_ENT_UPDATE_FL:
@@ -143,10 +151,12 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re
rec_id = XT_GET_DISK_4(record->xf.xf_rec_id_4);
xn_id = XT_GET_DISK_4(record->xf.xf_xact_id_4);
row_id = XT_GET_DISK_4(record->xf.xf_row_id_4);
- rec_len = XT_GET_DISK_2(record->xf.xf_size_2);
xn_set = TRUE;
type="rec";
+#ifdef TRACE_RECORD_DATA
+ rec_len = XT_GET_DISK_2(record->xf.xf_size_2);
rec_buf = (XTTabRecExtDPtr) &record->xf.xf_rec_type_1;
+#endif
ext_rec = (XTTabRecExtDPtr) &record->xf.xf_rec_type_1;
if (XT_REC_IS_EXT_DLOG(ext_rec->tr_rec_type_1)) {
log_id = XT_GET_DISK_2(ext_rec->re_log_id_2);
@@ -154,7 +164,9 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re
}
else {
ext_rec = NULL;
+#ifdef TRACE_RECORD_DATA
fix_rec = (XTTabRecFixDPtr) &record->xf.xf_rec_type_1;
+#endif
}
break;
case XT_LOG_ENT_REC_FREED:
@@ -173,10 +185,12 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re
rec_id = XT_GET_DISK_4(record->rb.rb_rec_id_4);
xn_id = XT_GET_DISK_4(record->rb.rb_xact_id_4);
row_id = XT_GET_DISK_4(record->rb.rb_row_id_4);
- rec_len = XT_GET_DISK_2(record->rb.rb_size_2);
xn_set = TRUE;
type="rec";
+#ifdef TRACE_RECORD_DATA
+ rec_len = XT_GET_DISK_2(record->rb.rb_size_2);
rec_buf = (XTTabRecExtDPtr) &record->rb.rb_rec_type_1;
+#endif
ext_rec = (XTTabRecExtDPtr) &record->rb.rb_rec_type_1;
if (XT_REC_IS_EXT_DLOG(record->rb.rb_rec_type_1)) {
log_id = XT_GET_DISK_2(ext_rec->re_log_id_2);
@@ -184,7 +198,9 @@ void xt_print_log_record(xtLogID log, xtLogOffset offset, XTXactLogBufferDPtr re
}
else {
ext_rec = NULL;
+#ifdef TRACE_RECORD_DATA
fix_rec = (XTTabRecFixDPtr) &record->rb.rb_rec_type_1;
+#endif
}
break;
case XT_LOG_ENT_REC_MOVED:
@@ -967,7 +983,8 @@ static void xres_apply_change(XTThreadPtr self, XTOpenTablePtr ot, XTXactLogBuff
xtLogID data_log_id = 0;
xtLogOffset data_log_offset = 0;
u_int cols_required = 0;
- xtBool record_loaded;
+ xtBool record_loaded
+ __attribute__ ((unused));
size_t rec_size;
rec_id = XT_GET_DISK_4(record->rb.rb_rec_id_4);
diff --git a/storage/pbxt/src/tabcache_xt.cc b/storage/pbxt/src/tabcache_xt.cc
index 92958f2da49..c5374b400c3 100644
--- a/storage/pbxt/src/tabcache_xt.cc
+++ b/storage/pbxt/src/tabcache_xt.cc
@@ -393,7 +393,8 @@ void XTTabCache::xt_tc_release_page(XT_ROW_REC_FILE_PTR XT_UNUSED(file), XTTabCa
TAB_CAC_WRITE_LOCK(&seg->tcs_lock, thread->t_id);
#ifdef DEBUG
- XTTabCachePagePtr lpage, ppage;
+ XTTabCachePagePtr lpage;
+ XTTabCachePagePtr ppage __attribute__ ((unused));
ppage = NULL;
lpage = seg->tcs_hash_table[page->tcp_hash_idx];
@@ -1202,7 +1203,7 @@ static void tabc_fr_main(XTThreadPtr self)
static void *tabc_fr_run_thread(XTThreadPtr self)
{
int count;
- void *mysql_thread;
+ void *mysql_thread __attribute__ ((unused));
myxt_wait_pbxt_plugin_slot_assigned(self);
diff --git a/storage/pbxt/src/table_xt.cc b/storage/pbxt/src/table_xt.cc
index 35b4ea3be3d..df9c157c2b6 100644
--- a/storage/pbxt/src/table_xt.cc
+++ b/storage/pbxt/src/table_xt.cc
@@ -1976,8 +1976,10 @@ xtPublic void xt_check_table(XTThreadPtr self, XTOpenTablePtr ot)
xtLogOffset log_offset;
#endif
xtRecordID rec_id;
+#ifdef DUMP_CHECK_TABLE
xtRecordID prev_rec_id;
xtXactID xn_id;
+#endif
xtRowID row_id;
u_llong free_rec_count = 0, free_count2 = 0;
u_llong delete_rec_count = 0;
@@ -2104,8 +2106,10 @@ xtPublic void xt_check_table(XTThreadPtr self, XTOpenTablePtr ot)
else
printf(" ");
#endif
+#ifdef DUMP_CHECK_TABLE
prev_rec_id = XT_GET_DISK_4(rec_buf->tr_prev_rec_id_4);
xn_id = XT_GET_DISK_4(rec_buf->tr_xact_id_4);
+#endif
row_id = XT_GET_DISK_4(rec_buf->tr_row_id_4);
switch (rec_buf->tr_rec_type_1 & XT_TAB_STATUS_MASK) {
case XT_TAB_STATUS_FREED:
diff --git a/storage/pbxt/src/thread_xt.cc b/storage/pbxt/src/thread_xt.cc
index 985d33840d3..72bfab0921c 100644
--- a/storage/pbxt/src/thread_xt.cc
+++ b/storage/pbxt/src/thread_xt.cc
@@ -485,7 +485,7 @@ static void thr_free_resources(XTThreadPtr self, XTResourcePtr top)
xtPublic void xt_bug(XTThreadPtr XT_UNUSED(self))
{
- static int *bug_ptr = NULL;
+ static int *bug_ptr __attribute__ ((unused))= NULL;
bug_ptr = NULL;
}
diff --git a/storage/pbxt/src/xactlog_xt.cc b/storage/pbxt/src/xactlog_xt.cc
index addc14ff5d8..69059046067 100644
--- a/storage/pbxt/src/xactlog_xt.cc
+++ b/storage/pbxt/src/xactlog_xt.cc
@@ -2117,7 +2117,7 @@ xtBool XTDatabaseLog::xlog_seq_next(XTXactSeqReadPtr seq, XTXactLogBufferDPtr *r
size_t rec_offset;
size_t max_rec_len;
size_t size;
- u_int check_size = 1;
+ u_int check_size __attribute__ ((unused))= 1;
/* Go to the next record (xseq_record_len must be initialized
* to 0 for this to work.
@@ -2629,7 +2629,7 @@ static void *xlog_wr_run_thread(XTThreadPtr self)
{
XTDatabaseHPtr db = (XTDatabaseHPtr) self->t_data;
int count;
- void *mysql_thread;
+ void *mysql_thread __attribute__ ((unused));
mysql_thread = myxt_create_thread();
diff --git a/storage/xtradb/ChangeLog b/storage/xtradb/ChangeLog
index 102db3d7824..f873f3a24bd 100644
--- a/storage/xtradb/ChangeLog
+++ b/storage/xtradb/ChangeLog
@@ -1,3 +1,105 @@
+2011-08-08 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#12835650 VARCHAR maximum length performance impact
+
+2011-08-08 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#12770537 I_S.TABLES.DATA_LENGTH DOES NOT SHOW ON-DISK SIZE
+ FOR COMPRESSED INNODB
+
+2011-07-19 The InnoDB Team
+
+ * buf/buf0buf.c, buf/buf0rea.c, handler/ha_innodb.cc,
+ include/buf0buf.h, include/buf0buf.ic, include/srv0srv.h,
+ srv/srv0srv.c:
+ Fix Bug#12356373 by reintroducing random readahead
+
+2011-06-30 The InnoDB Team
+
+ * row/row0row.c:
+ Fix Bug#12637786 Wrong secondary index entries on CHAR and VARCHAR
+ columns in ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED
+
+2011-06-16 The InnoDB Team
+
+ * btr/btr0cur.c, buf/buf0buddy.c, buf/buf0buf.c, buf/buf0lru.c,
+ include/buf0buddy.h, include/buf0buddy.ic, include/buf0buf.h,
+ include/buf0buf.ic, include/buf0lru.h, include/buf0types.h:
+ Fix Bug#61188 DROP TABLE extremely slow
+
+2011-06-16 The InnoDB Team
+
+ * buf/buf0buddy.c, buf/buf0buf.c, buf/buf0flu.c, buf/buf0lru.c,
+ include/buf0buf.h, include/buf0lru.h:
+ Fix Bug#61341 buf_LRU_insert_zip_clean can be O(N) on LRU length
+
+2011-06-16 The InnoDB Team
+
+ * page/page0zip.c, rem/rem0rec.c:
+ Fix Bug#61191 question about page_zip_available()
+
+2011-06-16 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, include/btr0btr.h, include/btr0cur.h,
+ include/btr0cur.ic, include/buf0buf.h, include/buf0buf.ic,
+ include/page0cur.ic, include/page0page.h, include/page0page.ic,
+ include/sync0rw.ic, include/sync0sync.h, page/page0cur.c,
+ page/page0page.c, row/row0ins.c, row/row0upd.c,
+ sync/sync0rw.c, sync/sync0sync.c:
+ Fix Bug#12612184 Race condition after btr_cur_pessimistic_update()
+
+2011-06-09 The InnoDB Team
+ * btr/btr0cur.c, include/rem0rec.h, include/rem0rec.ic,
+ * row/row0row.c, row/row0vers.c, trx/trx0rec.c:
+ Instrumentation for Bug#12612184 Race condition in row_upd_clust_rec()
+
+2011-05-19 The InnoDB Team
+
+ * row/row0row.c:
+ Fix Bug#12429576 Assertion failure on purge of column prefix index
+
+2011-04-07 The InnoDB Team
+
+ * handler/ha_innodb.cc, handler/ha_innodb.h, handler/handler0alter.cc:
+ Fix Bug #52409 Assertion failure: long semaphore wait
+
+2011-04-07 The InnoDB Team
+
+ * handler/ha_innodb.cc, include/trx0trx.h, include/trx0undo.h,
+ log/log0log.c, trx/trx0sys.c, trx/trx0trx.c, trx/trx0undo.c:
+ Fix Bug #59641 Prepared XA transaction in system after hard crash
+ causes future shutdown hang
+
+2011-03-30 The InnoDB Team
+
+ * srv/srv0srv.c, sync/sync0arr.h, sync/sync0arr.c:
+ Fix Bug#11877216 InnoDB too eager to commit suicide on a busy server
+
+2011-03-15 The InnoDB Team
+
+ * btr/btr0cur.c, page/page0zip.c:
+ Fix Bug#11849231 inflateInit() invoked without initializing all memory
+
+2011-02-28 The InnoDB Team
+
+ * btr/btr0sea.c, buf/buf0buf.c, buf/buf0lru.c:
+ Fix Bug#58549 Race condition in buf_LRU_drop_page_hash_for_tablespace()
+ and compressed tables
+
+2011-02-15 The InnoDB Team
+
+ * sync/sync0rw.c, innodb_bug59307.test:
+ Bug#59307 Valgrind: uninitialized value in
+ rw_lock_set_writer_id_and_recursion_flag()
+
+2011-02-14 The InnoDB Team
+
+ * handler/handler0alter.cc:
+ Bug#59749 Enabling concurrent reads while creating non-primary
+ unique index gives failures
+
2011-01-31 The InnoDB Team
* btr/btr0cur.c, include/row0upd.h,
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index 2fb14b06a7b..396ad422010 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.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.
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
@@ -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
--------------------------------------
@@ -289,7 +843,7 @@ btr_get_next_user_rec(
/**************************************************************//**
Creates a new index page (not the root, and also not
used in page reorganization). @see btr_page_empty(). */
-static
+UNIV_INTERN
void
btr_page_create(
/*============*/
@@ -302,6 +856,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);
@@ -501,6 +1056,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)) {
@@ -785,6 +1341,13 @@ 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(&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);
}
@@ -1026,6 +1589,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 */
@@ -1054,6 +1618,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. */
@@ -1168,7 +1734,7 @@ btr_parse_page_reorganize(
#ifndef UNIV_HOTBACKUP
/*************************************************************//**
Empties an index page. @see btr_page_create(). */
-static
+UNIV_INTERN
void
btr_page_empty(
/*===========*/
@@ -1187,6 +1753,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 */
@@ -1729,13 +2296,13 @@ btr_insert_on_non_leaf_level_func(
/**************************************************************//**
Attaches the halves of an index page on the appropriate level in an
index tree. */
-static
+UNIV_INTERN
void
btr_attach_half_pages(
/*==================*/
dict_index_t* index, /*!< in: the index tree */
buf_block_t* block, /*!< in/out: page to be split */
- rec_t* split_rec, /*!< in: first record on upper
+ const rec_t* split_rec, /*!< in: first record on upper
half page */
buf_block_t* new_block, /*!< in/out: the new half page */
ulint direction, /*!< in: FSP_UP or FSP_DOWN */
@@ -2427,15 +2994,16 @@ btr_node_ptr_delete(
ut_a(err == DB_SUCCESS);
if (!compressed) {
- btr_cur_compress_if_useful(&cursor, mtr);
+ btr_cur_compress_if_useful(&cursor, FALSE, mtr);
}
}
/*************************************************************//**
If page is the only on its level, this function moves its records to the
-father page, thus reducing the tree height. */
+father page, thus reducing the tree height.
+@return father block */
static
-void
+buf_block_t*
btr_lift_page_up(
/*=============*/
dict_index_t* index, /*!< in: index tree */
@@ -2527,6 +3095,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. */
@@ -2551,6 +3120,8 @@ btr_lift_page_up(
}
ut_ad(page_validate(father_page, index));
ut_ad(btr_check_node_ptr(index, father_block, mtr));
+
+ return(father_block);
}
/*************************************************************//**
@@ -2567,11 +3138,13 @@ UNIV_INTERN
ibool
btr_compress(
/*=========*/
- btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
- the page must not be empty: in record delete
- use btr_discard_page if the page would become
- empty */
- mtr_t* mtr) /*!< in: mtr */
+ btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
+ or lift; the page must not be empty:
+ when deleting records, use btr_discard_page()
+ if the page would become empty */
+ ibool adjust, /*!< in: TRUE if should adjust the
+ cursor position even if compression occurs */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
dict_index_t* index;
ulint space;
@@ -2589,12 +3162,14 @@ btr_compress(
ulint* offsets;
ulint data_size;
ulint n_recs;
+ ulint nth_rec = 0; /* remove bogus warning */
ulint max_ins_size;
ulint max_ins_size_reorg;
block = btr_cur_get_block(cursor);
page = btr_cur_get_page(cursor);
index = btr_cur_get_index(cursor);
+
ut_a((ibool) !!page_is_comp(page) == dict_table_is_comp(index->table));
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
@@ -2615,6 +3190,10 @@ btr_compress(
offsets = btr_page_get_father_block(NULL, heap, index, block, mtr,
&father_cursor);
+ if (adjust) {
+ nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
+ }
+
/* Decide the page to which we try to merge and which will inherit
the locks */
@@ -2641,9 +3220,9 @@ btr_compress(
} else {
/* The page is the only one on the level, lift the records
to the father */
- btr_lift_page_up(index, block, mtr);
- mem_heap_free(heap);
- return(TRUE);
+
+ merge_block = btr_lift_page_up(index, block, mtr);
+ goto func_exit;
}
n_recs = page_get_n_recs(page);
@@ -2725,6 +3304,10 @@ err_exit:
btr_node_ptr_delete(index, block, mtr);
lock_update_merge_left(merge_block, orig_pred, block);
+
+ if (adjust) {
+ nth_rec += page_rec_get_n_recs_before(orig_pred);
+ }
} else {
rec_t* orig_succ;
#ifdef UNIV_BTR_DEBUG
@@ -2788,7 +3371,7 @@ err_exit:
lock_update_merge_right(merge_block, orig_succ, block);
}
- mem_heap_free(heap);
+ btr_blob_dbg_remove(page, index, "btr_compress");
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
/* Update the free bits of the B-tree page in the
@@ -2840,6 +3423,16 @@ err_exit:
btr_page_free(index, block, mtr);
ut_ad(btr_check_node_ptr(index, merge_block, mtr));
+func_exit:
+ mem_heap_free(heap);
+
+ if (adjust) {
+ btr_cur_position(
+ index,
+ page_rec_get_nth(merge_block->frame, nth_rec),
+ merge_block, cursor);
+ }
+
return(TRUE);
}
@@ -3018,6 +3611,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/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c
index 9b306ea2864..51a2f784fbf 100644
--- a/storage/xtradb/btr/btr0cur.c
+++ b/storage/xtradb/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
@@ -1046,6 +1046,11 @@ btr_cur_ins_lock_and_undo(
rec_t* rec;
roll_ptr_t roll_ptr;
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip LOCK, UNDO */
+ return(DB_SUCCESS);
+ }
+
/* Check if we have to wait for a lock: enqueue an explicit lock
request if yes */
@@ -1177,7 +1182,7 @@ btr_cur_optimistic_insert(
}
#endif /* UNIV_DEBUG */
- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
max_size = page_get_max_insert_size_after_reorganize(page, 1);
leaf = page_is_leaf(page);
@@ -1272,6 +1277,12 @@ fail_err:
goto fail_err;
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip CHANGE, LOG */
+ *big_rec = big_rec_vec;
+ return(err); /* == DB_SUCCESS */
+ }
+
page_cursor = btr_cur_get_page_cur(cursor);
/* Now, try the insert */
@@ -1414,10 +1425,10 @@ btr_cur_pessimistic_insert(
*big_rec = NULL;
- ut_ad(mtr_memo_contains(mtr,
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr,
dict_index_get_lock(btr_cur_get_index(cursor)),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
/* Try first an optimistic insert; reset the cursor flag: we do not
@@ -1483,6 +1494,16 @@ btr_cur_pessimistic_insert(
}
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip CHANGE, LOG */
+ if (n_extents > 0) {
+ fil_space_release_free_extents(index->space,
+ n_reserved);
+ }
+ *big_rec = big_rec_vec;
+ return(DB_SUCCESS);
+ }
+
if (dict_index_get_page(index)
== buf_block_get_page_no(btr_cur_get_block(cursor))) {
@@ -1539,6 +1560,11 @@ btr_cur_upd_lock_and_undo(
ut_ad(cursor && update && thr && roll_ptr);
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip LOCK, UNDO */
+ return(DB_SUCCESS);
+ }
+
rec = btr_cur_get_rec(cursor);
index = cursor->index;
@@ -1837,6 +1863,14 @@ btr_cur_update_in_place(
return(err);
}
+ if (trx->fake_changes) {
+ /* skip CHANGE, LOG */
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(err); /* == DB_SUCCESS */
+ }
+
if (block->is_hashed) {
/* The function row_upd_changes_ord_field_binary works only
if the update vector was built for a clustered index, we must
@@ -1929,7 +1963,6 @@ btr_cur_optimistic_update(
ulint old_rec_size;
dtuple_t* new_entry;
roll_ptr_t roll_ptr;
- trx_t* trx;
mem_heap_t* heap;
ulint i;
ulint n_ext;
@@ -1940,12 +1973,16 @@ btr_cur_optimistic_update(
rec = btr_cur_get_rec(cursor);
index = cursor->index;
ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
/* The insert buffer tree should never be updated in place. */
ut_ad(!dict_index_is_ibuf(index));
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(rec, offsets)
+ || trx_is_recv(thr_get_trx(thr)));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
@@ -2050,6 +2087,11 @@ any_extern:
goto err_exit;
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip CHANGE, LOG */
+ goto err_exit; /* == DB_SUCCESS */
+ }
+
/* Ok, we may do the replacement. Store on the page infimum the
explicit locks on rec, before deleting rec (see the comment in
btr_cur_pessimistic_update). */
@@ -2068,13 +2110,11 @@ any_extern:
page_cur_move_to_prev(page_cursor);
- trx = thr_get_trx(thr);
-
if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr);
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
- trx->id);
+ thr_get_trx(thr)->id);
}
/* There are no externally stored columns in new_entry */
@@ -2160,7 +2200,9 @@ btr_cur_pessimistic_update(
/*=======================*/
ulint flags, /*!< in: undo logging, locking, and rollback
flags */
- btr_cur_t* cursor, /*!< in: cursor on the record to update */
+ btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
+ cursor may become invalid if *big_rec == NULL
+ || !(flags & BTR_KEEP_POS_FLAG) */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */
@@ -2200,9 +2242,9 @@ btr_cur_pessimistic_update(
rec = btr_cur_get_rec(cursor);
index = cursor->index;
- ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
@@ -2290,6 +2332,9 @@ btr_cur_pessimistic_update(
ut_ad(big_rec_vec == NULL);
+ /* fake_changes should not cause undo. so never reaches here */
+ ut_ad(!(trx->fake_changes));
+
btr_rec_free_updated_extern_fields(
index, rec, page_zip, offsets, update,
trx_is_recv(trx) ? RB_RECOVERY : RB_NORMAL, mtr);
@@ -2299,7 +2344,7 @@ btr_cur_pessimistic_update(
record to be inserted: we have to remember which fields were such */
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
- offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, heap);
+ ut_ad(rec_offs_validate(rec, index, offsets));
n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
if (UNIV_LIKELY_NULL(page_zip)) {
@@ -2322,6 +2367,16 @@ make_external:
err = DB_TOO_BIG_RECORD;
goto return_after_reservations;
}
+
+ ut_ad(page_is_leaf(page));
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(flags & BTR_KEEP_POS_FLAG);
+ }
+
+ if (trx->fake_changes) {
+ /* skip CHANGE, LOG */
+ err = DB_SUCCESS;
+ goto return_after_reservations;
}
/* Store state of explicit locks on rec on the page infimum record,
@@ -2349,6 +2404,8 @@ make_external:
rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr);
if (rec) {
+ page_cursor->rec = rec;
+
lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor),
rec, block);
@@ -2362,7 +2419,10 @@ make_external:
rec, index, offsets, mtr);
}
- btr_cur_compress_if_useful(cursor, mtr);
+ btr_cur_compress_if_useful(
+ cursor,
+ big_rec_vec != NULL && (flags & BTR_KEEP_POS_FLAG),
+ mtr);
if (page_zip && !dict_index_is_clust(index)
&& page_is_leaf(page)) {
@@ -2382,6 +2442,21 @@ make_external:
}
}
+ if (big_rec_vec) {
+ ut_ad(page_is_leaf(page));
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(flags & BTR_KEEP_POS_FLAG);
+
+ /* btr_page_split_and_insert() in
+ btr_cur_pessimistic_insert() invokes
+ mtr_memo_release(mtr, index->lock, MTR_MEMO_X_LOCK).
+ We must keep the index->lock when we created a
+ big_rec, so that row_upd_clust_rec() can store the
+ big_rec in the same mini-transaction. */
+
+ mtr_x_lock(dict_index_get_lock(index), mtr);
+ }
+
/* Was the record to be updated positioned as the first user
record on its page? */
was_first = page_cur_is_before_first(page_cursor);
@@ -2397,6 +2472,7 @@ make_external:
ut_a(rec);
ut_a(err == DB_SUCCESS);
ut_a(dummy_big_rec == NULL);
+ page_cursor->rec = rec;
if (dict_index_is_sec_or_ibuf(index)) {
/* Update PAGE_MAX_TRX_ID in the index page header.
@@ -2455,6 +2531,39 @@ return_after_reservations:
return(err);
}
+/**************************************************************//**
+Commits and restarts a mini-transaction so that it will retain an
+x-lock on index->lock and the cursor page. */
+UNIV_INTERN
+void
+btr_cur_mtr_commit_and_start(
+/*=========================*/
+ btr_cur_t* cursor, /*!< in: cursor */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+{
+ buf_block_t* block;
+
+ block = btr_cur_get_block(cursor);
+
+ ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(cursor->index),
+ MTR_MEMO_X_LOCK));
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ /* Keep the locks across the mtr_commit(mtr). */
+ rw_lock_x_lock(dict_index_get_lock(cursor->index));
+ rw_lock_x_lock(&block->lock);
+ mutex_enter(&block->mutex);
+ buf_block_buf_fix_inc(block, __FILE__, __LINE__);
+ mutex_exit(&block->mutex);
+ /* Write out the redo log. */
+ mtr_commit(mtr);
+ mtr_start(mtr);
+ /* Reassociate the locks with the mini-transaction.
+ They will be released on mtr_commit(mtr). */
+ mtr_memo_push(mtr, dict_index_get_lock(cursor->index),
+ MTR_MEMO_X_LOCK);
+ mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
+}
+
/*==================== B-TREE DELETE MARK AND UNMARK ===============*/
/****************************************************************//**
@@ -2625,6 +2734,11 @@ 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)));
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip LOCK, UNDO, CHANGE, LOG */
+ return(DB_SUCCESS);
+ }
+
err = lock_clust_rec_modify_check_and_lock(flags, block,
rec, index, offsets, thr);
@@ -2647,6 +2761,7 @@ btr_cur_del_mark_set_clust_rec(
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);
@@ -2761,6 +2876,11 @@ btr_cur_del_mark_set_sec_rec(
rec_t* rec;
ulint err;
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip LOCK, CHANGE, LOG */
+ return(DB_SUCCESS);
+ }
+
block = btr_cur_get_block(cursor);
rec = btr_cur_get_rec(cursor);
@@ -2833,10 +2953,12 @@ UNIV_INTERN
ibool
btr_cur_compress_if_useful(
/*=======================*/
- btr_cur_t* cursor, /*!< in: cursor on the page to compress;
- cursor does not stay valid if compression
- occurs */
- mtr_t* mtr) /*!< in: mtr */
+ btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
+ cursor does not stay valid if !adjust and
+ compression occurs */
+ ibool adjust, /*!< in: TRUE if should adjust the
+ cursor position even if compression occurs */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ut_ad(mtr_memo_contains(mtr,
dict_index_get_lock(btr_cur_get_index(cursor)),
@@ -2845,7 +2967,7 @@ btr_cur_compress_if_useful(
MTR_MEMO_PAGE_X_FIX));
return(btr_cur_compress_recommendation(cursor, mtr)
- && btr_compress(cursor, mtr));
+ && btr_compress(cursor, adjust, mtr));
}
/*******************************************************//**
@@ -3092,7 +3214,7 @@ return_after_reservations:
mem_heap_free(heap);
if (ret == FALSE) {
- ret = btr_cur_compress_if_useful(cursor, mtr);
+ ret = btr_cur_compress_if_useful(cursor, FALSE, mtr);
}
if (n_extents > 0) {
@@ -3116,6 +3238,7 @@ btr_cur_add_path_info(
{
btr_path_t* slot;
rec_t* rec;
+ page_t* page;
ut_a(cursor->path_arr);
@@ -3138,8 +3261,155 @@ btr_cur_add_path_info(
slot = cursor->path_arr + (root_height - height);
+ page = page_align(rec);
+
slot->nth_rec = page_rec_get_n_recs_before(rec);
- slot->n_recs = page_get_n_recs(page_align(rec));
+ slot->n_recs = page_get_n_recs(page);
+ slot->page_no = page_get_page_no(page);
+ slot->page_level = btr_page_get_level_low(page);
+}
+
+/*******************************************************************//**
+Estimate the number of rows between slot1 and slot2 for any level on a
+B-tree. This function starts from slot1->page and reads a few pages to
+the right, counting their records. If we reach slot2->page quickly then
+we know exactly how many records there are between slot1 and slot2 and
+we set is_n_rows_exact to TRUE. If we cannot reach slot2->page quickly
+then we calculate the average number of records in the pages scanned
+so far and assume that all pages that we did not scan up to slot2->page
+contain the same number of records, then we multiply that average to
+the number of pages between slot1->page and slot2->page (which is
+n_rows_on_prev_level). In this case we set is_n_rows_exact to FALSE.
+@return number of rows (exact or estimated) */
+static
+ib_int64_t
+btr_estimate_n_rows_in_range_on_level(
+/*==================================*/
+ dict_index_t* index, /*!< in: index */
+ btr_path_t* slot1, /*!< in: left border */
+ btr_path_t* slot2, /*!< in: right border */
+ ib_int64_t n_rows_on_prev_level, /*!< in: number of rows
+ on the previous level for the
+ same descend paths; used to
+ determine the numbe of pages
+ on this level */
+ ibool* is_n_rows_exact) /*!< out: TRUE if the returned
+ value is exact i.e. not an
+ estimation */
+{
+ ulint space;
+ ib_int64_t n_rows;
+ ulint n_pages_read;
+ ulint page_no;
+ ulint zip_size;
+ ulint level;
+
+ space = dict_index_get_space(index);
+
+ n_rows = 0;
+ n_pages_read = 0;
+
+ /* Assume by default that we will scan all pages between
+ slot1->page_no and slot2->page_no */
+ *is_n_rows_exact = TRUE;
+
+ /* add records from slot1->page_no which are to the right of
+ the record which serves as a left border of the range, if any */
+ if (slot1->nth_rec < slot1->n_recs) {
+ n_rows += slot1->n_recs - slot1->nth_rec;
+ }
+
+ /* add records from slot2->page_no which are to the left of
+ the record which servers as a right border of the range, if any */
+ if (slot2->nth_rec > 1) {
+ n_rows += slot2->nth_rec - 1;
+ }
+
+ /* count the records in the pages between slot1->page_no and
+ slot2->page_no (non inclusive), if any */
+
+ zip_size = fil_space_get_zip_size(space);
+
+ /* Do not read more than this number of pages in order not to hurt
+ 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
+
+ page_no = slot1->page_no;
+ level = slot1->page_level;
+
+ do {
+ mtr_t mtr;
+ page_t* page;
+ buf_block_t* block;
+
+ mtr_start(&mtr);
+
+ /* fetch the page */
+ block = buf_page_get(space, zip_size, page_no, RW_S_LATCH,
+ &mtr);
+
+ page = buf_block_get_frame(block);
+
+ /* It is possible that the tree has been reorganized in the
+ meantime and this is a different page. If this happens the
+ calculated estimate will be bogus, which is not fatal as
+ this is only an estimate. We are sure that a page with
+ page_no exists because InnoDB never frees pages, only
+ reuses them. */
+ if (fil_page_get_type(page) != FIL_PAGE_INDEX
+ || ut_dulint_cmp(btr_page_get_index_id(page), index->id)
+ || btr_page_get_level_low(page) != level) {
+
+ /* The page got reused for something else */
+ goto inexact;
+ }
+
+ n_pages_read++;
+
+ if (page_no != slot1->page_no) {
+ /* Do not count the records on slot1->page_no,
+ we already counted them before this loop. */
+ n_rows += page_get_n_recs(page);
+ }
+
+ page_no = btr_page_get_next(page, &mtr);
+
+ mtr_commit(&mtr);
+
+ if (n_pages_read == N_PAGES_READ_LIMIT
+ || page_no == FIL_NULL) {
+ /* Either we read too many pages or
+ we reached the end of the level without passing
+ through slot2->page_no, the tree must have changed
+ in the meantime */
+ goto inexact;
+ }
+
+ } while (page_no != slot2->page_no);
+
+ return(n_rows);
+
+inexact:
+
+ *is_n_rows_exact = FALSE;
+
+ /* We did interrupt before reaching slot2->page */
+
+ if (n_pages_read > 0) {
+ /* The number of pages on this level is
+ n_rows_on_prev_level, multiply it by the
+ average number of recs per page so far */
+ n_rows = n_rows_on_prev_level
+ * n_rows / n_pages_read;
+ } else {
+ /* The tree changed before we could even
+ start with slot1->page_no */
+ n_rows = 10;
+ }
+
+ return(n_rows);
}
/*******************************************************************//**
@@ -3164,6 +3434,7 @@ btr_estimate_n_rows_in_range(
ibool diverged_lot;
ulint divergence_level;
ib_int64_t n_rows;
+ ibool is_n_rows_exact;
ulint i;
mtr_t mtr;
@@ -3206,6 +3477,7 @@ btr_estimate_n_rows_in_range(
/* We have the path information for the range in path1 and path2 */
n_rows = 1;
+ is_n_rows_exact = TRUE;
diverged = FALSE; /* This becomes true when the path is not
the same any more */
diverged_lot = FALSE; /* This becomes true when the paths are
@@ -3221,7 +3493,7 @@ btr_estimate_n_rows_in_range(
if (slot1->nth_rec == ULINT_UNDEFINED
|| slot2->nth_rec == ULINT_UNDEFINED) {
- if (i > divergence_level + 1) {
+ if (i > divergence_level + 1 && !is_n_rows_exact) {
/* In trees whose height is > 1 our algorithm
tends to underestimate: multiply the estimate
by 2: */
@@ -3233,7 +3505,9 @@ btr_estimate_n_rows_in_range(
to over 1 / 2 of the estimated rows in the whole
table */
- if (n_rows > index->table->stat_n_rows / 2) {
+ if (n_rows > index->table->stat_n_rows / 2
+ && !is_n_rows_exact) {
+
n_rows = index->table->stat_n_rows / 2;
/* If there are just 0 or 1 rows in the table,
@@ -3259,10 +3533,15 @@ btr_estimate_n_rows_in_range(
divergence_level = i;
}
} else {
- /* Maybe the tree has changed between
- searches */
-
- return(10);
+ /* It is possible that
+ slot1->nth_rec >= slot2->nth_rec
+ if, for example, we have a single page
+ tree which contains (inf, 5, 6, supr)
+ and we select where x > 20 and x < 30;
+ in this case slot1->nth_rec will point
+ to the supr record and slot2->nth_rec
+ will point to 6 */
+ n_rows = 0;
}
} else if (diverged && !diverged_lot) {
@@ -3286,8 +3565,9 @@ btr_estimate_n_rows_in_range(
}
} else if (diverged_lot) {
- n_rows = (n_rows * (slot1->n_recs + slot2->n_recs))
- / 2;
+ n_rows = btr_estimate_n_rows_in_range_on_level(
+ index, slot1, slot2, n_rows,
+ &is_n_rows_exact);
}
}
}
@@ -3301,7 +3581,7 @@ static
void
btr_record_not_null_field_in_rec(
/*=============================*/
- rec_t* rec, /*!< in: physical record */
+ rec_t* rec __attribute__ ((unused)),/*!< in: physical record */
ulint n_unique, /*!< in: dict_index_get_n_unique(index),
number of columns uniquely determine
an index entry */
@@ -3321,9 +3601,8 @@ btr_record_not_null_field_in_rec(
for (i = 0; i < n_unique; i++) {
ulint rec_len;
- byte* field;
- field = rec_get_nth_field(rec, offsets, i, &rec_len);
+ rec_get_nth_field_offs(offsets, i, &rec_len);
if (rec_len != UNIV_SQL_NULL) {
n_not_null[i]++;
@@ -3680,6 +3959,8 @@ 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);
}
/*******************************************************************//**
@@ -3884,7 +4165,7 @@ 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, TRUE) != BUF_LRU_FREED
+ if (!buf_LRU_free_block(&block->page, all, TRUE)
&& all && block->page.zip.data
/* Now, buf_LRU_free_block() may release mutex temporarily */
&& buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
@@ -4185,6 +4466,11 @@ btr_store_big_rec_extern_fields_func(
}
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);
@@ -4260,6 +4546,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,
@@ -4428,6 +4719,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;
@@ -4674,27 +4996,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,
@@ -4710,7 +5050,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
@@ -4736,13 +5076,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;
@@ -4759,13 +5099,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"
@@ -4774,7 +5114,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:
@@ -4786,7 +5126,7 @@ inflate_error:
end_of_blob:
buf_page_release_zip(bpage);
- return;
+ goto func_exit;
}
buf_page_release_zip(bpage);
@@ -4798,6 +5138,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);
}
/*******************************************************************//**
@@ -4823,28 +5169,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/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c
index f95a5487c94..97fe06f0f5e 100644
--- a/storage/xtradb/btr/btr0pcur.c
+++ b/storage/xtradb/btr/btr0pcur.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
@@ -362,33 +362,6 @@ btr_pcur_restore_position_func(
return(FALSE);
}
-/**************************************************************//**
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-UNIV_INTERN
-void
-btr_pcur_release_leaf(
-/*==================*/
- btr_pcur_t* cursor, /*!< in: persistent cursor */
- mtr_t* mtr) /*!< in: mtr */
-{
- buf_block_t* block;
-
- ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
- ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
-
- block = btr_pcur_get_block(cursor);
-
- btr_leaf_page_release(block, cursor->latch_mode, mtr);
-
- cursor->latch_mode = BTR_NO_LATCHES;
-
- cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
-}
-
/*********************************************************//**
Moves the persistent cursor to the first record on the next page. Releases the
latch on the current page, and bufferunfixes it. Note that there must not be
diff --git a/storage/xtradb/btr/btr0sea.c b/storage/xtradb/btr/btr0sea.c
index 3b38e2799c2..6e6c533f4af 100644
--- a/storage/xtradb/btr/btr0sea.c
+++ b/storage/xtradb/btr/btr0sea.c
@@ -1373,8 +1373,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/xtradb/buf/buf0buddy.c b/storage/xtradb/buf/buf0buddy.c
index db94b4bed24..673d6c55efc 100644
--- a/storage/xtradb/buf/buf0buddy.c
+++ b/storage/xtradb/buf/buf0buddy.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2010, Innobase Oy. 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 the Free Software
@@ -45,6 +45,14 @@ static ulint buf_buddy_n_frames;
Protected by buf_pool_mutex. */
UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES_MAX + 1];
+/** Validate a given zip_free list. */
+#define BUF_BUDDY_LIST_VALIDATE(i) \
+ UT_LIST_VALIDATE(zip_list, buf_page_t, \
+ buf_pool->zip_free[i], \
+ ut_ad(buf_page_get_state( \
+ ut_list_node_313) \
+ == BUF_BLOCK_ZIP_FREE))
+
/**********************************************************************//**
Get the offset of the buddy of a compressed page frame.
@return the buddy relative of page */
@@ -76,22 +84,11 @@ buf_buddy_add_to_free(
buf_page_t* bpage, /*!< in,own: block to be freed */
ulint i) /*!< in: index of buf_pool->zip_free[] */
{
-#ifdef UNIV_DEBUG_VALGRIND
- buf_page_t* b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
-
- if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
-
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&zip_free_mutex));
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
ut_ad(buf_pool->zip_free[i].start != bpage);
UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_free[i], bpage);
-
-#ifdef UNIV_DEBUG_VALGRIND
- if (b) UNIV_MEM_FREE(b, BUF_BUDDY_LOW << i);
- UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
}
/**********************************************************************//**
@@ -103,26 +100,18 @@ buf_buddy_remove_from_free(
buf_page_t* bpage, /*!< in: block to be removed */
ulint i) /*!< in: index of buf_pool->zip_free[] */
{
-#ifdef UNIV_DEBUG_VALGRIND
+#ifdef UNIV_DEBUG
buf_page_t* prev = UT_LIST_GET_PREV(zip_list, bpage);
buf_page_t* next = UT_LIST_GET_NEXT(zip_list, bpage);
- if (prev) UNIV_MEM_VALID(prev, BUF_BUDDY_LOW << i);
- if (next) UNIV_MEM_VALID(next, BUF_BUDDY_LOW << i);
-
ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE);
ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* UNIV_DEBUG */
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&zip_free_mutex));
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
UT_LIST_REMOVE(zip_list, buf_pool->zip_free[i], bpage);
-
-#ifdef UNIV_DEBUG_VALGRIND
- if (prev) UNIV_MEM_FREE(prev, BUF_BUDDY_LOW << i);
- if (next) UNIV_MEM_FREE(next, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
}
/**********************************************************************//**
@@ -139,17 +128,13 @@ buf_buddy_alloc_zip(
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&zip_free_mutex));
ut_a(i < BUF_BUDDY_SIZES);
+ ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
+
+ ut_d(BUF_BUDDY_LIST_VALIDATE(i));
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* !UNIV_DEBUG_VALGRIND */
bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
if (bpage) {
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
buf_buddy_remove_from_free(bpage, i);
@@ -168,13 +153,10 @@ buf_buddy_alloc_zip(
}
}
-#ifdef UNIV_DEBUG
if (bpage) {
- memset(bpage, ~i, BUF_BUDDY_LOW << i);
+ ut_d(memset(bpage, ~i, BUF_BUDDY_LOW << i));
+ UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
}
-#endif /* UNIV_DEBUG */
-
- UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
return(bpage);
}
@@ -266,6 +248,7 @@ buf_buddy_alloc_from(
{
ulint offs = BUF_BUDDY_LOW << j;
ut_ad(j <= BUF_BUDDY_SIZES);
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
ut_ad(j >= i);
ut_ad(!ut_align_offset(buf, offs));
@@ -279,13 +262,7 @@ buf_buddy_alloc_from(
bpage = (buf_page_t*) ((byte*) buf + offs);
ut_d(memset(bpage, j, BUF_BUDDY_LOW << j));
bpage->state = BUF_BLOCK_ZIP_FREE;
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(
- ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* !UNIV_DEBUG_VALGRIND */
+ ut_d(BUF_BUDDY_LIST_VALIDATE(i));
buf_buddy_add_to_free(bpage, j);
}
@@ -295,8 +272,8 @@ 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.
-The buf_pool_mutex may only be released and reacquired if lru != NULL.
-@return allocated block, possibly NULL if lru==NULL */
+The buf_pool_mutex may be released and reacquired.
+@return allocated block, never NULL */
UNIV_INTERN
void*
buf_buddy_alloc_low(
@@ -305,14 +282,15 @@ buf_buddy_alloc_low(
or BUF_BUDDY_SIZES */
ibool* lru, /*!< in: pointer to a variable that will be assigned
TRUE if storage was allocated from the LRU list
- and buf_pool_mutex was temporarily released,
- or NULL if the LRU list should not be used */
+ and buf_pool_mutex was temporarily released */
ibool have_page_hash_mutex)
{
buf_block_t* block;
+ ut_ad(lru);
//ut_ad(buf_pool_mutex_own());
ut_ad(!mutex_own(&buf_pool_zip_mutex));
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
if (i < BUF_BUDDY_SIZES) {
/* Try to allocate from the buddy system. */
@@ -335,11 +313,6 @@ buf_buddy_alloc_low(
goto alloc_big;
}
- if (!lru) {
-
- return(NULL);
- }
-
/* Try replacing an uncompressed page in the buffer pool. */
//buf_pool_mutex_exit();
mutex_exit(&LRU_list_mutex);
@@ -368,76 +341,6 @@ func_exit:
}
/**********************************************************************//**
-Try to relocate the control block of a compressed page.
-@return TRUE if relocated */
-static
-ibool
-buf_buddy_relocate_block(
-/*=====================*/
- buf_page_t* bpage, /*!< in: block to relocate */
- buf_page_t* dpage) /*!< in: free block to relocate to */
-{
- buf_page_t* b;
-
- //ut_ad(buf_pool_mutex_own());
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(rw_lock_own(&page_hash_latch, RW_LOCK_EX));
-#endif
-
- switch (buf_page_get_state(bpage)) {
- case BUF_BLOCK_ZIP_FREE:
- case BUF_BLOCK_NOT_USED:
- case BUF_BLOCK_READY_FOR_USE:
- case BUF_BLOCK_FILE_PAGE:
- case BUF_BLOCK_MEMORY:
- case BUF_BLOCK_REMOVE_HASH:
- /* ut_error; */ /* optimistic */
- case BUF_BLOCK_ZIP_DIRTY:
- /* Cannot relocate dirty pages. */
- return(FALSE);
-
- case BUF_BLOCK_ZIP_PAGE:
- break;
- }
-
- mutex_enter(&buf_pool_zip_mutex);
- mutex_enter(&zip_free_mutex);
-
- if (!buf_page_can_relocate(bpage)) {
- mutex_exit(&buf_pool_zip_mutex);
- mutex_exit(&zip_free_mutex);
- return(FALSE);
- }
-
- if (bpage != buf_page_hash_get(bpage->space, bpage->offset)) {
- mutex_exit(&buf_pool_zip_mutex);
- mutex_exit(&zip_free_mutex);
- return(FALSE);
- }
-
- buf_relocate(bpage, dpage);
- ut_d(bpage->state = BUF_BLOCK_ZIP_FREE);
-
- /* relocate buf_pool->zip_clean */
- mutex_enter(&flush_list_mutex);
- b = UT_LIST_GET_PREV(zip_list, dpage);
- UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, dpage);
-
- if (b) {
- UT_LIST_INSERT_AFTER(zip_list, buf_pool->zip_clean, b, dpage);
- } else {
- UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, dpage);
- }
- mutex_exit(&flush_list_mutex);
-
- UNIV_MEM_INVALID(bpage, sizeof *bpage);
-
- mutex_exit(&buf_pool_zip_mutex);
- mutex_exit(&zip_free_mutex);
- return(TRUE);
-}
-
-/**********************************************************************//**
Try to relocate a block.
@return TRUE if relocated */
static
@@ -452,159 +355,120 @@ buf_buddy_relocate(
buf_page_t* bpage;
const ulint size = BUF_BUDDY_LOW << i;
ullint usec = ut_time_us(NULL);
+ mutex_t* mutex;
+ ulint space;
+ ulint page_no;
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&zip_free_mutex));
ut_ad(!mutex_own(&buf_pool_zip_mutex));
ut_ad(!ut_align_offset(src, size));
ut_ad(!ut_align_offset(dst, size));
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
UNIV_MEM_ASSERT_W(dst, size);
+ if (!have_page_hash_mutex) {
+ mutex_exit(&zip_free_mutex);
+ mutex_enter(&LRU_list_mutex);
+ rw_lock_x_lock(&page_hash_latch);
+ }
+
/* We assume that all memory from buf_buddy_alloc()
- is used for either compressed pages or buf_page_t
- objects covering compressed pages. */
+ is used for compressed page frames. */
/* We look inside the allocated objects returned by
- buf_buddy_alloc() and assume that anything of
- PAGE_ZIP_MIN_SIZE or larger is a compressed page that contains
- a valid space_id and page_no in the page header. Should the
- fields be invalid, we will be unable to relocate the block.
- We also assume that anything that fits sizeof(buf_page_t)
- actually is a properly initialized buf_page_t object. */
-
- if (size >= PAGE_ZIP_MIN_SIZE) {
- /* This is a compressed page. */
- mutex_t* mutex;
- ulint space, page_no;
+ buf_buddy_alloc() and assume that each block is a compressed
+ page that contains a valid space_id and page_no in the page
+ header. Should the fields be invalid, we will be unable to
+ relocate the block. */
+
+ /* The src block may be split into smaller blocks,
+ some of which may be free. Thus, the
+ mach_read_from_4() calls below may attempt to read
+ from free memory. The memory is "owned" by the buddy
+ allocator (and it has been allocated from the buffer
+ pool), so there is nothing wrong about this. The
+ mach_read_from_4() calls here will only trigger bogus
+ Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
+ space = mach_read_from_4((const byte *) src
+ + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+ page_no = mach_read_from_4((const byte *) src
+ + FIL_PAGE_OFFSET);
+ /* Suppress Valgrind warnings about conditional jump
+ on uninitialized value. */
+ UNIV_MEM_VALID(&space, sizeof space);
+ UNIV_MEM_VALID(&page_no, sizeof page_no);
+ bpage = buf_page_hash_get(space, page_no);
+
+ if (!bpage || bpage->zip.data != src) {
+ /* The block has probably been freshly
+ allocated by buf_LRU_get_free_block() but not
+ added to buf_pool->page_hash yet. Obviously,
+ it cannot be relocated. */
if (!have_page_hash_mutex) {
- mutex_exit(&zip_free_mutex);
- mutex_enter(&LRU_list_mutex);
- rw_lock_x_lock(&page_hash_latch);
- }
-
- /* The src block may be split into smaller blocks,
- some of which may be free. Thus, the
- mach_read_from_4() calls below may attempt to read
- from free memory. The memory is "owned" by the buddy
- allocator (and it has been allocated from the buffer
- pool), so there is nothing wrong about this. The
- mach_read_from_4() calls here will only trigger bogus
- Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
- space = mach_read_from_4(
- (const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- page_no = mach_read_from_4(
- (const byte*) src + FIL_PAGE_OFFSET);
- /* Suppress Valgrind warnings about conditional jump
- on uninitialized value. */
- UNIV_MEM_VALID(&space, sizeof space);
- UNIV_MEM_VALID(&page_no, sizeof page_no);
- bpage = buf_page_hash_get(space, page_no);
-
- if (!bpage || bpage->zip.data != src) {
- /* The block has probably been freshly
- allocated by buf_LRU_get_free_block() but not
- added to buf_pool->page_hash yet. Obviously,
- it cannot be relocated. */
-
- if (!have_page_hash_mutex) {
- mutex_enter(&zip_free_mutex);
- mutex_exit(&LRU_list_mutex);
- rw_lock_x_unlock(&page_hash_latch);
- }
- return(FALSE);
- }
-
- if (page_zip_get_size(&bpage->zip) != size) {
- /* The block is of different size. We would
- have to relocate all blocks covered by src.
- For the sake of simplicity, give up. */
- ut_ad(page_zip_get_size(&bpage->zip) < size);
-
- if (!have_page_hash_mutex) {
- mutex_enter(&zip_free_mutex);
- mutex_exit(&LRU_list_mutex);
- rw_lock_x_unlock(&page_hash_latch);
- }
- return(FALSE);
+ mutex_enter(&zip_free_mutex);
+ mutex_exit(&LRU_list_mutex);
+ rw_lock_x_unlock(&page_hash_latch);
}
+ return(FALSE);
+ }
- /* To keep latch order */
- if (have_page_hash_mutex)
- mutex_exit(&zip_free_mutex);
-
- /* The block must have been allocated, but it may
- contain uninitialized data. */
- UNIV_MEM_ASSERT_W(src, size);
-
- mutex = buf_page_get_mutex_enter(bpage);
-
- mutex_enter(&zip_free_mutex);
-
- if (mutex && buf_page_can_relocate(bpage)) {
- /* Relocate the compressed page. */
- ut_a(bpage->zip.data == src);
- memcpy(dst, src, size);
- bpage->zip.data = dst;
- mutex_exit(mutex);
-success:
- UNIV_MEM_INVALID(src, size);
- {
- buf_buddy_stat_t* buddy_stat
- = &buf_buddy_stat[i];
- buddy_stat->relocated++;
- buddy_stat->relocated_usec
- += ut_time_us(NULL) - usec;
- }
-
- if (!have_page_hash_mutex) {
- mutex_exit(&LRU_list_mutex);
- rw_lock_x_unlock(&page_hash_latch);
- }
- return(TRUE);
- }
+ if (page_zip_get_size(&bpage->zip) != size) {
+ /* The block is of different size. We would
+ have to relocate all blocks covered by src.
+ For the sake of simplicity, give up. */
+ ut_ad(page_zip_get_size(&bpage->zip) < size);
if (!have_page_hash_mutex) {
+ mutex_enter(&zip_free_mutex);
mutex_exit(&LRU_list_mutex);
rw_lock_x_unlock(&page_hash_latch);
}
+ return(FALSE);
+ }
- if (mutex) {
- mutex_exit(mutex);
- }
- } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
- /* This must be a buf_page_t object. */
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in
- buf_page_t. On other systems, Valgrind could complain
- about uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(src, size);
-#endif
-
+ /* To keep latch order */
+ if (have_page_hash_mutex)
mutex_exit(&zip_free_mutex);
- if (!have_page_hash_mutex) {
- mutex_enter(&LRU_list_mutex);
- rw_lock_x_lock(&page_hash_latch);
- }
+ /* The block must have been allocated, but it may
+ contain uninitialized data. */
+ UNIV_MEM_ASSERT_W(src, size);
- if (buf_buddy_relocate_block(src, dst)) {
- mutex_enter(&zip_free_mutex);
+ mutex = buf_page_get_mutex_enter(bpage);
- if (!have_page_hash_mutex) {
- mutex_exit(&LRU_list_mutex);
- rw_lock_x_unlock(&page_hash_latch);
- }
+ mutex_enter(&zip_free_mutex);
- goto success;
+ if (mutex && buf_page_can_relocate(bpage)) {
+ /* Relocate the compressed page. */
+ ut_a(bpage->zip.data == src);
+ memcpy(dst, src, size);
+ bpage->zip.data = dst;
+ mutex_exit(mutex);
+ UNIV_MEM_INVALID(src, size);
+ {
+ buf_buddy_stat_t* buddy_stat
+ = &buf_buddy_stat[i];
+ buddy_stat->relocated++;
+ buddy_stat->relocated_usec
+ += ut_time_us(NULL) - usec;
}
- mutex_enter(&zip_free_mutex);
-
if (!have_page_hash_mutex) {
mutex_exit(&LRU_list_mutex);
rw_lock_x_unlock(&page_hash_latch);
}
+ return(TRUE);
+ }
+
+ if (!have_page_hash_mutex) {
+ mutex_exit(&LRU_list_mutex);
+ rw_lock_x_unlock(&page_hash_latch);
+ }
+
+ if (mutex) {
+ mutex_exit(mutex);
}
return(FALSE);
@@ -629,12 +493,14 @@ buf_buddy_free_low(
ut_ad(mutex_own(&zip_free_mutex));
ut_ad(!mutex_own(&buf_pool_zip_mutex));
ut_ad(i <= BUF_BUDDY_SIZES);
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
ut_ad(buf_buddy_stat[i].used > 0);
buf_buddy_stat[i].used--;
+
recombine:
UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
- ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
+ ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE;
if (i == BUF_BUDDY_SIZES) {
mutex_exit(&zip_free_mutex);
@@ -647,32 +513,36 @@ recombine:
ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
ut_ad(!buf_pool_contains_zip(buf));
- /* Try to combine adjacent blocks. */
+ /* Do not recombine blocks if there are few free blocks.
+ We may waste up to 15360*max_len bytes to free blocks
+ (1024 + 2048 + 4096 + 8192 = 15360) */
+ if (UT_LIST_GET_LEN(buf_pool->zip_free[i]) < 16) {
+ goto func_exit;
+ }
+ /* Try to combine adjacent blocks. */
buddy = (buf_page_t*) buf_buddy_get(((byte*) buf), BUF_BUDDY_LOW << i);
#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
+ /* When Valgrind instrumentation is not enabled, we can read
+ buddy->state to quickly determine that a block is not free.
+ When the block is not free, buddy->state belongs to a compressed
+ page frame that may be flagged uninitialized in our Valgrind
+ instrumentation. */
if (buddy->state != BUF_BLOCK_ZIP_FREE) {
goto buddy_nonfree;
}
-
- /* The field buddy->state can only be trusted for free blocks.
- If buddy->state == BUF_BLOCK_ZIP_FREE, the block is free if
- it is in the free list. */
#endif /* !UNIV_DEBUG_VALGRIND */
for (bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); bpage; ) {
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
if (bpage == buddy) {
-buddy_free:
/* The buddy is free: recombine */
buf_buddy_remove_from_free(bpage, i);
-buddy_free2:
+buddy_is_free:
ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
ut_ad(!buf_pool_contains_zip(buddy));
i++;
@@ -682,122 +552,43 @@ buddy_free2:
}
ut_a(bpage != buf);
-
- {
- buf_page_t* next = UT_LIST_GET_NEXT(zip_list, bpage);
- UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
- bpage = next;
- }
+ UNIV_MEM_ASSERT_W(bpage, BUF_BUDDY_LOW << i);
+ bpage = UT_LIST_GET_NEXT(zip_list, bpage);
}
#ifndef UNIV_DEBUG_VALGRIND
buddy_nonfree:
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* !UNIV_DEBUG_VALGRIND */
+
+ ut_d(BUF_BUDDY_LIST_VALIDATE(i));
/* The buddy is not free. Is there a free block of this size? */
bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
if (bpage) {
+
/* Remove the block from the free list, because a successful
buf_buddy_relocate() will overwrite bpage->list. */
-
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
buf_buddy_remove_from_free(bpage, i);
/* Try to relocate the buddy of buf to the free block. */
if (buf_buddy_relocate(buddy, bpage, i, have_page_hash_mutex)) {
- ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
- goto buddy_free2;
+ buddy->state = BUF_BLOCK_ZIP_FREE;
+ goto buddy_is_free;
}
buf_buddy_add_to_free(bpage, i);
-
- /* Try to relocate the buddy of the free block to buf. */
- buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
- BUF_BUDDY_LOW << i);
-
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
-
- /* The buddy must not be (completely) free, because we
- always recombine adjacent free blocks.
-
- (Parts of the buddy can be free in
- buf_pool->zip_free[j] with j < i.) */
- ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(
- ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE
- && ut_list_node_313 != buddy)));
-#endif /* !UNIV_DEBUG_VALGRIND */
-
- if (buf_buddy_relocate(buddy, buf, i, have_page_hash_mutex)) {
-
- buf = bpage;
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
- ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
- goto buddy_free;
- }
}
+func_exit:
/* Free the block to the buddy list. */
bpage = buf;
-#ifdef UNIV_DEBUG
- if (i < buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)) {
- /* This area has most likely been allocated for at
- least one compressed-only block descriptor. Check
- that there are no live objects in the area. This is
- not a complete check: it may yield false positives as
- well as false negatives. Also, due to buddy blocks
- being recombined, it is possible (although unlikely)
- that this branch is never reached. */
-
- char* c;
-
-# ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing
- uninitialized memory. Besides, Valgrind performs a
- more exhaustive check, at every memory access. */
- const buf_page_t* b = buf;
- const buf_page_t* const b_end = (buf_page_t*)
- ((char*) b + (BUF_BUDDY_LOW << i));
-
- for (; b < b_end; b++) {
- /* Avoid false positives (and cause false
- negatives) by checking for b->space < 1000. */
-
- if ((b->state == BUF_BLOCK_ZIP_PAGE
- || b->state == BUF_BLOCK_ZIP_DIRTY)
- && b->space > 0 && b->space < 1000) {
- fprintf(stderr,
- "buddy dirty %p %u (%u,%u) %p,%lu\n",
- (void*) b,
- b->state, b->space, b->offset,
- buf, i);
- }
- }
-# endif /* !UNIV_DEBUG_VALGRIND */
-
- /* Scramble the block. This should make any pointers
- invalid and trigger a segmentation violation. Because
- the scrambling can be reversed, it may be possible to
- track down the object pointing to the freed data by
- dereferencing the unscrambled bpage->LRU or
- bpage->list pointers. */
- for (c = (char*) buf + (BUF_BUDDY_LOW << i);
- c-- > (char*) buf; ) {
- *c = ~*c ^ i;
- }
- } else {
- /* Fill large blocks with a constant pattern. */
- memset(bpage, i, BUF_BUDDY_LOW << i);
- }
-#endif /* UNIV_DEBUG */
+
+ /* Fill large blocks with a constant pattern. */
+ ut_d(memset(bpage, i, BUF_BUDDY_LOW << i));
+ UNIV_MEM_INVALID(bpage, BUF_BUDDY_LOW << i);
+
bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_add_to_free(bpage, i);
}
diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index 020896b5739..c76973a42ef 100644
--- a/storage/xtradb/buf/buf0buf.c
+++ b/storage/xtradb/buf/buf0buf.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, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -53,10 +53,6 @@ Created 11/5/1995 Heikki Tuuri
#include "page0zip.h"
#include "trx0trx.h"
#include "srv0start.h"
-#include "que0que.h"
-#include "read0read.h"
-#include "row0row.h"
-#include "ha_prototypes.h"
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
@@ -314,30 +310,6 @@ read-ahead or flush occurs */
UNIV_INTERN ibool buf_debug_prints = FALSE;
#endif /* UNIV_DEBUG */
-/* Buffer pool shared memory segment information */
-typedef struct buf_shm_info_struct buf_shm_info_t;
-
-struct buf_shm_info_struct {
- char head_str[8];
- ulint binary_id;
- ibool is_new; /* during initializing */
- ibool clean; /* clean shutdowned and free */
- ibool reusable; /* reusable */
- ulint buf_pool_size; /* backup value */
- ulint page_size; /* backup value */
- ulint frame_offset; /* offset of the first frame based on chunk->mem */
- ulint zip_hash_offset;
- ulint zip_hash_n;
-
- ulint checksum;
-
- buf_pool_t buf_pool_backup;
- buf_chunk_t chunk_backup;
-
- ib_uint64_t dummy;
-};
-
-#define BUF_SHM_INFO_HEAD "XTRA_SHM"
#endif /* !UNIV_HOTBACKUP */
/********************************************************************//**
@@ -767,6 +739,10 @@ buf_block_init(
block->page.in_flush_list = FALSE;
block->page.in_free_list = FALSE;
#endif /* UNIV_DEBUG */
+ block->page.flush_list.prev = NULL;
+ block->page.flush_list.next = NULL;
+ block->page.zip_list.prev = NULL;
+ block->page.zip_list.next = NULL;
block->page.in_LRU_list = FALSE;
block->in_unzip_LRU_list = FALSE;
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
@@ -784,45 +760,6 @@ buf_block_init(
#endif /* UNIV_SYNC_DEBUG */
}
-static
-void
-buf_block_reuse(
-/*============*/
- buf_block_t* block,
- ptrdiff_t frame_offset)
-{
- /* block_init */
- block->frame += frame_offset;
-
- UNIV_MEM_DESC(block->frame, UNIV_PAGE_SIZE, block);
-
- block->index = NULL;
-
-#ifdef UNIV_DEBUG
- /* recreate later */
- block->page.in_page_hash = FALSE;
- block->page.in_zip_hash = FALSE;
-#endif /* UNIV_DEBUG */
-
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- block->n_pointers = 0;
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-
- if (block->page.zip.data)
- block->page.zip.data += frame_offset;
-
- block->is_hashed = FALSE;
-
- mutex_create(&block->mutex, SYNC_BUF_BLOCK);
-
- rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
- ut_ad(rw_lock_validate(&(block->lock)));
-
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
-#endif /* UNIV_SYNC_DEBUG */
-}
-
/********************************************************************//**
Allocates a chunk of buffer frames.
@return chunk, or NULL on failure */
@@ -835,190 +772,28 @@ buf_chunk_init(
{
buf_block_t* block;
byte* frame;
- ulint zip_hash_n = 0;
- ulint zip_hash_mem_size = 0;
- hash_table_t* zip_hash_tmp = NULL;
ulint i;
ulint size_target;
- buf_shm_info_t* shm_info = NULL;
/* Round down to a multiple of page size,
although it already should be. */
mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
size_target = (mem_size / UNIV_PAGE_SIZE) - 1;
-
- srv_buffer_pool_shm_is_reused = FALSE;
-
- if (srv_buffer_pool_shm_key) {
- /* zip_hash size */
- zip_hash_n = (mem_size / UNIV_PAGE_SIZE) * 2;
- zip_hash_mem_size = ut_2pow_round(hash_create_needed(zip_hash_n)
- + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
- }
-
/* Reserve space for the block descriptors. */
mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block)
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
- if (srv_buffer_pool_shm_key) {
- mem_size += ut_2pow_round(sizeof(buf_shm_info_t)
- + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
- mem_size += zip_hash_mem_size;
- }
chunk->mem_size = mem_size;
-
- if (srv_buffer_pool_shm_key) {
- ulint binary_id;
- ibool is_new;
-
- ut_a(buf_pool->n_chunks == 1);
-
- fprintf(stderr,
- "InnoDB: Warning: The innodb_buffer_pool_shm_key option has been specified.\n"
- "InnoDB: Do not change the following between restarts of the server while this option is being used:\n"
- "InnoDB: * the mysqld executable between restarts of the server.\n"
- "InnoDB: * the value of innodb_buffer_pool_size.\n"
- "InnoDB: * the value of innodb_page_size.\n"
- "InnoDB: * datafiles created by InnoDB during this session.\n"
- "InnoDB: Otherwise, data corruption in datafiles may result.\n");
-
- /* FIXME: This is vague id still */
- binary_id = (ulint) ((byte*)mtr_commit - (byte*)btr_root_get)
- + (ulint) ((byte*)os_get_os_version - (byte*)buf_calc_page_new_checksum)
- + (ulint) ((byte*)page_dir_find_owner_slot - (byte*)dfield_data_is_binary_equal)
- + (ulint) ((byte*)que_graph_publish - (byte*)dict_casedn_str)
- + (ulint) ((byte*)read_view_oldest_copy_or_open_new - (byte*)fil_space_get_version)
- + (ulint) ((byte*)rec_get_n_extern_new - (byte*)fsp_get_size_low)
- + (ulint) ((byte*)row_get_trx_id_offset - (byte*)ha_create_func)
- + (ulint) ((byte*)srv_set_io_thread_op_info - (byte*)thd_is_replication_slave_thread)
- + (ulint) ((byte*)mutex_create_func - (byte*)ibuf_inside)
- + (ulint) ((byte*)trx_set_detailed_error - (byte*)lock_check_trx_id_sanity)
- + (ulint) ((byte*)ut_time - (byte*)mem_heap_strdup);
-
- chunk->mem = os_shm_alloc(&chunk->mem_size, srv_buffer_pool_shm_key, &is_new);
-
- if (UNIV_UNLIKELY(chunk->mem == NULL)) {
- return(NULL);
- }
-init_again:
-#ifdef UNIV_SET_MEM_TO_ZERO
- if (is_new) {
- memset(chunk->mem, '\0', chunk->mem_size);
- }
-#endif
- /* for ut_fold_binary_32(), these values should be 32-bit aligned */
- ut_a(sizeof(buf_shm_info_t) % 4 == 0);
- ut_a((ulint)chunk->mem % 4 == 0);
- ut_a(chunk->mem_size % 4 == 0);
-
- shm_info = chunk->mem;
-
- zip_hash_tmp = (hash_table_t*)((byte*)chunk->mem + chunk->mem_size - zip_hash_mem_size);
-
- if (is_new) {
- strncpy(shm_info->head_str, BUF_SHM_INFO_HEAD, 8);
- shm_info->binary_id = binary_id;
- shm_info->is_new = TRUE; /* changed to FALSE when the initialization is finished */
- shm_info->clean = FALSE; /* changed to TRUE when free the segment. */
- shm_info->reusable = FALSE; /* changed to TRUE when validation is finished. */
- shm_info->buf_pool_size = srv_buf_pool_size;
- shm_info->page_size = srv_page_size;
- shm_info->zip_hash_offset = chunk->mem_size - zip_hash_mem_size;
- shm_info->zip_hash_n = zip_hash_n;
- } else {
- ulint checksum;
-
- if (strncmp(shm_info->head_str, BUF_SHM_INFO_HEAD, 8)) {
- fprintf(stderr,
- "InnoDB: Error: The shared memory segment seems not to be for buffer pool.\n");
- return(NULL);
- }
- if (shm_info->binary_id != binary_id) {
- fprintf(stderr,
- "InnoDB: Error: The shared memory segment seems not to be for this binary.\n");
- return(NULL);
- }
- if (shm_info->is_new) {
- fprintf(stderr,
- "InnoDB: Error: The shared memory was not initialized yet.\n");
- return(NULL);
- }
- if (shm_info->buf_pool_size != srv_buf_pool_size) {
- fprintf(stderr,
- "InnoDB: Error: srv_buf_pool_size is different (shm=%lu current=%lu).\n",
- shm_info->buf_pool_size, srv_buf_pool_size);
- return(NULL);
- }
- if (shm_info->page_size != srv_page_size) {
- fprintf(stderr,
- "InnoDB: Error: srv_page_size is different (shm=%lu current=%lu).\n",
- shm_info->page_size, srv_page_size);
- return(NULL);
- }
- if (!shm_info->reusable) {
- fprintf(stderr,
- "InnoDB: Warning: The shared memory has unrecoverable contents.\n"
- "InnoDB: The shared memory segment is initialized.\n");
- is_new = TRUE;
- goto init_again;
- }
- if (!shm_info->clean) {
- fprintf(stderr,
- "InnoDB: Warning: The shared memory was not shut down cleanly.\n"
- "InnoDB: The shared memory segment is initialized.\n");
- is_new = TRUE;
- goto init_again;
- }
-
- ut_a(shm_info->zip_hash_offset == chunk->mem_size - zip_hash_mem_size);
- ut_a(shm_info->zip_hash_n == zip_hash_n);
-
- /* check checksum */
- if (srv_buffer_pool_shm_checksum) {
- checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t),
- chunk->mem_size - sizeof(buf_shm_info_t));
- } else {
- checksum = BUF_NO_CHECKSUM_MAGIC;
- }
-
- if (shm_info->checksum != BUF_NO_CHECKSUM_MAGIC
- && shm_info->checksum != checksum) {
- fprintf(stderr,
- "InnoDB: Error: checksum of the shared memory is not match. "
- "(stored=%lu calculated=%lu)\n",
- shm_info->checksum, checksum);
- return(NULL);
- }
-
- /* flag to use the segment. */
- shm_info->clean = FALSE; /* changed to TRUE when free the segment. */
- }
-
- /* init zip_hash contents */
- if (is_new) {
- hash_create_init(zip_hash_tmp, zip_hash_n);
- } else {
- /* adjust offset is done later */
- hash_create_reuse(zip_hash_tmp);
-
- srv_buffer_pool_shm_is_reused = TRUE;
- }
- } else {
chunk->mem = os_mem_alloc_large(&chunk->mem_size);
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
return(NULL);
}
- }
/* Allocate the block descriptors from
the start of the memory block. */
- if (srv_buffer_pool_shm_key) {
- chunk->blocks = (buf_block_t*)((byte*)chunk->mem + sizeof(buf_shm_info_t));
- } else {
chunk->blocks = chunk->mem;
- }
/* Align a pointer to the first frame. Note that when
os_large_page_size is smaller than UNIV_PAGE_SIZE,
@@ -1026,13 +801,8 @@ init_again:
it is bigger, we may allocate more blocks than requested. */
frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
- if (srv_buffer_pool_shm_key) {
- /* reserve zip_hash space and always -1 for reproductibity */
- chunk->size = (chunk->mem_size - zip_hash_mem_size) / UNIV_PAGE_SIZE - 1;
- } else {
chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
- (frame != chunk->mem);
- }
/* Subtract the space needed for block descriptors. */
{
@@ -1050,99 +820,6 @@ init_again:
chunk->size = size_target;
}
- if (shm_info && !(shm_info->is_new)) {
- /* convert the shared memory segment for reuse */
- ptrdiff_t phys_offset;
- ptrdiff_t logi_offset;
- ptrdiff_t blocks_offset;
- void* previous_frame_address;
-
- if (chunk->size < shm_info->chunk_backup.size) {
- fprintf(stderr,
- "InnoDB: Error: The buffer pool became smaller because of allocated address.\n"
- "InnoDB: Retrying may avoid this situation.\n");
- shm_info->clean = TRUE; /* release the flag for retrying */
- return(NULL);
- }
-
- chunk->size = shm_info->chunk_backup.size;
- phys_offset = frame - ((byte*)chunk->mem + shm_info->frame_offset);
- logi_offset = frame - chunk->blocks[0].frame;
- previous_frame_address = chunk->blocks[0].frame;
- blocks_offset = (byte*)chunk->blocks - (byte*)shm_info->chunk_backup.blocks;
-
- if (phys_offset || logi_offset || blocks_offset) {
- fprintf(stderr,
- "InnoDB: Buffer pool in the shared memory segment should be converted.\n"
- "InnoDB: Previous frames in address : %p\n"
- "InnoDB: Previous frames were located : %p\n"
- "InnoDB: Current frames should be located: %p\n"
- "InnoDB: Pysical offset : %ld (%#lx)\n"
- "InnoDB: Logical offset (frames) : %ld (%#lx)\n"
- "InnoDB: Logical offset (blocks) : %ld (%#lx)\n",
- (byte*)chunk->mem + shm_info->frame_offset,
- chunk->blocks[0].frame, frame,
- (long) phys_offset, (long) phys_offset,
- (long) logi_offset, (long) logi_offset,
- (long) blocks_offset, (long) blocks_offset);
- } else {
- fprintf(stderr,
- "InnoDB: Buffer pool in the shared memory segment can be used as it is.\n");
- }
-
- if (phys_offset) {
- fprintf(stderr,
- "InnoDB: Aligning physical offset...");
-
- memmove(frame, (byte*)chunk->mem + shm_info->frame_offset,
- chunk->size * UNIV_PAGE_SIZE);
-
- fprintf(stderr,
- " Done.\n");
- }
-
- /* buf_block_t */
- block = chunk->blocks;
- for (i = chunk->size; i--; ) {
- buf_block_reuse(block, logi_offset);
- block++;
- }
-
- if (logi_offset || blocks_offset) {
- fprintf(stderr,
- "InnoDB: Aligning logical offset...");
-
-
- /* buf_pool_t buf_pool_backup */
- UT_LIST_OFFSET(flush_list, buf_page_t, shm_info->buf_pool_backup.flush_list,
- previous_frame_address, logi_offset, blocks_offset);
- UT_LIST_OFFSET(free, buf_page_t, shm_info->buf_pool_backup.free,
- previous_frame_address, logi_offset, blocks_offset);
- UT_LIST_OFFSET(LRU, buf_page_t, shm_info->buf_pool_backup.LRU,
- previous_frame_address, logi_offset, blocks_offset);
- if (shm_info->buf_pool_backup.LRU_old)
- shm_info->buf_pool_backup.LRU_old =
- (buf_page_t*)((byte*)(shm_info->buf_pool_backup.LRU_old)
- + (((void*)shm_info->buf_pool_backup.LRU_old > previous_frame_address)
- ? logi_offset : blocks_offset));
-
- UT_LIST_OFFSET(unzip_LRU, buf_block_t, shm_info->buf_pool_backup.unzip_LRU,
- previous_frame_address, logi_offset, blocks_offset);
-
- UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_clean,
- previous_frame_address, logi_offset, blocks_offset);
- for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) {
- UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_free[i],
- previous_frame_address, logi_offset, blocks_offset);
- }
-
- HASH_OFFSET(zip_hash_tmp, buf_page_t, hash,
- previous_frame_address, logi_offset, blocks_offset);
-
- fprintf(stderr,
- " Done.\n");
- }
- } else {
/* Init block structs and assign frames for them. Then we
assign the frames to the first blocks (we already mapped the
memory above). */
@@ -1166,11 +843,6 @@ init_again:
block++;
frame += UNIV_PAGE_SIZE;
}
- }
-
- if (shm_info) {
- shm_info->frame_offset = chunk->blocks[0].frame - (byte*)chunk->mem;
- }
return(chunk);
}
@@ -1287,76 +959,6 @@ buf_chunk_not_freed(
return(NULL);
}
-/*********************************************************************//**
-Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state.
-@return TRUE if all freed */
-static
-ibool
-buf_chunk_all_free(
-/*===============*/
- const buf_chunk_t* chunk) /*!< in: chunk being checked */
-{
- const buf_block_t* block;
- ulint i;
-
- ut_ad(buf_pool);
- ut_ad(buf_pool_mutex_own()); /* but we need all mutex here */
-
- block = chunk->blocks;
-
- for (i = chunk->size; i--; block++) {
-
- if (buf_block_get_state(block) != BUF_BLOCK_NOT_USED) {
-
- return(FALSE);
- }
- }
-
- return(TRUE);
-}
-
-/********************************************************************//**
-Frees a chunk of buffer frames. */
-static
-void
-buf_chunk_free(
-/*===========*/
- buf_chunk_t* chunk) /*!< out: chunk of buffers */
-{
- buf_block_t* block;
- const buf_block_t* block_end;
-
- ut_ad(buf_pool_mutex_own()); /* but we need all mutex here */
-
- block_end = chunk->blocks + chunk->size;
-
- for (block = chunk->blocks; block < block_end; block++) {
- ut_a(buf_block_get_state(block) == BUF_BLOCK_NOT_USED);
- ut_a(!block->page.zip.data);
-
- ut_ad(!block->page.in_LRU_list);
- ut_ad(!block->in_unzip_LRU_list);
- ut_ad(!block->page.in_flush_list);
- /* Remove the block from the free list. */
- mutex_enter(&free_list_mutex);
- ut_ad(block->page.in_free_list);
- UT_LIST_REMOVE(free, buf_pool->free, (&block->page));
- mutex_exit(&free_list_mutex);
-
- /* Free the latches. */
- mutex_free(&block->mutex);
- rw_lock_free(&block->lock);
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_free(&block->debug_latch);
-#endif /* UNIV_SYNC_DEBUG */
- UNIV_MEM_UNDESC(block);
- }
-
- ut_a(!srv_buffer_pool_shm_key);
-
- os_mem_free_large(chunk->mem, chunk->mem_size);
-}
-
/********************************************************************//**
Creates the buffer pool.
@return own: buf_pool object, NULL if not enough memory or error */
@@ -1403,10 +1005,7 @@ buf_pool_init(void)
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
- /* zip_hash is allocated to shm when srv_buffer_pool_shm_key is enabled */
- if (!srv_buffer_pool_shm_key) {
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
- }
buf_pool->last_printout_time = time(NULL);
@@ -1421,86 +1020,6 @@ buf_pool_init(void)
--------------------------- */
/* All fields are initialized by mem_zalloc(). */
- if (srv_buffer_pool_shm_key) {
- buf_shm_info_t* shm_info;
-
- ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t));
- shm_info = chunk->mem;
-
- buf_pool->zip_hash = (hash_table_t*)((byte*)chunk->mem + shm_info->zip_hash_offset);
-
- if(shm_info->is_new) {
- shm_info->is_new = FALSE; /* initialization was finished */
- } else {
- buf_block_t* block = chunk->blocks;
- buf_page_t* b;
-
- /* shm_info->buf_pool_backup should be converted */
- /* at buf_chunk_init(). So copy simply. */
- buf_pool->flush_list = shm_info->buf_pool_backup.flush_list;
- buf_pool->freed_page_clock = shm_info->buf_pool_backup.freed_page_clock;
- buf_pool->free = shm_info->buf_pool_backup.free;
- buf_pool->LRU = shm_info->buf_pool_backup.LRU;
- buf_pool->LRU_old = shm_info->buf_pool_backup.LRU_old;
- buf_pool->LRU_old_len = shm_info->buf_pool_backup.LRU_old_len;
- buf_pool->unzip_LRU = shm_info->buf_pool_backup.unzip_LRU;
- buf_pool->zip_clean = shm_info->buf_pool_backup.zip_clean;
- for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) {
- buf_pool->zip_free[i] = shm_info->buf_pool_backup.zip_free[i];
- }
-
- for (i = 0; i < chunk->size; i++, block++) {
- if (buf_block_get_state(block)
- == BUF_BLOCK_FILE_PAGE) {
- ut_d(block->page.in_page_hash = TRUE);
- HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
- buf_page_address_fold(
- block->page.space,
- block->page.offset),
- &block->page);
- }
- }
-
- for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
- b = UT_LIST_GET_NEXT(zip_list, b)) {
- ut_ad(!b->in_flush_list);
- ut_ad(b->in_LRU_list);
-
- ut_d(b->in_page_hash = TRUE);
- HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
- buf_page_address_fold(b->space, b->offset), b);
- }
-
- for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
- b = UT_LIST_GET_NEXT(flush_list, b)) {
- ut_ad(b->in_flush_list);
- ut_ad(b->in_LRU_list);
-
- switch (buf_page_get_state(b)) {
- case BUF_BLOCK_ZIP_DIRTY:
- ut_d(b->in_page_hash = TRUE);
- HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
- buf_page_address_fold(b->space,
- b->offset), b);
- break;
- case BUF_BLOCK_FILE_PAGE:
- /* uncompressed page */
- break;
- case BUF_BLOCK_ZIP_FREE:
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_NOT_USED:
- case BUF_BLOCK_READY_FOR_USE:
- case BUF_BLOCK_MEMORY:
- case BUF_BLOCK_REMOVE_HASH:
- ut_error;
- break;
- }
- }
-
-
- }
- }
-
mutex_exit(&LRU_list_mutex);
rw_lock_x_unlock(&page_hash_latch);
buf_pool_mutex_exit();
@@ -1525,49 +1044,16 @@ buf_pool_free(void)
buf_chunk_t* chunk;
buf_chunk_t* chunks;
- if (srv_buffer_pool_shm_key) {
- buf_shm_info_t* shm_info;
-
- ut_a(buf_pool->n_chunks == 1);
-
- chunk = buf_pool->chunks;
- shm_info = chunk->mem;
- ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t));
-
- /* validation the shared memory segment doesn't have unrecoverable contents. */
- /* Currently, validation became not needed */
- shm_info->reusable = TRUE;
-
- memcpy(&(shm_info->buf_pool_backup), buf_pool, sizeof(buf_pool_t));
- memcpy(&(shm_info->chunk_backup), chunk, sizeof(buf_chunk_t));
-
- if (srv_fast_shutdown < 2) {
- if (srv_buffer_pool_shm_checksum) {
- shm_info->checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t),
- chunk->mem_size - sizeof(buf_shm_info_t));
- } else {
- shm_info->checksum = BUF_NO_CHECKSUM_MAGIC;
- }
- shm_info->clean = TRUE;
- }
-
- os_shm_free(chunk->mem, chunk->mem_size);
- } else {
chunks = buf_pool->chunks;
chunk = chunks + buf_pool->n_chunks;
while (--chunk >= chunks) {
- /* Bypass the checks of buf_chunk_free(), since they
- would fail at shutdown. */
os_mem_free_large(chunk->mem, chunk->mem_size);
}
- }
mem_free(buf_pool->chunks);
hash_table_free(buf_pool->page_hash);
- if (!srv_buffer_pool_shm_key) {
hash_table_free(buf_pool->zip_hash);
- }
mem_free(buf_pool);
buf_pool = NULL;
}
@@ -1741,335 +1227,6 @@ buf_relocate(
}
/********************************************************************//**
-Shrinks the buffer pool. */
-static
-void
-buf_pool_shrink(
-/*============*/
- ulint chunk_size) /*!< in: number of pages to remove */
-{
- buf_chunk_t* chunks;
- buf_chunk_t* chunk;
- ulint max_size;
- ulint max_free_size;
- buf_chunk_t* max_chunk;
- buf_chunk_t* max_free_chunk;
-
- ut_ad(!buf_pool_mutex_own());
-
-try_again:
- btr_search_disable(); /* Empty the adaptive hash index again */
- //buf_pool_mutex_enter();
- mutex_enter(&LRU_list_mutex);
-
- if (srv_buffer_pool_shm_key) {
- /* Cannot support shrink */
- goto func_done;
- }
-
-shrink_again:
- if (buf_pool->n_chunks <= 1) {
-
- /* Cannot shrink if there is only one chunk */
- goto func_done;
- }
-
- /* Search for the largest free chunk
- not larger than the size difference */
- chunks = buf_pool->chunks;
- chunk = chunks + buf_pool->n_chunks;
- max_size = max_free_size = 0;
- max_chunk = max_free_chunk = NULL;
-
- while (--chunk >= chunks) {
- if (chunk->size <= chunk_size
- && chunk->size > max_free_size) {
- if (chunk->size > max_size) {
- max_size = chunk->size;
- max_chunk = chunk;
- }
-
- if (buf_chunk_all_free(chunk)) {
- max_free_size = chunk->size;
- max_free_chunk = chunk;
- }
- }
- }
-
- if (!max_free_size) {
-
- ulint dirty = 0;
- ulint nonfree = 0;
- buf_block_t* block;
- buf_block_t* bend;
-
- /* Cannot shrink: try again later
- (do not assign srv_buf_pool_old_size) */
- if (!max_chunk) {
-
- goto func_exit;
- }
-
- block = max_chunk->blocks;
- bend = block + max_chunk->size;
-
- /* Move the blocks of chunk to the end of the
- LRU list and try to flush them. */
- for (; block < bend; block++) {
- switch (buf_block_get_state(block)) {
- case BUF_BLOCK_NOT_USED:
- continue;
- case BUF_BLOCK_FILE_PAGE:
- break;
- default:
- nonfree++;
- continue;
- }
-
- mutex_enter(&block->mutex);
- /* The following calls will temporarily
- release block->mutex and buf_pool_mutex.
- Therefore, we have to always retry,
- even if !dirty && !nonfree. */
-
- if (!buf_flush_ready_for_replace(&block->page)) {
-
- buf_LRU_make_block_old(&block->page);
- dirty++;
- } else if (buf_LRU_free_block(&block->page, TRUE, FALSE)
- != BUF_LRU_FREED) {
- nonfree++;
- }
-
- mutex_exit(&block->mutex);
- }
-
- //buf_pool_mutex_exit();
- mutex_exit(&LRU_list_mutex);
-
- /* Request for a flush of the chunk if it helps.
- Do not flush if there are non-free blocks, since
- flushing will not make the chunk freeable. */
- if (nonfree) {
- /* Avoid busy-waiting. */
- os_thread_sleep(100000);
- } else if (dirty
- && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
- == ULINT_UNDEFINED) {
-
- buf_flush_wait_batch_end(BUF_FLUSH_LRU);
- }
-
- goto try_again;
- }
-
- max_size = max_free_size;
- max_chunk = max_free_chunk;
-
- srv_buf_pool_old_size = srv_buf_pool_size;
-
- /* Rewrite buf_pool->chunks. Copy everything but max_chunk. */
- chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
- memcpy(chunks, buf_pool->chunks,
- (max_chunk - buf_pool->chunks) * sizeof *chunks);
- memcpy(chunks + (max_chunk - buf_pool->chunks),
- max_chunk + 1,
- buf_pool->chunks + buf_pool->n_chunks
- - (max_chunk + 1));
- ut_a(buf_pool->curr_size > max_chunk->size);
- buf_pool->curr_size -= max_chunk->size;
- srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
- chunk_size -= max_chunk->size;
- buf_chunk_free(max_chunk);
- mem_free(buf_pool->chunks);
- buf_pool->chunks = chunks;
- buf_pool->n_chunks--;
-
- /* Allow a slack of one megabyte. */
- if (chunk_size > 1048576 / UNIV_PAGE_SIZE) {
-
- goto shrink_again;
- }
-
-func_done:
- srv_buf_pool_old_size = srv_buf_pool_size;
-func_exit:
- //buf_pool_mutex_exit();
- mutex_exit(&LRU_list_mutex);
- btr_search_enable();
-}
-
-/********************************************************************//**
-Rebuild buf_pool->page_hash. */
-static
-void
-buf_pool_page_hash_rebuild(void)
-/*============================*/
-{
- ulint i;
- ulint n_chunks;
- buf_chunk_t* chunk;
- hash_table_t* page_hash;
- hash_table_t* zip_hash;
- buf_page_t* b;
-
- //buf_pool_mutex_enter();
- mutex_enter(&LRU_list_mutex);
- rw_lock_x_lock(&page_hash_latch);
- mutex_enter(&flush_list_mutex);
-
-
- /* Free, create, and populate the hash table. */
- hash_table_free(buf_pool->page_hash);
- buf_pool->page_hash = page_hash = hash_create(2 * buf_pool->curr_size);
- zip_hash = hash_create(2 * buf_pool->curr_size);
-
- HASH_MIGRATE(buf_pool->zip_hash, zip_hash, buf_page_t, hash,
- BUF_POOL_ZIP_FOLD_BPAGE);
-
- hash_table_free(buf_pool->zip_hash);
- buf_pool->zip_hash = zip_hash;
-
- /* Insert the uncompressed file pages to buf_pool->page_hash. */
-
- chunk = buf_pool->chunks;
- n_chunks = buf_pool->n_chunks;
-
- for (i = 0; i < n_chunks; i++, chunk++) {
- ulint j;
- buf_block_t* block = chunk->blocks;
-
- for (j = 0; j < chunk->size; j++, block++) {
- if (buf_block_get_state(block)
- == BUF_BLOCK_FILE_PAGE) {
- ut_ad(!block->page.in_zip_hash);
- ut_ad(block->page.in_page_hash);
-
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(
- block->page.space,
- block->page.offset),
- &block->page);
- }
- }
- }
-
- /* Insert the compressed-only pages to buf_pool->page_hash.
- All such blocks are either in buf_pool->zip_clean or
- in buf_pool->flush_list. */
-
- for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
- b = UT_LIST_GET_NEXT(zip_list, b)) {
- ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
- ut_ad(!b->in_flush_list);
- ut_ad(b->in_LRU_list);
- ut_ad(b->in_page_hash);
- ut_ad(!b->in_zip_hash);
-
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(b->space, b->offset), b);
- }
-
- for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
- b = UT_LIST_GET_NEXT(flush_list, b)) {
- ut_ad(b->in_flush_list);
- ut_ad(b->in_LRU_list);
- ut_ad(b->in_page_hash);
- ut_ad(!b->in_zip_hash);
-
- switch (buf_page_get_state(b)) {
- case BUF_BLOCK_ZIP_DIRTY:
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(b->space,
- b->offset), b);
- break;
- case BUF_BLOCK_FILE_PAGE:
- /* uncompressed page */
- break;
- case BUF_BLOCK_ZIP_FREE:
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_NOT_USED:
- case BUF_BLOCK_READY_FOR_USE:
- case BUF_BLOCK_MEMORY:
- case BUF_BLOCK_REMOVE_HASH:
- ut_error;
- break;
- }
- }
-
- //buf_pool_mutex_exit();
- mutex_exit(&LRU_list_mutex);
- rw_lock_x_unlock(&page_hash_latch);
- mutex_exit(&flush_list_mutex);
-}
-
-/********************************************************************//**
-Resizes the buffer pool. */
-UNIV_INTERN
-void
-buf_pool_resize(void)
-/*=================*/
-{
- if (srv_buffer_pool_shm_key) {
- /* Cannot support resize */
- return;
- }
-
- //buf_pool_mutex_enter();
- mutex_enter(&LRU_list_mutex);
-
- if (srv_buf_pool_old_size == srv_buf_pool_size) {
-
- //buf_pool_mutex_exit();
- mutex_exit(&LRU_list_mutex);
- return;
- }
-
- if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
-
- //buf_pool_mutex_exit();
- mutex_exit(&LRU_list_mutex);
-
- /* Disable adaptive hash indexes and empty the index
- in order to free up memory in the buffer pool chunks. */
- buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
- / UNIV_PAGE_SIZE);
- } else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
-
- /* Enlarge the buffer pool by at least one megabyte */
-
- ulint mem_size
- = srv_buf_pool_size - srv_buf_pool_curr_size;
- buf_chunk_t* chunks;
- buf_chunk_t* chunk;
-
- chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
-
- memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
- * sizeof *chunks);
-
- chunk = &chunks[buf_pool->n_chunks];
-
- if (!buf_chunk_init(chunk, mem_size)) {
- mem_free(chunks);
- } else {
- buf_pool->curr_size += chunk->size;
- srv_buf_pool_curr_size = buf_pool->curr_size
- * UNIV_PAGE_SIZE;
- mem_free(buf_pool->chunks);
- buf_pool->chunks = chunks;
- buf_pool->n_chunks++;
- }
-
- srv_buf_pool_old_size = srv_buf_pool_size;
- //buf_pool_mutex_exit();
- mutex_exit(&LRU_list_mutex);
- }
-
- buf_pool_page_hash_rebuild();
-}
-
-/********************************************************************//**
Moves a page to the start of the buffer pool LRU list. This high-level
function can be used to prevent an important page from slipping out of
the buffer pool. */
@@ -2303,6 +1460,27 @@ lookup:
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
}
+ if (UNIV_UNLIKELY(bpage->space_was_being_deleted)) {
+ /* This page is obsoleted, should discard and retry */
+ rw_lock_s_unlock(&page_hash_latch);
+
+ mutex_enter(&LRU_list_mutex);
+ block_mutex = buf_page_get_mutex_enter(bpage);
+
+ if (UNIV_UNLIKELY(!block_mutex)) {
+ mutex_exit(&LRU_list_mutex);
+ goto lookup;
+ }
+
+ buf_LRU_free_block(bpage, TRUE, TRUE);
+
+ mutex_exit(&LRU_list_mutex);
+ mutex_exit(block_mutex);
+ block_mutex = NULL;
+
+ goto lookup;
+ }
+
if (UNIV_UNLIKELY(!bpage->zip.data)) {
/* There is no compressed page. */
err_exit:
@@ -2311,13 +1489,12 @@ err_exit:
return(NULL);
}
- if (srv_pass_corrupt_table) {
+ if (srv_pass_corrupt_table <= 1) {
if (bpage->is_corrupt) {
rw_lock_s_unlock(&page_hash_latch);
return(NULL);
}
}
- ut_a(!(bpage->is_corrupt));
block_mutex = buf_page_get_mutex_enter(bpage);
@@ -2340,13 +1517,32 @@ err_exit:
case BUF_BLOCK_FILE_PAGE:
ut_a(block_mutex == &((buf_block_t*) bpage)->mutex);
- /* Discard the uncompressed page frame if possible. */
- if (buf_LRU_free_block(bpage, FALSE, FALSE) == BUF_LRU_FREED) {
+ /* release mutex to obey to latch-order */
+ mutex_exit(block_mutex);
+
+ /* get LRU_list_mutex for buf_LRU_free_block() */
+ mutex_enter(&LRU_list_mutex);
+ mutex_enter(block_mutex);
+ if (UNIV_UNLIKELY(bpage->space != space
+ || bpage->offset != offset
+ || !bpage->in_LRU_list
+ || !bpage->zip.data)) {
+ /* someone should interrupt, retry */
+ mutex_exit(&LRU_list_mutex);
+ mutex_exit(block_mutex);
+ goto lookup;
+ }
+
+ /* Discard the uncompressed page frame if possible. */
+ if (buf_LRU_free_block(bpage, FALSE, TRUE)) {
+ mutex_exit(&LRU_list_mutex);
mutex_exit(block_mutex);
goto lookup;
}
+ mutex_exit(&LRU_list_mutex);
+
buf_block_buf_fix_inc((buf_block_t*) bpage,
__FILE__, __LINE__);
goto got_block;
@@ -2516,16 +1712,19 @@ buf_block_align(
/* 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
@@ -2651,7 +1850,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 */
+ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mini-transaction */
@@ -2661,7 +1860,7 @@ buf_page_get_gen(
ulint fix_type;
ibool must_read;
ulint retries = 0;
- mutex_t* block_mutex= 0;
+ mutex_t* block_mutex = NULL;
trx_t* trx = NULL;
ulint sec;
ulint ms;
@@ -2673,9 +1872,19 @@ 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));
+#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:
+ 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
@@ -2693,13 +1902,8 @@ loop:
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
/* If the guess is a compressed page descriptor that
- has been allocated by buf_buddy_alloc(), it may have
- been invalidated by buf_buddy_relocate(). In that
- case, block could point to something that happens to
- contain the expected bits in block->page. Similarly,
- the guess may be pointing to a buffer pool chunk that
- has been released when resizing the buffer pool. */
-
+ has been allocated by buf_page_alloc_descriptor(),
+ it may have been freed by buf_relocate(). */
if (!block_mutex) {
block = guess = NULL;
} else if (!buf_block_is_uncompressed(block)
@@ -2720,6 +1924,27 @@ loop:
rw_lock_s_lock(&page_hash_latch);
block = (buf_block_t*) buf_page_hash_get(space, offset);
if (block) {
+ if (UNIV_UNLIKELY(block->page.space_was_being_deleted)) {
+ /* This page is obsoleted, should discard and retry */
+ rw_lock_s_unlock(&page_hash_latch);
+
+ mutex_enter(&LRU_list_mutex);
+ block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
+
+ if (UNIV_UNLIKELY(!block_mutex)) {
+ mutex_exit(&LRU_list_mutex);
+ goto loop;
+ }
+
+ buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE);
+
+ mutex_exit(&LRU_list_mutex);
+ mutex_exit(block_mutex);
+ block_mutex = NULL;
+
+ goto loop;
+ }
+
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
ut_a(block_mutex);
}
@@ -2732,7 +1957,8 @@ loop2:
//buf_pool_mutex_exit();
- if (mode == BUF_GET_IF_IN_POOL) {
+ if (mode == BUF_GET_IF_IN_POOL
+ || mode == BUF_PEEK_IF_IN_POOL) {
return(NULL);
}
@@ -2771,7 +1997,8 @@ loop2:
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 only being read to buffer */
//buf_pool_mutex_exit();
mutex_exit(block_mutex);
@@ -2779,13 +2006,12 @@ loop2:
return(NULL);
}
- if (srv_pass_corrupt_table) {
+ if (srv_pass_corrupt_table <= 1) {
if (block->page.is_corrupt) {
mutex_exit(block_mutex);
return(NULL);
}
}
- ut_a(!(block->page.is_corrupt));
switch (buf_block_get_state(block)) {
buf_page_t* bpage;
@@ -2897,8 +2123,10 @@ wait_until_unfixed:
if (buf_page_get_state(&block->page)
== BUF_BLOCK_ZIP_PAGE) {
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(zip_list, buf_pool->zip_clean,
&block->page);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
ut_ad(!block->page.in_flush_list);
} else {
/* Relocate buf_pool->flush_list. */
@@ -2931,10 +2159,10 @@ wait_until_unfixed:
buf_pool->n_pend_unzip++;
mutex_exit(&buf_pool_mutex);
- buf_buddy_free(bpage, sizeof *bpage, FALSE);
-
//buf_pool_mutex_exit();
+ buf_page_free_descriptor(bpage);
+
/* Decompress the page and apply buffered operations
while not holding buf_pool_mutex or block->mutex. */
success = buf_zip_decompress(block, srv_use_checksums);
@@ -2981,9 +2209,9 @@ wait_until_unfixed:
/* Try to evict the block from the buffer pool, to use the
insert buffer as much as possible. */
- if (buf_LRU_free_block(&block->page, TRUE, FALSE) == BUF_LRU_FREED) {
- buf_pool_mutex_exit();
- mutex_exit(&block->mutex);
+ if (buf_LRU_free_block(&block->page, TRUE, FALSE)) {
+ //buf_pool_mutex_exit();
+ mutex_exit(block_mutex);
fprintf(stderr,
"innodb_change_buffering_debug evict %u %u\n",
(unsigned) space, (unsigned) offset);
@@ -3011,7 +2239,9 @@ wait_until_unfixed:
//buf_pool_mutex_exit();
mutex_exit(block_mutex);
- buf_page_set_accessed_make_young(&block->page, access_time);
+ if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL)) {
+ buf_page_set_accessed_make_young(&block->page, access_time);
+ }
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(!block->page.file_page_was_freed);
@@ -3077,7 +2307,7 @@ 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 */
@@ -3531,6 +2761,7 @@ buf_page_init_for_read(
{
buf_block_t* block;
buf_page_t* bpage;
+ buf_page_t* bpage_in_bp;
mtr_t mtr;
ibool lru = FALSE;
void* data;
@@ -3566,11 +2797,29 @@ buf_page_init_for_read(
ut_ad(block);
}
+retry:
//buf_pool_mutex_enter();
mutex_enter(&LRU_list_mutex);
rw_lock_x_lock(&page_hash_latch);
- if (buf_page_hash_get(space, offset)) {
+ bpage_in_bp = buf_page_hash_get(space, offset);
+
+ if (UNIV_UNLIKELY(bpage_in_bp && bpage_in_bp->space_was_being_deleted)) {
+ mutex_t* block_mutex = buf_page_get_mutex_enter(bpage_in_bp);
+
+ /* This page is obsoleted, should discard and retry */
+ rw_lock_x_unlock(&page_hash_latch);
+ ut_a(block_mutex);
+
+ buf_LRU_free_block(bpage_in_bp, TRUE, TRUE);
+
+ mutex_exit(&LRU_list_mutex);
+ mutex_exit(block_mutex);
+
+ goto retry;
+ }
+
+ if (bpage_in_bp) {
/* The page is already in the buffer pool. */
err_exit:
if (block) {
@@ -3648,17 +2897,12 @@ err_exit:
mutex_exit(&LRU_list_mutex);
mutex_exit(&block->mutex);
} else {
- /* Defer buf_buddy_alloc() until after the block has
- been found not to exist. The buf_buddy_alloc() and
- buf_buddy_free() calls may be expensive because of
- buf_buddy_relocate(). */
/* The compressed page must be allocated before the
control block (bpage), in order to avoid the
invocation of buf_buddy_relocate_block() on
uninitialized data. */
data = buf_buddy_alloc(zip_size, &lru, TRUE);
- bpage = buf_buddy_alloc(sizeof *bpage, &lru, TRUE);
/* If buf_buddy_alloc() allocated storage from the LRU list,
it released and reacquired buf_pool_mutex. Thus, we must
@@ -3666,17 +2910,16 @@ err_exit:
if (UNIV_UNLIKELY(lru)
&& UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
- /* The block was added by some other thread. */
- buf_buddy_free(bpage, sizeof *bpage, TRUE);
buf_buddy_free(data, zip_size, TRUE);
mutex_exit(&LRU_list_mutex);
rw_lock_x_unlock(&page_hash_latch);
-
bpage = NULL;
goto func_exit;
}
+ bpage = buf_page_alloc_descriptor();
+
page_zip_des_init(&bpage->zip);
page_zip_set_size(&bpage->zip, zip_size);
bpage->zip.data = data;
@@ -3706,9 +2949,11 @@ err_exit:
/* The block must be put to the LRU list, to the old blocks */
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
mutex_enter(&flush_list_mutex);
buf_LRU_insert_zip_clean(bpage);
mutex_exit(&flush_list_mutex);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
mutex_exit(&LRU_list_mutex);
@@ -3759,12 +3004,28 @@ buf_page_create(
free_block = buf_LRU_get_free_block();
+retry:
//buf_pool_mutex_enter();
mutex_enter(&LRU_list_mutex);
rw_lock_x_lock(&page_hash_latch);
block = (buf_block_t*) buf_page_hash_get(space, offset);
+ if (UNIV_UNLIKELY(block && block->page.space_was_being_deleted)) {
+ mutex_t* block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
+
+ /* This page is obsoleted, should discard and retry */
+ rw_lock_x_unlock(&page_hash_latch);
+ ut_a(block_mutex);
+
+ buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE);
+
+ mutex_exit(&LRU_list_mutex);
+ mutex_exit(block_mutex);
+
+ goto retry;
+ }
+
if (block && buf_page_in_file(&block->page)) {
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(space, offset) == 0);
@@ -3889,13 +3150,11 @@ UNIV_INTERN
void
buf_page_io_complete(
/*=================*/
- buf_page_t* bpage, /*!< in: pointer to the block in question */
- trx_t* trx)
+ buf_page_t* bpage) /*!< in: pointer to the block in question */
{
enum buf_io_fix io_type;
const ibool uncompressed = (buf_page_get_state(bpage)
== BUF_BLOCK_FILE_PAGE);
- enum buf_flush flush_type;
mutex_t* block_mutex;
ut_a(buf_page_in_file(bpage));
@@ -4012,14 +3271,18 @@ corrupt:
if (srv_pass_corrupt_table && !trx_sys_sys_space(bpage->space)
&& bpage->space < SRV_LOG_SPACE_FIRST_ID) {
+ trx_t* trx;
+
fprintf(stderr,
"InnoDB: space %u will be treated as corrupt.\n",
bpage->space);
fil_space_set_corrupt(bpage->space);
- if (trx && trx->dict_operation_lock_mode == 0) {
- dict_table_set_corrupt_by_space(bpage->space, TRUE);
- } else {
+
+ trx = innobase_get_trx();
+ if (trx && trx->dict_operation_lock_mode == RW_X_LATCH) {
dict_table_set_corrupt_by_space(bpage->space, FALSE);
+ } else {
+ dict_table_set_corrupt_by_space(bpage->space, TRUE);
}
bpage->is_corrupt = TRUE;
} else
@@ -4049,9 +3312,10 @@ corrupt:
}
}
- //buf_pool_mutex_enter();
+ //enum buf_flush flush_type;
+ //buf_pool_mutex_enter();
if (io_type == BUF_IO_WRITE) {
- flush_type = buf_page_get_flush_type(bpage);
+ //flush_type = buf_page_get_flush_type(bpage);
/* to keep consistency at buf_LRU_insert_zip_clean() */
//if (flush_type == BUF_FLUSH_LRU) { /* optimistic! */
mutex_enter(&LRU_list_mutex);
@@ -4781,12 +4045,16 @@ buf_print_io(
/* Statistics about read ahead algorithm */
fprintf(file, "Pages read ahead %.2f/s,"
- " evicted without access %.2f/s\n",
+ " evicted without access %.2f/s,"
+ " Random read ahead %.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,
+ (buf_pool->stat.n_ra_pages_read_rnd
+ - buf_pool->old_stat.n_ra_pages_read_rnd)
/ time_elapsed);
/* Print some values to help us with visualizing what is
diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c
index cda8d3b170e..0ea3ed29d2b 100644
--- a/storage/xtradb/buf/buf0flu.c
+++ b/storage/xtradb/buf/buf0flu.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.
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
@@ -459,7 +459,9 @@ buf_flush_remove(
case BUF_BLOCK_ZIP_DIRTY:
buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE);
UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
buf_LRU_insert_zip_clean(bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
break;
case BUF_BLOCK_FILE_PAGE:
UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
@@ -769,7 +771,7 @@ corrupted_page:
flush:
/* Now flush the doublewrite buffer data to disk */
- fil_flush(srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE);
+ fil_flush(srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE, FALSE);
/* We know that the writes have been flushed to disk now
and in recovery we will find them in the doublewrite buffer
@@ -1084,7 +1086,7 @@ buf_flush_page_try(
/*===============*/
buf_block_t* block) /*!< in/out: buffer control block */
{
- ut_ad(buf_pool_mutex_own());
+ //ut_ad(buf_pool_mutex_own());
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(mutex_own(&block->mutex));
@@ -1092,8 +1094,11 @@ buf_flush_page_try(
return(FALSE);
}
+ buf_pool_mutex_enter();
+
if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0
|| buf_pool->init_flush[BUF_FLUSH_LRU]) {
+ buf_pool_mutex_exit();
/* There is already a flush batch of the same type running */
return(FALSE);
}
diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c
index 583eec9bd9c..df74ccf500f 100644
--- a/storage/xtradb/buf/buf0lru.c
+++ b/storage/xtradb/buf/buf0lru.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.
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
@@ -259,18 +259,20 @@ buf_LRU_drop_page_hash_for_tablespace(
* BUF_LRU_DROP_SEARCH_HASH_SIZE);
//buf_pool_mutex_enter();
mutex_enter(&LRU_list_mutex);
+ num_entries = 0;
scan_again:
- num_entries = 0;
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) {
+ /* bpage->state,space,io_fix,buf_fix_count are protected by block_mutex at XtraDB */
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
buf_page_t* prev_bpage;
+ ibool is_fixed;
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
- if (!block_mutex) {
+ if (UNIV_UNLIKELY(!block_mutex)) {
goto next_page;
}
@@ -278,59 +280,77 @@ scan_again:
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. */
+ /* Compressed pages are never hashed.
+ Skip blocks of other tablespaces.
+ Skip I/O-fixed blocks (to be dealt with later). */
mutex_exit(block_mutex);
- goto next_page;
+next_page:
+ bpage = prev_bpage;
+ continue;
}
- if (((buf_block_t*) bpage)->is_hashed) {
+ //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);
- /* 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;
+ if (is_fixed) {
mutex_exit(block_mutex);
- ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
- ++num_entries;
+ 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();
- mutex_exit(&LRU_list_mutex);
+ /* Store the page number so that we can drop the hash
+ index in a batch later. */
+ page_arr[num_entries] = bpage->offset;
+ mutex_exit(block_mutex);
- buf_LRU_drop_page_hash_batch(id, zip_size, page_arr,
- num_entries);
- num_entries = 0;
- //buf_pool_mutex_enter();
- mutex_enter(&LRU_list_mutex);
- } else {
- 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;
}
-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;
+ /* Array full. We release the buf_pool_mutex to
+ obey the latching order. */
+ //buf_pool_mutex_exit();
+ mutex_exit(&LRU_list_mutex);
+ buf_LRU_drop_page_hash_batch(id, zip_size, page_arr,
+ num_entries);
+ //buf_pool_mutex_enter();
+ mutex_enter(&LRU_list_mutex);
+ num_entries = 0;
+
+ /* 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.
+
+ 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);
+
+ /* obtain block_mutex again to avoid race condition of bpage->state */
+ block_mutex = buf_page_get_mutex_enter(bpage);
+ if (!block_mutex) {
goto scan_again;
}
+
+ if (bpage
+ && buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
+ mutex_exit(block_mutex);
+ goto scan_again;
+ }
+ mutex_exit(block_mutex);
}
//buf_pool_mutex_exit();
@@ -372,7 +392,7 @@ scan_again:
while (bpage != NULL) {
buf_page_t* prev_bpage;
- ibool prev_bpage_buf_fix = FALSE;
+ mutex_t* block_mutex = NULL;
ut_a(buf_page_in_file(bpage));
@@ -385,26 +405,28 @@ scan_again:
if (buf_page_get_space(bpage) != id) {
/* Skip this block, as it does not belong to
the space that is being invalidated. */
+ goto next_page;
} else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
/* We cannot remove this page during this scan
yet; maybe the system is currently reading it
in, or flushing the modifications to the file */
all_freed = FALSE;
+ goto next_page;
} else {
- mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
+ block_mutex = buf_page_get_mutex_enter(bpage);
if (!block_mutex) {
/* It may be impossible case...
Something wrong, so will be scan_again */
all_freed = FALSE;
-
- goto next_page_no_mutex;
+ goto next_page;
}
if (bpage->buf_fix_count > 0) {
+ mutex_exit(block_mutex);
/* We cannot remove this page during
this scan yet; maybe the system is
currently reading it in, or flushing
@@ -414,108 +436,61 @@ scan_again:
goto next_page;
}
+ }
+
+ ut_ad(mutex_own(block_mutex));
#ifdef UNIV_DEBUG
- if (buf_debug_prints) {
- fprintf(stderr,
- "Dropping space %lu page %lu\n",
- (ulong) buf_page_get_space(bpage),
- (ulong) buf_page_get_page_no(bpage));
- }
+ if (buf_debug_prints) {
+ fprintf(stderr,
+ "Dropping space %lu page %lu\n",
+ (ulong) buf_page_get_space(bpage),
+ (ulong) buf_page_get_page_no(bpage));
+ }
#endif
- if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
- /* This is a compressed-only block
- descriptor. Ensure that prev_bpage
- cannot be relocated when bpage is freed. */
- if (UNIV_LIKELY(prev_bpage != NULL)) {
- switch (buf_page_get_state(
- prev_bpage)) {
- case BUF_BLOCK_FILE_PAGE:
- /* Descriptors of uncompressed
- blocks will not be relocated,
- because we are holding the
- buf_pool_mutex. */
- break;
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_ZIP_DIRTY:
- /* Descriptors of compressed-
- only blocks can be relocated,
- unless they are buffer-fixed.
- Because both bpage and
- prev_bpage are protected by
- buf_pool_zip_mutex, it is
- not necessary to acquire
- further mutexes. */
- ut_ad(&buf_pool_zip_mutex
- == block_mutex);
- ut_ad(mutex_own(block_mutex));
- prev_bpage_buf_fix = TRUE;
- prev_bpage->buf_fix_count++;
- break;
- default:
- ut_error;
- }
- }
- } else if (((buf_block_t*) bpage)->is_hashed) {
- ulint page_no;
- ulint zip_size;
-
- //buf_pool_mutex_exit();
- mutex_exit(&LRU_list_mutex);
- rw_lock_x_unlock(&page_hash_latch);
+ if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
+ /* This is a compressed-only block
+ descriptor. Do nothing. */
+ } else if (((buf_block_t*) bpage)->is_hashed) {
+ ulint page_no;
+ ulint zip_size;
- zip_size = buf_page_get_zip_size(bpage);
- page_no = buf_page_get_page_no(bpage);
+ //buf_pool_mutex_exit();
+ mutex_exit(&LRU_list_mutex);
+ rw_lock_x_unlock(&page_hash_latch);
- mutex_exit(block_mutex);
+ zip_size = buf_page_get_zip_size(bpage);
+ page_no = buf_page_get_page_no(bpage);
- /* Note that the following call will acquire
- an S-latch on the page */
+ mutex_exit(block_mutex);
- btr_search_drop_page_hash_when_freed(
- id, zip_size, page_no);
- goto scan_again;
- }
+ /* Note that the following call will acquire
+ an S-latch on the page */
- if (bpage->oldest_modification != 0) {
+ btr_search_drop_page_hash_when_freed(
+ id, zip_size, page_no);
+ goto scan_again;
+ }
- buf_flush_remove(bpage);
- }
+ if (bpage->oldest_modification != 0) {
- /* Remove from the LRU list. */
+ buf_flush_remove(bpage);
+ }
- if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
- != BUF_BLOCK_ZIP_FREE) {
- buf_LRU_block_free_hashed_page((buf_block_t*)
- bpage, TRUE);
- } else {
- /* The block_mutex should have been
- released by buf_LRU_block_remove_hashed_page()
- when it returns BUF_BLOCK_ZIP_FREE. */
- ut_ad(block_mutex == &buf_pool_zip_mutex);
- ut_ad(!mutex_own(block_mutex));
-
- if (prev_bpage_buf_fix) {
- /* We temporarily buffer-fixed
- prev_bpage, so that
- buf_buddy_free() could not
- relocate it, in case it was a
- compressed-only block
- descriptor. */
-
- mutex_enter(block_mutex);
- ut_ad(prev_bpage->buf_fix_count > 0);
- prev_bpage->buf_fix_count--;
- mutex_exit(block_mutex);
- }
+ /* Remove from the LRU list. */
- goto next_page_no_mutex;
- }
-next_page:
+ if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
+ != BUF_BLOCK_ZIP_FREE) {
+ buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
mutex_exit(block_mutex);
+ } else {
+ /* The block_mutex should have been released
+ by buf_LRU_block_remove_hashed_page() when it
+ returns BUF_BLOCK_ZIP_FREE. */
+ ut_ad(block_mutex == &buf_pool_zip_mutex);
+ ut_ad(!mutex_own(block_mutex));
}
-
-next_page_no_mutex:
+next_page:
bpage = prev_bpage;
}
@@ -539,6 +514,8 @@ buf_LRU_mark_space_was_deleted(
ulint id) /*!< in: space id */
{
buf_page_t* bpage;
+ buf_chunk_t* chunk;
+ ulint i, j;
mutex_enter(&LRU_list_mutex);
@@ -552,8 +529,32 @@ buf_LRU_mark_space_was_deleted(
}
mutex_exit(&LRU_list_mutex);
+
+ rw_lock_s_lock(&btr_search_latch);
+ chunk = buf_pool->chunks;
+ for (i = buf_pool->n_chunks; i--; chunk++) {
+ buf_block_t* block = chunk->blocks;
+ for (j = chunk->size; j--; block++) {
+ if (buf_block_get_state(block)
+ != BUF_BLOCK_FILE_PAGE
+ || !block->is_hashed
+ || buf_page_get_space(&block->page) != id) {
+ continue;
+ }
+
+ rw_lock_s_unlock(&btr_search_latch);
+
+ rw_lock_x_lock(&block->lock);
+ btr_search_drop_page_hash_index(block);
+ rw_lock_x_unlock(&block->lock);
+
+ rw_lock_s_lock(&btr_search_latch);
+ }
+ }
+ rw_lock_s_unlock(&btr_search_latch);
}
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/********************************************************************//**
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
UNIV_INTERN
@@ -587,6 +588,7 @@ buf_LRU_insert_zip_clean(
UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, bpage);
}
}
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//**
Try to free an uncompressed page of a compressed block from the unzip
@@ -629,7 +631,7 @@ restart:
UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
- enum buf_lru_free_block_status freed;
+ ibool freed;
mutex_enter(&block->mutex);
if (!block->in_unzip_LRU_list || !block->page.in_LRU_list
@@ -645,24 +647,9 @@ restart:
freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex);
mutex_exit(&block->mutex);
- switch (freed) {
- case BUF_LRU_FREED:
+ if (freed) {
return(TRUE);
-
- case BUF_LRU_CANNOT_RELOCATE:
- /* If we failed to relocate, try
- regular LRU eviction. */
- return(FALSE);
-
- case BUF_LRU_NOT_FREED:
- /* The block was buffer-fixed or I/O-fixed.
- Keep looking. */
- continue;
}
-
- /* inappropriate return value from
- buf_LRU_free_block() */
- ut_error;
}
return(FALSE);
@@ -695,10 +682,9 @@ restart:
UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
- enum buf_lru_free_block_status freed;
- unsigned accessed;
- mutex_t* block_mutex
- = buf_page_get_mutex_enter(bpage);
+ ibool freed;
+ unsigned accessed;
+ mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
if (!block_mutex) {
goto restart;
@@ -717,8 +703,7 @@ restart:
freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex);
mutex_exit(block_mutex);
- switch (freed) {
- case BUF_LRU_FREED:
+ if (freed) {
/* Keep track of pages that are evicted without
ever being accessed. This gives us a measure of
the effectiveness of readahead */
@@ -726,21 +711,7 @@ restart:
++buf_pool->stat.n_ra_pages_evicted;
}
return(TRUE);
-
- case BUF_LRU_NOT_FREED:
- /* The block was dirty, buffer-fixed, or I/O-fixed.
- Keep looking. */
- continue;
-
- case BUF_LRU_CANNOT_RELOCATE:
- /* This should never occur, because we
- want to discard the compressed page too. */
- break;
}
-
- /* inappropriate return value from
- buf_LRU_free_block() */
- ut_error;
}
return(FALSE);
@@ -1457,17 +1428,16 @@ buf_LRU_make_block_old(
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
+NOTE: If this function returns TRUE, it will temporarily
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
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
-BUF_LRU_NOT_FREED otherwise. */
+@return TRUE if freed, FALSE otherwise. */
UNIV_INTERN
-enum buf_lru_free_block_status
+ibool
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
@@ -1493,7 +1463,7 @@ buf_LRU_free_block(
if (!bpage->in_LRU_list || !block_mutex || !buf_page_can_relocate(bpage)) {
/* Do not free buffer-fixed or I/O-fixed blocks. */
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
if (bpage->space_was_being_deleted && bpage->oldest_modification != 0) {
@@ -1509,7 +1479,7 @@ buf_LRU_free_block(
/* Do not completely free dirty blocks. */
if (bpage->oldest_modification) {
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
} else if (bpage->oldest_modification) {
/* Do not completely free dirty blocks. */
@@ -1517,7 +1487,7 @@ buf_LRU_free_block(
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
ut_ad(buf_page_get_state(bpage)
== BUF_BLOCK_ZIP_DIRTY);
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
goto alloc;
@@ -1526,14 +1496,8 @@ buf_LRU_free_block(
If it cannot be allocated (without freeing a block
from the LRU list), refuse to free bpage. */
alloc:
- //buf_pool_mutex_exit_forbid();
- b = buf_buddy_alloc(sizeof *b, NULL, FALSE);
- //buf_pool_mutex_exit_allow();
-
- if (UNIV_UNLIKELY(!b)) {
- return(BUF_LRU_CANNOT_RELOCATE);
- }
-
+ b = buf_page_alloc_descriptor();
+ ut_a(b);
//memcpy(b, bpage, sizeof *b);
}
@@ -1563,7 +1527,7 @@ not_freed:
if (!have_LRU_mutex)
mutex_exit(&LRU_list_mutex);
rw_lock_x_unlock(&page_hash_latch);
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
} else if (zip || !bpage->zip.data) {
if (bpage->oldest_modification)
goto not_freed;
@@ -1670,7 +1634,9 @@ not_freed:
mutex_enter(&flush_list_mutex);
if (b->state == BUF_BLOCK_ZIP_PAGE) {
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
buf_LRU_insert_zip_clean(b);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
} else {
/* Relocate on buf_pool->flush_list. */
buf_flush_relocate_on_flush_list(bpage, b);
@@ -1746,7 +1712,7 @@ not_freed:
rw_lock_x_unlock(&page_hash_latch);
}
- return(BUF_LRU_FREED);
+ return(TRUE);
}
/******************************************************************//**
@@ -1967,15 +1933,16 @@ buf_LRU_block_remove_hashed_page(
ut_a(bpage->zip.data);
ut_a(buf_page_get_zip_size(bpage));
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
mutex_exit(&buf_pool_zip_mutex);
//buf_pool_mutex_exit_forbid();
buf_buddy_free(bpage->zip.data,
page_zip_get_size(&bpage->zip), TRUE);
- buf_buddy_free(bpage, sizeof(*bpage), TRUE);
//buf_pool_mutex_exit_allow();
- UNIV_MEM_UNDESC(bpage);
+ buf_page_free_descriptor(bpage);
return(BUF_BLOCK_ZIP_FREE);
case BUF_BLOCK_FILE_PAGE:
@@ -2284,6 +2251,11 @@ buf_LRU_file_restore(void)
" InnoDB: cannot open %s\n", LRU_DUMP_FILE);
goto end;
}
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Restoring buffer pool pages from %s\n",
+ LRU_DUMP_FILE);
+
if (size == 0 || size_high > 0 || size % 8) {
fprintf(stderr, " InnoDB: broken LRU dump file\n");
goto end;
@@ -2385,7 +2357,7 @@ buf_LRU_file_restore(void)
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: reading pages based on the dumped LRU list was done."
+ " InnoDB: Completed reading buffer pool pages"
" (requested: %lu, read: %lu)\n", req, reads);
ret = TRUE;
end:
diff --git a/storage/xtradb/buf/buf0rea.c b/storage/xtradb/buf/buf0rea.c
index 59de70d9a8a..966a9b5d7a6 100644
--- a/storage/xtradb/buf/buf0rea.c
+++ b/storage/xtradb/buf/buf0rea.c
@@ -38,6 +38,14 @@ Created 11/5/1995 Heikki Tuuri
#include "srv0start.h"
#include "srv0srv.h"
+/** The size in blocks of the area where the random read-ahead algorithm counts
+the accessed pages when deciding whether to read-ahead */
+#define BUF_READ_AHEAD_RANDOM_AREA BUF_READ_AHEAD_AREA
+
+/** There must be at least this many pages in buf_pool in the area to start
+a random read-ahead */
+#define BUF_READ_AHEAD_RANDOM_THRESHOLD (5 + BUF_READ_AHEAD_RANDOM_AREA / 8)
+
/** The linear read-ahead area size */
#define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA
@@ -201,13 +209,179 @@ not_to_recover:
if (sync) {
/* The i/o is already completed when we arrive from
fil_read */
- buf_page_io_complete(bpage, trx);
+ buf_page_io_complete(bpage);
}
return(1);
}
/********************************************************************//**
+Applies a random read-ahead in buf_pool if there are at least a threshold
+value of accessed pages from the random read-ahead area. Does not read any
+page, not even the one at the position (space, offset), if the read-ahead
+mechanism is not activated. NOTE 1: the calling thread may own latches on
+pages: to avoid deadlocks this function must be written such that it cannot
+end up waiting for these latches! NOTE 2: the calling thread must want
+access to the page given: this rule is set to prevent unintended read-aheads
+performed by ibuf routines, a situation which could result in a deadlock if
+the OS does not support asynchronous i/o.
+@return number of page read requests issued; NOTE that if we read ibuf
+pages, it may happen that the page at the given page number does not
+get read even if we return a positive value! */
+static
+ulint
+buf_read_ahead_random(
+/*==================*/
+ ulint space, /*!< in: space id */
+ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
+ ulint offset, /*!< in: page number of a page which the current thread
+ wants to access */
+ trx_t* trx)
+{
+ ib_int64_t tablespace_version;
+ ulint recent_blocks = 0;
+ ulint count;
+ ulint ibuf_mode;
+ ulint low, high;
+ ulint err;
+ ulint i;
+ ulint buf_read_ahead_random_area;
+
+ if (!srv_random_read_ahead) {
+ /* Disabled by user */
+ return(0);
+ }
+
+ if (srv_startup_is_before_trx_rollback_phase) {
+ /* No read-ahead to avoid thread deadlocks */
+ return(0);
+ }
+
+ if (ibuf_bitmap_page(zip_size, offset)
+ || trx_sys_hdr_page(space, offset)) {
+
+ /* If it is an ibuf bitmap page or trx sys hdr, we do
+ no read-ahead, as that could break the ibuf page access
+ order */
+
+ return(0);
+ }
+
+ /* Remember the tablespace version before we ask the tablespace size
+ below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
+ do not try to read outside the bounds of the tablespace! */
+
+ tablespace_version = fil_space_get_version(space);
+
+ buf_read_ahead_random_area = BUF_READ_AHEAD_RANDOM_AREA;
+
+ low = (offset / buf_read_ahead_random_area)
+ * buf_read_ahead_random_area;
+ high = (offset / buf_read_ahead_random_area + 1)
+ * buf_read_ahead_random_area;
+ if (high > fil_space_get_size(space)) {
+
+ high = fil_space_get_size(space);
+ }
+
+ //buf_pool_mutex_enter();
+ mutex_enter(&buf_pool_mutex);
+
+ if (buf_pool->n_pend_reads
+ > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
+ //buf_pool_mutex_exit();
+ mutex_exit(&buf_pool_mutex);
+
+ return(0);
+ }
+ mutex_exit(&buf_pool_mutex);
+
+ /* Count how many blocks in the area have been recently accessed,
+ that is, reside near the start of the LRU list. */
+
+ rw_lock_s_lock(&page_hash_latch);
+ for (i = low; i < high; i++) {
+ const buf_page_t* bpage = buf_page_hash_get(space, i);
+
+ if (bpage
+ && buf_page_is_accessed(bpage)
+ && buf_page_peek_if_young(bpage)) {
+
+ recent_blocks++;
+
+ if (recent_blocks >= BUF_READ_AHEAD_RANDOM_THRESHOLD) {
+
+ //buf_pool_mutex_exit();
+ rw_lock_s_unlock(&page_hash_latch);
+ goto read_ahead;
+ }
+ }
+ }
+
+ //buf_pool_mutex_exit();
+ rw_lock_s_unlock(&page_hash_latch);
+ /* Do nothing */
+ return(0);
+
+read_ahead:
+ /* Read all the suitable blocks within the area */
+
+ if (ibuf_inside()) {
+ ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
+ } else {
+ ibuf_mode = BUF_READ_ANY_PAGE;
+ }
+
+ count = 0;
+
+ for (i = low; i < high; i++) {
+ /* It is only sensible to do read-ahead in the non-sync aio
+ mode: hence FALSE as the first parameter */
+
+ if (!ibuf_bitmap_page(zip_size, i)) {
+ count += buf_read_page_low(
+ &err, FALSE,
+ ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
+ space, zip_size, FALSE,
+ tablespace_version, i, trx);
+ if (err == DB_TABLESPACE_DELETED) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Warning: in random"
+ " readahead trying to access\n"
+ "InnoDB: tablespace %lu page %lu,\n"
+ "InnoDB: but the tablespace does not"
+ " exist or is just being dropped.\n",
+ (ulong) space, (ulong) i);
+ }
+ }
+ }
+
+ /* In simulated aio we wake the aio handler threads only after
+ queuing all aio requests, in native aio the following call does
+ nothing: */
+
+ os_aio_simulated_wake_handler_threads();
+
+#ifdef UNIV_DEBUG
+ if (buf_debug_prints && (count > 0)) {
+ fprintf(stderr,
+ "Random read-ahead space %lu offset %lu pages %lu\n",
+ (ulong) space, (ulong) offset,
+ (ulong) count);
+ }
+#endif /* UNIV_DEBUG */
+
+ /* Read ahead is considered one I/O operation for the purpose of
+ LRU policy decision. */
+ buf_LRU_stat_inc_io();
+
+ buf_pool->stat.n_ra_pages_read_rnd += count;
+ return(count);
+}
+
+
+/********************************************************************//**
High-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
@@ -226,6 +400,9 @@ buf_read_page(
ulint count;
ulint err;
+ count = buf_read_ahead_random(space, zip_size, offset, trx);
+ srv_buf_pool_reads += count;
+
tablespace_version = fil_space_get_version(space);
/* We do the i/o in the synchronous aio mode to save thread
diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index 18880a5c72c..a8a1d7a11e6 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -4524,6 +4524,8 @@ dict_store_statistics(
break;
}
+ btr_pcur_store_position(&pcur, &mtr);
+
if (rec_get_deleted_flag(rec, 0)) {
/* don't count */
i--;
@@ -4564,6 +4566,10 @@ dict_store_statistics(
rests--;
next_rec:
+ mtr_commit(&mtr);
+ mtr_start(&mtr);
+ btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr);
+
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
btr_pcur_close(&pcur);
@@ -4654,6 +4660,7 @@ dict_update_statistics(
do {
if (table->is_corrupt) {
ut_a(srv_pass_corrupt_table);
+ dict_table_stats_unlock(table, RW_X_LATCH);
return;
}
diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c
index edd77e2530f..64d7fad3557 100644
--- a/storage/xtradb/dict/dict0load.c
+++ b/storage/xtradb/dict/dict0load.c
@@ -554,9 +554,10 @@ dict_load_columns(
}
/********************************************************************//**
-Loads definitions for index fields. */
+Loads definitions for index fields.
+@return DB_SUCCESS if ok, DB_CORRUPTION if failed */
static
-void
+ulint
dict_load_fields(
/*=============*/
dict_index_t* index, /*!< in: index whose fields to load */
@@ -575,6 +576,7 @@ dict_load_fields(
byte* buf;
ulint i;
mtr_t mtr;
+ ulint error = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -641,6 +643,26 @@ dict_load_fields(
field = rec_get_nth_field_old(rec, 4, &len);
+ if (prefix_len >= DICT_MAX_INDEX_COL_LEN) {
+ fprintf(stderr, "InnoDB: Error: load index"
+ " '%s' failed.\n"
+ "InnoDB: index field '%s' has a prefix"
+ " length of %lu bytes,\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, mem_heap_strdupl(
+ heap, (char*) field, len),
+ (ulong) prefix_len,
+ (ulong) (DICT_MAX_INDEX_COL_LEN - 1));
+ error = DB_CORRUPTION;
+ goto func_exit;
+ }
+
dict_mem_index_add_field(index,
mem_heap_strdupl(heap,
(char*) field, len),
@@ -650,8 +672,10 @@ next_rec:
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
+func_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
+ return(error);
}
/********************************************************************//**
@@ -802,7 +826,25 @@ dict_load_indexes(
space, type, n_fields);
index->id = id;
- 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
+ && !(index->type & DICT_CLUSTERED)) {
+ error = DB_SUCCESS;
+ goto next_rec;
+ } else {
+ goto func_exit;
+ }
+ }
+
error = dict_index_add_to_cache(table, index, page_no,
FALSE);
/* The data dictionary tables should never contain
@@ -1028,9 +1070,18 @@ err_exit:
} 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;
+
+ /* 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
+ || !(index->type & DICT_CLUSTERED)) {
+ dict_table_remove_from_cache(table);
+ table = NULL;
+ }
}
#if 0
if (err != DB_SUCCESS && table != NULL) {
diff --git a/storage/xtradb/dict/dict0mem.c b/storage/xtradb/dict/dict0mem.c
index f2d219bfd4f..c3da053c2de 100644
--- a/storage/xtradb/dict/dict0mem.c
+++ b/storage/xtradb/dict/dict0mem.c
@@ -36,6 +36,9 @@ Created 1/8/1996 Heikki Tuuri
#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 */
@@ -318,6 +321,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/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c
index 3c535bf7331..1ef0a9a46fb 100644
--- a/storage/xtradb/fil/fil0fil.c
+++ b/storage/xtradb/fil/fil0fil.c
@@ -46,6 +46,8 @@ Created 10/25/1995 Heikki Tuuri
#include "row0mysql.h"
#include "row0row.h"
#include "que0que.h"
+#include "btr0btr.h"
+#include "btr0sea.h"
#ifndef UNIV_HOTBACKUP
# include "buf0lru.h"
# include "ibuf0ibuf.h"
@@ -817,7 +819,7 @@ fil_node_close_file(
ut_ad(node && system);
ut_ad(mutex_own(&(system->mutex)));
ut_a(node->open);
- ut_a(node->n_pending == 0 || srv_lazy_drop_table);
+ ut_a(node->n_pending == 0 || node->space->is_being_deleted);
ut_a(node->n_pending_flushes == 0);
ut_a(node->modification_counter == node->flush_counter);
@@ -830,7 +832,7 @@ fil_node_close_file(
ut_a(system->n_open > 0);
system->n_open--;
- if (node->space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(node->space->id)) {
+ if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(node->space->id)) {
ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
/* The node is in the LRU list, remove it */
@@ -1029,7 +1031,7 @@ fil_node_free(
ut_ad(node && system && space);
ut_ad(mutex_own(&(system->mutex)));
ut_a(node->magic_n == FIL_NODE_MAGIC_N);
- ut_a(node->n_pending == 0 || srv_lazy_drop_table);
+ ut_a(node->n_pending == 0 || space->is_being_deleted);
if (node->open) {
/* We fool the assertion in fil_node_close_file() to think
@@ -2579,7 +2581,7 @@ retry:
os_thread_sleep(20000);
- fil_flush(id);
+ fil_flush(id, TRUE);
goto retry;
@@ -2792,7 +2794,7 @@ error_exit2:
goto error_exit;
}
- ret = os_file_flush(file);
+ ret = os_file_flush(file, TRUE);
if (!ret) {
fputs("InnoDB: Error: file flush of tablespace ", stderr);
@@ -2977,7 +2979,7 @@ fil_reset_too_high_lsns(
}
}
- success = os_file_flush(file);
+ success = os_file_flush(file, TRUE);
if (!success) {
goto func_exit;
@@ -2999,7 +3001,7 @@ fil_reset_too_high_lsns(
goto func_exit;
}
- success = os_file_flush(file);
+ success = os_file_flush(file, TRUE);
func_exit:
os_file_close(file);
ut_free(buf2);
@@ -3009,6 +3011,97 @@ func_exit:
}
/********************************************************************//**
+Checks if a page is corrupt. (for offline page)
+*/
+static
+ibool
+fil_page_buf_page_is_corrupted_offline(
+/*===================================*/
+ const byte* page, /*!< in: a database page */
+ ulint zip_size) /*!< in: size of compressed page;
+ 0 for uncompressed pages */
+{
+ ulint checksum_field;
+ ulint old_checksum_field;
+
+ if (!zip_size
+ && memcmp(page + FIL_PAGE_LSN + 4,
+ page + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
+ return(TRUE);
+ }
+
+ checksum_field = mach_read_from_4(page
+ + FIL_PAGE_SPACE_OR_CHKSUM);
+
+ if (zip_size) {
+ return(checksum_field != BUF_NO_CHECKSUM_MAGIC
+ && checksum_field
+ != page_zip_calc_checksum(page, zip_size));
+ }
+
+ old_checksum_field = mach_read_from_4(
+ page + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+
+ if (old_checksum_field != mach_read_from_4(page
+ + FIL_PAGE_LSN)
+ && old_checksum_field != BUF_NO_CHECKSUM_MAGIC
+ && old_checksum_field
+ != buf_calc_page_old_checksum(page)) {
+ return(TRUE);
+ }
+
+ if (!srv_fast_checksum
+ && checksum_field != 0
+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
+ && checksum_field
+ != buf_calc_page_new_checksum(page)) {
+ return(TRUE);
+ }
+
+ if (srv_fast_checksum
+ && checksum_field != 0
+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
+ && checksum_field
+ != buf_calc_page_new_checksum_32(page)
+ && checksum_field
+ != buf_calc_page_new_checksum(page)) {
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+/********************************************************************//**
+*/
+static
+void
+fil_page_buf_page_store_checksum(
+/*=============================*/
+ byte* page,
+ ulint zip_size)
+{
+ if (!zip_size) {
+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
+ srv_use_checksums
+ ? (!srv_fast_checksum
+ ? buf_calc_page_new_checksum(page)
+ : buf_calc_page_new_checksum_32(page))
+ : BUF_NO_CHECKSUM_MAGIC);
+ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
+ srv_use_checksums
+ ? buf_calc_page_old_checksum(page)
+ : BUF_NO_CHECKSUM_MAGIC);
+ } else {
+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
+ srv_use_checksums
+ ? page_zip_calc_checksum(page, zip_size)
+ : BUF_NO_CHECKSUM_MAGIC);
+ }
+}
+
+/********************************************************************//**
Tries to open a single-table tablespace and optionally checks the space id is
right in it. If does not succeed, prints an error message to the .err log. This
function is used to open a tablespace when we start up mysqld, and also in
@@ -3123,6 +3216,7 @@ fil_open_single_table_tablespace(
fil_system_t* system;
fil_node_t* node = NULL;
fil_space_t* space;
+ ulint zip_size;
buf3 = ut_malloc(2 * UNIV_PAGE_SIZE);
descr_page = ut_align(buf3, UNIV_PAGE_SIZE);
@@ -3140,12 +3234,15 @@ fil_open_single_table_tablespace(
/* store as first descr page */
memcpy(descr_page, page, UNIV_PAGE_SIZE);
+ zip_size = dict_table_flags_to_zip_size(flags);
+ ut_a(zip_size == dict_table_flags_to_zip_size(space_flags));
+
/* get free limit (page number) of the table space */
/* these should be same to the definition in fsp0fsp.c */
#define FSP_HEADER_OFFSET FIL_PAGE_DATA
#define FSP_FREE_LIMIT 12
free_limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + page);
- free_limit_bytes = (ib_int64_t)free_limit * (ib_int64_t)UNIV_PAGE_SIZE;
+ free_limit_bytes = (ib_int64_t)free_limit * (ib_int64_t)(zip_size ? zip_size : UNIV_PAGE_SIZE);
/* overwrite fsp header */
fsp_header_init_fields(page, id, flags);
@@ -3154,16 +3251,9 @@ fil_open_single_table_tablespace(
space_flags = flags;
if (mach_read_ull(page + FIL_PAGE_FILE_FLUSH_LSN) > current_lsn)
mach_write_ull(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn);
- mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
- srv_use_checksums
- ? (!srv_fast_checksum
- ? buf_calc_page_new_checksum(page)
- : buf_calc_page_new_checksum_32(page))
- : BUF_NO_CHECKSUM_MAGIC);
- mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
- srv_use_checksums
- ? buf_calc_page_old_checksum(page)
- : BUF_NO_CHECKSUM_MAGIC);
+
+ fil_page_buf_page_store_checksum(page, zip_size);
+
success = os_file_write(filepath, file, page, 0, 0, UNIV_PAGE_SIZE);
/* get file size */
@@ -3173,7 +3263,7 @@ fil_open_single_table_tablespace(
if (size_bytes < free_limit_bytes) {
free_limit_bytes = size_bytes;
- if (size_bytes >= (ib_int64_t) (FSP_EXTENT_SIZE * UNIV_PAGE_SIZE)) {
+ if (size_bytes >= (ib_int64_t) (FSP_EXTENT_SIZE * (zip_size ? zip_size : UNIV_PAGE_SIZE))) {
fprintf(stderr, "InnoDB: free limit of %s is larger than its real size.\n", filepath);
file_is_corrupt = TRUE;
}
@@ -3237,75 +3327,41 @@ skip_info:
size_bytes = ut_2pow_round(size_bytes, 1024 * 1024);
}
*/
- if (!(flags & DICT_TF_ZSSIZE_MASK)) {
+
+ if (zip_size) {
+ fprintf(stderr, "InnoDB: Warning: importing compressed table is still EXPERIMENTAL, currently.\n");
+ }
+
+ {
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
ib_int64_t offset;
- size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
+ size = (ulint) (size_bytes / (zip_size ? zip_size : UNIV_PAGE_SIZE));
/* over write space id of all pages */
rec_offs_init(offsets_);
fprintf(stderr, "InnoDB: Progress in %%:");
- for (offset = 0; offset < free_limit_bytes; offset += UNIV_PAGE_SIZE) {
- ulint checksum_field;
- ulint old_checksum_field;
+ for (offset = 0; offset < free_limit_bytes;
+ offset += zip_size ? zip_size : UNIV_PAGE_SIZE) {
ibool page_is_corrupt;
success = os_file_read(file, page,
(ulint)(offset & 0xFFFFFFFFUL),
- (ulint)(offset >> 32), UNIV_PAGE_SIZE);
+ (ulint)(offset >> 32),
+ zip_size ? zip_size : UNIV_PAGE_SIZE);
page_is_corrupt = FALSE;
/* check consistency */
- if (memcmp(page + FIL_PAGE_LSN + 4,
- page + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
-
+ if (fil_page_buf_page_is_corrupted_offline(page, zip_size)) {
page_is_corrupt = TRUE;
}
if (mach_read_from_4(page + FIL_PAGE_OFFSET)
- != offset / UNIV_PAGE_SIZE) {
-
- page_is_corrupt = TRUE;
- }
-
- checksum_field = mach_read_from_4(page
- + FIL_PAGE_SPACE_OR_CHKSUM);
-
- old_checksum_field = mach_read_from_4(
- page + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM);
-
- if (old_checksum_field != mach_read_from_4(page
- + FIL_PAGE_LSN)
- && old_checksum_field != BUF_NO_CHECKSUM_MAGIC
- && old_checksum_field
- != buf_calc_page_old_checksum(page)) {
-
- page_is_corrupt = TRUE;
- }
-
- if (!srv_fast_checksum
- && checksum_field != 0
- && checksum_field != BUF_NO_CHECKSUM_MAGIC
- && checksum_field
- != buf_calc_page_new_checksum(page)) {
-
- page_is_corrupt = TRUE;
- }
-
- if (srv_fast_checksum
- && checksum_field != 0
- && checksum_field != BUF_NO_CHECKSUM_MAGIC
- && checksum_field
- != buf_calc_page_new_checksum_32(page)
- && checksum_field
- != buf_calc_page_new_checksum(page)) {
+ != offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)) {
page_is_corrupt = TRUE;
}
@@ -3316,7 +3372,8 @@ skip_info:
/* it should be overwritten already */
ut_a(!page_is_corrupt);
- } else if (!((offset / UNIV_PAGE_SIZE) % UNIV_PAGE_SIZE)) {
+ } else if (!((offset / (zip_size ? zip_size : UNIV_PAGE_SIZE))
+ % (zip_size ? zip_size : UNIV_PAGE_SIZE))) {
/* descr page (not header) */
if (page_is_corrupt) {
file_is_corrupt = TRUE;
@@ -3327,7 +3384,7 @@ skip_info:
}
/* store as descr page */
- memcpy(descr_page, page, UNIV_PAGE_SIZE);
+ memcpy(descr_page, page, (zip_size ? zip_size : UNIV_PAGE_SIZE));
} else if (descr_is_corrupt) {
/* unknown state of the page */
@@ -3355,9 +3412,12 @@ skip_info:
ulint bit_index;
descr = descr_page + XDES_ARR_OFFSET
- + XDES_SIZE * (ut_2pow_remainder((offset / UNIV_PAGE_SIZE), UNIV_PAGE_SIZE) / FSP_EXTENT_SIZE);
+ + XDES_SIZE * (ut_2pow_remainder(
+ (offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)),
+ (zip_size ? zip_size : UNIV_PAGE_SIZE)) / FSP_EXTENT_SIZE);
- index = XDES_FREE_BIT + XDES_BITS_PER_PAGE * ((offset / UNIV_PAGE_SIZE) % FSP_EXTENT_SIZE);
+ index = XDES_FREE_BIT
+ + XDES_BITS_PER_PAGE * ((offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)) % FSP_EXTENT_SIZE);
byte_index = index / 8;
bit_index = index % 8;
@@ -3375,7 +3435,7 @@ skip_info:
}
if (page_is_corrupt) {
- fprintf(stderr, " [errp:%ld]", (long) (offset / UNIV_PAGE_SIZE));
+ fprintf(stderr, " [errp:%ld]", (long) (offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)));
/* cannot treat corrupt page */
goto skip_write;
@@ -3385,7 +3445,13 @@ skip_info:
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id);
for (i = 0; (ulint) i < n_index; i++) {
- if ((ulint) (offset / UNIV_PAGE_SIZE) == root_page[i]) {
+ if ((ulint) (offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)) == root_page[i]) {
+ if (fil_page_get_type(page) != FIL_PAGE_INDEX) {
+ file_is_corrupt = TRUE;
+ fprintf(stderr, " [etyp:%lld]",
+ offset / (zip_size ? zip_size : UNIV_PAGE_SIZE));
+ goto skip_write;
+ }
/* this is index root page */
mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
+ FSEG_HDR_SPACE, id);
@@ -3398,7 +3464,14 @@ skip_info:
if (fil_page_get_type(page) == FIL_PAGE_INDEX) {
dulint tmp = mach_read_from_8(page + (PAGE_HEADER + PAGE_INDEX_ID));
- if (mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0
+ for (i = 0; i < n_index; i++) {
+ if (ut_dulint_cmp(old_id[i], tmp) == 0) {
+ mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), new_id[i]);
+ break;
+ }
+ }
+
+ if (!zip_size && mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0
&& ut_dulint_cmp(old_id[0], tmp) == 0) {
/* leaf page of cluster index, reset trx_id of records */
rec_t* rec;
@@ -3417,7 +3490,7 @@ skip_info:
ULINT_UNDEFINED, &heap);
n_fields = rec_offs_n_fields(offsets);
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
trx_write_trx_id(rec + offset, ut_dulint_create(0, 1));
@@ -3437,44 +3510,34 @@ skip_info:
rec = page_rec_get_next(rec);
n_recs--;
}
- }
-
- for (i = 0; i < n_index; i++) {
- if (ut_dulint_cmp(old_id[i], tmp) == 0) {
- mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), new_id[i]);
- break;
- }
+ } else if (mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0
+ && ut_dulint_cmp(old_id[0], tmp) != 0) {
+ mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), ut_dulint_create(0, 1));
}
}
if (mach_read_ull(page + FIL_PAGE_LSN) > current_lsn) {
mach_write_ull(page + FIL_PAGE_LSN, current_lsn);
- mach_write_ull(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
- current_lsn);
+ if (!zip_size) {
+ mach_write_ull(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
+ current_lsn);
+ }
}
- mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
- srv_use_checksums
- ? (!srv_fast_checksum
- ? buf_calc_page_new_checksum(page)
- : buf_calc_page_new_checksum_32(page))
- : BUF_NO_CHECKSUM_MAGIC);
- mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
- srv_use_checksums
- ? buf_calc_page_old_checksum(page)
- : BUF_NO_CHECKSUM_MAGIC);
+ fil_page_buf_page_store_checksum(page, zip_size);
success = os_file_write(filepath, file, page,
(ulint)(offset & 0xFFFFFFFFUL),
- (ulint)(offset >> 32), UNIV_PAGE_SIZE);
+ (ulint)(offset >> 32),
+ zip_size ? zip_size : UNIV_PAGE_SIZE);
}
skip_write:
if (free_limit_bytes
- && ((ib_int64_t)((offset + UNIV_PAGE_SIZE) * 100) / free_limit_bytes)
+ && ((ib_int64_t)((offset + (zip_size ? zip_size : UNIV_PAGE_SIZE)) * 100) / free_limit_bytes)
!= ((offset * 100) / free_limit_bytes)) {
fprintf(stderr, " %lu",
- (ulong)((ib_int64_t)((offset + UNIV_PAGE_SIZE) * 100) / free_limit_bytes));
+ (ulong)((ib_int64_t)((offset + (zip_size ? zip_size : UNIV_PAGE_SIZE)) * 100) / free_limit_bytes));
}
}
@@ -3530,13 +3593,6 @@ skip_write:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
- } else {
- /* zip page? */
- size = (ulint)
- (size_bytes
- / dict_table_flags_to_zip_size(flags));
- fprintf(stderr, "InnoDB: import: table %s seems to be in newer format."
- " It may not be able to treated for now.\n", name);
}
/* .exp file should be removed */
success = os_file_delete(info_file_path);
@@ -3618,6 +3674,271 @@ func_exit:
os_file_close(file);
mem_free(filepath);
+ if (srv_expand_import && dict_table_flags_to_zip_size(flags)) {
+ ulint page_no;
+ ulint zip_size;
+ ulint height;
+ ulint root_height = 0;
+ rec_t* node_ptr;
+ dict_table_t* table;
+ dict_index_t* index;
+ buf_block_t* block;
+ page_t* page;
+ page_zip_des_t* page_zip;
+ mtr_t mtr;
+
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+
+ rec_offs_init(offsets_);
+
+ zip_size = dict_table_flags_to_zip_size(flags);
+
+ table = dict_table_get_low(name);
+ index = dict_table_get_first_index(table);
+ page_no = dict_index_get_page(index);
+ ut_a(page_no == 3);
+
+ fprintf(stderr, "InnoDB: It is compressed .ibd file. need to convert additionaly on buffer pool.\n");
+
+ /* down to leaf */
+ mtr_start(&mtr);
+ mtr_set_log_mode(&mtr, MTR_LOG_NONE);
+
+ height = ULINT_UNDEFINED;
+
+ for (;;) {
+ block = buf_page_get(space_id, zip_size, page_no,
+ RW_NO_LATCH, &mtr);
+ page = buf_block_get_frame(block);
+
+ block->check_index_page_at_flush = TRUE;
+
+ if (height == ULINT_UNDEFINED) {
+ height = btr_page_get_level(page, &mtr);
+ root_height = height;
+ }
+
+ if (height == 0) {
+ break;
+ }
+
+ node_ptr = page_rec_get_next(page_get_infimum_rec(page));
+
+ height--;
+
+ offsets = rec_get_offsets(node_ptr, index, offsets, ULINT_UNDEFINED, &heap);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
+ }
+
+ mtr_commit(&mtr);
+
+ fprintf(stderr, "InnoDB: pages needs split are ...");
+
+ /* scan reaf pages */
+ while (page_no != FIL_NULL) {
+ rec_t* rec;
+ rec_t* supremum;
+ ulint n_recs;
+
+ mtr_start(&mtr);
+
+ block = buf_page_get(space_id, zip_size, page_no,
+ RW_X_LATCH, &mtr);
+ page = buf_block_get_frame(block);
+ page_zip = buf_block_get_page_zip(block);
+
+ if (!page_zip) {
+ /*something wrong*/
+ fprintf(stderr, "InnoDB: Something wrong with reading page %lu.\n", page_no);
+convert_err_exit:
+ mtr_commit(&mtr);
+ mutex_enter(&fil_system->mutex);
+ fil_space_free(space_id, FALSE);
+ mutex_exit(&fil_system->mutex);
+ success = FALSE;
+ goto convert_exit;
+ }
+
+ supremum = page_get_supremum_rec(page);
+ rec = page_rec_get_next(page_get_infimum_rec(page));
+ n_recs = page_get_n_recs(page);
+
+ /* illegal operation as InnoDB online system. so not logged */
+ while (rec && rec != supremum && n_recs > 0) {
+ ulint n_fields;
+ ulint i;
+ ulint offset = index->trx_id_offset;
+
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ n_fields = rec_offs_n_fields(offsets);
+ if (!offset) {
+ offset = row_get_trx_id_offset(index, offsets);
+ }
+ trx_write_trx_id(rec + offset, ut_dulint_create(0, 1));
+
+ for (i = 0; i < n_fields; i++) {
+ if (rec_offs_nth_extern(offsets, i)) {
+ ulint local_len;
+ byte* data;
+
+ data = rec_get_nth_field(rec, offsets, i, &local_len);
+
+ local_len -= BTR_EXTERN_FIELD_REF_SIZE;
+
+ mach_write_to_4(data + local_len + BTR_EXTERN_SPACE_ID, id);
+ }
+ }
+
+ rec = page_rec_get_next(rec);
+ n_recs--;
+ }
+
+ /* dummy logged update for along with modified page path */
+ if (ut_dulint_cmp(index->id, btr_page_get_index_id(page)) != 0) {
+ /* this should be adjusted already */
+ fprintf(stderr, "InnoDB: The page %lu seems to be converted wrong.\n", page_no);
+ goto convert_err_exit;
+ }
+ btr_page_set_index_id(page, page_zip, index->id, &mtr);
+
+ /* confirm whether fits to the page size or not */
+ if (!page_zip_compress(page_zip, page, index, &mtr)
+ && !btr_page_reorganize(block, index, &mtr)) {
+ buf_block_t* new_block;
+ page_t* new_page;
+ page_zip_des_t* new_page_zip;
+ rec_t* split_rec;
+ ulint n_uniq;
+
+ /* split page is needed */
+ fprintf(stderr, " %lu", page_no);
+
+ mtr_x_lock(dict_index_get_lock(index), &mtr);
+
+ n_uniq = dict_index_get_n_unique_in_tree(index);
+
+ if(page_get_n_recs(page) < 2) {
+ /* no way to make smaller */
+ fprintf(stderr, "InnoDB: The page %lu cannot be store to the page size.\n", page_no);
+ goto convert_err_exit;
+ }
+
+ if (UNIV_UNLIKELY(page_no == dict_index_get_page(index))) {
+ ulint new_page_no;
+ dtuple_t* node_ptr;
+ ulint level;
+ rec_t* node_ptr_rec;
+ page_cur_t page_cursor;
+
+ /* it is root page, need to raise before split */
+
+ level = btr_page_get_level(page, &mtr);
+
+ new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr);
+ new_page = buf_block_get_frame(new_block);
+ new_page_zip = buf_block_get_page_zip(new_block);
+ btr_page_create(new_block, new_page_zip, index, level, &mtr);
+
+ btr_page_set_next(new_page, new_page_zip, FIL_NULL, &mtr);
+ btr_page_set_prev(new_page, new_page_zip, FIL_NULL, &mtr);
+
+ page_zip_copy_recs(new_page_zip, new_page,
+ page_zip, page, index, &mtr);
+ btr_search_move_or_delete_hash_entries(new_block, block, index);
+
+ rec = page_rec_get_next(page_get_infimum_rec(new_page));
+ new_page_no = buf_block_get_page_no(new_block);
+
+ node_ptr = dict_index_build_node_ptr(index, rec, new_page_no, heap,
+ level);
+ dtuple_set_info_bits(node_ptr,
+ dtuple_get_info_bits(node_ptr)
+ | REC_INFO_MIN_REC_FLAG);
+ btr_page_empty(block, page_zip, index, level + 1, &mtr);
+
+ btr_page_set_next(page, page_zip, FIL_NULL, &mtr);
+ btr_page_set_prev(page, page_zip, FIL_NULL, &mtr);
+
+ page_cur_set_before_first(block, &page_cursor);
+
+ node_ptr_rec = page_cur_tuple_insert(&page_cursor, node_ptr,
+ index, 0, &mtr);
+ ut_a(node_ptr_rec);
+
+ if (!btr_page_reorganize(block, index, &mtr)) {
+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", page_no);
+ goto convert_err_exit;
+ }
+
+ /* move to the raised page */
+ page_no = new_page_no;
+ block = new_block;
+ page = new_page;
+ page_zip = new_page_zip;
+
+ fprintf(stderr, "(raise_to:%lu)", page_no);
+ }
+
+ split_rec = page_get_middle_rec(page);
+
+ new_block = btr_page_alloc(index, page_no + 1, FSP_UP,
+ btr_page_get_level(page, &mtr), &mtr);
+ new_page = buf_block_get_frame(new_block);
+ new_page_zip = buf_block_get_page_zip(new_block);
+ btr_page_create(new_block, new_page_zip, index,
+ btr_page_get_level(page, &mtr), &mtr);
+
+ offsets = rec_get_offsets(split_rec, index, offsets, n_uniq, &heap);
+
+ btr_attach_half_pages(index, block,
+ split_rec, new_block, FSP_UP, &mtr);
+
+ page_zip_copy_recs(new_page_zip, new_page,
+ page_zip, page, index, &mtr);
+ page_delete_rec_list_start(split_rec - page + new_page,
+ new_block, index, &mtr);
+ btr_search_move_or_delete_hash_entries(new_block, block, index);
+ page_delete_rec_list_end(split_rec, block, index,
+ ULINT_UNDEFINED, ULINT_UNDEFINED, &mtr);
+
+ fprintf(stderr, "(new:%lu)", buf_block_get_page_no(new_block));
+
+ /* Are they needed? */
+ if (!btr_page_reorganize(block, index, &mtr)) {
+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", page_no);
+ goto convert_err_exit;
+ }
+ if (!btr_page_reorganize(new_block, index, &mtr)) {
+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", buf_block_get_page_no(new_block));
+ goto convert_err_exit;
+ }
+ }
+
+ page_no = btr_page_get_next(page, &mtr);
+
+ mtr_commit(&mtr);
+
+ if (heap) {
+ mem_heap_empty(heap);
+ }
+ }
+
+ fprintf(stderr, "...done.\nInnoDB: waiting the flush batch of the additional conversion.\n");
+
+ /* should wait for the not-logged changes are all flushed */
+ buf_flush_batch(BUF_FLUSH_LIST, ULINT_MAX, mtr.end_lsn + 1);
+ buf_flush_wait_batch_end(BUF_FLUSH_LIST);
+
+ fprintf(stderr, "InnoDB: done.\n");
+convert_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ }
+
return(success);
}
#endif /* !UNIV_HOTBACKUP */
@@ -4466,7 +4787,7 @@ fil_extend_space_to_desired_size(
mutex_exit(&fil_system->mutex);
mutex_exit(&fil_system->file_extend_mutex);
- fil_flush(space_id);
+ fil_flush(space_id, TRUE);
return(success);
}
@@ -4835,7 +5156,7 @@ _fil_io(
&& ((buf_page_t*)message)->space_was_being_deleted) {
if (mode == OS_AIO_NORMAL) {
- buf_page_io_complete(message, trx);
+ buf_page_io_complete(message);
return(DB_SUCCESS); /*fake*/
}
if (type == OS_FILE_READ) {
@@ -4946,14 +5267,14 @@ _fil_io(
ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
- if (srv_pass_corrupt_table && space->is_corrupt) {
+ if (srv_pass_corrupt_table == 1 && space->is_corrupt) {
/* should ignore i/o for the crashed space */
mutex_enter(&fil_system->mutex);
fil_node_complete_io(node, fil_system, type);
mutex_exit(&fil_system->mutex);
if (mode == OS_AIO_NORMAL) {
ut_a(space->purpose == FIL_TABLESPACE);
- buf_page_io_complete(message, trx);
+ buf_page_io_complete(message);
}
if (type == OS_FILE_READ) {
return(DB_TABLESPACE_DELETED);
@@ -4961,7 +5282,19 @@ _fil_io(
return(DB_SUCCESS);
}
} else {
- ut_a(!space->is_corrupt);
+ if (srv_pass_corrupt_table > 1 && space->is_corrupt) {
+ /* should ignore write i/o for the crashed space */
+ if (type == OS_FILE_WRITE) {
+ mutex_enter(&fil_system->mutex);
+ fil_node_complete_io(node, fil_system, type);
+ mutex_exit(&fil_system->mutex);
+ if (mode == OS_AIO_NORMAL) {
+ ut_a(space->purpose == FIL_TABLESPACE);
+ buf_page_io_complete(message);
+ }
+ return(DB_SUCCESS);
+ }
+ }
#ifdef UNIV_HOTBACKUP
/* In ibbackup do normal i/o, not aio */
if (type == OS_FILE_READ) {
@@ -5122,7 +5455,7 @@ fil_aio_wait(
|| buf_page_get_state(message) != BUF_BLOCK_FILE_PAGE);
srv_set_io_thread_op_info(segment, "complete io for buf page");
- buf_page_io_complete(message, NULL);
+ buf_page_io_complete(message);
return;
}
@@ -5146,7 +5479,7 @@ fil_aio_wait(
if (fil_node->space->purpose == FIL_TABLESPACE) {
srv_set_io_thread_op_info(segment, "complete io for buf page");
- buf_page_io_complete(message, NULL);
+ buf_page_io_complete(message);
} else {
srv_set_io_thread_op_info(segment, "complete io for log");
log_io_complete(message);
@@ -5161,8 +5494,9 @@ UNIV_INTERN
void
fil_flush(
/*======*/
- ulint space_id) /*!< in: file space id (this can be a group of
+ ulint space_id, /*!< in: file space id (this can be a group of
log files or a tablespace of the database) */
+ ibool metadata)
{
fil_space_t* space;
fil_node_t* node;
@@ -5233,7 +5567,7 @@ retry:
/* fprintf(stderr, "Flushing to file %s\n",
node->name); */
- os_file_flush(file);
+ os_file_flush(file, metadata);
mutex_enter(&fil_system->mutex);
@@ -5316,7 +5650,7 @@ fil_flush_file_spaces(
a non-existing space id. */
for (i = 0; i < n_space_ids; i++) {
- fil_flush(space_ids[i]);
+ fil_flush(space_ids[i], TRUE);
}
mem_free(space_ids);
diff --git a/storage/xtradb/ha/hash0hash.c b/storage/xtradb/ha/hash0hash.c
index 0f4fc55d895..30c304dafcd 100644
--- a/storage/xtradb/ha/hash0hash.c
+++ b/storage/xtradb/ha/hash0hash.c
@@ -128,70 +128,6 @@ hash_create(
}
/*************************************************************//**
-*/
-UNIV_INTERN
-ulint
-hash_create_needed(
-/*===============*/
- ulint n)
-{
- ulint prime;
- ulint offset;
-
- prime = ut_find_prime(n);
-
- offset = (sizeof(hash_table_t) + 7) / 8;
- offset *= 8;
-
- return(offset + sizeof(hash_cell_t) * prime);
-}
-
-UNIV_INTERN
-void
-hash_create_init(
-/*=============*/
- hash_table_t* table,
- ulint n)
-{
- ulint prime;
- ulint offset;
-
- prime = ut_find_prime(n);
-
- offset = (sizeof(hash_table_t) + 7) / 8;
- offset *= 8;
-
- table->array = (hash_cell_t*)(((byte*)table) + offset);
- table->n_cells = prime;
-# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- table->adaptive = FALSE;
-# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- table->n_mutexes = 0;
- table->mutexes = NULL;
- table->heaps = NULL;
- table->heap = NULL;
- ut_d(table->magic_n = HASH_TABLE_MAGIC_N);
-
- /* Initialize the cell array */
- hash_table_clear(table);
-}
-
-UNIV_INTERN
-void
-hash_create_reuse(
-/*==============*/
- hash_table_t* table)
-{
- ulint offset;
-
- offset = (sizeof(hash_table_t) + 7) / 8;
- offset *= 8;
-
- table->array = (hash_cell_t*)(((byte*)table) + offset);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
-}
-
-/*************************************************************//**
Frees a hash table. */
UNIV_INTERN
void
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index dfe98f09e4f..66243ad2e34 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -196,11 +196,14 @@ static my_bool innobase_create_status_file = FALSE;
static my_bool innobase_stats_on_metadata = TRUE;
static my_bool innobase_use_sys_stats_table = FALSE;
static my_bool innobase_buffer_pool_shm_checksum = TRUE;
+static uint innobase_buffer_pool_shm_key = 0;
static char* internal_innobase_data_file_path = NULL;
static char* innodb_version_str = (char*) INNODB_VERSION_STR;
+static my_bool innobase_blocking_lru_restore = FALSE;
+
/** 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 */
@@ -364,6 +367,12 @@ static MYSQL_THDVAR_ULONG(flush_log_at_trx_commit_session, PLUGIN_VAR_RQCMDARG,
"The value 3 regards innodb_flush_log_at_trx_commit (default).",
NULL, NULL, 3, 0, 3, 0);
+static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG,
+ "In the transaction after enabled, UPDATE, INSERT and DELETE only move the cursor to the records "
+ "and do nothing other operations (no changes, no ibuf, no undo, no transaction log) in the transaction. "
+ "This is to cause replication prefetch IO. ATTENTION: the transaction started after enabled is affected.",
+ NULL, NULL, FALSE);
+
static handler *innobase_create_handler(handlerton *hton,
TABLE_SHARE *table,
@@ -533,6 +542,8 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
{"buffer_pool_pages_total",
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
+ {"buffer_pool_read_ahead_rnd",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
{"buffer_pool_read_ahead",
(char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
{"buffer_pool_read_ahead_evicted",
@@ -1395,6 +1406,8 @@ innobase_trx_init(
trx->check_unique_secondary = !thd_test_options(
thd, OPTION_RELAXED_UNIQUE_CHECKS);
+ trx->fake_changes = THDVAR(thd, fake_changes);
+
#ifdef EXTENDED_SLOWLOG
if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) {
trx->take_stats = TRUE;
@@ -2457,6 +2470,12 @@ innobase_change_buffering_inited_ok:
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
+ if (innobase_buffer_pool_shm_key) {
+ fprintf(stderr,
+ "InnoDB: Warning: innodb_buffer_pool_shm_key is deprecated function.\n"
+ "InnoDB: innodb_buffer_pool_shm_key was ignored.\n");
+ }
+
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
@@ -2473,7 +2492,8 @@ innobase_change_buffering_inited_ok:
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
srv_use_checksums = (ibool) innobase_use_checksums;
srv_fast_checksum = (ibool) innobase_fast_checksum;
- srv_buffer_pool_shm_checksum = (ibool) innobase_buffer_pool_shm_checksum;
+
+ srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore;
#ifdef HAVE_LARGE_PAGES
if ((os_use_large_pages = (ibool) my_use_large_pages))
@@ -2511,6 +2531,10 @@ innobase_change_buffering_inited_ok:
innobase_commit_concurrency_init_default();
+#ifndef EXTENDED_FOR_KILLIDLE
+ srv_kill_idle_transaction = 0;
+#endif
+
/* Since we in this module access directly the fields of a trx
struct, and due to different headers and flags it might happen that
mutex_t has a different size in this module and in InnoDB
@@ -2808,6 +2832,11 @@ innobase_commit(
trx_search_latch_release_if_reserved(trx);
}
+ if (trx->fake_changes && (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
+ innobase_rollback(hton, thd, all); /* rollback implicitly */
+ thd->main_da.reset_diagnostics_area(); /* because debug assertion code complains, if something left */
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
/* The flag trx->active_trans is set to 1 in
1. ::external_lock(),
@@ -3798,7 +3827,7 @@ ha_innobase::open(
DBUG_RETURN(1);
}
- if (share->ib_table && share->ib_table->is_corrupt) {
+ if (srv_pass_corrupt_table <= 1 && share->ib_table && share->ib_table->is_corrupt) {
free_share(share);
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
@@ -3831,18 +3860,18 @@ retry:
/* Get pointer to a table object in InnoDB dictionary cache */
ib_table = dict_table_get(norm_name, TRUE);
- if (ib_table && ib_table->is_corrupt) {
+ if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
free_share(share);
my_free(upd_buff, MYF(0));
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
}
- if (share->ib_table) {
- ut_a(share->ib_table == ib_table);
- } else {
- share->ib_table = ib_table;
- }
+ share->ib_table = ib_table;
+
+
+
+
if (NULL == ib_table) {
if (is_part && retries < 10) {
@@ -4139,25 +4168,6 @@ field_in_record_is_null(
return(0);
}
-/**************************************************************//**
-Sets a field in a record to SQL NULL. Uses the record format
-information in table to track the null bit in record. */
-static inline
-void
-set_field_in_record_to_null(
-/*========================*/
- TABLE* table, /*!< in: MySQL table object */
- Field* field, /*!< in: MySQL field object */
- char* record) /*!< in: a row in MySQL format */
-{
- int null_offset;
-
- null_offset = (uint) ((char*) field->null_ptr
- - (char*) table->record[0]);
-
- record[null_offset] = record[null_offset] | field->null_bit;
-}
-
/*************************************************************//**
InnoDB uses this function to compare two data fields for which the data type
is such that we must use MySQL code to compare them. NOTE that the prototype
@@ -5811,7 +5821,7 @@ ha_innobase::index_read(
ha_statistic_increment(&SSV::ha_read_key_count);
- if (share->ib_table->is_corrupt) {
+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
DBUG_RETURN(HA_ERR_CRASHED);
}
@@ -5880,7 +5890,7 @@ ha_innobase::index_read(
ret = DB_UNSUPPORTED;
}
- if (share->ib_table->is_corrupt) {
+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
DBUG_RETURN(HA_ERR_CRASHED);
}
@@ -5999,7 +6009,7 @@ ha_innobase::change_active_index(
{
DBUG_ENTER("change_active_index");
- if (share->ib_table->is_corrupt) {
+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
DBUG_RETURN(HA_ERR_CRASHED);
}
@@ -6094,7 +6104,7 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
- if (share->ib_table->is_corrupt) {
+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
DBUG_RETURN(HA_ERR_CRASHED);
}
@@ -6107,7 +6117,7 @@ ha_innobase::general_fetch(
innodb_srv_conc_exit_innodb(prebuilt->trx);
- if (share->ib_table->is_corrupt) {
+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
DBUG_RETURN(HA_ERR_CRASHED);
}
@@ -6448,10 +6458,6 @@ 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 */
@@ -6573,6 +6579,8 @@ err_col:
col_len);
}
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_create_table_for_mysql(table, trx);
if (error == DB_DUPLICATE_KEY) {
@@ -6972,7 +6980,7 @@ ha_innobase::create(
if (srv_file_per_table
&& !mysqld_embedded
- && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
+ && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
if ((name[1] == ':')
|| (name[0] == '\\' && name[1] == '\\')) {
@@ -6989,42 +6997,17 @@ 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) {
@@ -7166,16 +7149,43 @@ 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);
+
+ if (trx->fake_changes) {
+ innobase_commit_low(trx);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
+ /* 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);
@@ -7375,6 +7385,10 @@ ha_innobase::delete_all_rows(void)
DBUG_RETURN(HA_ERR_CRASHED);
}
+ if (prebuilt->trx->fake_changes) {
+ goto fallback;
+ }
+
/* Truncate the table in InnoDB */
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
@@ -7435,10 +7449,10 @@ 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;
+ if (trx->fake_changes) {
+ innobase_commit_low(trx);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
name_len = strlen(name);
@@ -7447,6 +7461,8 @@ ha_innobase::delete_table(
/* Drop the table in InnoDB */
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_drop_table_for_mysql(norm_name, trx,
thd_sql_command(thd)
== SQLCOM_DROP_DB);
@@ -7527,6 +7543,12 @@ innobase_drop_database(
trx->mysql_thd = NULL;
#else
trx = innobase_trx_allocate(thd);
+ if (trx->fake_changes) {
+ my_free(namebuf, MYF(0));
+ innobase_commit_low(trx);
+ trx_free_for_mysql(trx);
+ return; /* ignore */
+ }
#endif
row_drop_database_for_mysql(namebuf, trx);
my_free(namebuf, MYF(0));
@@ -7563,12 +7585,6 @@ innobase_rename_table(
char* norm_from;
DBUG_ENTER("innobase_rename_table");
- 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));
@@ -7583,6 +7599,8 @@ innobase_rename_table(
row_mysql_lock_data_dictionary(trx);
}
+ srv_lower_case_table_names = lower_case_table_names;
+
error = row_rename_table_for_mysql(
norm_from, norm_to, trx, lock_and_commit);
@@ -7640,6 +7658,11 @@ ha_innobase::rename_table(
trx_search_latch_release_if_reserved(parent_trx);
trx = innobase_trx_allocate(thd);
+ if (trx->fake_changes) {
+ innobase_commit_low(trx);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
error = innobase_rename_table(trx, from, to, TRUE);
@@ -8143,6 +8166,8 @@ ha_innobase::info_low(
if (flag & HA_STATUS_VARIABLE) {
+ ulint page_size;
+
dict_table_stats_lock(ib_table, RW_S_LATCH);
n_rows = ib_table->stat_n_rows;
@@ -8185,14 +8210,19 @@ ha_innobase::info_low(
prebuilt->autoinc_last_value = 0;
}
+ page_size = dict_table_zip_size(ib_table);
+ if (page_size == 0) {
+ page_size = UNIV_PAGE_SIZE;
+ }
+
stats.records = (ha_rows)n_rows;
stats.deleted = 0;
- stats.data_file_length = ((ulonglong)
- ib_table->stat_clustered_index_size)
- * UNIV_PAGE_SIZE;
- stats.index_file_length = ((ulonglong)
- ib_table->stat_sum_of_other_index_sizes)
- * UNIV_PAGE_SIZE;
+ stats.data_file_length
+ = ((ulonglong) ib_table->stat_clustered_index_size)
+ * page_size;
+ stats.index_file_length =
+ ((ulonglong) ib_table->stat_sum_of_other_index_sizes)
+ * page_size;
dict_table_stats_unlock(ib_table, RW_S_LATCH);
@@ -9147,10 +9177,18 @@ ha_innobase::external_lock(
reset_template(prebuilt);
- if (lock_type == F_WRLCK) {
+ if (lock_type == F_WRLCK
+ || (table->s->tmp_table
+ && thd_sql_command(thd) == SQLCOM_LOCK_TABLES)) {
/* If this is a SELECT, then it is in UPDATE TABLE ...
- or SELECT ... FOR UPDATE */
+ or SELECT ... FOR UPDATE
+
+ For temporary tables which are locked for READ by LOCK TABLES
+ updates are still allowed by SQL-layer. In order to accomodate
+ for such a situation we always request X-lock for such table
+ at LOCK TABLES time.
+ */
prebuilt->select_lock_type = LOCK_X;
prebuilt->stored_select_lock_type = LOCK_X;
}
@@ -10397,6 +10435,10 @@ innobase_xa_prepare(
return(0);
}
+ if (trx->fake_changes) {
+ return(0);
+ }
+
thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
/* Release a possible FIFO ticket and search latch. Since we will
@@ -10514,7 +10556,7 @@ innobase_commit_by_xid(
if (trx) {
innobase_commit_low(trx);
-
+ trx_free_for_background(trx);
return(XA_OK);
} else {
return(XAER_NOTA);
@@ -10540,7 +10582,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);
}
@@ -11232,19 +11276,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;
@@ -11256,7 +11300,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 "
@@ -11275,6 +11319,48 @@ innobase_index_name_is_reserved(
return(false);
}
+/***********************************************************************
+functions for kill session of idle transaction */
+extern "C"
+ibool
+innobase_thd_is_idle(
+/*=================*/
+ const void* thd) /*!< in: thread handle (THD*) */
+{
+#ifdef EXTENDED_FOR_KILLIDLE
+ return(thd_command((const THD*) thd) == COM_SLEEP);
+#else
+ return(FALSE);
+#endif
+}
+
+extern "C"
+ib_int64_t
+innobase_thd_get_start_time(
+/*========================*/
+ const void* thd) /*!< in: thread handle (THD*) */
+{
+#ifdef EXTENDED_FOR_KILLIDLE
+ return((ib_int64_t)thd_start_time((const THD*) thd));
+#else
+ return(0); /*dummy value*/
+#endif
+}
+
+extern "C"
+void
+innobase_thd_kill(
+/*==============*/
+ void* thd)
+{
+#ifdef EXTENDED_FOR_KILLIDLE
+ thd_kill((THD*) thd);
+#else
+ return;
+#endif
+}
+
+
static SHOW_VAR innodb_status_variables_export[]= {
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
{NullS, NullS, SHOW_LONG}
@@ -11334,7 +11420,7 @@ static MYSQL_SYSVAR_BOOL(recovery_stats, innobase_recovery_stats,
static MYSQL_SYSVAR_ULINT(use_purge_thread, srv_use_purge_thread,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Number of purge devoted threads. #### over 1 is EXPERIMENTAL ####",
- NULL, NULL, 1, 0, 64, 0);
+ NULL, NULL, 1, 0, UNIV_MAX_PARALLELISM, 0);
static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
@@ -11506,16 +11592,16 @@ static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment,
static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
- NULL, NULL, 128*1024*1024L, 32*1024*1024L, LONGLONG_MAX, 1024*1024L);
+ NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
-static MYSQL_SYSVAR_UINT(buffer_pool_shm_key, srv_buffer_pool_shm_key,
+static MYSQL_SYSVAR_UINT(buffer_pool_shm_key, innobase_buffer_pool_shm_key,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "[experimental] The key value of shared memory segment for the buffer pool. 0 (default) disables the feature.",
+ "[Deprecated option] no effect",
NULL, NULL, 0, 0, INT_MAX32, 0);
static MYSQL_SYSVAR_BOOL(buffer_pool_shm_checksum, innobase_buffer_pool_shm_checksum,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
- "Enable buffer_pool_shm checksum validation (enabled by default).",
+ "[Deprecated option] no effect",
NULL, NULL, TRUE);
static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
@@ -11528,6 +11614,15 @@ static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
NULL, NULL, 500L, 1L, ~0L, 0);
+static MYSQL_SYSVAR_LONG(kill_idle_transaction, srv_kill_idle_transaction,
+ PLUGIN_VAR_RQCMDARG,
+#ifdef EXTENDED_FOR_KILLIDLE
+ "If non-zero value, the idle session with transaction which is idle over the value in seconds is killed by InnoDB.",
+#else
+ "No effect for this build.",
+#endif
+ NULL, NULL, 0, 0, LONG_MAX, 0);
+
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
"Number of file I/O threads in InnoDB.",
@@ -11663,6 +11758,11 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
NULL, NULL, 0, 0, 1, 0);
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead,
+ PLUGIN_VAR_NOCMDARG,
+ "Whether to use read ahead for random access within an extent.",
+ NULL, NULL, FALSE);
+
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 "
@@ -11786,13 +11886,19 @@ static MYSQL_SYSVAR_UINT(auto_lru_dump, srv_auto_lru_dump,
"0 (the default) disables automatic dumps.",
NULL, NULL, 0, 0, UINT_MAX32, 0);
+static MYSQL_SYSVAR_BOOL(blocking_lru_restore, innobase_blocking_lru_restore,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Block XtraDB startup process until buffer pool is full restored from a "
+ "dump file (if present). Disabled by default.",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_ULINT(pass_corrupt_table, srv_pass_corrupt_table,
PLUGIN_VAR_RQCMDARG,
"Pass corruptions of user tables as 'corrupt table' instead of not crashing itself, "
"when used with file_per_table. "
"All file io for the datafile after detected as corrupt are disabled, "
"except for the deletion.",
- NULL, NULL, 0, 0, 1, 0);
+ NULL, NULL, 0, 0, 2, 0);
static MYSQL_SYSVAR_ULINT(lazy_drop_table, srv_lazy_drop_table,
PLUGIN_VAR_RQCMDARG,
@@ -11812,6 +11918,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(fast_checksum),
MYSQL_SYSVAR(commit_concurrency),
MYSQL_SYSVAR(concurrency_tickets),
+ MYSQL_SYSVAR(kill_idle_transaction),
MYSQL_SYSVAR(data_file_path),
MYSQL_SYSVAR(doublewrite_file),
MYSQL_SYSVAR(data_home_dir),
@@ -11886,12 +11993,15 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
MYSQL_SYSVAR(change_buffering_debug),
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+ MYSQL_SYSVAR(random_read_ahead),
MYSQL_SYSVAR(read_ahead_threshold),
MYSQL_SYSVAR(io_capacity),
MYSQL_SYSVAR(auto_lru_dump),
+ MYSQL_SYSVAR(blocking_lru_restore),
MYSQL_SYSVAR(use_purge_thread),
MYSQL_SYSVAR(pass_corrupt_table),
MYSQL_SYSVAR(lazy_drop_table),
+ MYSQL_SYSVAR(fake_changes),
NULL
};
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index c60a5eae19e..bfe7432b32d 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -319,15 +319,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/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index c54b4a17fd2..37fddf71cbc 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -649,44 +649,47 @@ ha_innobase::add_index(
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);
+ if (prebuilt->trx->fake_changes) {
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
- /* 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);
if (UNIV_UNLIKELY(!innodb_table)) {
- error = HA_ERR_NO_SUCH_TABLE;
- goto err_exit;
+ 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 = ER_WRONG_NAME_FOR_INDEX;
- } else {
- /* Check that index keys are sensible */
- error = innobase_check_index_keys(key_info, num_of_keys,
- innodb_table);
- }
+ /* Check that index keys are sensible */
+ error = innobase_check_index_keys(key_info, num_of_keys, innodb_table);
if (UNIV_UNLIKELY(error)) {
-err_exit:
+ 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);
+ if (trx->fake_changes) {
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);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
+ 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. */
@@ -758,8 +761,12 @@ err_exit:
ut_d(dict_table_check_for_dup_indexes(innodb_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;
@@ -782,10 +789,6 @@ err_exit:
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
@@ -911,6 +914,14 @@ error:
}
convert_error:
+ if (error == DB_SUCCESS) {
+ /* Build index is successful. We will need to
+ rebuild index translation table. Reset the
+ index entry count in the translation table
+ to zero, so that translation table will be rebuilt */
+ share->idx_trans_tbl.index_count = 0;
+ }
+
error = convert_error_code_to_mysql(error,
innodb_table->flags,
user_thd);
@@ -963,6 +974,10 @@ ha_innobase::prepare_drop_index(
trx_search_latch_release_if_reserved(prebuilt->trx);
trx = prebuilt->trx;
+ if (trx->fake_changes) {
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
/* Test and mark all the indexes to be dropped */
row_mysql_lock_data_dictionary(trx);
@@ -1167,6 +1182,12 @@ ha_innobase::final_drop_index(
/* Create a background transaction for the operations on
the data dictionary tables. */
trx = innobase_trx_allocate(user_thd);
+ if (trx->fake_changes) {
+ trx_general_rollback_for_mysql(trx, NULL);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
trx_start_if_not_started(trx);
/* Flag this transaction as a dictionary operation, so that
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index f6160614686..d8be00afa6f 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -1006,7 +1006,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -1055,7 +1055,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -1108,7 +1108,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -1157,7 +1157,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -1210,7 +1210,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -1259,7 +1259,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -3158,7 +3158,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_rseg =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -3207,7 +3207,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg_maria =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
@@ -3246,6 +3246,189 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg_maria =
/***********************************************************************
*/
+static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
+{
+ {STRUCT_FLD(field_name, "result_message"),
+ STRUCT_FLD(field_length, 1024),
+ 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)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+#ifndef INNODB_COMPATIBILITY_HOOKS
+#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
+#endif
+
+extern "C" {
+char **thd_query(MYSQL_THD thd);
+}
+
+static
+int
+i_s_innodb_admin_command_fill(
+/*==========================*/
+ THD* thd,
+ TABLE_LIST* tables,
+ COND* cond)
+{
+ TABLE* i_s_table = (TABLE *) tables->table;
+ char** query_str;
+ char* ptr;
+ char quote = '\0';
+ const char* command_head = "XTRA_";
+
+ DBUG_ENTER("i_s_innodb_admin_command_fill");
+
+ /* deny access to non-superusers */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ if(thd_sql_command(thd) != SQLCOM_SELECT) {
+ field_store_string(i_s_table->field[0],
+ "SELECT command is only accepted.");
+ goto end_func;
+ }
+
+ query_str = thd_query(thd);
+ ptr = *query_str;
+
+ for (; *ptr; ptr++) {
+ if (*ptr == quote) {
+ quote = '\0';
+ } else if (quote) {
+ } else if (*ptr == '`' || *ptr == '"') {
+ quote = *ptr;
+ } else {
+ long i;
+ for (i = 0; command_head[i]; i++) {
+ if (toupper((int)(unsigned char)(ptr[i]))
+ != toupper((int)(unsigned char)
+ (command_head[i]))) {
+ goto nomatch;
+ }
+ }
+ break;
+nomatch:
+ ;
+ }
+ }
+
+ if (!*ptr) {
+ field_store_string(i_s_table->field[0],
+ "No XTRA_* command in the SQL statement."
+ " Please add /*!XTRA_xxxx*/ to the SQL.");
+ goto end_func;
+ }
+
+ if (!strncasecmp("XTRA_HELLO", ptr, 10)) {
+ /* This is example command XTRA_HELLO */
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: administration command test for XtraDB"
+ " 'XTRA_HELLO' was detected.\n");
+
+ field_store_string(i_s_table->field[0],
+ "Hello!");
+ goto end_func;
+ }
+ else if (!strncasecmp("XTRA_LRU_DUMP", ptr, 13)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_DUMP'"
+ " was detected.\n");
+
+ if (buf_LRU_file_dump()) {
+ field_store_string(i_s_table->field[0],
+ "XTRA_LRU_DUMP was succeeded.");
+ } else {
+ field_store_string(i_s_table->field[0],
+ "XTRA_LRU_DUMP was failed.");
+ }
+
+ goto end_func;
+ }
+ else if (!strncasecmp("XTRA_LRU_RESTORE", ptr, 16)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_RESTORE'"
+ " was detected.\n");
+
+ if (buf_LRU_file_restore()) {
+ field_store_string(i_s_table->field[0],
+ "XTRA_LRU_RESTORE was succeeded.");
+ } else {
+ field_store_string(i_s_table->field[0],
+ "XTRA_LRU_RESTORE was failed.");
+ }
+
+ goto end_func;
+ }
+
+ field_store_string(i_s_table->field[0],
+ "Undefined XTRA_* command.");
+ goto end_func;
+
+end_func:
+ if (schema_table_store_record(thd, i_s_table)) {
+ DBUG_RETURN(1);
+ } else {
+ DBUG_RETURN(0);
+ }
+}
+
+static
+int
+i_s_innodb_admin_command_init(
+/*==========================*/
+ void* p)
+{
+ DBUG_ENTER("i_s_innodb_admin_command_init");
+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = i_s_innodb_admin_command_info;
+ schema->fill_table = i_s_innodb_admin_command_fill;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
+ STRUCT_FLD(author, "Percona"),
+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(__reserved1, NULL)
+};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
+ STRUCT_FLD(author, "Percona"),
+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
+/***********************************************************************
+*/
static ST_FIELD_INFO i_s_innodb_table_stats_info[] =
{
{STRUCT_FLD(field_name, "table_schema"),
@@ -3561,7 +3744,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_table_stats =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_TABLE_STATS"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB table statistics in memory"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_table_stats_init),
@@ -3577,7 +3760,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_table_stats_maria =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_TABLE_STATS"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB table statistics in memory"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_table_stats_init),
@@ -3594,7 +3777,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_INDEX_STATS"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB index statistics in memory"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_index_stats_init),
@@ -3610,7 +3793,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats_maria =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_INDEX_STATS"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB index statistics in memory"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_index_stats_init),
@@ -3622,188 +3805,6 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats_maria =
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
};
-/***********************************************************************
-*/
-static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
-{
- {STRUCT_FLD(field_name, "result_message"),
- STRUCT_FLD(field_length, 1024),
- 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)},
-
- END_OF_ST_FIELD_INFO
-};
-
-#ifndef INNODB_COMPATIBILITY_HOOKS
-#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
-#endif
-
-extern "C" {
-char **thd_query(MYSQL_THD thd);
-}
-
-static
-int
-i_s_innodb_admin_command_fill(
-/*==========================*/
- THD* thd,
- TABLE_LIST* tables,
- COND* cond)
-{
- TABLE* i_s_table = (TABLE *) tables->table;
- char** query_str;
- char* ptr;
- char quote = '\0';
- const char* command_head = "XTRA_";
-
- DBUG_ENTER("i_s_innodb_admin_command_fill");
-
- /* deny access to non-superusers */
- if (check_global_access(thd, PROCESS_ACL)) {
- DBUG_RETURN(0);
- }
-
- if(thd_sql_command(thd) != SQLCOM_SELECT) {
- field_store_string(i_s_table->field[0],
- "SELECT command is only accepted.");
- goto end_func;
- }
-
- query_str = thd_query(thd);
- ptr = *query_str;
-
- for (; *ptr; ptr++) {
- if (*ptr == quote) {
- quote = '\0';
- } else if (quote) {
- } else if (*ptr == '`' || *ptr == '"') {
- quote = *ptr;
- } else {
- long i;
- for (i = 0; command_head[i]; i++) {
- if (toupper((int)(unsigned char)(ptr[i]))
- != toupper((int)(unsigned char)
- (command_head[i]))) {
- goto nomatch;
- }
- }
- break;
-nomatch:
- ;
- }
- }
-
- if (!*ptr) {
- field_store_string(i_s_table->field[0],
- "No XTRA_* command in the SQL statement."
- " Please add /*!XTRA_xxxx*/ to the SQL.");
- goto end_func;
- }
-
- if (!strncasecmp("XTRA_HELLO", ptr, 10)) {
- /* This is example command XTRA_HELLO */
-
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: administration command test for XtraDB"
- " 'XTRA_HELLO' was detected.\n");
-
- field_store_string(i_s_table->field[0],
- "Hello!");
- goto end_func;
- }
- else if (!strncasecmp("XTRA_LRU_DUMP", ptr, 13)) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_DUMP'"
- " was detected.\n");
-
- if (buf_LRU_file_dump()) {
- field_store_string(i_s_table->field[0],
- "XTRA_LRU_DUMP was succeeded.");
- } else {
- field_store_string(i_s_table->field[0],
- "XTRA_LRU_DUMP was failed.");
- }
-
- goto end_func;
- }
- else if (!strncasecmp("XTRA_LRU_RESTORE", ptr, 16)) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_RESTORE'"
- " was detected.\n");
-
- if (buf_LRU_file_restore()) {
- field_store_string(i_s_table->field[0],
- "XTRA_LRU_RESTORE was succeeded.");
- } else {
- field_store_string(i_s_table->field[0],
- "XTRA_LRU_RESTORE was failed.");
- }
-
- goto end_func;
- }
-
- field_store_string(i_s_table->field[0],
- "Undefined XTRA_* command.");
- goto end_func;
-
-end_func:
- if (schema_table_store_record(thd, i_s_table)) {
- DBUG_RETURN(1);
- } else {
- DBUG_RETURN(0);
- }
-}
-
-static
-int
-i_s_innodb_admin_command_init(
-/*==========================*/
- void* p)
-{
- DBUG_ENTER("i_s_innodb_admin_command_init");
- ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
-
- schema->fields_info = i_s_innodb_admin_command_info;
- schema->fill_table = i_s_innodb_admin_command_fill;
-
- DBUG_RETURN(0);
-}
-
-UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command =
-{
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
- STRUCT_FLD(info, &i_s_info),
- STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
- STRUCT_FLD(author, plugin_author),
- STRUCT_FLD(descr, "XtraDB specific command acceptor"),
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
- STRUCT_FLD(init, i_s_innodb_admin_command_init),
- STRUCT_FLD(deinit, i_s_common_deinit),
- STRUCT_FLD(version, 0x0100 /* 1.0 */),
- STRUCT_FLD(status_vars, NULL),
- STRUCT_FLD(system_vars, NULL),
- STRUCT_FLD(__reserved1, NULL)
-};
-
-UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command_maria =
-{
- STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
- STRUCT_FLD(info, &i_s_info),
- STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
- STRUCT_FLD(author, plugin_author),
- STRUCT_FLD(descr, "XtraDB specific command acceptor"),
- STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
- STRUCT_FLD(init, i_s_innodb_admin_command_init),
- STRUCT_FLD(deinit, i_s_common_deinit),
- STRUCT_FLD(version, 0x0100 /* 1.0 */),
- STRUCT_FLD(status_vars, NULL),
- STRUCT_FLD(system_vars, NULL),
- STRUCT_FLD(version_info, "1.0"),
- STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
-};
static ST_FIELD_INFO i_s_innodb_sys_tables_info[] =
{
@@ -4340,15 +4341,14 @@ i_s_innodb_schema_table_fill(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur)) {
/* end of index */
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
break;
}
+
+ btr_pcur_store_position(&pcur, &mtr);
+
if (rec_get_deleted_flag(rec, 0)) {
/* record marked as deleted */
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- continue;
+ goto next_record;
}
if (id == 0) {
@@ -4359,33 +4359,23 @@ i_s_innodb_schema_table_fill(
status = copy_sys_stats_rec(table, index, rec);
}
if (status) {
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
break;
}
-#if 0
- btr_pcur_store_position(&pcur, &mtr);
- mtr_commit(&mtr);
-
status = schema_table_store_record(thd, table);
if (status) {
- btr_pcur_close(&pcur);
break;
}
+next_record:
+ mtr_commit(&mtr);
mtr_start(&mtr);
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
-#else
- status = schema_table_store_record(thd, table);
- if (status) {
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
- break;
- }
-#endif
}
+ btr_pcur_close(&pcur);
+ mtr_commit(&mtr);
+
mutex_exit(&(dict_sys->mutex));
DBUG_RETURN(status);
@@ -4441,7 +4431,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_SYS_TABLES"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB SYS_TABLES table"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_sys_tables_init),
@@ -4457,7 +4447,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tables_maria =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_SYS_TABLES"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB SYS_TABLES table"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_sys_tables_init),
@@ -4474,7 +4464,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB SYS_INDEXES table"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_sys_indexes_init),
@@ -4490,7 +4480,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_indexes_maria =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB SYS_INDEXES table"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_sys_indexes_init),
@@ -4507,7 +4497,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_stats =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_SYS_STATS"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB SYS_STATS table"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_sys_stats_init),
@@ -4523,7 +4513,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_stats_maria =
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "INNODB_SYS_STATS"),
- STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(author, "Percona"),
STRUCT_FLD(descr, "InnoDB SYS_STATS table"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_sys_stats_init),
diff --git a/storage/xtradb/handler/innodb_patch_info.h b/storage/xtradb/handler/innodb_patch_info.h
index e68f12d0fec..38b97411340 100644
--- a/storage/xtradb/handler/innodb_patch_info.h
+++ b/storage/xtradb/handler/innodb_patch_info.h
@@ -47,6 +47,5 @@ struct innodb_enhancement {
{"innodb_fast_checksum","Using the checksum on 32bit-unit calculation","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_files_extend","allow >4GB transaction log files, and can vary universal page size of datafiles","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_sys_tables_sys_indexes","Expose InnoDB SYS_TABLES and SYS_INDEXES schema tables","","http://www.percona.com/docs/wiki/percona-xtradb"},
-{"innodb_buffer_pool_shm","Put buffer pool contents to shared memory segment and reuse it at clean restart [experimental]","","http://www.percona.com/docs/wiki/percona-xtradb"},
{NULL, NULL, NULL, NULL}
};
diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c
index 3f741da60bb..64dc9a5591d 100644
--- a/storage/xtradb/ibuf/ibuf0ibuf.c
+++ b/storage/xtradb/ibuf/ibuf0ibuf.c
@@ -2613,6 +2613,8 @@ ibuf_insert_low(
ut_a(trx_sys_multiple_tablespace_format);
+ ut_ad(!(thr_get_trx(thr)->fake_changes));
+
do_merge = FALSE;
mutex_enter(&ibuf_mutex);
diff --git a/storage/xtradb/include/btr0btr.h b/storage/xtradb/include/btr0btr.h
index dde3a0bab69..1fe40965c0f 100644
--- a/storage/xtradb/include/btr0btr.h
+++ b/storage/xtradb/include/btr0btr.h
@@ -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.
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
@@ -81,6 +81,91 @@ UNIQUE definition on secondary indexes when we decide if we can use
the insert buffer to speed up inserts */
#define BTR_IGNORE_SEC_UNIQUE 2048
+#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 */
@@ -123,6 +208,17 @@ btr_block_get_func(
@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))
+/**************************************************************//**
+Sets the index id field of a page. */
+UNIV_INLINE
+void
+btr_page_set_index_id(
+/*==================*/
+ page_t* page, /*!< in: page to be created */
+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
+ part will be updated, or NULL */
+ dulint id, /*!< in: index id */
+ mtr_t* mtr); /*!< in: mtr */
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
Gets the index id field of a page.
@@ -160,6 +256,17 @@ btr_page_get_next(
const page_t* page, /*!< in: index page */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************//**
+Sets the next index page field. */
+UNIV_INLINE
+void
+btr_page_set_next(
+/*==============*/
+ page_t* page, /*!< in: index page */
+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
+ part will be updated, or NULL */
+ ulint next, /*!< in: next page number */
+ mtr_t* mtr); /*!< in: mini-transaction handle */
+/********************************************************//**
Gets the previous index page number.
@return prev page number */
UNIV_INLINE
@@ -168,6 +275,17 @@ btr_page_get_prev(
/*==============*/
const page_t* page, /*!< in: index page */
mtr_t* mtr); /*!< in: mini-transaction handle */
+/********************************************************//**
+Sets the previous index page field. */
+UNIV_INLINE
+void
+btr_page_set_prev(
+/*==============*/
+ page_t* page, /*!< in: index page */
+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
+ part will be updated, or NULL */
+ ulint prev, /*!< in: previous page number */
+ mtr_t* mtr); /*!< in: mini-transaction handle */
/*************************************************************//**
Gets pointer to the previous user record in the tree. It is assumed
that the caller has appropriate latches on the page and its neighbor.
@@ -213,6 +331,18 @@ btr_node_ptr_get_child_page_no(
/*===========================*/
const rec_t* rec, /*!< in: node pointer record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
+/**************************************************************//**
+Creates a new index page (not the root, and also not
+used in page reorganization). @see btr_page_empty(). */
+UNIV_INTERN
+void
+btr_page_create(
+/*============*/
+ buf_block_t* block, /*!< in/out: page to be created */
+ page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
+ dict_index_t* index, /*!< in: index */
+ ulint level, /*!< in: the B-tree level of the page */
+ mtr_t* mtr); /*!< in: mtr */
/************************************************************//**
Creates the root node for a new index tree.
@return page number of the created root, FIL_NULL if did not succeed */
@@ -283,6 +413,17 @@ btr_page_reorganize(
dict_index_t* index, /*!< in: record descriptor */
mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
+Empties an index page. @see btr_page_create(). */
+UNIV_INTERN
+void
+btr_page_empty(
+/*===========*/
+ buf_block_t* block, /*!< in: page to be emptied */
+ page_zip_des_t* page_zip,/*!< out: compressed page, or NULL */
+ dict_index_t* index, /*!< in: index of the page */
+ ulint level, /*!< in: the B-tree level of the page */
+ mtr_t* mtr); /*!< in: mtr */
+/*************************************************************//**
Decides if the page should be split at the convergence point of
inserts converging to left.
@return TRUE if split recommended */
@@ -341,6 +482,20 @@ btr_insert_on_non_leaf_level_func(
# define btr_insert_on_non_leaf_level(i,l,t,m) \
btr_insert_on_non_leaf_level_func(i,l,t,__FILE__,__LINE__,m)
#endif /* !UNIV_HOTBACKUP */
+/**************************************************************//**
+Attaches the halves of an index page on the appropriate level in an
+index tree. */
+UNIV_INTERN
+void
+btr_attach_half_pages(
+/*==================*/
+ dict_index_t* index, /*!< in: the index tree */
+ buf_block_t* block, /*!< in/out: page to be split */
+ const rec_t* split_rec, /*!< in: first record on upper
+ half page */
+ buf_block_t* new_block, /*!< in/out: the new half page */
+ ulint direction, /*!< in: FSP_UP or FSP_DOWN */
+ mtr_t* mtr); /*!< in: mtr */
/****************************************************************//**
Sets a record as the predefined minimum record. */
UNIV_INTERN
@@ -385,11 +540,14 @@ UNIV_INTERN
ibool
btr_compress(
/*=========*/
- btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
- the page must not be empty: in record delete
- use btr_discard_page if the page would become
- empty */
- mtr_t* mtr); /*!< in: mtr */
+ btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
+ or lift; the page must not be empty:
+ when deleting records, use btr_discard_page()
+ if the page would become empty */
+ ibool adjust, /*!< in: TRUE if should adjust the
+ cursor position even if compression occurs */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/*************************************************************//**
Discards a page from a B-tree. This is used to remove the last record from
a B-tree page: the whole page must be removed at the same time. This cannot
diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h
index ece3621fa97..6f4ce95d72f 100644
--- a/storage/xtradb/include/btr0cur.h
+++ b/storage/xtradb/include/btr0cur.h
@@ -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.
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
@@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the
update vector or inserted entry */
+#define BTR_KEEP_POS_FLAG 8 /* btr_cur_pessimistic_update()
+ must keep cursor position when
+ moving columns to big_rec */
#ifndef UNIV_HOTBACKUP
#include "que0types.h"
@@ -309,7 +312,9 @@ btr_cur_pessimistic_update(
/*=======================*/
ulint flags, /*!< in: undo logging, locking, and rollback
flags */
- btr_cur_t* cursor, /*!< in: cursor on the record to update */
+ btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
+ cursor may become invalid if *big_rec == NULL
+ || !(flags & BTR_KEEP_POS_FLAG) */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */
@@ -321,6 +326,16 @@ btr_cur_pessimistic_update(
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr); /*!< in: mtr; must be committed before
latching any further pages */
+/*****************************************************************
+Commits and restarts a mini-transaction so that it will retain an
+x-lock on index->lock and the cursor page. */
+UNIV_INTERN
+void
+btr_cur_mtr_commit_and_start(
+/*=========================*/
+ btr_cur_t* cursor, /*!< in: cursor */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/***********************************************************//**
Marks a clustered index record deleted. Writes an undo log record to
undo log on this delete marking. Writes in the trx id field the id
@@ -376,10 +391,13 @@ UNIV_INTERN
ibool
btr_cur_compress_if_useful(
/*=======================*/
- btr_cur_t* cursor, /*!< in: cursor on the page to compress;
+ btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
cursor does not stay valid if compression
occurs */
- mtr_t* mtr); /*!< in: mtr */
+ ibool adjust, /*!< in: TRUE if should adjust the
+ cursor position even if compression occurs */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/*******************************************************//**
Removes the record on which the tree cursor is positioned. It is assumed
that the mtr has an x-latch on the page where the cursor is positioned,
@@ -652,6 +670,11 @@ struct btr_path_struct{
order); value ULINT_UNDEFINED
denotes array end */
ulint n_recs; /*!< number of records on the page */
+ ulint page_no; /*!< no of the page containing the record */
+ ulint page_level; /*!< level of the page, if later we fetch
+ the page under page_no and it is no different
+ level then we know that the tree has been
+ reorganized */
};
#define BTR_PATH_ARRAY_N_SLOTS 250 /*!< size of path array (in slots) */
diff --git a/storage/xtradb/include/btr0cur.ic b/storage/xtradb/include/btr0cur.ic
index 280583f6ccf..c833b3e8572 100644
--- a/storage/xtradb/include/btr0cur.ic
+++ b/storage/xtradb/include/btr0cur.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
@@ -139,7 +139,7 @@ btr_cur_compress_recommendation(
btr_cur_t* cursor, /*!< in: btr cursor */
mtr_t* mtr) /*!< in: mtr */
{
- page_t* page;
+ const page_t* page;
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
diff --git a/storage/xtradb/include/btr0pcur.h b/storage/xtradb/include/btr0pcur.h
index 2334a266280..f59514d04b3 100644
--- a/storage/xtradb/include/btr0pcur.h
+++ b/storage/xtradb/include/btr0pcur.h
@@ -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
@@ -244,18 +244,6 @@ btr_pcur_restore_position_func(
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_restore_position(l,cur,mtr) \
btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr)
-/**************************************************************//**
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-UNIV_INTERN
-void
-btr_pcur_release_leaf(
-/*==================*/
- btr_pcur_t* cursor, /*!< in: persistent cursor */
- mtr_t* mtr); /*!< in: mtr */
/*********************************************************//**
Gets the rel_pos field for a cursor whose position has been stored.
@return BTR_PCUR_ON, ... */
@@ -282,10 +270,9 @@ 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
-to the page where pcur is positioned, this can be used instead of
-btr_pcur_release_leaf. Function btr_pcur_store_position should be used
-before calling this, if restoration of cursor is wanted later. */
+that is, the cursor becomes detached.
+Function btr_pcur_store_position should be used before calling this,
+if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit_specify_mtr(
diff --git a/storage/xtradb/include/btr0pcur.ic b/storage/xtradb/include/btr0pcur.ic
index 0c38797e6c5..0f9b969e7c5 100644
--- a/storage/xtradb/include/btr0pcur.ic
+++ b/storage/xtradb/include/btr0pcur.ic
@@ -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
@@ -396,10 +396,9 @@ btr_pcur_move_to_next(
/**************************************************************//**
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
-that is, the cursor becomes detached. If there have been modifications
-to the page where pcur is positioned, this can be used instead of
-btr_pcur_release_leaf. Function btr_pcur_store_position should be used
-before calling this, if restoration of cursor is wanted later. */
+that is, the cursor becomes detached.
+Function btr_pcur_store_position should be used before calling this,
+if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit_specify_mtr(
diff --git a/storage/xtradb/include/btr0types.h b/storage/xtradb/include/btr0types.h
index ef4a6b04b34..07c06fb18d7 100644
--- a/storage/xtradb/include/btr0types.h
+++ b/storage/xtradb/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/xtradb/include/buf0buddy.h b/storage/xtradb/include/buf0buddy.h
index 3a35f8e46e9..f4c3da8692d 100644
--- a/storage/xtradb/include/buf0buddy.h
+++ b/storage/xtradb/include/buf0buddy.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2009, Innobase Oy. 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 the Free Software
@@ -37,25 +37,20 @@ 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. 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
-control blocks must be properly initialized immediately after
-buf_buddy_alloc() has returned the memory, before releasing
-buf_pool_mutex.
-@return allocated block, possibly NULL if lru == NULL */
+block->mutex. The buf_pool_mutex may be released and reacquired.
+This function should only be used for allocating compressed page frames.
+@return allocated block, never NULL */
UNIV_INLINE
void*
buf_buddy_alloc(
/*============*/
- ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */
+ ulint size, /*!< in: compressed page size
+ (between PAGE_ZIP_MIN_SIZE and UNIV_PAGE_SIZE) */
ibool* lru, /*!< in: pointer to a variable that will be assigned
TRUE if storage was allocated from the LRU list
- and buf_pool_mutex was temporarily released,
- or NULL if the LRU list should not be used */
+ and buf_pool_mutex was temporarily released */
ibool have_page_hash_mutex)
- __attribute__((malloc));
-
+ __attribute__((malloc, nonnull));
/**********************************************************************//**
Release a block. */
UNIV_INLINE
diff --git a/storage/xtradb/include/buf0buddy.ic b/storage/xtradb/include/buf0buddy.ic
index 69659fb69d6..63241311e1f 100644
--- a/storage/xtradb/include/buf0buddy.ic
+++ b/storage/xtradb/include/buf0buddy.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2009, Innobase Oy. 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 the Free Software
@@ -36,8 +36,8 @@ 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.
-The buf_pool_mutex may only be released and reacquired if lru != NULL.
-@return allocated block, possibly NULL if lru==NULL */
+The buf_pool_mutex may be released and reacquired.
+@return allocated block, never NULL */
UNIV_INTERN
void*
buf_buddy_alloc_low(
@@ -46,10 +46,9 @@ buf_buddy_alloc_low(
or BUF_BUDDY_SIZES */
ibool* lru, /*!< in: pointer to a variable that will be assigned
TRUE if storage was allocated from the LRU list
- and buf_pool_mutex was temporarily released,
- or NULL if the LRU list should not be used */
+ and buf_pool_mutex was temporarily released */
ibool have_page_hash_mutex)
- __attribute__((malloc));
+ __attribute__((malloc, nonnull));
/**********************************************************************//**
Deallocate a block. */
@@ -76,6 +75,8 @@ buf_buddy_get_slot(
ulint i;
ulint s;
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+
for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) {
}
@@ -86,27 +87,26 @@ 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
-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
-control blocks must be properly initialized immediately after
-buf_buddy_alloc() has returned the memory, before releasing
-buf_pool_mutex.
-@return allocated block, possibly NULL if lru == NULL */
+block->mutex. The buf_pool_mutex may be released and reacquired.
+This function should only be used for allocating compressed page frames.
+@return allocated block, never NULL */
UNIV_INLINE
void*
buf_buddy_alloc(
/*============*/
- ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */
+ ulint size, /*!< in: compressed page size
+ (between PAGE_ZIP_MIN_SIZE and UNIV_PAGE_SIZE) */
ibool* lru, /*!< in: pointer to a variable that will be assigned
TRUE if storage was allocated from the LRU list
- and buf_pool_mutex was temporarily released,
- or NULL if the LRU list should not be used */
+ and buf_pool_mutex was temporarily released */
ibool have_page_hash_mutex)
{
//ut_ad(buf_pool_mutex_own());
+ ut_ad(ut_is_2pow(size));
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+ ut_ad(size <= UNIV_PAGE_SIZE);
- return(buf_buddy_alloc_low(buf_buddy_get_slot(size), lru, have_page_hash_mutex));
+ return((byte*) buf_buddy_alloc_low(buf_buddy_get_slot(size), lru, have_page_hash_mutex));
}
/**********************************************************************//**
@@ -121,6 +121,9 @@ buf_buddy_free(
ibool have_page_hash_mutex)
{
//ut_ad(buf_pool_mutex_own());
+ ut_ad(ut_is_2pow(size));
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+ ut_ad(size <= UNIV_PAGE_SIZE);
if (!have_page_hash_mutex) {
mutex_enter(&LRU_list_mutex);
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index bc0e9170281..838dd7f3900 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.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.
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
@@ -36,12 +36,13 @@ Created 11/5/1995 Heikki Tuuri
#include "ut0rbt.h"
#ifndef UNIV_HOTBACKUP
#include "os0proc.h"
-#include "srv0srv.h"
/** @name Modes for buf_page_get_gen */
/* @{ */
#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
@@ -140,12 +141,6 @@ buf_relocate(
BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
buf_page_t* dpage) /*!< in/out: destination control block */
__attribute__((nonnull));
-/********************************************************************//**
-Resizes the buffer pool. */
-UNIV_INTERN
-void
-buf_pool_resize(void);
-/*=================*/
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
@@ -162,6 +157,23 @@ ib_uint64_t
buf_pool_get_oldest_modification(void);
/*==================================*/
/********************************************************************//**
+Allocates a buf_page_t descriptor. This function must succeed. In case
+of failure we assert in this function. */
+UNIV_INLINE
+buf_page_t*
+buf_page_alloc_descriptor(void)
+/*===========================*/
+ __attribute__((malloc));
+/********************************************************************//**
+Free a buf_page_t descriptor. */
+UNIV_INLINE
+void
+buf_page_free_descriptor(
+/*=====================*/
+ buf_page_t* bpage) /*!< in: bpage descriptor to free. */
+ __attribute__((nonnull));
+
+/********************************************************************//**
Allocates a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
UNIV_INLINE
@@ -285,7 +297,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 */
+ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mini-transaction */
@@ -415,6 +427,18 @@ buf_block_get_freed_page_clock(
__attribute__((pure));
/********************************************************************//**
+Tells if a block is still close enough to the MRU end of the LRU list
+meaning that it is not in danger of getting evicted and also implying
+that it has been accessed recently.
+Note that this is for heuristics only and does not reserve buffer pool
+mutex.
+@return TRUE if block is close to MRU end of LRU */
+UNIV_INLINE
+ibool
+buf_page_peek_if_young(
+/*===================*/
+ const buf_page_t* bpage); /*!< in: block */
+/********************************************************************//**
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex.
@@ -466,6 +490,31 @@ buf_block_get_modify_clock(
#else /* !UNIV_HOTBACKUP */
# define buf_block_modify_clock_inc(block) ((void) 0)
#endif /* !UNIV_HOTBACKUP */
+/*******************************************************************//**
+Increments the bufferfix count. */
+UNIV_INLINE
+void
+buf_block_buf_fix_inc_func(
+/*=======================*/
+#ifdef UNIV_SYNC_DEBUG
+ const char* file, /*!< in: file name */
+ ulint line, /*!< in: line */
+#endif /* UNIV_SYNC_DEBUG */
+ buf_block_t* block) /*!< in/out: block to bufferfix */
+ __attribute__((nonnull));
+#ifdef UNIV_SYNC_DEBUG
+/** Increments the bufferfix count.
+@param b in/out: block to bufferfix
+@param f in: file name where requested
+@param l in: line number where requested */
+# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
+#else /* UNIV_SYNC_DEBUG */
+/** Increments the bufferfix count.
+@param b in/out: block to bufferfix
+@param f in: file name where requested
+@param l in: line number where requested */
+# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
+#endif /* UNIV_SYNC_DEBUG */
/********************************************************************//**
Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value
@@ -986,8 +1035,7 @@ UNIV_INTERN
void
buf_page_io_complete(
/*=================*/
- buf_page_t* bpage, /*!< in: pointer to the block in question */
- trx_t* trx);
+ buf_page_t* bpage); /*!< in: pointer to the block in question */
/********************************************************************//**
Calculates a folded value of a file page address to use in the page hash
table.
@@ -1301,10 +1349,7 @@ struct buf_block_struct{
/**********************************************************************//**
Compute the hash fold value for blocks in buf_pool->zip_hash. */
/* @{ */
-/* the fold should be relative when srv_buffer_pool_shm_key is enabled */
-#define BUF_POOL_ZIP_FOLD_PTR(ptr) (!srv_buffer_pool_shm_key\
- ?((ulint) (ptr) / UNIV_PAGE_SIZE)\
- :((ulint) ((byte*)ptr - (byte*)(buf_pool->chunks->blocks->frame)) / UNIV_PAGE_SIZE))
+#define BUF_POOL_ZIP_FOLD_PTR(ptr) ((ulint) (ptr) / UNIV_PAGE_SIZE)
#define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->frame)
#define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
/* @} */
@@ -1330,6 +1375,8 @@ struct buf_pool_stat_struct{
ulint n_pages_written;/*!< number write operations */
ulint n_pages_created;/*!< number of pages created
in the pool with no read */
+ ulint n_ra_pages_read_rnd;/*!< number of pages read in
+ as part of random read ahead */
ulint n_ra_pages_read;/*!< number of pages read in
as part of read ahead */
ulint n_ra_pages_evicted;/*!< number of read ahead
@@ -1453,8 +1500,10 @@ struct buf_pool_struct{
frames and buf_page_t descriptors of blocks that exist
in the buffer pool only in compressed form. */
/* @{ */
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_BASE_NODE_T(buf_page_t) zip_clean;
/*!< unmodified compressed pages */
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX];
/*!< buddy free lists */
//#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
@@ -1486,8 +1535,8 @@ Use these instead of accessing buf_pool_mutex directly. */
/** Test if buf_pool_mutex is owned. */
#define buf_pool_mutex_own() mutex_own(&buf_pool_mutex)
/** Acquire the buffer pool mutex. */
+/* the buf_pool_mutex is changed the latch order */
#define buf_pool_mutex_enter() do { \
- ut_ad(!mutex_own(&buf_pool_zip_mutex)); \
mutex_enter(&buf_pool_mutex); \
} while (0)
diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index 2cb0d8ef497..a081d6a34c0 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -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
@@ -62,6 +62,27 @@ buf_block_get_freed_page_clock(
}
/********************************************************************//**
+Tells if a block is still close enough to the MRU end of the LRU list
+meaning that it is not in danger of getting evicted and also implying
+that it has been accessed recently.
+Note that this is for heuristics only and does not reserve buffer pool
+mutex.
+@return TRUE if block is close to MRU end of LRU */
+UNIV_INLINE
+ibool
+buf_page_peek_if_young(
+/*===================*/
+ const buf_page_t* bpage) /*!< in: block */
+{
+ /* FIXME: bpage->freed_page_clock is 31 bits */
+ return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
+ < ((ulint) bpage->freed_page_clock
+ + (buf_pool->curr_size
+ * (BUF_LRU_OLD_RATIO_DIV - buf_LRU_old_ratio)
+ / (BUF_LRU_OLD_RATIO_DIV * 4))));
+}
+
+/********************************************************************//**
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex.
@@ -89,12 +110,7 @@ buf_page_peek_if_too_old(
buf_pool->stat.n_pages_not_made_young++;
return(FALSE);
} else {
- /* FIXME: bpage->freed_page_clock is 31 bits */
- return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
- > ((ulint) bpage->freed_page_clock
- + (buf_pool->curr_size
- * (BUF_LRU_OLD_RATIO_DIV - buf_LRU_old_ratio)
- / (BUF_LRU_OLD_RATIO_DIV * 4))));
+ return(!buf_page_peek_if_young(bpage));
}
}
@@ -754,6 +770,35 @@ buf_block_get_lock_hash_val(
}
/********************************************************************//**
+Allocates a buf_page_t descriptor. This function must succeed. In case
+of failure we assert in this function.
+@return: the allocated descriptor. */
+UNIV_INLINE
+buf_page_t*
+buf_page_alloc_descriptor(void)
+/*===========================*/
+{
+ buf_page_t* bpage;
+
+ bpage = (buf_page_t*) ut_malloc(sizeof *bpage);
+ ut_d(memset(bpage, 0, sizeof *bpage));
+ UNIV_MEM_ALLOC(bpage, sizeof *bpage);
+
+ return(bpage);
+}
+
+/********************************************************************//**
+Free a buf_page_t descriptor. */
+UNIV_INLINE
+void
+buf_page_free_descriptor(
+/*=====================*/
+ buf_page_t* bpage) /*!< in: bpage descriptor to free. */
+{
+ ut_free(bpage);
+}
+
+/********************************************************************//**
Allocates a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
UNIV_INLINE
@@ -910,19 +955,6 @@ buf_block_buf_fix_inc_func(
block->page.buf_fix_count++;
}
-#ifdef UNIV_SYNC_DEBUG
-/** Increments the bufferfix count.
-@param b in/out: block to bufferfix
-@param f in: file name where requested
-@param l in: line number where requested */
-# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
-#else /* UNIV_SYNC_DEBUG */
-/** Increments the bufferfix count.
-@param b in/out: block to bufferfix
-@param f in: file name where requested
-@param l in: line number where requested */
-# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
-#endif /* UNIV_SYNC_DEBUG */
/*******************************************************************//**
Decrements the bufferfix count. */
@@ -1119,7 +1151,7 @@ buf_block_dbg_add_level(
where we have acquired latch */
ulint level) /*!< in: latching order level */
{
- sync_thread_add_level(&block->lock, level);
+ sync_thread_add_level(&block->lock, level, FALSE);
}
#endif /* UNIV_SYNC_DEBUG */
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/include/buf0lru.h b/storage/xtradb/include/buf0lru.h
index fe7c067dfb7..8abebfb675c 100644
--- a/storage/xtradb/include/buf0lru.h
+++ b/storage/xtradb/include/buf0lru.h
@@ -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.
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
@@ -30,18 +30,6 @@ Created 11/5/1995 Heikki Tuuri
#include "ut0byte.h"
#include "buf0types.h"
-/** The return type of buf_LRU_free_block() */
-enum buf_lru_free_block_status {
- /** freed */
- BUF_LRU_FREED = 0,
- /** not freed because the caller asked to remove the
- uncompressed frame but the control block cannot be
- relocated */
- BUF_LRU_CANNOT_RELOCATE,
- /** not freed because of some other reason */
- BUF_LRU_NOT_FREED
-};
-
/******************************************************************//**
Tries to remove LRU flushed blocks from the end of the LRU list and put them
to the free list. This is beneficial for the efficiency of the insert buffer
@@ -91,6 +79,7 @@ void
buf_LRU_mark_space_was_deleted(
/*===========================*/
ulint id); /*!< in: space id */
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/********************************************************************//**
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
UNIV_INTERN
@@ -98,22 +87,22 @@ void
buf_LRU_insert_zip_clean(
/*=====================*/
buf_page_t* bpage); /*!< in: pointer to the block in question */
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//**
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
+NOTE: If this function returns TRUE, it will temporarily
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
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
-BUF_LRU_NOT_FREED otherwise. */
+@return TRUE if freed, FALSE otherwise. */
UNIV_INTERN
-enum buf_lru_free_block_status
+ibool
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
diff --git a/storage/xtradb/include/buf0types.h b/storage/xtradb/include/buf0types.h
index ce3e5ecc9c5..9dd847bdaca 100644
--- a/storage/xtradb/include/buf0types.h
+++ b/storage/xtradb/include/buf0types.h
@@ -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
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,8 @@ Created 11/17/1995 Heikki Tuuri
#ifndef buf0types_h
#define buf0types_h
+#include "page0types.h"
+
/** Buffer page (uncompressed or compressed) */
typedef struct buf_page_struct buf_page_t;
/** Buffer block for which an uncompressed page exists */
@@ -58,17 +60,10 @@ enum buf_io_fix {
/** Parameters of binary buddy system for compressed pages (buf0buddy.h) */
/* @{ */
-#if UNIV_WORD_SIZE <= 4 /* 32-bit system */
-/** Base-2 logarithm of the smallest buddy block size */
-# define BUF_BUDDY_LOW_SHIFT 6
-#else /* 64-bit system */
-/** Base-2 logarithm of the smallest buddy block size */
-# define BUF_BUDDY_LOW_SHIFT 7
-#endif
+#define BUF_BUDDY_LOW_SHIFT PAGE_ZIP_MIN_SIZE_SHIFT
+
#define BUF_BUDDY_LOW (1 << BUF_BUDDY_LOW_SHIFT)
- /*!< minimum block size in the binary
- buddy system; must be at least
- sizeof(buf_page_t) */
+
#define BUF_BUDDY_SIZES (UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT)
#define BUF_BUDDY_SIZES_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - BUF_BUDDY_LOW_SHIFT)
/*!< number of buddy sizes */
diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h
index f47293bedf6..3554274847c 100644
--- a/storage/xtradb/include/dict0mem.h
+++ b/storage/xtradb/include/dict0mem.h
@@ -340,6 +340,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 */
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index fbf8ca20db3..11c4cb4ba03 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -670,8 +670,9 @@ UNIV_INTERN
void
fil_flush(
/*======*/
- ulint space_id); /*!< in: file space id (this can be a group of
+ ulint space_id, /*!< in: file space id (this can be a group of
log files or a tablespace of the database) */
+ ibool metadata);
/**********************************************************************//**
Flushes to disk writes in file spaces of the given type possibly cached by
the OS. */
diff --git a/storage/xtradb/include/hash0hash.h b/storage/xtradb/include/hash0hash.h
index 492c767acc4..b17c21a45ef 100644
--- a/storage/xtradb/include/hash0hash.h
+++ b/storage/xtradb/include/hash0hash.h
@@ -49,28 +49,6 @@ hash_table_t*
hash_create(
/*========*/
ulint n); /*!< in: number of array cells */
-
-/*************************************************************//**
-*/
-UNIV_INTERN
-ulint
-hash_create_needed(
-/*===============*/
- ulint n);
-
-UNIV_INTERN
-void
-hash_create_init(
-/*=============*/
- hash_table_t* table,
- ulint n);
-
-UNIV_INTERN
-void
-hash_create_reuse(
-/*==============*/
- hash_table_t* table);
-
#ifndef UNIV_HOTBACKUP
/*************************************************************//**
Creates a mutex array to protect a hash table. */
@@ -350,33 +328,6 @@ do {\
}\
} while (0)
-/********************************************************************//**
-Align nodes with moving location.*/
-#define HASH_OFFSET(TABLE, NODE_TYPE, PTR_NAME, FADDR, FOFFSET, BOFFSET) \
-do {\
- ulint i2222;\
- ulint cell_count2222;\
-\
- cell_count2222 = hash_get_n_cells(TABLE);\
-\
- for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
- NODE_TYPE* node2222;\
-\
- if ((TABLE)->array[i2222].node) \
- (TABLE)->array[i2222].node = (void*)((byte*)(TABLE)->array[i2222].node \
- + (((TABLE)->array[i2222].node > (void*)FADDR)?FOFFSET:BOFFSET));\
- node2222 = HASH_GET_FIRST((TABLE), i2222);\
-\
- while (node2222) {\
- if (node2222->PTR_NAME) \
- node2222->PTR_NAME = (void*)((byte*)(node2222->PTR_NAME) \
- + ((((void*)node2222->PTR_NAME) > (void*)FADDR)?FOFFSET:BOFFSET));\
-\
- node2222 = node2222->PTR_NAME;\
- }\
- }\
-} while (0)
-
/************************************************************//**
Gets the mutex index for a fold value in a hash table.
@return mutex number */
diff --git a/storage/xtradb/include/mtr0mtr.h b/storage/xtradb/include/mtr0mtr.h
index bc3f1951be9..8a9ec8ea7f0 100644
--- a/storage/xtradb/include/mtr0mtr.h
+++ b/storage/xtradb/include/mtr0mtr.h
@@ -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.
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
@@ -213,16 +213,6 @@ ulint
mtr_set_savepoint(
/*==============*/
mtr_t* mtr); /*!< in: mtr */
-/**********************************************************//**
-Releases the latches stored in an mtr memo down to a savepoint.
-NOTE! The mtr must not have made changes to buffer pages after the
-savepoint, as these can be handled only by mtr_commit. */
-UNIV_INTERN
-void
-mtr_rollback_to_savepoint(
-/*======================*/
- mtr_t* mtr, /*!< in: mtr */
- ulint savepoint); /*!< in: savepoint */
#ifndef UNIV_HOTBACKUP
/**********************************************************//**
Releases the (index tree) s-latch stored in an mtr memo after a
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index 732e930517b..98cab5ef874 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -469,7 +469,8 @@ UNIV_INTERN
ibool
os_file_flush(
/*==========*/
- os_file_t file); /*!< in, own: handle to a file */
+ os_file_t file, /*!< in, own: handle to a file */
+ ibool metadata);
/***********************************************************************//**
Retrieves the last error number if an error occurs in a file io function.
The number should be retrieved before any other OS calls (because they may
diff --git a/storage/xtradb/include/os0proc.h b/storage/xtradb/include/os0proc.h
index 582cef6f803..fd46bd7db87 100644
--- a/storage/xtradb/include/os0proc.h
+++ b/storage/xtradb/include/os0proc.h
@@ -32,11 +32,6 @@ Created 9/30/1995 Heikki Tuuri
#ifdef UNIV_LINUX
#include <sys/ipc.h>
#include <sys/shm.h>
-#else
-# if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
-#include <sys/ipc.h>
-#include <sys/shm.h>
-# endif
#endif
typedef void* os_process_t;
@@ -75,29 +70,6 @@ os_mem_free_large(
ulint size); /*!< in: size returned by
os_mem_alloc_large() */
-
-/****************************************************************//**
-Allocates or attaches and reuses shared memory segment.
-The content is not cleared automatically.
-@return allocated memory */
-UNIV_INTERN
-void*
-os_shm_alloc(
-/*=========*/
- ulint* n, /*!< in/out: number of bytes */
- uint key,
- ibool* is_new);
-
-/****************************************************************//**
-Detach shared memory segment. */
-UNIV_INTERN
-void
-os_shm_free(
-/*========*/
- void *ptr, /*!< in: pointer returned by
- os_shm_alloc() */
- ulint size); /*!< in: size returned by
- os_shm_alloc() */
#ifndef UNIV_NONINL
#include "os0proc.ic"
#endif
diff --git a/storage/xtradb/include/page0cur.ic b/storage/xtradb/include/page0cur.ic
index 3520677dfb3..81474fa35f5 100644
--- a/storage/xtradb/include/page0cur.ic
+++ b/storage/xtradb/include/page0cur.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
@@ -27,6 +27,8 @@ Created 10/4/1994 Heikki Tuuri
#include "buf0types.h"
#ifdef UNIV_DEBUG
+# include "rem0cmp.h"
+
/*********************************************************//**
Gets pointer to the page frame where the cursor is positioned.
@return page */
@@ -268,6 +270,7 @@ page_cur_tuple_insert(
index, rec, offsets, mtr);
}
+ ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, offsets));
mem_heap_free(heap);
return(rec);
}
diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h
index 5b2bcf7c054..aeaef030505 100644
--- a/storage/xtradb/include/page0page.h
+++ b/storage/xtradb/include/page0page.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
@@ -284,16 +284,42 @@ page_get_supremum_offset(
const page_t* page); /*!< in: page which must have record(s) */
#define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
#define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
+
/************************************************************//**
-Returns the middle record of record list. If there are an even number
-of records in the list, returns the first record of upper half-list.
-@return middle record */
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return nth record */
UNIV_INTERN
+const rec_t*
+page_rec_get_nth_const(
+/*===================*/
+ const page_t* page, /*!< in: page */
+ ulint nth) /*!< in: nth record */
+ __attribute__((nonnull, warn_unused_result));
+/************************************************************//**
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return nth record */
+UNIV_INLINE
+rec_t*
+page_rec_get_nth(
+/*=============*/
+ page_t* page, /*< in: page */
+ ulint nth) /*!< in: nth record */
+ __attribute__((nonnull, warn_unused_result));
+
+#ifndef UNIV_HOTBACKUP
+/************************************************************//**
+Returns the middle record of the records on the page. If there is an
+even number of records in the list, returns the first record of the
+upper half-list.
+@return middle record */
+UNIV_INLINE
rec_t*
page_get_middle_rec(
/*================*/
- page_t* page); /*!< in: page */
-#ifndef UNIV_HOTBACKUP
+ page_t* page) /*!< in: page */
+ __attribute__((nonnull, warn_unused_result));
/*************************************************************//**
Compares a data tuple to a physical record. Differs from the function
cmp_dtuple_rec_with_match in the way that the record must reside on an
@@ -348,6 +374,7 @@ page_get_n_recs(
/***************************************************************//**
Returns the number of records before the given record in chain.
The number includes infimum and supremum records.
+This is the inverse function of page_rec_get_nth().
@return number of records */
UNIV_INTERN
ulint
diff --git a/storage/xtradb/include/page0page.ic b/storage/xtradb/include/page0page.ic
index dab9dc742e4..b34408aed17 100644
--- a/storage/xtradb/include/page0page.ic
+++ b/storage/xtradb/include/page0page.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
@@ -423,7 +423,37 @@ page_rec_is_infimum(
return(page_rec_is_infimum_low(page_offset(rec)));
}
+/************************************************************//**
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return nth record */
+UNIV_INLINE
+rec_t*
+page_rec_get_nth(
+/*=============*/
+ page_t* page, /*!< in: page */
+ ulint nth) /*!< in: nth record */
+{
+ return((rec_t*) page_rec_get_nth_const(page, nth));
+}
+
#ifndef UNIV_HOTBACKUP
+/************************************************************//**
+Returns the middle record of the records on the page. If there is an
+even number of records in the list, returns the first record of the
+upper half-list.
+@return middle record */
+UNIV_INLINE
+rec_t*
+page_get_middle_rec(
+/*================*/
+ page_t* page) /*!< in: page */
+{
+ ulint middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
+
+ return(page_rec_get_nth(page, middle));
+}
+
/*************************************************************//**
Compares a data tuple to a physical record. Differs from the function
cmp_dtuple_rec_with_match in the way that the record must reside on an
diff --git a/storage/xtradb/include/page0zip.h b/storage/xtradb/include/page0zip.h
index 4d37302ed20..fe3d2e52e0b 100644
--- a/storage/xtradb/include/page0zip.h
+++ b/storage/xtradb/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/xtradb/include/rem0rec.h b/storage/xtradb/include/rem0rec.h
index 17d08afabb9..06de23be757 100644
--- a/storage/xtradb/include/rem0rec.h
+++ b/storage/xtradb/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() */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_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_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec.
@return nonzero if externally stored */
diff --git a/storage/xtradb/include/rem0rec.ic b/storage/xtradb/include/rem0rec.ic
index fa96c97f95e..3875a4cf814 100644
--- a/storage/xtradb/include/rem0rec.ic
+++ b/storage/xtradb/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));
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_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_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
/******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec.
@return nonzero if externally stored */
diff --git a/storage/xtradb/include/row0row.h b/storage/xtradb/include/row0row.h
index 723b7b53395..36fb26482ce 100644
--- a/storage/xtradb/include/row0row.h
+++ b/storage/xtradb/include/row0row.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -38,16 +38,16 @@ Created 4/20/1996 Heikki Tuuri
#include "btr0types.h"
/*********************************************************************//**
-Gets the offset of the trx id field, in bytes relative to the origin of
+Gets the offset of the DB_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) */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: record offsets */
+ __attribute__((nonnull, warn_unused_result));
/*********************************************************************//**
Reads the trx id field from a clustered index record.
@return value of the field */
@@ -55,9 +55,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 */
@@ -65,9 +66,10 @@ UNIV_INLINE
roll_ptr_t
row_get_rec_roll_ptr(
/*=================*/
- 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));
/*****************************************************************//**
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.
diff --git a/storage/xtradb/include/row0row.ic b/storage/xtradb/include/row0row.ic
index 05c007641af..0b9ca982af8 100644
--- a/storage/xtradb/include/row0row.ic
+++ b/storage/xtradb/include/row0row.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -28,15 +28,42 @@ Created 4/20/1996 Heikki Tuuri
#include "trx0undo.h"
/*********************************************************************//**
+Gets the offset of the DB_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(
+/*==================*/
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: record offsets */
+{
+ ulint pos;
+ ulint offset;
+ ulint len;
+
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(rec_offs_validate(NULL, 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;
@@ -46,7 +73,7 @@ row_get_rec_trx_id(
offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
return(trx_read_trx_id(rec + offset));
@@ -59,9 +86,9 @@ UNIV_INLINE
roll_ptr_t
row_get_rec_roll_ptr(
/*=================*/
- 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;
@@ -71,7 +98,7 @@ row_get_rec_roll_ptr(
offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
diff --git a/storage/xtradb/include/row0upd.ic b/storage/xtradb/include/row0upd.ic
index 18e22f1eca9..0894ed373b0 100644
--- a/storage/xtradb/include/row0upd.ic
+++ b/storage/xtradb/include/row0upd.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -171,7 +171,7 @@ row_upd_rec_sys_fields(
ulint offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
#if DATA_TRX_ID + 1 != DATA_ROLL_PTR
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index d4329d16a62..c120db5cbcc 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -159,13 +159,10 @@ extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
-extern uint srv_buffer_pool_shm_key;
-extern ibool srv_buffer_pool_shm_is_reused;
-extern ibool srv_buffer_pool_shm_checksum;
-
extern ibool srv_thread_concurrency_timer_based;
extern ulint srv_n_file_io_threads;
+extern my_bool srv_random_read_ahead;
extern ulong srv_read_ahead_threshold;
extern ulint srv_n_read_io_threads;
extern ulint srv_n_write_io_threads;
@@ -288,6 +285,7 @@ extern ibool srv_print_latch_waits;
extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold;
extern ulint srv_dml_needed_delay;
+extern lint srv_kill_idle_transaction;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
query threads, and lock table: we allocate
@@ -351,6 +349,9 @@ extern ulint srv_buf_pool_reads;
/** Time in seconds between automatic buffer pool dumps */
extern uint srv_auto_lru_dump;
+/** Whether startup should be blocked until buffer pool is fully restored */
+extern ibool srv_blocking_lru_restore;
+
/** Status variables to be passed to MySQL */
typedef struct export_var_struct export_struc;
@@ -694,6 +695,7 @@ struct export_var_struct{
ulint innodb_buffer_pool_wait_free; /*!< srv_buf_pool_wait_free */
ulint innodb_buffer_pool_pages_flushed; /*!< srv_buf_pool_flushed */
ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
+ ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */
ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */
ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
ulint innodb_deadlocks; /* ??? */
diff --git a/storage/xtradb/include/sync0arr.h b/storage/xtradb/include/sync0arr.h
index 5f1280f5e28..6e931346238 100644
--- a/storage/xtradb/include/sync0arr.h
+++ b/storage/xtradb/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/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic
index 7116f1b7c9b..485a63a1b18 100644
--- a/storage/xtradb/include/sync0rw.ic
+++ b/storage/xtradb/include/sync0rw.ic
@@ -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
@@ -603,16 +603,16 @@ rw_lock_x_unlock_direct(
ut_ad((lock->lock_word % X_LOCK_DECR) == 0);
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
-#endif
-
if (lock->lock_word == 0) {
lock->recursive = FALSE;
UNIV_MEM_INVALID(&lock->writer_thread,
sizeof lock->writer_thread);
}
+#ifdef UNIV_SYNC_DEBUG
+ rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
+#endif
+
lock->lock_word += X_LOCK_DECR;
ut_ad(!lock->waiters);
diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h
index f2ff83101ab..8b9a075e875 100644
--- a/storage/xtradb/include/sync0sync.h
+++ b/storage/xtradb/include/sync0sync.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
@@ -219,8 +219,10 @@ void
sync_thread_add_level(
/*==================*/
void* latch, /*!< in: pointer to a mutex or an rw-lock */
- ulint level); /*!< in: level in the latching order; if
+ ulint level, /*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
+ ibool relock) /*!< in: TRUE if re-entering an x-lock */
+ __attribute__((nonnull));
/******************************************************************//**
Removes a latch from the thread level array if it is found there.
@return TRUE if found in the array; it is no error if the latch is
diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h
index 2637189f37e..eafa1ab6409 100644
--- a/storage/xtradb/include/trx0sys.h
+++ b/storage/xtradb/include/trx0sys.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -317,6 +317,17 @@ ibool
trx_in_trx_list(
/*============*/
trx_t* in_trx);/*!< in: trx */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/***********************************************************//**
+Assert that a transaction has been recovered.
+@return TRUE */
+UNIV_INLINE
+ibool
+trx_assert_recovered(
+/*=================*/
+ trx_id_t trx_id) /*!< in: transaction identifier */
+ __attribute__((warn_unused_result));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/*****************************************************************//**
Updates the offset information about the end of the MySQL binlog entry
which corresponds to the transaction just being committed. In a MySQL
diff --git a/storage/xtradb/include/trx0sys.ic b/storage/xtradb/include/trx0sys.ic
index 5e0f07c8b9d..234fc0b92e9 100644
--- a/storage/xtradb/include/trx0sys.ic
+++ b/storage/xtradb/include/trx0sys.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -311,6 +311,28 @@ trx_get_on_id(
return(NULL);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/***********************************************************//**
+Assert that a transaction has been recovered.
+@return TRUE */
+UNIV_INLINE
+ibool
+trx_assert_recovered(
+/*=================*/
+ trx_id_t trx_id) /*!< in: transaction identifier */
+{
+ trx_t* trx;
+
+ mutex_enter(&kernel_mutex);
+ trx = trx_get_on_id(trx_id);
+ ut_a(trx);
+ ut_a(trx->is_recovered);
+ mutex_exit(&kernel_mutex);
+
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
/****************************************************************//**
Returns the minumum trx id in trx list. This is the smallest id for which
the trx can possibly be active. (But, you must look at the trx->conc_state to
diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h
index 173c63918d3..700476bcd85 100644
--- a/storage/xtradb/include/trx0trx.h
+++ b/storage/xtradb/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 */
+ __attribute__((nonnull));
+/********************************************************************//**
Frees a transaction object for MySQL. */
UNIV_INTERN
void
@@ -498,6 +509,7 @@ struct trx_struct{
150 bytes in the undo log size as then
we skip XA steps */
ulint flush_log_at_trx_commit_session;
+ ulint fake_changes;
ulint flush_log_later;/* In 2PC, we hold the
prepare_commit mutex across
both phases. In that case, we
@@ -589,6 +601,8 @@ struct trx_struct{
ulint mysql_process_no;/* since in Linux, 'top' reports
process id's and not thread id's, we
store the process number too */
+ time_t idle_start;
+ ib_int64_t last_stmt_start;
/*------------------------------*/
ulint n_mysql_tables_in_use; /* number of Innobase tables
used in the processing of the current
diff --git a/storage/xtradb/include/trx0undo.h b/storage/xtradb/include/trx0undo.h
index a084f2394b5..4f15cd85833 100644
--- a/storage/xtradb/include/trx0undo.h
+++ b/storage/xtradb/include/trx0undo.h
@@ -298,6 +298,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 */
+ __attribute__((nonnull));
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
Parses the redo log entry of an undo log page initialization.
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 7b11a16dae9..902d0c94ddd 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -1,8 +1,7 @@
/*****************************************************************************
-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.
-Copyright (c) 2009, Sun Microsystems, Inc.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -46,8 +45,8 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 1
#define INNODB_VERSION_MINOR 0
-#define INNODB_VERSION_BUGFIX 15
-#define PERCONA_INNODB_VERSION 12.7
+#define INNODB_VERSION_BUGFIX 17
+#define PERCONA_INNODB_VERSION 13.0
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
@@ -197,6 +196,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 */
diff --git a/storage/xtradb/include/ut0lst.h b/storage/xtradb/include/ut0lst.h
index 245dfc226c3..7b15c052978 100644
--- a/storage/xtradb/include/ut0lst.h
+++ b/storage/xtradb/include/ut0lst.h
@@ -257,48 +257,5 @@ do { \
ut_a(ut_list_node_313 == NULL); \
} while (0)
-/********************************************************************//**
-Align nodes with moving location.
-@param NAME the name of the list
-@param TYPE node type
-@param BASE base node (not a pointer to it)
-@param OFFSET offset moved */
-#define UT_LIST_OFFSET(NAME, TYPE, BASE, FADDR, FOFFSET, BOFFSET) \
-do { \
- ulint ut_list_i_313; \
- TYPE* ut_list_node_313; \
- \
- if ((BASE).start) \
- (BASE).start = (void*)((byte*)((BASE).start) \
- + (((void*)((BASE).start) > (void*)FADDR)?FOFFSET:BOFFSET));\
- if ((BASE).end) \
- (BASE).end = (void*)((byte*)((BASE).end) \
- + (((void*)((BASE).end) > (void*)FADDR)?FOFFSET:BOFFSET));\
- \
- ut_list_node_313 = (BASE).start; \
- \
- for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
- ut_a(ut_list_node_313); \
- if ((ut_list_node_313->NAME).prev) \
- (ut_list_node_313->NAME).prev = (void*)((byte*)((ut_list_node_313->NAME).prev)\
- + (((void*)((ut_list_node_313->NAME).prev) > (void*)FADDR)?FOFFSET:BOFFSET));\
- if ((ut_list_node_313->NAME).next) \
- (ut_list_node_313->NAME).next = (void*)((byte*)((ut_list_node_313->NAME).next)\
- + (((void*)((ut_list_node_313->NAME).next)> (void*)FADDR)?FOFFSET:BOFFSET));\
- ut_list_node_313 = (ut_list_node_313->NAME).next; \
- } \
- \
- ut_a(ut_list_node_313 == NULL); \
- \
- ut_list_node_313 = (BASE).end; \
- \
- for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
- ut_a(ut_list_node_313); \
- ut_list_node_313 = (ut_list_node_313->NAME).prev; \
- } \
- \
- ut_a(ut_list_node_313 == NULL); \
-} while (0)
-
#endif
diff --git a/storage/xtradb/include/ut0mem.h b/storage/xtradb/include/ut0mem.h
index f14606be966..9c6ee9049ec 100644
--- a/storage/xtradb/include/ut0mem.h
+++ b/storage/xtradb/include/ut0mem.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
@@ -210,43 +210,6 @@ ut_strlcpy_rev(
ulint size); /*!< in: size of destination buffer */
/**********************************************************************//**
-Compute strlen(ut_strcpyq(str, q)).
-@return length of the string when quoted */
-UNIV_INLINE
-ulint
-ut_strlenq(
-/*=======*/
- const char* str, /*!< in: null-terminated string */
- char q); /*!< in: the quote character */
-
-/**********************************************************************//**
-Make a quoted copy of a NUL-terminated string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_memcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_strcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src); /*!< in: null-terminated string */
-
-/**********************************************************************//**
-Make a quoted copy of a fixed-length string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_strcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_memcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src, /*!< in: string to be quoted */
- ulint len); /*!< in: length of src */
-
-/**********************************************************************//**
Return the number of times s2 occurs in s1. Overlapping instances of s2
are only counted once.
@return the number of times s2 occurs in s1 */
diff --git a/storage/xtradb/include/ut0mem.ic b/storage/xtradb/include/ut0mem.ic
index f36c28f1989..c06e2b3ae81 100644
--- a/storage/xtradb/include/ut0mem.ic
+++ b/storage/xtradb/include/ut0mem.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
@@ -99,27 +99,6 @@ ut_strcmp(const char* str1, const char* str2)
}
/**********************************************************************//**
-Compute strlen(ut_strcpyq(str, q)).
-@return length of the string when quoted */
-UNIV_INLINE
-ulint
-ut_strlenq(
-/*=======*/
- const char* str, /*!< in: null-terminated string */
- char q) /*!< in: the quote character */
-{
- ulint len;
-
- for (len = 0; *str; len++, str++) {
- if (*str == q) {
- len++;
- }
- }
-
- return(len);
-}
-
-/**********************************************************************//**
Converts a raw binary data to a NUL-terminated hex string. The output is
truncated if there is not enough space in "hex", make sure "hex_size" is at
least (2 * raw_size + 1) if you do not want this to happen. Returns the
diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c
index 4fcb5b2c522..e5da4f46ec9 100644
--- a/storage/xtradb/lock/lock0lock.c
+++ b/storage/xtradb/lock/lock0lock.c
@@ -3908,6 +3908,10 @@ lock_table(
trx = thr_get_trx(thr);
+ if (trx->fake_changes && mode == LOCK_IX) {
+ mode = LOCK_IS;
+ }
+
lock_mutex_enter_kernel();
/* Look for stronger locks the same trx already has on the table */
@@ -5109,6 +5113,11 @@ lock_rec_insert_check_and_lock(
}
trx = thr_get_trx(thr);
+
+ if (trx->fake_changes) {
+ return(DB_SUCCESS);
+ }
+
next_rec = page_rec_get_next_const(rec);
next_rec_heap_no = page_rec_get_heap_no(next_rec);
@@ -5277,6 +5286,10 @@ lock_clust_rec_modify_check_and_lock(
return(DB_SUCCESS);
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ return(DB_SUCCESS);
+ }
+
heap_no = rec_offs_comp(offsets)
? rec_get_heap_no_new(rec)
: rec_get_heap_no_old(rec);
@@ -5335,6 +5348,10 @@ lock_sec_rec_modify_check_and_lock(
return(DB_SUCCESS);
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ return(DB_SUCCESS);
+ }
+
heap_no = page_rec_get_heap_no(rec);
/* Another transaction cannot have an implicit lock on the record,
@@ -5422,6 +5439,10 @@ lock_sec_rec_read_check_and_lock(
return(DB_SUCCESS);
}
+ if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
+ mode = LOCK_S;
+ }
+
heap_no = page_rec_get_heap_no(rec);
lock_mutex_enter_kernel();
@@ -5499,6 +5520,10 @@ lock_clust_rec_read_check_and_lock(
return(DB_SUCCESS);
}
+ if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
+ mode = LOCK_S;
+ }
+
heap_no = page_rec_get_heap_no(rec);
lock_mutex_enter_kernel();
diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c
index c39f60bd4b9..fc8745629d6 100644
--- a/storage/xtradb/log/log0log.c
+++ b/storage/xtradb/log/log0log.c
@@ -1114,7 +1114,7 @@ log_io_complete(
&& srv_unix_file_flush_method != SRV_UNIX_ALL_O_DIRECT
&& srv_unix_file_flush_method != SRV_UNIX_NOSYNC) {
- fil_flush(group->space_id);
+ fil_flush(group->space_id, FALSE);
}
#ifdef UNIV_DEBUG
@@ -1137,7 +1137,7 @@ log_io_complete(
&& srv_unix_file_flush_method != SRV_UNIX_NOSYNC
&& srv_flush_log_at_trx_commit != 2) {
- fil_flush(group->space_id);
+ fil_flush(group->space_id, FALSE);
}
mutex_enter(&(log_sys->mutex));
@@ -1528,7 +1528,7 @@ loop:
group = UT_LIST_GET_FIRST(log_sys->log_groups);
- fil_flush(group->space_id);
+ fil_flush(group->space_id, FALSE);
log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
}
@@ -2623,7 +2623,7 @@ log_io_complete_archive(void)
mutex_exit(&(log_sys->mutex));
- fil_flush(group->archive_space_id);
+ fil_flush(group->archive_space_id, TRUE);
mutex_enter(&(log_sys->mutex));
@@ -3122,12 +3122,13 @@ loop:
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. */
+ /* 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. */
if (trx_n_mysql_transactions > 0
- || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
+ || UT_LIST_GET_LEN(trx_sys->trx_list) > trx_n_prepared) {
mutex_exit(&kernel_mutex);
diff --git a/storage/xtradb/log/log0recv.c b/storage/xtradb/log/log0recv.c
index 895067c700a..fae7fbd0da0 100644
--- a/storage/xtradb/log/log0recv.c
+++ b/storage/xtradb/log/log0recv.c
@@ -2899,7 +2899,6 @@ recv_init_crash_recovery(void)
/*==========================*/
{
ut_a(!recv_needed_recovery);
- ut_a(!srv_buffer_pool_shm_is_reused);
recv_needed_recovery = TRUE;
@@ -3622,7 +3621,7 @@ recv_reset_log_files_for_backup(
exit(1);
}
- os_file_flush(log_file);
+ os_file_flush(log_file, TRUE);
os_file_close(log_file);
}
@@ -3645,7 +3644,7 @@ recv_reset_log_files_for_backup(
os_file_write(name, log_file, buf, 0, 0,
LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
- os_file_flush(log_file);
+ os_file_flush(log_file, TRUE);
os_file_close(log_file);
ut_free(buf);
diff --git a/storage/xtradb/mtr/mtr0mtr.c b/storage/xtradb/mtr/mtr0mtr.c
index 34e6d3ffc92..a9f1c35f84c 100644
--- a/storage/xtradb/mtr/mtr0mtr.c
+++ b/storage/xtradb/mtr/mtr0mtr.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.
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
@@ -248,40 +248,6 @@ mtr_commit(
}
#ifndef UNIV_HOTBACKUP
-/**********************************************************//**
-Releases the latches stored in an mtr memo down to a savepoint.
-NOTE! The mtr must not have made changes to buffer pages after the
-savepoint, as these can be handled only by mtr_commit. */
-UNIV_INTERN
-void
-mtr_rollback_to_savepoint(
-/*======================*/
- mtr_t* mtr, /*!< in: mtr */
- ulint savepoint) /*!< in: savepoint */
-{
- mtr_memo_slot_t* slot;
- dyn_array_t* memo;
- ulint offset;
-
- ut_ad(mtr);
- ut_ad(mtr->magic_n == MTR_MAGIC_N);
- ut_ad(mtr->state == MTR_ACTIVE);
-
- memo = &(mtr->memo);
-
- offset = dyn_array_get_data_size(memo);
- ut_ad(offset >= savepoint);
-
- while (offset > savepoint) {
- offset -= sizeof(mtr_memo_slot_t);
-
- slot = dyn_array_get_element(memo, offset);
-
- ut_ad(slot->type != MTR_MEMO_MODIFY);
- mtr_memo_slot_release(mtr, slot);
- }
-}
-
/***************************************************//**
Releases an object in the memo stack. */
UNIV_INTERN
diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c
index 5b8e656d8b2..1e863109bed 100644
--- a/storage/xtradb/os/os0file.c
+++ b/storage/xtradb/os/os0file.c
@@ -1912,7 +1912,7 @@ os_file_set_size(
ut_free(buf2);
- ret = os_file_flush(file);
+ ret = os_file_flush(file, TRUE);
if (ret) {
return(TRUE);
@@ -1950,7 +1950,8 @@ static
int
os_file_fsync(
/*==========*/
- os_file_t file) /*!< in: handle to a file */
+ os_file_t file, /*!< in: handle to a file */
+ ibool metadata)
{
int ret;
int failures;
@@ -1959,7 +1960,16 @@ os_file_fsync(
failures = 0;
do {
+#if defined(HAVE_FDATASYNC) && HAVE_DECL_FDATASYNC
+ if (metadata) {
+ ret = fsync(file);
+ } else {
+ ret = fdatasync(file);
+ }
+#else
+ (void) metadata;
ret = fsync(file);
+#endif
os_n_fsyncs++;
@@ -1978,6 +1988,9 @@ os_file_fsync(
failures++;
retry = TRUE;
+ } else if (ret == -1 && errno == EINTR) {
+ /* Handle signal interruptions correctly */
+ retry = TRUE;
} else {
retry = FALSE;
@@ -1995,7 +2008,8 @@ UNIV_INTERN
ibool
os_file_flush(
/*==========*/
- os_file_t file) /*!< in, own: handle to a file */
+ os_file_t file, /*!< in, own: handle to a file */
+ ibool metadata)
{
#ifdef __WIN__
BOOL ret;
@@ -2045,18 +2059,18 @@ os_file_flush(
/* If we are not on an operating system that supports this,
then fall back to a plain fsync. */
- ret = os_file_fsync(file);
+ ret = os_file_fsync(file, metadata);
} else {
ret = fcntl(file, F_FULLFSYNC, NULL);
if (ret) {
/* If we are not on a file system that supports this,
then fall back to a plain fsync. */
- ret = os_file_fsync(file);
+ ret = os_file_fsync(file, metadata);
}
}
#else
- ret = os_file_fsync(file);
+ ret = os_file_fsync(file, metadata);
#endif
if (ret == 0) {
@@ -2109,6 +2123,7 @@ _os_file_pread(
off_t offs;
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
ssize_t n_bytes;
+ ssize_t n_read;
#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
ulint sec;
ulint ms;
@@ -2149,7 +2164,18 @@ _os_file_pread(
os_n_pending_reads++;
os_mutex_exit(os_file_count_mutex);
- n_bytes = pread(file, buf, (ssize_t)n, offs);
+ /* Handle signal interruptions correctly */
+ for (n_bytes = 0; n_bytes < (ssize_t) n; ) {
+ n_read = pread(file, buf, (ssize_t)n, offs);
+ if (n_read > 0) {
+ n_bytes += n_read;
+ offs += n_read;
+ } else if (n_read == -1 && errno == EINTR) {
+ continue;
+ } else {
+ break;
+ }
+ }
os_mutex_enter(os_file_count_mutex);
os_file_n_pending_preads--;
@@ -2168,6 +2194,7 @@ _os_file_pread(
{
off_t ret_offset;
ssize_t ret;
+ ssize_t n_read;
#ifndef UNIV_HOTBACKUP
ulint i;
#endif /* !UNIV_HOTBACKUP */
@@ -2188,7 +2215,17 @@ _os_file_pread(
if (ret_offset < 0) {
ret = -1;
} else {
- ret = read(file, buf, (ssize_t)n);
+ /* Handle signal interruptions correctly */
+ for (ret = 0; ret < (ssize_t) n; ) {
+ n_read = read(file, buf, (ssize_t)n);
+ if (n_read > 0) {
+ ret += n_read;
+ } else if (n_read == -1 && errno == EINTR) {
+ continue;
+ } else {
+ break;
+ }
+ }
}
#ifndef UNIV_HOTBACKUP
@@ -2227,6 +2264,7 @@ os_file_pwrite(
offset */
{
ssize_t ret;
+ ssize_t n_written;
off_t offs;
ut_a((offset & 0xFFFFFFFFUL) == offset);
@@ -2254,7 +2292,18 @@ os_file_pwrite(
os_n_pending_writes++;
os_mutex_exit(os_file_count_mutex);
- ret = pwrite(file, buf, (ssize_t)n, offs);
+ /* Handle signal interruptions correctly */
+ for (ret = 0; ret < (ssize_t) n; ) {
+ n_written = pwrite(file, buf, (ssize_t)n, offs);
+ if (n_written > 0) {
+ ret += n_written;
+ offs += n_written;
+ } else if (n_written == -1 && errno == EINTR) {
+ continue;
+ } else {
+ break;
+ }
+ }
os_mutex_enter(os_file_count_mutex);
os_file_n_pending_pwrites--;
@@ -2270,7 +2319,7 @@ os_file_pwrite(
the OS crashes, a database page is only partially
physically written to disk. */
- ut_a(TRUE == os_file_flush(file));
+ ut_a(TRUE == os_file_flush(file, TRUE));
}
# endif /* UNIV_DO_FLUSH */
@@ -2301,7 +2350,17 @@ os_file_pwrite(
goto func_exit;
}
- ret = write(file, buf, (ssize_t)n);
+ /* Handle signal interruptions correctly */
+ for (ret = 0; ret < (ssize_t) n; ) {
+ n_written = write(file, buf, (ssize_t)n);
+ if (n_written > 0) {
+ ret += n_written;
+ } else if (n_written == -1 && errno == EINTR) {
+ continue;
+ } else {
+ break;
+ }
+ }
# ifdef UNIV_DO_FLUSH
if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
@@ -2312,7 +2371,7 @@ os_file_pwrite(
the OS crashes, a database page is only partially
physically written to disk. */
- ut_a(TRUE == os_file_flush(file));
+ ut_a(TRUE == os_file_flush(file, TRUE));
}
# endif /* UNIV_DO_FLUSH */
@@ -2679,7 +2738,7 @@ retry:
# ifdef UNIV_DO_FLUSH
if (!os_do_not_call_flush_at_each_write) {
- ut_a(TRUE == os_file_flush(file));
+ ut_a(TRUE == os_file_flush(file, TRUE));
}
# endif /* UNIV_DO_FLUSH */
@@ -3534,7 +3593,7 @@ os_aio_simulated_wake_handler_thread(
{
os_aio_array_t* array;
os_aio_slot_t* slot;
- ulint segment;
+ ulint segment __attribute__ ((unused));
ulint n;
ulint i;
@@ -3940,7 +3999,7 @@ os_aio_windows_handle(
#ifdef UNIV_DO_FLUSH
if (slot->type == OS_FILE_WRITE
&& !os_do_not_call_flush_at_each_write) {
- ut_a(TRUE == os_file_flush(slot->file));
+ ut_a(TRUE == os_file_flush(slot->file, TRUE));
}
#endif /* UNIV_DO_FLUSH */
} else if (os_file_handle_error(slot->name, "Windows aio")) {
@@ -4020,7 +4079,7 @@ os_aio_simulated_handle(
ulint* space_id)
{
os_aio_array_t* array;
- ulint segment;
+ ulint segment __attribute__ ((unused));
os_aio_slot_t* slot;
os_aio_slot_t* slot2;
os_aio_slot_t* consecutive_ios[OS_AIO_MERGE_N_CONSECUTIVE];
diff --git a/storage/xtradb/os/os0proc.c b/storage/xtradb/os/os0proc.c
index 4567d96b6f4..48922886f23 100644
--- a/storage/xtradb/os/os0proc.c
+++ b/storage/xtradb/os/os0proc.c
@@ -229,173 +229,3 @@ os_mem_free_large(
}
#endif
}
-
-/****************************************************************//**
-Allocates or attaches and reuses shared memory segment.
-The content is not cleared automatically.
-@return allocated memory */
-UNIV_INTERN
-void*
-os_shm_alloc(
-/*=========*/
- ulint* n, /*!< in/out: number of bytes */
- uint key,
- ibool* is_new)
-{
- void* ptr;
-#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
- ulint size;
- int shmid;
-
- *is_new = FALSE;
- fprintf(stderr,
- "InnoDB: The shared memory segment containing the buffer pool is: key %#x (%d).\n",
- key, key);
-# if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
- if (!os_use_large_pages || !os_large_page_size) {
- goto skip;
- }
-
- /* Align block size to os_large_page_size */
- ut_ad(ut_is_2pow(os_large_page_size));
- size = ut_2pow_round(*n + (os_large_page_size - 1),
- os_large_page_size);
-
- shmid = shmget((key_t)key, (size_t)size,
- IPC_CREAT | IPC_EXCL | SHM_HUGETLB | SHM_R | SHM_W);
- if (shmid < 0) {
- if (errno == EEXIST) {
- fprintf(stderr,
- "InnoDB: HugeTLB: The shared memory segment exists.\n");
- shmid = shmget((key_t)key, (size_t)size,
- SHM_HUGETLB | SHM_R | SHM_W);
- if (shmid < 0) {
- fprintf(stderr,
- "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n",
- size, errno);
- goto skip;
- } else {
- fprintf(stderr,
- "InnoDB: HugeTLB: The existent shared memory segment is used.\n");
- }
- } else {
- fprintf(stderr,
- "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (new) errno %d\n",
- size, errno);
- goto skip;
- }
- } else {
- *is_new = TRUE;
- fprintf(stderr,
- "InnoDB: HugeTLB: A new shared memory segment has been created .\n");
- }
-
- ptr = shmat(shmid, NULL, 0);
- if (ptr == (void *)-1) {
- fprintf(stderr,
- "InnoDB: HugeTLB: Warning: Failed to attach shared memory segment, errno %d\n",
- errno);
- ptr = NULL;
- }
-
- if (ptr) {
- *n = size;
- os_fast_mutex_lock(&ut_list_mutex);
- ut_total_allocated_memory += size;
- os_fast_mutex_unlock(&ut_list_mutex);
- UNIV_MEM_ALLOC(ptr, size);
- return(ptr);
- }
-skip:
- *is_new = FALSE;
-# endif /* HAVE_LARGE_PAGES && defined UNIV_LINUX */
-# ifdef HAVE_GETPAGESIZE
- size = getpagesize();
-# else
- size = UNIV_PAGE_SIZE;
-# endif
- /* Align block size to system page size */
- ut_ad(ut_is_2pow(size));
- size = *n = ut_2pow_round(*n + (size - 1), size);
-
- shmid = shmget((key_t)key, (size_t)size,
- IPC_CREAT | IPC_EXCL | SHM_R | SHM_W);
- if (shmid < 0) {
- if (errno == EEXIST) {
- fprintf(stderr,
- "InnoDB: A shared memory segment containing the buffer pool seems to already exist.\n");
- shmid = shmget((key_t)key, (size_t)size,
- SHM_R | SHM_W);
- if (shmid < 0) {
- fprintf(stderr,
- "InnoDB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n",
- size, errno);
- ptr = NULL;
- goto end;
- } else {
- fprintf(stderr,
- "InnoDB: The existent shared memory segment is used.\n");
- }
- } else {
- fprintf(stderr,
- "InnoDB: Warning: Failed to allocate %lu bytes. (new) errno %d\n",
- size, errno);
- ptr = NULL;
- goto end;
- }
- } else {
- *is_new = TRUE;
- fprintf(stderr,
- "InnoDB: A new shared memory segment has been created.\n");
- }
-
- ptr = shmat(shmid, NULL, 0);
- if (ptr == (void *)-1) {
- fprintf(stderr,
- "InnoDB: Warning: Failed to attach shared memory segment, errno %d\n",
- errno);
- ptr = NULL;
- }
-
- if (ptr) {
- *n = size;
- os_fast_mutex_lock(&ut_list_mutex);
- ut_total_allocated_memory += size;
- os_fast_mutex_unlock(&ut_list_mutex);
- UNIV_MEM_ALLOC(ptr, size);
- }
-end:
-#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
- fprintf(stderr, "InnoDB: shared memory segment is not supported.\n");
- ptr = NULL;
-#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
- return(ptr);
-}
-
-/****************************************************************//**
-Detach shared memory segment. */
-UNIV_INTERN
-void
-os_shm_free(
-/*========*/
- void *ptr, /*!< in: pointer returned by
- os_shm_alloc() */
- ulint size) /*!< in: size returned by
- os_shm_alloc() */
-{
- os_fast_mutex_lock(&ut_list_mutex);
- ut_a(ut_total_allocated_memory >= size);
- os_fast_mutex_unlock(&ut_list_mutex);
-
-#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
- if (!shmdt(ptr)) {
- os_fast_mutex_lock(&ut_list_mutex);
- ut_a(ut_total_allocated_memory >= size);
- ut_total_allocated_memory -= size;
- os_fast_mutex_unlock(&ut_list_mutex);
- UNIV_MEM_FREE(ptr, size);
- }
-#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
- fprintf(stderr, "InnoDB: shared memory segment is not supported.\n");
-#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
-}
diff --git a/storage/xtradb/page/page0cur.c b/storage/xtradb/page/page0cur.c
index f10f16a7dd9..b8c492328e8 100644
--- a/storage/xtradb/page/page0cur.c
+++ b/storage/xtradb/page/page0cur.c
@@ -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
@@ -1149,6 +1149,8 @@ use_heap:
current_rec, index, mtr);
}
+ btr_blob_dbg_add_rec(insert_rec, index, offsets, "insert");
+
return(insert_rec);
}
@@ -1178,14 +1180,15 @@ page_cur_insert_rec_zip_reorg(
/* Before trying to reorganize the page,
store the number of preceding records on the page. */
pos = page_rec_get_n_recs_before(rec);
+ ut_ad(pos > 0);
if (page_zip_reorganize(block, index, mtr)) {
/* The page was reorganized: Find rec by seeking to pos,
and update *current_rec. */
- rec = page + PAGE_NEW_INFIMUM;
-
- while (--pos) {
- rec = page + rec_get_next_offs(rec, TRUE);
+ if (pos > 1) {
+ rec = page_rec_get_nth(page, pos - 1);
+ } else {
+ rec = page + PAGE_NEW_INFIMUM;
}
*current_rec = rec;
@@ -1195,10 +1198,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);
}
@@ -1279,6 +1284,12 @@ page_cur_insert_rec_zip(
insert_rec = page_cur_insert_rec_zip_reorg(
current_rec, block, index, insert_rec,
page, page_zip, mtr);
+#ifdef UNIV_DEBUG
+ if (insert_rec) {
+ rec_offs_make_valid(
+ insert_rec, index, offsets);
+ }
+#endif /* UNIV_DEBUG */
}
return(insert_rec);
@@ -1490,6 +1501,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 +1710,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 +1960,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/xtradb/page/page0page.c b/storage/xtradb/page/page0page.c
index 10008f9ac25..a284b1480a3 100644
--- a/storage/xtradb/page/page0page.c
+++ b/storage/xtradb/page/page0page.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.
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
@@ -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));
@@ -1476,55 +1487,54 @@ page_dir_balance_slot(
}
}
-#ifndef UNIV_HOTBACKUP
/************************************************************//**
-Returns the middle record of the record list. If there are an even number
-of records in the list, returns the first record of the upper half-list.
-@return middle record */
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return nth record */
UNIV_INTERN
-rec_t*
-page_get_middle_rec(
-/*================*/
- page_t* page) /*!< in: page */
+const rec_t*
+page_rec_get_nth_const(
+/*===================*/
+ const page_t* page, /*!< in: page */
+ ulint nth) /*!< in: nth record */
{
- page_dir_slot_t* slot;
- ulint middle;
+ const page_dir_slot_t* slot;
ulint i;
ulint n_owned;
- ulint count;
- rec_t* rec;
+ const rec_t* rec;
- /* This many records we must leave behind */
- middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
-
- count = 0;
+ ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
for (i = 0;; i++) {
slot = page_dir_get_nth_slot(page, i);
n_owned = page_dir_slot_get_n_owned(slot);
- if (count + n_owned > middle) {
+ if (n_owned > nth) {
break;
} else {
- count += n_owned;
+ nth -= n_owned;
}
}
ut_ad(i > 0);
slot = page_dir_get_nth_slot(page, i - 1);
- rec = (rec_t*) page_dir_slot_get_rec(slot);
- rec = page_rec_get_next(rec);
-
- /* There are now count records behind rec */
+ rec = page_dir_slot_get_rec(slot);
- for (i = 0; i < middle - count; i++) {
- rec = page_rec_get_next(rec);
+ if (page_is_comp(page)) {
+ do {
+ rec = page_rec_get_next_low(rec, TRUE);
+ ut_ad(rec);
+ } while (nth--);
+ } else {
+ do {
+ rec = page_rec_get_next_low(rec, FALSE);
+ ut_ad(rec);
+ } while (nth--);
}
return(rec);
}
-#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**
Returns the number of records before the given record in chain.
@@ -1586,6 +1596,7 @@ page_rec_get_n_recs_before(
n--;
ut_ad(n >= 0);
+ ut_ad(n < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
return((ulint) n);
}
diff --git a/storage/xtradb/page/page0zip.c b/storage/xtradb/page/page0zip.c
index 5b4f5d3b76a..3d5c5a226c7 100644
--- a/storage/xtradb/page/page0zip.c
+++ b/storage/xtradb/page/page0zip.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 2005, 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
@@ -151,6 +151,20 @@ page_zip_empty_size(
#endif /* !UNIV_HOTBACKUP */
/*************************************************************//**
+Gets the number of elements in the dense page directory,
+including deleted records (the free list).
+@return number of elements in the dense page directory */
+UNIV_INLINE
+ulint
+page_zip_dir_elems(
+/*===============*/
+ const page_zip_des_t* page_zip) /*!< in: compressed page */
+{
+ /* Exclude the page infimum and supremum from the record count. */
+ return(page_dir_get_n_heap(page_zip->data) - PAGE_HEAP_NO_USER_LOW);
+}
+
+/*************************************************************//**
Gets the size of the compressed page trailer (the dense page directory),
including deleted records (the free list).
@return length of dense page directory, in bytes */
@@ -160,14 +174,42 @@ page_zip_dir_size(
/*==============*/
const page_zip_des_t* page_zip) /*!< in: compressed page */
{
- /* Exclude the page infimum and supremum from the record count. */
- ulint size = PAGE_ZIP_DIR_SLOT_SIZE
- * (page_dir_get_n_heap(page_zip->data)
- - PAGE_HEAP_NO_USER_LOW);
- return(size);
+ return(PAGE_ZIP_DIR_SLOT_SIZE * page_zip_dir_elems(page_zip));
+}
+
+/*************************************************************//**
+Gets an offset to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@return offset of the dense page directory */
+UNIV_INLINE
+ulint
+page_zip_dir_start_offs(
+/*====================*/
+ const page_zip_des_t* page_zip, /*!< in: compressed page */
+ ulint n_dense) /*!< in: directory size */
+{
+ ut_ad(n_dense * PAGE_ZIP_DIR_SLOT_SIZE < page_zip_get_size(page_zip));
+
+ return(page_zip_get_size(page_zip) - n_dense * PAGE_ZIP_DIR_SLOT_SIZE);
}
/*************************************************************//**
+Gets a pointer to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@param[in] page_zip compressed page
+@param[in] n_dense number of entries in the directory
+@return pointer to the dense page directory */
+#define page_zip_dir_start_low(page_zip, n_dense) \
+ ((page_zip)->data + page_zip_dir_start_offs(page_zip, n_dense))
+/*************************************************************//**
+Gets a pointer to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@param[in] page_zip compressed page
+@return pointer to the dense page directory */
+#define page_zip_dir_start(page_zip) \
+ page_zip_dir_start_low(page_zip, page_zip_dir_elems(page_zip))
+
+/*************************************************************//**
Gets the size of the compressed page trailer (the dense page directory),
only including user records (excluding the free list).
@return length of dense page directory comprising existing records, in bytes */
@@ -653,13 +695,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 +726,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;
}
@@ -2246,8 +2288,7 @@ zlib_done:
}
/* Restore the uncompressed columns in heap_no order. */
- storage = page_zip->data + page_zip_get_size(page_zip)
- - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start_low(page_zip, n_dense);
for (slot = 0; slot < n_dense; slot++) {
rec_t* rec = recs[slot];
@@ -2732,8 +2773,7 @@ zlib_done:
return(FALSE);
}
- storage = page_zip->data + page_zip_get_size(page_zip)
- - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start_low(page_zip, n_dense);
externs = storage - n_dense
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
@@ -2916,19 +2956,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)) {
@@ -3462,9 +3501,7 @@ page_zip_write_rec(
}
/* Write the data bytes. Store the uncompressed bytes separately. */
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start(page_zip);
if (page_is_leaf(page)) {
ulint len;
@@ -3760,9 +3797,7 @@ corrupt:
field = page + offset;
storage = page_zip->data + z_offset;
- storage_end = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage_end = page_zip_dir_start(page_zip);
heap_no = 1 + (storage_end - storage) / REC_NODE_PTR_SIZE;
@@ -3798,7 +3833,9 @@ page_zip_write_node_ptr(
{
byte* field;
byte* storage;
+#ifdef UNIV_DEBUG
page_t* page = page_align(rec);
+#endif /* UNIV_DEBUG */
ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
ut_ad(page_simple_validate_new(page));
@@ -3815,9 +3852,7 @@ page_zip_write_node_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
UNIV_MEM_ASSERT_RW(rec, size);
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE
+ storage = page_zip_dir_start(page_zip)
- (rec_get_heap_no_new(rec) - 1) * REC_NODE_PTR_SIZE;
field = rec + size - REC_NODE_PTR_SIZE;
@@ -3866,7 +3901,9 @@ page_zip_write_trx_id_and_roll_ptr(
{
byte* field;
byte* storage;
+#ifdef UNIV_DEBUG
page_t* page = page_align(rec);
+#endif /* UNIV_DEBUG */
ulint len;
ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
@@ -3884,9 +3921,7 @@ page_zip_write_trx_id_and_roll_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE
+ storage = page_zip_dir_start(page_zip)
- (rec_get_heap_no_new(rec) - 1)
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
@@ -3917,17 +3952,9 @@ page_zip_write_trx_id_and_roll_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
}
-#ifdef UNIV_ZIP_DEBUG
-/** Set this variable in a debugger to disable page_zip_clear_rec().
-The only observable effect should be the compression ratio due to
-deleted records not being zeroed out. In rare cases, there can be
-page_zip_validate() failures on the node_ptr, trx_id and roll_ptr
-columns if the space is reallocated for a smaller record. */
-UNIV_INTERN ibool page_zip_clear_rec_disable;
-#endif /* UNIV_ZIP_DEBUG */
-
/**********************************************************************//**
-Clear an area on the uncompressed and compressed page, if possible. */
+Clear an area on the uncompressed and compressed page.
+Do not clear the data payload, as that would grow the modification log. */
static
void
page_zip_clear_rec(
@@ -3939,6 +3966,9 @@ page_zip_clear_rec(
{
ulint heap_no;
page_t* page = page_align(rec);
+ byte* storage;
+ byte* field;
+ ulint len;
/* page_zip_validate() would fail here if a record
containing externally stored columns is being deleted. */
ut_ad(rec_offs_validate(rec, index, offsets));
@@ -3954,60 +3984,38 @@ page_zip_clear_rec(
UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
rec_offs_extra_size(offsets));
- if (
-#ifdef UNIV_ZIP_DEBUG
- !page_zip_clear_rec_disable &&
-#endif /* UNIV_ZIP_DEBUG */
- page_zip->m_end
- + 1 + ((heap_no - 1) >= 64)/* size of the log entry */
- + page_zip_get_trailer_len(page_zip,
- dict_index_is_clust(index), NULL)
- < page_zip_get_size(page_zip)) {
- byte* data;
-
- /* Clear only the data bytes, because the allocator and
- the decompressor depend on the extra bytes. */
- memset(rec, 0, rec_offs_data_size(offsets));
-
- if (!page_is_leaf(page)) {
- /* Clear node_ptr on the compressed page. */
- byte* storage = page_zip->data
- + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page)
- - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
-
- memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
- 0, REC_NODE_PTR_SIZE);
- } else if (dict_index_is_clust(index)) {
- /* Clear trx_id and roll_ptr on the compressed page. */
- byte* storage = page_zip->data
- + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page)
- - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
-
- memset(storage - (heap_no - 1)
- * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
- 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
- }
+ if (!page_is_leaf(page)) {
+ /* Clear node_ptr. On the compressed page,
+ there is an array of node_ptr immediately before the
+ dense page directory, at the very end of the page. */
+ storage = page_zip_dir_start(page_zip);
+ ut_ad(dict_index_get_n_unique_in_tree(index) ==
+ rec_offs_n_fields(offsets) - 1);
+ field = rec_get_nth_field(rec, offsets,
+ rec_offs_n_fields(offsets) - 1,
+ &len);
+ ut_ad(len == REC_NODE_PTR_SIZE);
- /* Log that the data was zeroed out. */
- data = page_zip->data + page_zip->m_end;
- ut_ad(!*data);
- if (UNIV_UNLIKELY(heap_no - 1 >= 64)) {
- *data++ = (byte) (0x80 | (heap_no - 1) >> 7);
- ut_ad(!*data);
- }
- *data++ = (byte) ((heap_no - 1) << 1 | 1);
- ut_ad(!*data);
- ut_ad((ulint) (data - page_zip->data)
- < page_zip_get_size(page_zip));
- page_zip->m_end = data - page_zip->data;
- page_zip->m_nonempty = TRUE;
- } else if (page_is_leaf(page) && dict_index_is_clust(index)) {
- /* Do not clear the record, because there is not enough space
- to log the operation. */
+ ut_ad(!rec_offs_any_extern(offsets));
+ memset(field, 0, REC_NODE_PTR_SIZE);
+ memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
+ 0, REC_NODE_PTR_SIZE);
+ } else if (dict_index_is_clust(index)) {
+ /* Clear trx_id and roll_ptr. On the compressed page,
+ there is an array of these fields immediately before the
+ dense page directory, at the very end of the page. */
+ const ulint trx_id_pos
+ = dict_col_get_clust_pos(
+ dict_table_get_sys_col(
+ index->table, DATA_TRX_ID), index);
+ storage = page_zip_dir_start(page_zip);
+ field = rec_get_nth_field(rec, offsets, trx_id_pos, &len);
+ ut_ad(len == DATA_TRX_ID_LEN);
+
+ memset(field, 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
+ memset(storage - (heap_no - 1)
+ * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
+ 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
if (rec_offs_any_extern(offsets)) {
ulint i;
@@ -4016,15 +4024,18 @@ page_zip_clear_rec(
/* Clear all BLOB pointers in order to make
page_zip_validate() pass. */
if (rec_offs_nth_extern(offsets, i)) {
- ulint len;
- byte* field = rec_get_nth_field(
+ field = rec_get_nth_field(
rec, offsets, i, &len);
+ ut_ad(len
+ == BTR_EXTERN_FIELD_REF_SIZE);
memset(field + len
- BTR_EXTERN_FIELD_REF_SIZE,
0, BTR_EXTERN_FIELD_REF_SIZE);
}
}
}
+ } else {
+ ut_ad(!rec_offs_any_extern(offsets));
}
#ifdef UNIV_ZIP_DEBUG
@@ -4455,6 +4466,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 */
@@ -4513,7 +4526,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
@@ -4583,6 +4596,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/xtradb/que/que0que.c b/storage/xtradb/que/que0que.c
index 9c1d61c1731..5fccbb180fe 100644
--- a/storage/xtradb/que/que0que.c
+++ b/storage/xtradb/que/que0que.c
@@ -1418,6 +1418,12 @@ que_eval_sql(
ut_a(trx->error_state == DB_SUCCESS);
+ if (trx->fake_changes) {
+ /* fake_changes should not access to system tables */
+ fprintf(stderr, "InnoDB: ERROR: innodb_fake_changes tried to access to system tables.\n");
+ return(DB_ERROR);
+ }
+
if (reserve_dict_mutex) {
mutex_enter(&dict_sys->mutex);
}
diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c
index 37ba8ca2ffe..9f90d2940dd 100644
--- a/storage/xtradb/rem/rem0rec.c
+++ b/storage/xtradb/rem/rem0rec.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.
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
@@ -408,7 +408,7 @@ rec_init_offsets(
do {
ulint len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
- len = offs += 4;
+ len = offs += REC_NODE_PTR_SIZE;
goto resolved;
}
@@ -640,7 +640,7 @@ rec_get_offsets_reverse(
do {
ulint len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
- len = offs += 4;
+ len = offs += REC_NODE_PTR_SIZE;
goto resolved;
}
@@ -1131,9 +1131,9 @@ rec_convert_dtuple_to_rec_comp(
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
- ut_ad(len == 4);
+ ut_ad(len == REC_NODE_PTR_SIZE);
memcpy(end, dfield_get_data(field), len);
- end += 4;
+ end += REC_NODE_PTR_SIZE;
break;
}
diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c
index efcea62f212..0e62185c02e 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.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
@@ -345,9 +345,9 @@ row_ins_clust_index_entry_by_modify(
return(DB_LOCK_TABLE_FULL);
}
- err = btr_cur_pessimistic_update(0, cursor,
- heap, big_rec, update,
- 0, thr, mtr);
+ err = btr_cur_pessimistic_update(
+ BTR_KEEP_POS_FLAG, cursor, heap, big_rec, update,
+ 0, thr, mtr);
}
return(err);
@@ -1512,6 +1512,11 @@ exit_func:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
+
+ if (trx->fake_changes) {
+ err = DB_SUCCESS;
+ }
+
return(err);
}
@@ -1992,6 +1997,7 @@ row_ins_index_entry_low(
ulint modify = 0; /* remove warning */
rec_t* insert_rec;
rec_t* rec;
+ ulint* offsets;
ulint err;
ulint n_unique;
big_rec_t* big_rec = NULL;
@@ -2013,7 +2019,7 @@ row_ins_index_entry_low(
}
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
- mode | BTR_INSERT | ignore_sec_unique,
+ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT | ignore_sec_unique),
&cursor, 0, __FILE__, __LINE__, &mtr);
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
@@ -2073,7 +2079,7 @@ row_ins_index_entry_low(
btr_cur_search_to_nth_level(index, 0, entry,
PAGE_CUR_LE,
- mode | BTR_INSERT,
+ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT),
&cursor, 0,
__FILE__, __LINE__, &mtr);
}
@@ -2097,6 +2103,42 @@ row_ins_index_entry_low(
err = row_ins_clust_index_entry_by_modify(
mode, &cursor, &heap, &big_rec, entry,
thr, &mtr);
+
+ if (big_rec) {
+ ut_a(err == DB_SUCCESS);
+ /* Write out the externally stored
+ columns while still x-latching
+ index->lock and block->lock. We have
+ to mtr_commit(mtr) first, so that the
+ redo log will be written in the
+ correct order. Otherwise, we would run
+ into trouble on crash recovery if mtr
+ freed B-tree pages on which some of
+ the big_rec fields will be written. */
+ btr_cur_mtr_commit_and_start(&cursor, &mtr);
+
+ rec = btr_cur_get_rec(&cursor);
+ offsets = rec_get_offsets(
+ rec, index, NULL,
+ ULINT_UNDEFINED, &heap);
+
+ err = btr_store_big_rec_extern_fields(
+ index, btr_cur_get_block(&cursor),
+ rec, offsets, &mtr, FALSE, big_rec);
+ /* If writing big_rec fails (for
+ example, because of DB_OUT_OF_FILE_SPACE),
+ the record will be corrupted. Even if
+ we did not update any externally
+ stored columns, our update could cause
+ the record to grow so that a
+ non-updated column was selected for
+ external storage. This non-update
+ would not have been written to the
+ undo log, and thus the record cannot
+ be rolled back. */
+ ut_a(err == DB_SUCCESS);
+ goto stored_big_rec;
+ }
} else {
ut_ad(!n_ext);
err = row_ins_sec_index_entry_by_modify(
@@ -2125,8 +2167,22 @@ function_exit:
mtr_commit(&mtr);
if (UNIV_LIKELY_NULL(big_rec)) {
- rec_t* rec;
- ulint* offsets;
+
+ if (thr_get_trx(thr)->fake_changes) {
+ /* skip store extern */
+ if (modify) {
+ dtuple_big_rec_free(big_rec);
+ } else {
+ dtuple_convert_back_big_rec(index, entry, big_rec);
+ }
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
+ return(err);
+ }
+
mtr_start(&mtr);
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
@@ -2140,6 +2196,7 @@ function_exit:
index, btr_cur_get_block(&cursor),
rec, offsets, &mtr, FALSE, big_rec);
+stored_big_rec:
if (modify) {
dtuple_big_rec_free(big_rec);
} else {
diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c
index 1b97cbb0009..cb003ad62e0 100644
--- a/storage/xtradb/row/row0mysql.c
+++ b/storage/xtradb/row/row0mysql.c
@@ -1190,6 +1190,7 @@ run_again:
prebuilt->table->stat_n_rows--;
}
+ if (!(trx->fake_changes))
row_update_statistics_if_needed(prebuilt->table);
trx->op_info = "";
@@ -1450,6 +1451,7 @@ run_again:
that changes indexed columns, UPDATEs that change only non-indexed
columns would not affect statistics. */
if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
+ if (!(trx->fake_changes))
row_update_statistics_if_needed(prebuilt->table);
}
@@ -1668,6 +1670,7 @@ run_again:
srv_n_rows_updated++;
}
+ if (!(trx->fake_changes))
row_update_statistics_if_needed(table);
return(err);
@@ -2556,10 +2559,29 @@ row_discard_tablespace_for_mysql(
err = DB_ERROR;
} else {
+ dict_index_t* index;
+
/* Set the flag which tells that now it is legal to
IMPORT a tablespace for this table */
table->tablespace_discarded = TRUE;
table->ibd_file_missing = TRUE;
+
+ /* check adaptive hash entries */
+ index = dict_table_get_first_index(table);
+ while (index) {
+ ulint ref_count = btr_search_info_get_ref_count(index->search_info);
+ if (ref_count) {
+ fprintf(stderr, "InnoDB: Warning:"
+ " hash index ref_count (%lu) is not zero"
+ " after fil_discard_tablespace().\n"
+ "index: \"%s\""
+ " table: \"%s\"\n",
+ ref_count,
+ index->name,
+ table->name);
+ }
+ index = dict_table_get_next_index(index);
+ }
}
}
@@ -2597,6 +2619,11 @@ row_import_tablespace_for_mysql(
current_lsn = log_get_lsn();
+ /* Enlarge the fatal lock wait timeout during import. */
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
/* It is possible, though very improbable, that the lsn's in the
tablespace to be imported have risen above the current system lsn, if
a lengthy purge, ibuf merge, or rollback was performed on a backup
@@ -2708,6 +2735,11 @@ funct_exit:
trx->op_info = "";
+ /* Restore the fatal semaphore wait timeout */
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
return((int) err);
}
@@ -2901,6 +2933,19 @@ row_truncate_table_for_mysql(
table->space = space;
index = dict_table_get_first_index(table);
do {
+ ulint ref_count = btr_search_info_get_ref_count(index->search_info);
+ /* check adaptive hash entries */
+ if (ref_count) {
+ fprintf(stderr, "InnoDB: Warning:"
+ " hash index ref_count (%lu) is not zero"
+ " after fil_discard_tablespace().\n"
+ "index: \"%s\""
+ " table: \"%s\"\n",
+ ref_count,
+ index->name,
+ table->name);
+ }
+
index->space = space;
index = dict_table_get_next_index(index);
} while (index);
diff --git a/storage/xtradb/row/row0row.c b/storage/xtradb/row/row0row.c
index 0783d482f76..cea70e98dee 100644
--- a/storage/xtradb/row/row0row.c
+++ b/storage/xtradb/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.
@@ -130,12 +101,27 @@ row_build_index_entry(
dfield_copy(dfield, dfield2);
- if (dfield_is_null(dfield) || ind_field->prefix_len == 0) {
+ if (dfield_is_null(dfield)) {
+ continue;
+ }
+
+ if (ind_field->prefix_len == 0
+ && (!dfield_is_ext(dfield)
+ || dict_index_is_clust(index))) {
+ /* The dfield_copy() above suffices for
+ columns that are stored in-page, or for
+ clustered index record columns that are not
+ part of a column prefix in the PRIMARY KEY. */
continue;
}
- /* If a column prefix index, take only the prefix.
- Prefix-indexed columns may be externally stored. */
+ /* If the column is stored externally (off-page) in
+ the clustered index, it must be an ordering field in
+ the secondary index. In the Antelope format, only
+ prefix-indexed columns may be stored off-page in the
+ clustered index record. In the Barracuda format, also
+ fully indexed long CHAR or VARCHAR columns may be
+ stored off-page. */
ut_ad(col->ord_part);
if (UNIV_LIKELY_NULL(ext)) {
@@ -148,17 +134,41 @@ row_build_index_entry(
}
dfield_set_data(dfield, buf, len);
}
+
+ if (ind_field->prefix_len == 0) {
+ /* In the Barracuda format
+ (ROW_FORMAT=DYNAMIC or
+ ROW_FORMAT=COMPRESSED), we can have a
+ secondary index on an entire column
+ that is stored off-page in the
+ clustered index. As this is not a
+ prefix index (prefix_len == 0),
+ include the entire off-page column in
+ the secondary index record. */
+ continue;
+ }
} else if (dfield_is_ext(dfield)) {
+ /* This table is either in Antelope format
+ (ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT)
+ or a purge record where the ordered part of
+ the field is not external.
+ In Antelope, the maximum column prefix
+ index length is 767 bytes, and the clustered
+ index record contains a 768-byte prefix of
+ each off-page column. */
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));
+ dfield_set_len(dfield, len);
}
- len = dtype_get_at_most_n_mbchars(
- col->prtype, col->mbminlen, col->mbmaxlen,
- ind_field->prefix_len, len, dfield_get_data(dfield));
- dfield_set_len(dfield, len);
+ /* If a column prefix index, take only the prefix. */
+ if (ind_field->prefix_len) {
+ len = dtype_get_at_most_n_mbchars(
+ col->prtype, col->mbminlen, col->mbmaxlen,
+ ind_field->prefix_len, len,
+ dfield_get_data(dfield));
+ dfield_set_len(dfield, len);
+ }
}
ut_ad(dtuple_check_typed(entry));
@@ -223,6 +233,7 @@ row_build(
ut_ad(index && rec && heap);
ut_ad(dict_index_is_clust(index));
+ ut_ad(!mutex_own(&kernel_mutex));
if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_,
@@ -231,6 +242,22 @@ row_build(
ut_ad(rec_offs_validate(rec, index, offsets));
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ /* This condition can occur during crash recovery before
+ trx_rollback_active() has completed execution.
+
+ This condition is possible if the server crashed
+ during an insert or update before
+ btr_store_big_rec_extern_fields() did mtr_commit() all
+ BLOB pointers to the clustered index record.
+
+ If the record contains a null BLOB pointer, look up the
+ transaction that holds the implicit lock on this record, and
+ assert that it was recovered (and will soon be rolled back). */
+ ut_a(!rec_offs_any_null_extern(rec, offsets)
+ || trx_assert_recovered(row_get_rec_trx_id(rec, index, offsets)));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
@@ -431,6 +458,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);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ } else {
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}
entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);
diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c
index 1ced125b7bd..e8e9465d838 100644
--- a/storage/xtradb/row/row0sel.c
+++ b/storage/xtradb/row/row0sel.c
@@ -2544,6 +2544,8 @@ row_sel_field_store_in_mysql_format(
ut_ad(len != UNIV_SQL_NULL);
UNIV_MEM_ASSERT_RW(data, len);
+ UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
+ UNIV_MEM_INVALID(dest, templ->mysql_col_len);
switch (templ->type) {
case DATA_INT:
@@ -2580,14 +2582,16 @@ row_sel_field_store_in_mysql_format(
dest = row_mysql_store_true_var_len(
dest, len, templ->mysql_length_bytes);
+ /* Copy the actual data. Leave the rest of the
+ buffer uninitialized. */
+ memcpy(dest, data, len);
+ break;
}
/* Copy the actual data */
ut_memcpy(dest, data, len);
- /* Pad with trailing spaces. We pad with spaces also the
- unused end of a >= 5.0.3 true VARCHAR column, just in case
- MySQL expects its contents to be deterministic. */
+ /* Pad with trailing spaces. */
pad_ptr = dest + len;
@@ -3120,6 +3124,39 @@ sel_restore_position_for_mysql(
}
/********************************************************************//**
+Copies a cached field for MySQL from the fetch cache. */
+static
+void
+row_sel_copy_cached_field_for_mysql(
+/*================================*/
+ byte* buf, /*!< in/out: row buffer */
+ const byte* cache, /*!< in: cached row */
+ const mysql_row_templ_t*templ) /*!< in: column template */
+{
+ ulint len;
+
+ buf += templ->mysql_col_offset;
+ cache += templ->mysql_col_offset;
+
+ UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len);
+
+ if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR
+ && templ->type != DATA_INT) {
+ /* Check for != DATA_INT to make sure we do
+ not treat MySQL ENUM or SET as a true VARCHAR!
+ Find the actual length of the true VARCHAR field. */
+ row_mysql_read_true_varchar(
+ &len, cache, templ->mysql_length_bytes);
+ len += templ->mysql_length_bytes;
+ UNIV_MEM_INVALID(buf, templ->mysql_col_len);
+ } else {
+ len = templ->mysql_col_len;
+ }
+
+ ut_memcpy(buf, cache, len);
+}
+
+/********************************************************************//**
Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE
void
@@ -3131,26 +3168,22 @@ row_sel_pop_cached_row_for_mysql(
{
ulint i;
const mysql_row_templ_t*templ;
- byte* cached_rec;
+ const byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
+ UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len);
+
+ cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first];
+
if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) {
/* Copy cache record field by field, don't touch fields that
are not covered by current key */
- cached_rec = prebuilt->fetch_cache[
- prebuilt->fetch_cache_first];
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(cached_rec
- + templ->mysql_col_offset,
- templ->mysql_col_len);
-#endif
- ut_memcpy(buf + templ->mysql_col_offset,
- cached_rec + templ->mysql_col_offset,
- templ->mysql_col_len);
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, templ);
/* Copy NULL bit of the current field from cached_rec
to buf */
if (templ->mysql_null_bit_mask) {
@@ -3160,17 +3193,24 @@ row_sel_pop_cached_row_for_mysql(
& (byte)templ->mysql_null_bit_mask;
}
}
+ } else if (prebuilt->mysql_prefix_len > 63) {
+ /* The record is long. Copy it field by field, in case
+ there are some long VARCHAR column of which only a
+ small length is being used. */
+ UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len);
+
+ /* First copy the NULL bits. */
+ ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len);
+ /* Then copy the requested fields. */
+
+ for (i = 0; i < prebuilt->n_template; i++) {
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, prebuilt->mysql_template + i);
+ }
+ } else {
+ ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len);
}
- else {
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
- [prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
-#endif
- ut_memcpy(buf,
- prebuilt->fetch_cache[prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
- }
+
prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++;
@@ -3964,7 +4004,13 @@ rec_loop:
if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
wrong_offs:
- if (srv_force_recovery == 0 || moves_up == FALSE) {
+ if (srv_pass_corrupt_table && !trx_sys_sys_space(index->table->space)) {
+ index->table->is_corrupt = TRUE;
+ fil_space_set_corrupt(index->table->space);
+ }
+
+ if ((srv_force_recovery == 0 || moves_up == FALSE)
+ && srv_pass_corrupt_table <= 1) {
ut_print_timestamp(stderr);
buf_page_print(page_align(rec), 0);
fprintf(stderr,
@@ -4015,7 +4061,8 @@ wrong_offs:
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
- if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
+ if (UNIV_UNLIKELY(srv_force_recovery > 0)
+ || (srv_pass_corrupt_table == 2 && index->table->is_corrupt)) {
if (!rec_validate(rec, offsets)
|| !btr_index_rec_validate(rec, index, FALSE)) {
fprintf(stderr,
diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c
index a6fb266c4ed..5765d3b76d2 100644
--- a/storage/xtradb/row/row0upd.c
+++ b/storage/xtradb/row/row0upd.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, 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
@@ -504,14 +504,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)) {
@@ -1556,8 +1591,9 @@ row_upd_sec_index_entry(
mtr_start(&mtr);
- found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
- &mtr);
+ found = row_search_index_entry(index, entry,
+ trx->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
+ &pcur, &mtr);
btr_cur = btr_pcur_get_btr_cur(&pcur);
rec = btr_cur_get_rec(btr_cur);
@@ -1787,9 +1823,11 @@ row_upd_clust_rec_by_insert(
the previous invocation of this function. Mark the
off-page columns in the entry inherited. */
+ if (!(trx->fake_changes)) {
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
@@ -1819,7 +1857,7 @@ err_exit:
delete-marked old record, mark them disowned by the
old record and owned by the new entry. */
- if (rec_offs_any_extern(offsets)) {
+ if (rec_offs_any_extern(offsets) && !(trx->fake_changes)) {
change_ownership = row_upd_clust_rec_by_insert_inherit(
rec, offsets, entry, node->update);
@@ -1947,33 +1985,50 @@ row_upd_clust_rec(
the same transaction do not modify the record in the meantime.
Therefore we can assert that the restoration of the cursor succeeds. */
- ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
+ ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_TREE,
+ pcur, mtr));
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(index->table)));
- err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
- &heap, &big_rec, node->update,
- node->cmpl_info, thr, mtr);
- mtr_commit(mtr);
-
- if (err == DB_SUCCESS && big_rec) {
+ err = btr_cur_pessimistic_update(
+ BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur,
+ &heap, &big_rec, node->update, node->cmpl_info, thr, mtr);
+ /* skip store extern for fake_changes */
+ if (big_rec && !(thr_get_trx(thr)->fake_changes)) {
ulint offsets_[REC_OFFS_NORMAL_SIZE];
rec_t* rec;
rec_offs_init(offsets_);
- mtr_start(mtr);
+ ut_a(err == DB_SUCCESS);
+ /* Write out the externally stored columns while still
+ x-latching index->lock and block->lock. We have to
+ mtr_commit(mtr) first, so that the redo log will be
+ written in the correct order. Otherwise, we would run
+ into trouble on crash recovery if mtr freed B-tree
+ pages on which some of the big_rec fields will be
+ written. */
+ btr_cur_mtr_commit_and_start(btr_cur, mtr);
- ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
rec = btr_cur_get_rec(btr_cur);
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(btr_cur), rec,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
mtr, TRUE, big_rec);
- mtr_commit(mtr);
+ /* If writing big_rec fails (for example, because of
+ DB_OUT_OF_FILE_SPACE), the record will be corrupted.
+ Even if we did not update any externally stored
+ columns, our update could cause the record to grow so
+ that a non-updated column was selected for external
+ storage. This non-update would not have been written
+ to the undo log, and thus the record cannot be rolled
+ back. */
+ ut_a(err == DB_SUCCESS);
}
+ mtr_commit(mtr);
+
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -2082,7 +2137,8 @@ row_upd_clust_step(
ut_a(pcur->rel_pos == BTR_PCUR_ON);
- success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
+ success = btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
+ pcur, mtr);
if (!success) {
err = DB_RECORD_NOT_FOUND;
diff --git a/storage/xtradb/row/row0vers.c b/storage/xtradb/row/row0vers.c
index d4fde0b939b..8a7bb842293 100644
--- a/storage/xtradb/row/row0vers.c
+++ b/storage/xtradb/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 */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(
+ version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_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);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(prev_version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
trx_id = row_get_rec_trx_id(prev_version, index, *offsets);
if (read_view_sees_trx_id(view, trx_id)) {
@@ -682,6 +691,10 @@ row_vers_build_for_semi_consistent_read(
/* We found a version that belongs to a
committed transaction: return it. */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (rec == version) {
*old_vers = rec;
err = DB_SUCCESS;
@@ -739,6 +752,9 @@ row_vers_build_for_semi_consistent_read(
version = prev_version;
*offsets = rec_get_offsets(version, index, *offsets,
ULINT_UNDEFINED, offset_heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
}/* for (;;) */
if (heap) {
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index f39d1b8a758..2ff729efbb1 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -86,6 +86,11 @@ Created 10/8/1995 Heikki Tuuri
#include "trx0i_s.h"
#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
+/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
+ibool innobase_thd_is_idle(const void* thd);
+ib_int64_t innobase_thd_get_start_time(const void* thd);
+void innobase_thd_kill(void* thd);
+
/* prototypes for new functions added to ha_innodb.cc */
ibool innobase_get_slow_log();
@@ -100,6 +105,9 @@ UNIV_INTERN ulint srv_activity_count = 0;
/* The following is the maximum allowed duration of a lock wait. */
UNIV_INTERN ulint srv_fatal_semaphore_wait_threshold = 600;
+/**/
+UNIV_INTERN lint srv_kill_idle_transaction = 0;
+
/* How much data manipulation language (DML) statements need to be delayed,
in microseconds, in order to reduce the lagging of the purge thread. */
UNIV_INTERN ulint srv_dml_needed_delay = 0;
@@ -211,17 +219,15 @@ UNIV_INTERN ulint srv_buf_pool_curr_size = 0;
UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX;
UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;
-/* key value for shm */
-UNIV_INTERN uint srv_buffer_pool_shm_key = 0;
-UNIV_INTERN ibool srv_buffer_pool_shm_is_reused = FALSE;
-UNIV_INTERN ibool srv_buffer_pool_shm_checksum = TRUE;
-
/* This parameter is deprecated. Use srv_n_io_[read|write]_threads
instead. */
UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX;
+/* Switch to enable random read ahead. */
+UNIV_INTERN my_bool srv_random_read_ahead = FALSE;
+
/* The universal page size of the database */
UNIV_INTERN ulint srv_page_size_shift = 0;
UNIV_INTERN ulint srv_page_size = 0;
@@ -320,6 +326,9 @@ UNIV_INTERN ulint srv_buf_pool_reads = 0;
/** Time in seconds between automatic buffer pool dumps */
UNIV_INTERN uint srv_auto_lru_dump = 0;
+/** Whether startup should be blocked until buffer pool is fully restored */
+UNIV_INTERN ibool srv_blocking_lru_restore;
+
/* structure to pass status variables to MySQL */
UNIV_INTERN export_struc export_vars;
@@ -2153,6 +2162,8 @@ srv_export_innodb_status(void)
export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free;
export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
+ export_vars.innodb_buffer_pool_read_ahead_rnd
+ = buf_pool->stat.n_ra_pages_read_rnd;
export_vars.innodb_buffer_pool_read_ahead
= buf_pool->stat.n_ra_pages_read;
export_vars.innodb_buffer_pool_read_ahead_evicted
@@ -2485,6 +2496,12 @@ srv_error_monitor_thread(
ulint fatal_cnt = 0;
ib_uint64_t old_lsn;
ib_uint64_t new_lsn;
+ /* 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;
@@ -2533,7 +2550,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) {
@@ -2548,6 +2566,38 @@ loop:
}
} else {
fatal_cnt = 0;
+ old_waiter = waiter;
+ old_sema = sema;
+ }
+
+ if (srv_kill_idle_transaction && trx_sys) {
+ trx_t* trx;
+ time_t now;
+rescan_idle:
+ now = time(NULL);
+ mutex_enter(&kernel_mutex);
+ trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
+ while (trx) {
+ if (trx->conc_state == TRX_ACTIVE
+ && trx->mysql_thd
+ && innobase_thd_is_idle(trx->mysql_thd)) {
+ ib_int64_t start_time; /* as stmt ID */
+
+ start_time = innobase_thd_get_start_time(trx->mysql_thd);
+ if (trx->last_stmt_start != start_time) {
+ trx->idle_start = now;
+ trx->last_stmt_start = start_time;
+ } else if (difftime(now, trx->idle_start)
+ > srv_kill_idle_transaction) {
+ /* kill the session */
+ mutex_exit(&kernel_mutex);
+ innobase_thd_kill(trx->mysql_thd);
+ goto rescan_idle;
+ }
+ }
+ trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
+ }
+ mutex_exit(&kernel_mutex);
}
/* Flush stderr so that a database user gets the output
@@ -2593,7 +2643,9 @@ srv_LRU_dump_restore_thread(
os_thread_pf(os_thread_get_curr_id()));
#endif
- if (srv_auto_lru_dump)
+ /* If srv_blocking_lru_restore is TRUE, restore will be done
+ synchronously on startup. */
+ if (srv_auto_lru_dump && !srv_blocking_lru_restore)
buf_LRU_file_restore();
last_dump_time = time(NULL);
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index cef045d72e1..ba4328c80e1 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -88,6 +88,7 @@ Created 2/16/1996 Heikki Tuuri
# include "thr0loc.h"
# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
# include "zlib.h" /* for ZLIB_VERSION */
+# include "buf0lru.h" /* for buf_LRU_file_restore() */
/** Log sequence number immediately after startup */
UNIV_INTERN ib_uint64_t srv_start_lsn;
@@ -126,9 +127,9 @@ static mutex_t ios_mutex;
static ulint ios;
/** io_handler_thread parameters for thread identification */
-static ulint n[SRV_MAX_N_IO_THREADS + 7 + 64];
+static ulint n[SRV_MAX_N_IO_THREADS + 7 + UNIV_MAX_PARALLELISM];
/** io_handler_thread identifiers */
-static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7 + 64];
+static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7 + UNIV_MAX_PARALLELISM];
/** We use this mutex to test the return value of pthread_mutex_trylock
on successful locking. HP-UX does NOT return 0, though Linux et al do. */
@@ -1200,6 +1201,12 @@ innobase_start_or_create_for_mysql(void)
);
#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
fprintf(stderr,
"InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!\n");
@@ -1744,8 +1751,6 @@ innobase_start_or_create_for_mysql(void)
Note that this is not as heavy weight as it seems. At
this point there will be only ONE page in the buf_LRU
and there must be no page in the buf_flush list. */
- /* buffer_pool_shm should not be reused when recovery was needed. */
- if (!srv_buffer_pool_shm_is_reused)
buf_pool_invalidate();
/* We always try to do a recovery, even if the database had
@@ -1875,6 +1880,11 @@ innobase_start_or_create_for_mysql(void)
os_thread_create(&srv_LRU_dump_restore_thread, NULL,
thread_ids + 5 + SRV_MAX_N_IO_THREADS);
+ /* If srv_blocking_lru_restore is TRUE, load buffer pool contents
+ synchronously */
+ if (srv_auto_lru_dump && srv_blocking_lru_restore)
+ buf_LRU_file_restore();
+
srv_is_being_started = FALSE;
if (trx_doublewrite == NULL) {
diff --git a/storage/xtradb/sync/sync0arr.c b/storage/xtradb/sync/sync0arr.c
index 57a288089c7..4e788b4a968 100644
--- a/storage/xtradb/sync/sync0arr.c
+++ b/storage/xtradb/sync/sync0arr.c
@@ -913,8 +913,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;
@@ -922,24 +924,40 @@ sync_array_print_long_waits(void)
ulint i;
ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
ibool fatal = FALSE;
+ double longest_diff = 0;
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 > 240) {
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) {
diff --git a/storage/xtradb/sync/sync0rw.c b/storage/xtradb/sync/sync0rw.c
index 9431de15fda..fe000e7d008 100644
--- a/storage/xtradb/sync/sync0rw.c
+++ b/storage/xtradb/sync/sync0rw.c
@@ -261,6 +261,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);
@@ -762,7 +765,9 @@ rw_lock_add_debug_info(
rw_lock_debug_mutex_exit();
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
- sync_thread_add_level(lock, lock->level);
+ sync_thread_add_level(lock, lock->level,
+ lock_type == RW_LOCK_EX
+ && lock->lock_word < 0);
}
}
diff --git a/storage/xtradb/sync/sync0sync.c b/storage/xtradb/sync/sync0sync.c
index 3a80da9318b..277a53e4fb2 100644
--- a/storage/xtradb/sync/sync0sync.c
+++ b/storage/xtradb/sync/sync0sync.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, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -668,7 +668,7 @@ mutex_set_debug_info(
ut_ad(mutex);
ut_ad(file_name);
- sync_thread_add_level(mutex, mutex->level);
+ sync_thread_add_level(mutex, mutex->level, FALSE);
mutex->file_name = file_name;
mutex->line = line;
@@ -1094,8 +1094,9 @@ void
sync_thread_add_level(
/*==================*/
void* latch, /*!< in: pointer to a mutex or an rw-lock */
- ulint level) /*!< in: level in the latching order; if
+ ulint level, /*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
+ ibool relock) /*!< in: TRUE if re-entering an x-lock */
{
sync_level_t* array;
sync_level_t* slot;
@@ -1143,6 +1144,10 @@ sync_thread_add_level(
array = thread_slot->levels;
+ if (relock) {
+ goto levels_ok;
+ }
+
/* NOTE that there is a problem with _NODE and _LEAF levels: if the
B-tree height changes, then a leaf can change to an internal node
or the other way around. We do not know at present if this can cause
@@ -1287,6 +1292,7 @@ sync_thread_add_level(
ut_error;
}
+levels_ok:
for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
slot = sync_thread_levels_get_nth(array, i);
diff --git a/storage/xtradb/trx/trx0i_s.c b/storage/xtradb/trx/trx0i_s.c
index e148234888b..5cc9df2d5c4 100644
--- a/storage/xtradb/trx/trx0i_s.c
+++ b/storage/xtradb/trx/trx0i_s.c
@@ -504,7 +504,7 @@ 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);
diff --git a/storage/xtradb/trx/trx0rec.c b/storage/xtradb/trx/trx0rec.c
index 71629f01d73..a7a393d31c8 100644
--- a/storage/xtradb/trx/trx0rec.c
+++ b/storage/xtradb/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
@@ -1590,6 +1590,10 @@ trx_undo_prev_version_build(
return(DB_ERROR);
}
+# if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+ ut_a(!rec_offs_any_null_extern(rec, offsets));
+# endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint n_ext;
diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c
index a9fb5bb38d8..b5bec64ee37 100644
--- a/storage/xtradb/trx/trx0sys.c
+++ b/storage/xtradb/trx/trx0sys.c
@@ -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"
@@ -1872,10 +1873,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. */
@@ -1907,6 +1910,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/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c
index 98bd9e4ac58..bf042db4972 100644
--- a/storage/xtradb/trx/trx0trx.c
+++ b/storage/xtradb/trx/trx0trx.c
@@ -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;
/*************************************************************//**
Set detailed error message for the transaction. */
@@ -111,6 +114,8 @@ trx_create(
trx->flush_log_at_trx_commit_session = 3; /* means to use innodb_flush_log_at_trx_commit value */
+ trx->fake_changes = FALSE;
+
trx->check_foreigns = TRUE;
trx->check_unique_secondary = TRUE;
@@ -134,6 +139,9 @@ trx_create(
trx->mysql_relay_log_file_name = "";
trx->mysql_relay_log_pos = 0;
+ trx->idle_start = 0;
+ trx->last_stmt_start = 0;
+
mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
trx->rseg = NULL;
@@ -354,6 +362,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
@@ -495,6 +557,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"
@@ -573,6 +636,7 @@ trx_lists_init_at_db_start(void)
trx->conc_state
= TRX_PREPARED;
+ trx_n_prepared++;
} else {
fprintf(stderr,
"InnoDB: Since"
@@ -878,6 +942,11 @@ trx_commit_off_kernel(
|| 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
@@ -1945,6 +2014,7 @@ trx_prepare_off_kernel(
/*--------------------------------------*/
trx->conc_state = TRX_PREPARED;
+ trx_n_prepared++;
/*--------------------------------------*/
if (lsn) {
@@ -2127,10 +2197,11 @@ trx_get_trx_by_xid(
while (trx) {
/* Compare two X/Open XA transaction id's: their
length should be the same and binary comparison
- of gtrid_lenght+bqual_length bytes should be
+ of gtrid_length+bqual_length bytes should be
the same */
- if (trx->conc_state == TRX_PREPARED
+ 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,
diff --git a/storage/xtradb/trx/trx0undo.c b/storage/xtradb/trx/trx0undo.c
index 9ed83b5d5c1..ec1cd2d2c43 100644
--- a/storage/xtradb/trx/trx0undo.c
+++ b/storage/xtradb/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"
@@ -2014,4 +2015,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/xtradb/ut/ut0mem.c b/storage/xtradb/ut/ut0mem.c
index bf55e4273b6..95fb2187b79 100644
--- a/storage/xtradb/ut/ut0mem.c
+++ b/storage/xtradb/ut/ut0mem.c
@@ -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
@@ -489,53 +489,6 @@ ut_strlcpy_rev(
return(src_size);
}
-/**********************************************************************//**
-Make a quoted copy of a NUL-terminated string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_memcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_strcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src) /*!< in: null-terminated string */
-{
- while (*src) {
- if ((*dest++ = *src++) == q) {
- *dest++ = q;
- }
- }
-
- return(dest);
-}
-
-/**********************************************************************//**
-Make a quoted copy of a fixed-length string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_strcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_memcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src, /*!< in: string to be quoted */
- ulint len) /*!< in: length of src */
-{
- const char* srcend = src + len;
-
- while (src < srcend) {
- if ((*dest++ = *src++) == q) {
- *dest++ = q;
- }
- }
-
- return(dest);
-}
-
#ifndef UNIV_HOTBACKUP
/**********************************************************************//**
Return the number of times s2 occurs in s1. Overlapping instances of s2