summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-09-16 14:03:17 +0200
committerSergei Golubchik <sergii@pisem.net>2014-09-16 14:03:17 +0200
commit7e29c1b53968914f42300a7f628088b99601f4db (patch)
treed9b55e33bd83a02251cd8a3fe560ef149c7b21ca
parent1e3e81a6c9971a56c94086227aa438d133172863 (diff)
parent33656e042dc7e983c9612a011fdef64a8dd40aa1 (diff)
downloadmariadb-git-7e29c1b53968914f42300a7f628088b99601f4db.tar.gz
5.5 merge
-rw-r--r--.bzrignore8
-rw-r--r--CMakeLists.txt6
-rw-r--r--client/mysql.cc2
-rw-r--r--cmake/build_configurations/mysql_release.cmake7
-rw-r--r--cmake/jemalloc.cmake65
-rw-r--r--cmake/readline.cmake68
-rw-r--r--cmd-line-utils/readline/CMakeLists.txt3
-rw-r--r--cmd-line-utils/readline/history.h4
-rw-r--r--cmd-line-utils/readline/keymaps.h6
-rw-r--r--cmd-line-utils/readline/readline.h8
-rw-r--r--cmd-line-utils/readline/xmalloc.h2
-rw-r--r--debian/dist/Debian/control6
-rw-r--r--debian/dist/Ubuntu/control6
-rw-r--r--extra/jemalloc/COPYING27
-rw-r--r--extra/jemalloc/ChangeLog434
-rw-r--r--extra/jemalloc/INSTALL293
-rw-r--r--extra/jemalloc/Makefile.in324
-rw-r--r--extra/jemalloc/README16
-rw-r--r--extra/jemalloc/VERSION1
-rwxr-xr-xextra/jemalloc/autogen.sh17
-rw-r--r--extra/jemalloc/bin/jemalloc.sh9
-rw-r--r--extra/jemalloc/bin/jemalloc.sh.in9
-rwxr-xr-xextra/jemalloc/bin/pprof5348
-rwxr-xr-xextra/jemalloc/config.guess1530
-rw-r--r--extra/jemalloc/config.stamp.in0
-rwxr-xr-xextra/jemalloc/config.sub1773
-rwxr-xr-xextra/jemalloc/configure8339
-rw-r--r--extra/jemalloc/configure.ac1333
-rw-r--r--extra/jemalloc/doc/html.xsl.in4
-rw-r--r--extra/jemalloc/doc/jemalloc.31482
-rw-r--r--extra/jemalloc/doc/jemalloc.html1417
-rw-r--r--extra/jemalloc/doc/jemalloc.xml.in2176
-rw-r--r--extra/jemalloc/doc/manpages.xsl.in4
-rw-r--r--extra/jemalloc/doc/stylesheet.xsl7
-rw-r--r--extra/jemalloc/include/jemalloc/internal/arena.h1038
-rw-r--r--extra/jemalloc/include/jemalloc/internal/atomic.h304
-rw-r--r--extra/jemalloc/include/jemalloc/internal/base.h26
-rw-r--r--extra/jemalloc/include/jemalloc/internal/bitmap.h184
-rw-r--r--extra/jemalloc/include/jemalloc/internal/chunk.h63
-rw-r--r--extra/jemalloc/include/jemalloc/internal/chunk_dss.h38
-rw-r--r--extra/jemalloc/include/jemalloc/internal/chunk_mmap.h22
-rw-r--r--extra/jemalloc/include/jemalloc/internal/ckh.h88
-rw-r--r--extra/jemalloc/include/jemalloc/internal/ctl.h117
-rw-r--r--extra/jemalloc/include/jemalloc/internal/extent.h46
-rw-r--r--extra/jemalloc/include/jemalloc/internal/hash.h331
-rw-r--r--extra/jemalloc/include/jemalloc/internal/huge.h40
-rw-r--r--extra/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in1030
-rw-r--r--extra/jemalloc/include/jemalloc/internal/mb.h115
-rw-r--r--extra/jemalloc/include/jemalloc/internal/mutex.h99
-rw-r--r--extra/jemalloc/include/jemalloc/internal/private_namespace.h392
-rw-r--r--extra/jemalloc/include/jemalloc/internal/prng.h60
-rw-r--r--extra/jemalloc/include/jemalloc/internal/prof.h579
-rw-r--r--extra/jemalloc/include/jemalloc/internal/ql.h83
-rw-r--r--extra/jemalloc/include/jemalloc/internal/qr.h67
-rw-r--r--extra/jemalloc/include/jemalloc/internal/quarantine.h67
-rw-r--r--extra/jemalloc/include/jemalloc/internal/rb.h973
-rw-r--r--extra/jemalloc/include/jemalloc/internal/rtree.h164
-rwxr-xr-xextra/jemalloc/include/jemalloc/internal/size_classes.sh122
-rw-r--r--extra/jemalloc/include/jemalloc/internal/stats.h173
-rw-r--r--extra/jemalloc/include/jemalloc/internal/tcache.h442
-rw-r--r--extra/jemalloc/include/jemalloc/internal/tsd.h397
-rw-r--r--extra/jemalloc/include/jemalloc/internal/util.h160
-rw-r--r--extra/jemalloc/include/jemalloc/jemalloc.h.in157
-rw-r--r--extra/jemalloc/include/jemalloc/jemalloc_defs.h.in267
-rw-r--r--extra/jemalloc/include/msvc_compat/inttypes.h313
-rw-r--r--extra/jemalloc/include/msvc_compat/stdbool.h16
-rw-r--r--extra/jemalloc/include/msvc_compat/stdint.h247
-rw-r--r--extra/jemalloc/include/msvc_compat/strings.h23
-rwxr-xr-xextra/jemalloc/install-sh250
-rw-r--r--extra/jemalloc/src/arena.c2385
-rw-r--r--extra/jemalloc/src/atomic.c2
-rw-r--r--extra/jemalloc/src/base.c142
-rw-r--r--extra/jemalloc/src/bitmap.c90
-rw-r--r--extra/jemalloc/src/chunk.c385
-rw-r--r--extra/jemalloc/src/chunk_dss.c197
-rw-r--r--extra/jemalloc/src/chunk_mmap.c210
-rw-r--r--extra/jemalloc/src/ckh.c563
-rw-r--r--extra/jemalloc/src/ctl.c1673
-rw-r--r--extra/jemalloc/src/extent.c39
-rw-r--r--extra/jemalloc/src/hash.c2
-rw-r--r--extra/jemalloc/src/huge.c313
-rw-r--r--extra/jemalloc/src/jemalloc.c1868
-rw-r--r--extra/jemalloc/src/mb.c2
-rw-r--r--extra/jemalloc/src/mutex.c149
-rw-r--r--extra/jemalloc/src/prof.c1283
-rw-r--r--extra/jemalloc/src/quarantine.c190
-rw-r--r--extra/jemalloc/src/rtree.c67
-rw-r--r--extra/jemalloc/src/stats.c549
-rw-r--r--extra/jemalloc/src/tcache.c476
-rw-r--r--extra/jemalloc/src/tsd.c107
-rw-r--r--extra/jemalloc/src/util.c641
-rw-r--r--extra/jemalloc/src/zone.c258
-rw-r--r--extra/jemalloc/test/ALLOCM_ARENA.c67
-rw-r--r--extra/jemalloc/test/ALLOCM_ARENA.exp2
-rw-r--r--extra/jemalloc/test/aligned_alloc.c119
-rw-r--r--extra/jemalloc/test/aligned_alloc.exp25
-rw-r--r--extra/jemalloc/test/allocated.c118
-rw-r--r--extra/jemalloc/test/allocated.exp2
-rw-r--r--extra/jemalloc/test/allocm.c194
-rw-r--r--extra/jemalloc/test/allocm.exp25
-rw-r--r--extra/jemalloc/test/bitmap.c153
-rw-r--r--extra/jemalloc/test/bitmap.exp2
-rw-r--r--extra/jemalloc/test/jemalloc_test.h.in53
-rw-r--r--extra/jemalloc/test/mremap.c60
-rw-r--r--extra/jemalloc/test/mremap.exp2
-rw-r--r--extra/jemalloc/test/posix_memalign.c115
-rw-r--r--extra/jemalloc/test/posix_memalign.exp25
-rw-r--r--extra/jemalloc/test/rallocm.c127
-rw-r--r--extra/jemalloc/test/rallocm.exp2
-rw-r--r--extra/jemalloc/test/thread_arena.c81
-rw-r--r--extra/jemalloc/test/thread_arena.exp2
-rw-r--r--extra/jemalloc/test/thread_tcache_enabled.c91
-rw-r--r--extra/jemalloc/test/thread_tcache_enabled.exp2
-rw-r--r--include/myisam.h6
-rw-r--r--mysql-test/disabled.def1
-rw-r--r--mysql-test/include/mysqlhotcopy.inc2
-rw-r--r--mysql-test/r/derived_view.result88
-rw-r--r--mysql-test/r/join_cache.result152
-rw-r--r--mysql-test/r/join_nested_jcl6.result6
-rw-r--r--mysql-test/r/join_outer_jcl6.result2
-rw-r--r--mysql-test/r/kill_processlist-6619.result14
-rw-r--r--mysql-test/r/sp-bugs.result6
-rw-r--r--mysql-test/r/variables.result9
-rw-r--r--mysql-test/t/derived_view.test93
-rw-r--r--mysql-test/t/join_cache.test132
-rw-r--r--mysql-test/t/kill_processlist-6619.test17
-rw-r--r--mysql-test/t/sp-bugs.test13
-rw-r--r--mysql-test/t/variables.test8
-rw-r--r--plugin/auth_socket/CMakeLists.txt53
-rw-r--r--plugin/auth_socket/auth_socket.c26
-rw-r--r--scripts/mysqlhotcopy.sh3
-rw-r--r--sql/ha_partition.cc5
-rw-r--r--sql/handler.cc11
-rw-r--r--sql/sp_head.cc6
-rw-r--r--sql/sql_join_cache.cc2
-rw-r--r--sql/sql_select.cc47
-rw-r--r--sql/sql_show.cc132
-rw-r--r--sql/table.cc47
-rw-r--r--sql/table.h2
-rw-r--r--storage/innobase/include/os0sync.h5
-rw-r--r--storage/tokudb/CMakeLists.txt37
-rw-r--r--storage/tokudb/README.md8
-rw-r--r--storage/tokudb/ft-index/CMakeLists.txt8
-rw-r--r--storage/tokudb/ft-index/CTestCustom.cmake.in244
-rw-r--r--storage/tokudb/ft-index/buildheader/CMakeLists.txt2
-rw-r--r--storage/tokudb/ft-index/buildheader/make_tdb.cc11
-rw-r--r--storage/tokudb/ft-index/cmake/merge_archives_unix.cmake.in49
-rw-r--r--storage/tokudb/ft-index/cmake_modules/TokuBuildTagDatabases.cmake6
-rw-r--r--storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake2
-rw-r--r--storage/tokudb/ft-index/ft/CMakeLists.txt3
-rw-r--r--storage/tokudb/ft-index/ft/background_job_manager.cc5
-rw-r--r--storage/tokudb/ft-index/ft/block_table.cc6
-rw-r--r--storage/tokudb/ft-index/ft/bndata.cc642
-rw-r--r--storage/tokudb/ft-index/ft/bndata.h290
-rw-r--r--storage/tokudb/ft-index/ft/cachetable.cc83
-rw-r--r--storage/tokudb/ft-index/ft/cachetable.h45
-rw-r--r--storage/tokudb/ft-index/ft/checksum-benchmarks/adler32.cc236
-rw-r--r--storage/tokudb/ft-index/ft/compression-ratio/cratio.cc195
-rw-r--r--storage/tokudb/ft-index/ft/fifo.cc7
-rw-r--r--storage/tokudb/ft-index/ft/fifo.h15
-rw-r--r--storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc159
-rw-r--r--storage/tokudb/ft-index/ft/ft-cachetable-wrappers.h83
-rw-r--r--storage/tokudb/ft-index/ft/ft-flusher.cc105
-rw-r--r--storage/tokudb/ft-index/ft/ft-flusher.h4
-rw-r--r--storage/tokudb/ft-index/ft/ft-hot-flusher.cc37
-rw-r--r--storage/tokudb/ft-index/ft/ft-internal.h78
-rw-r--r--storage/tokudb/ft-index/ft/ft-node-deserialize.cc4
-rw-r--r--storage/tokudb/ft-index/ft/ft-ops.cc1251
-rw-r--r--storage/tokudb/ft-index/ft/ft-ops.h75
-rw-r--r--storage/tokudb/ft-index/ft/ft-serialize.cc12
-rw-r--r--storage/tokudb/ft-index/ft/ft-test-helpers.cc81
-rw-r--r--storage/tokudb/ft-index/ft/ft-verify.cc110
-rw-r--r--storage/tokudb/ft-index/ft/ft.cc78
-rw-r--r--storage/tokudb/ft-index/ft/ft.h6
-rw-r--r--storage/tokudb/ft-index/ft/ft_layout_version.h8
-rw-r--r--storage/tokudb/ft-index/ft/ft_node-serialize.cc279
-rw-r--r--storage/tokudb/ft-index/ft/ftloader-internal.h28
-rw-r--r--storage/tokudb/ft-index/ft/ftloader.cc54
-rw-r--r--storage/tokudb/ft-index/ft/ftloader.h14
-rw-r--r--storage/tokudb/ft-index/ft/fttypes.h10
-rw-r--r--storage/tokudb/ft-index/ft/ftverify.cc1
-rw-r--r--storage/tokudb/ft-index/ft/hash-benchmarks/hash-benchmark-manually-open.cc378
-rw-r--r--storage/tokudb/ft-index/ft/hash-benchmarks/hash-benchmark.cc1205
-rw-r--r--storage/tokudb/ft-index/ft/le-cursor.h4
-rw-r--r--storage/tokudb/ft-index/ft/leafentry.h3
-rw-r--r--storage/tokudb/ft-index/ft/locking-benchmarks/mfence-benchmark.cc217
-rw-r--r--storage/tokudb/ft-index/ft/locking-benchmarks/process_locks.cc233
-rw-r--r--storage/tokudb/ft-index/ft/locking-benchmarks/pthread-locks.cc272
-rw-r--r--storage/tokudb/ft-index/ft/locking-benchmarks/trylock-rdtsc.cc (renamed from storage/tokudb/ft-index/src/tests/test_insert_unique.cc)245
-rw-r--r--storage/tokudb/ft-index/ft/locking-benchmarks/trylock.cc213
-rw-r--r--storage/tokudb/ft-index/ft/log-internal.h8
-rw-r--r--storage/tokudb/ft-index/ft/log.h9
-rw-r--r--storage/tokudb/ft-index/ft/log_upgrade.cc4
-rw-r--r--storage/tokudb/ft-index/ft/logcursor.cc3
-rw-r--r--storage/tokudb/ft-index/ft/logformat.cc18
-rw-r--r--storage/tokudb/ft-index/ft/logger.cc57
-rw-r--r--storage/tokudb/ft-index/ft/logger.h1
-rw-r--r--storage/tokudb/ft-index/ft/memarena.cc (renamed from storage/tokudb/ft-index/util/memarena.cc)60
-rw-r--r--storage/tokudb/ft-index/ft/memarena.h (renamed from storage/tokudb/ft-index/util/memarena.h)23
-rw-r--r--storage/tokudb/ft-index/ft/omt.cc230
-rw-r--r--storage/tokudb/ft-index/ft/omt.h416
-rw-r--r--storage/tokudb/ft-index/ft/quicklz.cc1
-rw-r--r--storage/tokudb/ft-index/ft/rbuf.h6
-rw-r--r--storage/tokudb/ft-index/ft/recover.cc93
-rw-r--r--storage/tokudb/ft-index/ft/recover.h4
-rw-r--r--storage/tokudb/ft-index/ft/roll.cc4
-rw-r--r--storage/tokudb/ft-index/ft/rollback-apply.cc24
-rw-r--r--storage/tokudb/ft-index/ft/rollback-apply.h2
-rw-r--r--storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc6
-rw-r--r--storage/tokudb/ft-index/ft/rollback.cc10
-rw-r--r--storage/tokudb/ft-index/ft/rollback_log_node_cache.cc2
-rw-r--r--storage/tokudb/ft-index/ft/sub_block.cc9
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-checkpoint-pending.cc4
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-test.cc8
-rw-r--r--storage/tokudb/ft-index/ft/tests/dmt-test2.cc373
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc76
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-clock-test.cc111
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc180
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-serialize-sub-block-test.cc22
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc411
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-test-cursor-2.cc10
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-test-cursor.cc166
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-test-header.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-test.cc118
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-bad-generate.cc6
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-extractor-errors.cc6
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc8
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-merge-files-dbufio.cc6
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc6
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-writer-errors.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-writer.cc6
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/is_empty.cc26
-rw-r--r--storage/tokudb/ft-index/ft/tests/keyrange.cc4
-rw-r--r--storage/tokudb/ft-index/ft/tests/le-cursor-provdel.cc18
-rw-r--r--storage/tokudb/ft-index/ft/tests/le-cursor-right.cc32
-rw-r--r--storage/tokudb/ft-index/ft/tests/le-cursor-walk.cc16
-rw-r--r--storage/tokudb/ft-index/ft/tests/make-tree.cc44
-rw-r--r--storage/tokudb/ft-index/ft/tests/mempool-115.cc14
-rw-r--r--storage/tokudb/ft-index/ft/tests/minicron-test.cc4
-rw-r--r--storage/tokudb/ft-index/ft/tests/msnfilter.cc64
-rw-r--r--storage/tokudb/ft-index/ft/tests/omt-test.cc (renamed from storage/tokudb/ft-index/ft/tests/dmt-test.cc)467
-rw-r--r--storage/tokudb/ft-index/ft/tests/orthopush-flush.cc28
-rw-r--r--storage/tokudb/ft-index/ft/tests/shortcut.cc12
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-checkpoint-during-flush.cc32
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-checkpoint-during-merge.cc44
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-checkpoint-during-rebalance.cc46
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-checkpoint-during-split.cc56
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-dirty-flushes-on-cleaner.cc90
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-flushes-on-cleaner.cc102
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-hot-with-bounds.cc14
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc16
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-merges-on-cleaner.cc70
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-oldest-referenced-xid-flush.cc21
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-pick-child-to-flush.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/test.h2
-rw-r--r--storage/tokudb/ft-index/ft/tests/test1308a.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/test3681.cc4
-rw-r--r--storage/tokudb/ft-index/ft/tests/test3884.cc67
-rw-r--r--storage/tokudb/ft-index/ft/tests/test4244.cc9
-rw-r--r--storage/tokudb/ft-index/ft/tests/test_logcursor.cc8
-rw-r--r--storage/tokudb/ft-index/ft/tests/test_rightmost_leaf_seqinsert_heuristic.cc183
-rw-r--r--storage/tokudb/ft-index/ft/tests/test_rightmost_leaf_split_merge.cc212
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc42
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc38
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-dup-in-leaf.cc28
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc38
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc44
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc28
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc38
-rw-r--r--storage/tokudb/ft-index/ft/tests/x1764-test.cc (renamed from storage/tokudb/ft-index/util/tests/x1764-test.cc)36
-rw-r--r--storage/tokudb/ft-index/ft/tests/xid_lsn_independent.cc8
-rw-r--r--storage/tokudb/ft-index/ft/tokuftdump.cc20
-rw-r--r--storage/tokudb/ft-index/ft/txn.cc7
-rw-r--r--storage/tokudb/ft-index/ft/txn.h2
-rw-r--r--storage/tokudb/ft-index/ft/txn_manager.cc21
-rw-r--r--storage/tokudb/ft-index/ft/ule-internal.h3
-rw-r--r--storage/tokudb/ft-index/ft/ule.cc83
-rw-r--r--storage/tokudb/ft-index/ft/wbuf.h19
-rw-r--r--storage/tokudb/ft-index/ft/worker-thread-benchmarks/threadpool.cc166
-rw-r--r--storage/tokudb/ft-index/ft/worker-thread-benchmarks/threadpool.h136
-rw-r--r--storage/tokudb/ft-index/ft/worker-thread-benchmarks/worker-test.cc261
-rw-r--r--storage/tokudb/ft-index/ft/worker-thread-benchmarks/worker-test.cilk74
-rw-r--r--storage/tokudb/ft-index/ft/worker-thread-benchmarks/workqueue.h207
-rw-r--r--storage/tokudb/ft-index/ft/x1764-speedup/x1764-speedup-test.cc175
-rw-r--r--storage/tokudb/ft-index/ft/x1764.cc (renamed from storage/tokudb/ft-index/util/x1764.cc)12
-rw-r--r--storage/tokudb/ft-index/ft/x1764.h (renamed from storage/tokudb/ft-index/util/x1764.h)12
-rw-r--r--storage/tokudb/ft-index/ft/xids-internal.h10
-rw-r--r--storage/tokudb/ft-index/ft/xids.h2
-rw-r--r--storage/tokudb/ft-index/include/CMakeLists.txt5
-rw-r--r--storage/tokudb/ft-index/include/tdb-internal.h110
-rw-r--r--storage/tokudb/ft-index/locktree/lock_request.cc2
-rw-r--r--storage/tokudb/ft-index/locktree/lock_request.h2
-rw-r--r--storage/tokudb/ft-index/locktree/locktree.cc130
-rw-r--r--storage/tokudb/ft-index/locktree/locktree.h692
-rw-r--r--storage/tokudb/ft-index/locktree/manager.cc238
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc17
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_not_killed.cc17
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_start_deadlock.cc30
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_start_pending.cc23
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_wait_time_callback.cc16
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc25
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_create_destroy.cc25
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_1big7lt_1small.cc31
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_1lt.cc8
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_2lt.cc8
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc4
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc10
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc55
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_misc.cc28
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc31
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_simple_lock.cc6
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_single_txnid_optimization.cc23
-rw-r--r--storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc13
-rw-r--r--storage/tokudb/ft-index/locktree/tests/manager_locktree_map.cc2
-rw-r--r--storage/tokudb/ft-index/locktree/tests/manager_params.cc2
-rw-r--r--storage/tokudb/ft-index/locktree/tests/manager_reference_release_lt.cc2
-rw-r--r--storage/tokudb/ft-index/locktree/tests/manager_status.cc3
-rw-r--r--storage/tokudb/ft-index/locktree/tests/range_buffer_test.cc2
-rw-r--r--storage/tokudb/ft-index/portability/CMakeLists.txt11
-rw-r--r--storage/tokudb/ft-index/portability/huge_page_detection.cc26
-rw-r--r--storage/tokudb/ft-index/portability/huge_page_detection.h96
-rw-r--r--storage/tokudb/ft-index/portability/memory.cc40
-rw-r--r--storage/tokudb/ft-index/portability/os_malloc.cc2
-rw-r--r--storage/tokudb/ft-index/portability/portability.cc2
-rw-r--r--storage/tokudb/ft-index/portability/tests/test-cache-line-boundary-fails.cc8
-rw-r--r--storage/tokudb/ft-index/portability/tests/test-fsync.cc4
-rw-r--r--storage/tokudb/ft-index/portability/tests/test-hugepage.cc10
-rw-r--r--storage/tokudb/ft-index/portability/tests/test-xid.cc2
-rw-r--r--storage/tokudb/ft-index/portability/toku_assert.cc86
-rw-r--r--storage/tokudb/ft-index/portability/toku_atomic.h3
-rw-r--r--storage/tokudb/ft-index/portability/toku_byteswap.h2
-rw-r--r--storage/tokudb/ft-index/portability/toku_crash.h7
-rw-r--r--storage/tokudb/ft-index/portability/toku_htonl.h1
-rw-r--r--storage/tokudb/ft-index/portability/toku_os_types.h2
-rw-r--r--storage/tokudb/ft-index/portability/toku_pthread.cc2
-rw-r--r--storage/tokudb/ft-index/portability/toku_pthread.h15
-rw-r--r--storage/tokudb/ft-index/portability/toku_random.h2
-rw-r--r--storage/tokudb/ft-index/portability/toku_time.h2
-rwxr-xr-xstorage/tokudb/ft-index/scripts/run.stress-tests.py5
-rwxr-xr-xstorage/tokudb/ft-index/scripts/watch.stress-tests.bash2
-rw-r--r--storage/tokudb/ft-index/src/indexer-undo-do.cc10
-rw-r--r--storage/tokudb/ft-index/src/loader.cc12
-rw-r--r--storage/tokudb/ft-index/src/tests/CMakeLists.txt383
-rw-r--r--storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-detect.cc300
-rw-r--r--storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-nowait.cc177
-rw-r--r--storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-on-the-fly.cc292
-rw-r--r--storage/tokudb/ft-index/src/tests/bdb.suppressions87
-rw-r--r--storage/tokudb/ft-index/src/tests/big-nested-abort-abort.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/big-nested-abort-commit.cc3
-rw-r--r--storage/tokudb/ft-index/src/tests/big-nested-commit-abort.cc3
-rw-r--r--storage/tokudb/ft-index/src/tests/big-nested-commit-commit.cc5
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-first-empty.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-first.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-last.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-next-prev-deadlock.cc14
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-next-prev.cc10
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-prelock-range.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-put-timeout.cc23
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-put-wakeup.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-put.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-set-range-0.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-set-range-n.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-set-range-reverse-0.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-set.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-table-lock.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/checkpoint1.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/checkpoint_fairness.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/checkpoint_stress.cc7
-rw-r--r--storage/tokudb/ft-index/src/tests/cilktests/bar2.cilk22
-rw-r--r--storage/tokudb/ft-index/src/tests/cilktests/foo.cilk41
-rw-r--r--storage/tokudb/ft-index/src/tests/cilktests/foo2.cpp131
-rw-r--r--storage/tokudb/ft-index/src/tests/cilktests/get.cilk27
-rw-r--r--storage/tokudb/ft-index/src/tests/cilktests/measurecilkrun.cilk106
-rw-r--r--storage/tokudb/ft-index/src/tests/create-datadir.cc11
-rw-r--r--storage/tokudb/ft-index/src/tests/cursor-more-than-a-leaf-provdel.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/db-put-simple-deadlock-threads.cc12
-rw-r--r--storage/tokudb/ft-index/src/tests/db-put-simple-deadlock.cc15
-rw-r--r--storage/tokudb/ft-index/src/tests/db-put-simple-lockwait.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/db-put-update-deadlock.cc20
-rw-r--r--storage/tokudb/ft-index/src/tests/dump-env.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/filesize.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/hotindexer-undo-do-test.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/inflate.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/inflate2.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/loader-blobs-create-leaf.c.notyet149
-rw-r--r--storage/tokudb/ft-index/src/tests/loader-create-commit-nproc-limit.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/loader-nproc-close.cc (renamed from storage/tokudb/ft-index/src/tests/loader-close-nproc-limit.cc)0
-rw-r--r--storage/tokudb/ft-index/src/tests/loader-nproc-create.cc (renamed from storage/tokudb/ft-index/src/tests/loader-create-nproc-limit.cc)0
-rw-r--r--storage/tokudb/ft-index/src/tests/medium-nested-commit-commit.cc3
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-compare-db-descriptor.cc10
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-compare-db.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-fcreate-basementnodesize.cc7
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-fcreate-nodesize.cc7
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-missing-dbfile-2.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-missing-dbfile.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor-multihandle.cc10
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor.cc10
-rw-r--r--storage/tokudb/ft-index/src/tests/recovery_stress.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/root_fifo_2.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/rowsize.cc7
-rw-r--r--storage/tokudb/ft-index/src/tests/simple.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test-prepare.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test-prepare2.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test-prepare3.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test-xa-prepare.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test.h44
-rw-r--r--storage/tokudb/ft-index/src/tests/test1426.cc196
-rw-r--r--storage/tokudb/ft-index/src/tests/test1753.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test1842.cc5
-rw-r--r--storage/tokudb/ft-index/src/tests/test3039.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/test3219.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test4573-logtrim.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test5092.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test938.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test938c.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test_abort1.cc20
-rw-r--r--storage/tokudb/ft-index/src/tests/test_abort2.cc7
-rw-r--r--storage/tokudb/ft-index/src/tests/test_abort3.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_abort4.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_abort5.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_abort_delete_first.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/test_archive1.cc7
-rw-r--r--storage/tokudb/ft-index/src/tests/test_blobs_leaf_split.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_cachesize.cc9
-rw-r--r--storage/tokudb/ft-index/src/tests/test_cursor_delete2.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_dbt_mem_behavior.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_delete.cc13
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_env_open_nocreate.cc29
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_env_open_open_close.cc11
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_env_set_lg_dir.cc5
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_env_set_tmp_dir.cc5
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_env_strdup_null.cc3
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_get_put_flags.cc9
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_remove.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_txn_locks_nonheaviside.cc18
-rw-r--r--storage/tokudb/ft-index/src/tests/test_db_txn_locks_read_uncommitted.cc25
-rw-r--r--storage/tokudb/ft-index/src/tests/test_env_close_flags.cc10
-rw-r--r--storage/tokudb/ft-index/src/tests/test_env_create_db_create.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/test_env_open_flags.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/test_groupcommit_count.cc12
-rw-r--r--storage/tokudb/ft-index/src/tests/test_locktree_close.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test_log1.cc5
-rw-r--r--storage/tokudb/ft-index/src/tests/test_log10.cc11
-rw-r--r--storage/tokudb/ft-index/src/tests/test_log1_abort.cc8
-rw-r--r--storage/tokudb/ft-index/src/tests/test_log7.cc5
-rw-r--r--storage/tokudb/ft-index/src/tests/test_log8.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_log9.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_logflush.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_logmax.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_reverse_compare_fun.cc10
-rw-r--r--storage/tokudb/ft-index/src/tests/test_set_func_malloc.cc3
-rw-r--r--storage/tokudb/ft-index/src/tests/test_txn_abort7.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/test_txn_abort8.cc (renamed from storage/tokudb/ft-index/src/tests/test_equal_keys_with_different_bytes.cc)109
-rw-r--r--storage/tokudb/ft-index/src/tests/test_txn_abort9.cc162
-rw-r--r--storage/tokudb/ft-index/src/tests/test_txn_close_open_commit.cc168
-rw-r--r--storage/tokudb/ft-index/src/tests/test_txn_commit8.cc156
-rw-r--r--storage/tokudb/ft-index/src/tests/test_txn_cursor_last.cc10
-rw-r--r--storage/tokudb/ft-index/src/tests/test_txn_nested1.cc73
-rw-r--r--storage/tokudb/ft-index/src/tests/test_txn_nested_abort4.cc4
-rw-r--r--storage/tokudb/ft-index/src/tests/test_weakxaction.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/upgrade-test-1.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/xa-dirty-commit.cc193
-rw-r--r--storage/tokudb/ft-index/src/tests/xa-dirty-rollback.cc193
-rw-r--r--storage/tokudb/ft-index/src/tests/xa-txn-discard-abort.cc195
-rw-r--r--storage/tokudb/ft-index/src/tests/xa-txn-discard-commit.cc196
-rw-r--r--storage/tokudb/ft-index/src/ydb-internal.h11
-rw-r--r--storage/tokudb/ft-index/src/ydb.cc283
-rw-r--r--storage/tokudb/ft-index/src/ydb_cursor.cc19
-rw-r--r--storage/tokudb/ft-index/src/ydb_db.cc16
-rw-r--r--storage/tokudb/ft-index/src/ydb_db.h2
-rw-r--r--storage/tokudb/ft-index/src/ydb_lib.cc35
-rw-r--r--storage/tokudb/ft-index/src/ydb_load.h2
-rw-r--r--storage/tokudb/ft-index/src/ydb_row_lock.cc12
-rw-r--r--storage/tokudb/ft-index/src/ydb_txn.cc46
-rw-r--r--storage/tokudb/ft-index/src/ydb_write.cc108
-rw-r--r--storage/tokudb/ft-index/toku_include/CMakeLists.txt17
-rw-r--r--storage/tokudb/ft-index/toku_include/memory.h (renamed from storage/tokudb/ft-index/portability/memory.h)18
-rw-r--r--storage/tokudb/ft-index/toku_include/old-db.h276
-rw-r--r--storage/tokudb/ft-index/toku_include/rdtsc.h (renamed from storage/tokudb/ft-index/portability/rdtsc.h)0
-rw-r--r--storage/tokudb/ft-index/toku_include/toku_assert.h (renamed from storage/tokudb/ft-index/portability/toku_assert.h)16
-rw-r--r--storage/tokudb/ft-index/toku_include/toku_config.h.in (renamed from storage/tokudb/ft-index/portability/toku_config.h.in)0
-rw-r--r--storage/tokudb/ft-index/toku_include/toku_htod.h (renamed from storage/tokudb/ft-index/portability/toku_htod.h)2
-rw-r--r--storage/tokudb/ft-index/toku_include/toku_list.h (renamed from storage/tokudb/ft-index/portability/toku_list.h)0
-rw-r--r--storage/tokudb/ft-index/toku_include/toku_os.h (renamed from storage/tokudb/ft-index/portability/toku_os.h)13
-rw-r--r--storage/tokudb/ft-index/toku_include/toku_portability.h (renamed from storage/tokudb/ft-index/portability/toku_portability.h)93
-rw-r--r--storage/tokudb/ft-index/toku_include/toku_race_tools.h (renamed from storage/tokudb/ft-index/portability/toku_race_tools.h)2
-rw-r--r--storage/tokudb/ft-index/tools/CMakeLists.txt11
-rw-r--r--storage/tokudb/ft-index/util/CMakeLists.txt2
-rw-r--r--storage/tokudb/ft-index/util/context.h2
-rw-r--r--storage/tokudb/ft-index/util/dmt.cc1265
-rw-r--r--storage/tokudb/ft-index/util/dmt.h728
-rw-r--r--storage/tokudb/ft-index/util/doubly_linked_list.h2
-rw-r--r--storage/tokudb/ft-index/util/fmutex.h109
-rw-r--r--storage/tokudb/ft-index/util/kibbutz.cc6
-rw-r--r--storage/tokudb/ft-index/util/mempool.cc61
-rw-r--r--storage/tokudb/ft-index/util/mempool.h36
-rw-r--r--storage/tokudb/ft-index/util/omt.cc5
-rw-r--r--storage/tokudb/ft-index/util/scoped_malloc.cc2
-rw-r--r--storage/tokudb/ft-index/util/tests/omt-test.cc950
-rw-r--r--storage/tokudb/ft-index/utils/CMakeLists.txt21
-rwxr-xr-xstorage/tokudb/ft-index/utils/parseTraceFiles.py (renamed from storage/tokudb/ft-index/tools/parseTraceFiles.py)0
-rwxr-xr-xstorage/tokudb/ft-index/utils/pmprof (renamed from storage/tokudb/ft-index/tools/pmprof)0
-rw-r--r--storage/tokudb/ft-index/utils/tokudb_common.h (renamed from storage/tokudb/ft-index/tools/tokudb_common.h)0
-rw-r--r--storage/tokudb/ft-index/utils/tokudb_common_funcs.h (renamed from storage/tokudb/ft-index/tools/tokudb_common_funcs.h)14
-rw-r--r--storage/tokudb/ft-index/utils/tokudb_dump.cc (renamed from storage/tokudb/ft-index/tools/tokudb_dump.cc)9
-rw-r--r--storage/tokudb/ft-index/utils/tokudb_gen.cc (renamed from storage/tokudb/ft-index/tools/tokudb_gen.cc)7
-rw-r--r--storage/tokudb/ft-index/utils/tokudb_load.cc (renamed from storage/tokudb/ft-index/tools/tokudb_load.cc)0
-rw-r--r--storage/tokudb/ha_tokudb.cc218
-rw-r--r--storage/tokudb/ha_tokudb.h1
-rw-r--r--storage/tokudb/ha_tokudb_alter_56.cc50
-rw-r--r--storage/tokudb/hatoku_hton.cc45
-rw-r--r--storage/tokudb/hatoku_hton.h2
-rw-r--r--storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb/include/have_tokudb.inc1
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_create_select_hash_part.result328
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_create_select_nonpart.result242
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_create_select_range_part.result335
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_create_temp_select_nonpart.result242
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_delete_nonpart.result54
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_delete_trigger.result54
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_insert_select_dup_key_nonpart.result207
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_insert_select_nonpart.result205
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_insert_select_trigger.result45
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_insert_select_update_trigger.result121
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_replace_select_nonpart.result367
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_replace_select_trigger.result121
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bf_select_part.result543
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/information-schema-global-status.result2
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_create_select_hash_part.test143
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_create_select_nonpart.test118
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_create_select_range_part.test138
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_create_temp_select_nonpart.test118
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_delete_nonpart.test68
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_delete_trigger.test70
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_insert_select_dup_key_nonpart.test127
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_insert_select_nonpart.test122
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_insert_select_trigger.test65
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_insert_select_update_trigger.test170
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_replace_select_nonpart.test190
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_replace_select_trigger.test169
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bf_select_part.test220
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_mixed.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_statement.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_released.test6
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test3
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks_released.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/mdev5932.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/part_index_scan.result248
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/mdev5932.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/part_index_scan.test157
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/rpl_mixed_replace_into.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/rpl_row_replace_into.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/rpl_stmt_replace_into.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/xa-3.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/xa-4.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_mariadb/r/autoinc.result36
-rw-r--r--storage/tokudb/mysql-test/tokudb_mariadb/t/autoinc.test51
-rw-r--r--storage/tokudb/scripts/atc.ontime/atc_ontime_create.sql95
-rw-r--r--storage/tokudb/scripts/atc.ontime/atc_ontime_create_covered.sql103
-rw-r--r--storage/tokudb/scripts/atc.ontime/nodistinct.q8.sql2
-rw-r--r--storage/tokudb/scripts/atc.ontime/q0.result2
-rw-r--r--storage/tokudb/scripts/atc.ontime/q0.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q1.result8
-rw-r--r--storage/tokudb/scripts/atc.ontime/q1.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q2.result8
-rw-r--r--storage/tokudb/scripts/atc.ontime/q2.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q3.result11
-rw-r--r--storage/tokudb/scripts/atc.ontime/q3.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q4.result21
-rw-r--r--storage/tokudb/scripts/atc.ontime/q4.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q5.result21
-rw-r--r--storage/tokudb/scripts/atc.ontime/q5.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q6.result21
-rw-r--r--storage/tokudb/scripts/atc.ontime/q6.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q7.result22
-rw-r--r--storage/tokudb/scripts/atc.ontime/q7.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.10y.destcityname.result11
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.10y.destcityname.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.10y.result11
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.10y.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.1y.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.1y.year5.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.2y.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.3y.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.4y.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.result11
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q8.year5.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/q9.result22
-rw-r--r--storage/tokudb/scripts/atc.ontime/q9.sql1
-rw-r--r--storage/tokudb/scripts/atc.ontime/qcount.main.sql2
-rw-r--r--storage/tokudb/scripts/atc.ontime/qcount.result2
-rw-r--r--storage/tokudb/scripts/atc.ontime/qcount.sql1
-rw-r--r--storage/tokudb/scripts/atc.readme19
-rwxr-xr-xstorage/tokudb/scripts/nightly.mysql.build.and.test.bash58
-rw-r--r--storage/tokudb/scripts/nightly.mysql.build.and.test.my.cnf7
-rwxr-xr-xstorage/tokudb/scripts/run.atc.ontime.bash267
-rwxr-xr-xstorage/tokudb/scripts/run.iibench.bash172
-rwxr-xr-xstorage/tokudb/scripts/run.mysql.tests.bash196
-rwxr-xr-xstorage/tokudb/scripts/run.sql.bench.bash153
-rwxr-xr-xstorage/tokudb/scripts/run.tpch.bash342
-rwxr-xr-xstorage/tokudb/scripts/setup.mysql.bash231
-rwxr-xr-xstorage/tokudb/scripts/test.mysql.bash51
-rw-r--r--storage/tokudb/scripts/testbuildfromsrc.bash32
-rw-r--r--storage/tokudb/scripts/testsandbox.bash32
-rw-r--r--storage/tokudb/scripts/tpch.readme34
-rw-r--r--storage/xtradb/include/os0sync.h5
-rw-r--r--storage/xtradb/os/os0stacktrace.cc2
611 files changed, 19859 insertions, 57584 deletions
diff --git a/.bzrignore b/.bzrignore
index 1de58b16581..682d8e983d5 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -1436,7 +1436,7 @@ storage/tokudb/ft-index/portability/tests/try-uninit
storage/tokudb/ft-index/src/merge_archives_tokufractaltree_static.cmake
storage/tokudb/ft-index/src/tokufractaltree_static_depends.cc
storage/tokudb/ft-index/src/tests/recovery_fileops_unit_dir
-storage/tokudb/ft-index/portability/toku_config.h
+storage/tokudb/ft-index/toku_include/toku_config.h
storage/tokudb/ft-index/util/tests/marked-omt-test
storage/tokudb/ft-index/util/tests/omt-tmpl-test
storage/tokudb/ft-index/util/tests/sort-tmpl-test
@@ -1450,9 +1450,9 @@ storage/tokudb/ft-index/util/tests/test_partitioned_counter
storage/tokudb/ft-index/util/tests/test_partitioned_counter_5833
storage/tokudb/ft-index/util/tests/threadpool-test
storage/tokudb/ft-index/util/tests/threadpool-testrunf
-storage/tokudb/ft-index/tools/tokudb_dump
-storage/tokudb/ft-index/tools/tokudb_gen
-storage/tokudb/ft-index/tools/tokudb_load
+storage/tokudb/ft-index/utils/tokudb_dump
+storage/tokudb/ft-index/utils/tokudb_gen
+storage/tokudb/ft-index/utils/tokudb_load
storage/connect/connect.cnf
storage/cassandra/cassandra.cnf
libmysql/libmysql_versions.ld
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 75f24629995..be9616ea515 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -508,8 +508,10 @@ ADD_CUSTOM_TARGET(INFO_BIN ALL
INSTALL_DOCUMENTATION(README CREDITS COPYING COPYING.LESSER EXCEPTIONS-CLIENT
COMPONENT Readme)
-INSTALL_DOCUMENTATION(${CMAKE_BINARY_DIR}/Docs/INFO_SRC
- ${CMAKE_BINARY_DIR}/Docs/INFO_BIN)
+
+# MDEV-6526 these files are not installed anymore
+#INSTALL_DOCUMENTATION(${CMAKE_BINARY_DIR}/Docs/INFO_SRC
+# ${CMAKE_BINARY_DIR}/Docs/INFO_BIN)
IF(UNIX)
INSTALL_DOCUMENTATION(Docs/INSTALL-BINARY COMPONENT Readme)
diff --git a/client/mysql.cc b/client/mysql.cc
index b1570e32a80..e81761106ca 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -90,7 +90,7 @@ extern "C" {
#if defined(__WIN__)
#include <conio.h>
#else
-#include <readline/readline.h>
+#include <readline.h>
#define HAVE_READLINE
#define USE_POPEN
#endif
diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake
index 85ec0480a40..28bfcfe6e08 100644
--- a/cmake/build_configurations/mysql_release.cmake
+++ b/cmake/build_configurations/mysql_release.cmake
@@ -122,14 +122,9 @@ ENDIF()
IF(UNIX)
SET(WITH_EXTRA_CHARSETS all CACHE STRING "")
- IF(EXISTS "${CMAKE_SOURCE_DIR}/COPYING")
- OPTION(WITH_READLINE "" ON)
- ELSE()
- OPTION(WITH_LIBEDIT "" ON)
- ENDIF()
-
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ SET(WITH_JEMALLOC "yes" CACHE STRING "")
IF(NOT IGNORE_AIO_CHECK)
# Ensure aio is available on Linux (required by InnoDB)
diff --git a/cmake/jemalloc.cmake b/cmake/jemalloc.cmake
index b677f226266..f22499cd843 100644
--- a/cmake/jemalloc.cmake
+++ b/cmake/jemalloc.cmake
@@ -1,67 +1,24 @@
-# old cmake does not have ExternalProject file
-IF(CMAKE_VERSION VERSION_LESS "2.8.6")
- MACRO (CHECK_JEMALLOC)
- ENDMACRO()
- RETURN()
-ENDIF()
+INCLUDE (CheckLibraryExists)
-INCLUDE(ExternalProject)
+SET(WITH_JEMALLOC auto CACHE STRING
+ "Build with jemalloc. Possible values are 'yes', 'no', 'auto'")
-MACRO (USE_BUNDLED_JEMALLOC)
- SET(SOURCE_DIR "${CMAKE_SOURCE_DIR}/extra/jemalloc")
- SET(BINARY_DIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/extra/jemalloc/build")
- SET(LIBJEMALLOC "libjemalloc")
- SET(JEMALLOC_CONFIGURE_OPTS "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" "--with-private-namespace=jemalloc_internal_" "--enable-cc-silence")
- IF (CMAKE_BUILD_TYPE MATCHES "Debug" AND NOT APPLE) # see the comment in CMakeLists.txt
- LIST(APPEND JEMALLOC_CONFIGURE_OPTS --enable-debug)
+MACRO (CHECK_JEMALLOC)
+ # compatibility with old WITH_JEMALLOC values
+ IF(WITH_JEMALLOC STREQUAL "bundled")
+ MESSAGE(FATAL_ERROR "MariaDB no longer bundles jemalloc")
ENDIF()
-
- IF(CMAKE_GENERATOR MATCHES "Makefiles")
- SET(MAKE_COMMAND ${CMAKE_MAKE_PROGRAM})
- ELSE() # Xcode/Ninja generators
- SET(MAKE_COMMAND make)
+ IF(WITH_JEMALLOC STREQUAL "system")
+ SET(WITH_JEMALLOC "yes")
ENDIF()
-
- ExternalProject_Add(jemalloc
- PREFIX extra/jemalloc
- SOURCE_DIR ${SOURCE_DIR}
- BINARY_DIR ${BINARY_DIR}
- STAMP_DIR ${BINARY_DIR}
- CONFIGURE_COMMAND "${SOURCE_DIR}/configure" ${JEMALLOC_CONFIGURE_OPTS}
- BUILD_COMMAND ${MAKE_COMMAND} "build_lib_static"
- INSTALL_COMMAND ""
- )
- ADD_LIBRARY(libjemalloc STATIC IMPORTED)
- SET_TARGET_PROPERTIES(libjemalloc PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/lib/libjemalloc_pic.a")
- ADD_DEPENDENCIES(libjemalloc jemalloc)
-ENDMACRO()
-
-IF(CMAKE_SYSTEM_NAME MATCHES "Linux" OR APPLE)
- # Linux and OSX are the only systems where bundled jemalloc can be built without problems,
- # as they both have GNU make and jemalloc actually compiles.
- # Also, BSDs use jemalloc as malloc already
- SET(WITH_JEMALLOC_DEFAULT "yes")
-ELSE()
- SET(WITH_JEMALLOC_DEFAULT "no")
-ENDIF()
-SET(WITH_JEMALLOC ${WITH_JEMALLOC_DEFAULT} CACHE STRING
- "Which jemalloc to use. Possible values are 'no', 'bundled', 'system', 'yes' (system if possible, otherwise bundled)")
-
-MACRO (CHECK_JEMALLOC)
- IF(WITH_JEMALLOC STREQUAL "system" OR WITH_JEMALLOC STREQUAL "yes")
+ IF(WITH_JEMALLOC STREQUAL "yes" OR WITH_JEMALLOC STREQUAL "auto")
CHECK_LIBRARY_EXISTS(jemalloc malloc_stats_print "" HAVE_JEMALLOC)
IF (HAVE_JEMALLOC)
SET(LIBJEMALLOC jemalloc)
SET(MALLOC_LIBRARY "system jemalloc")
- ELSEIF (WITH_JEMALLOC STREQUAL "system")
- MESSAGE(FATAL_ERROR "system jemalloc is not found")
ELSEIF (WITH_JEMALLOC STREQUAL "yes")
- SET(trybundled 1)
+ MESSAGE(FATAL_ERROR "jemalloc is not found")
ENDIF()
ENDIF()
- IF(WITH_JEMALLOC STREQUAL "bundled" OR trybundled)
- USE_BUNDLED_JEMALLOC()
- SET(MALLOC_LIBRARY "bundled jemalloc")
- ENDIF()
ENDMACRO()
diff --git a/cmake/readline.cmake b/cmake/readline.cmake
index c99557683a6..c72f8d0da5c 100644
--- a/cmake/readline.cmake
+++ b/cmake/readline.cmake
@@ -116,24 +116,23 @@ ENDMACRO()
MACRO (MYSQL_USE_BUNDLED_READLINE)
SET(USE_NEW_READLINE_INTERFACE 1)
SET(HAVE_HIST_ENTRY 0 CACHE INTERNAL "" FORCE)
- SET(READLINE_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/cmd-line-utils)
- SET(READLINE_LIBRARY readline)
+ SET(MY_READLINE_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/cmd-line-utils/readline)
+ SET(MY_READLINE_LIBRARY readline)
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/cmd-line-utils/readline)
ENDMACRO()
MACRO (MYSQL_FIND_SYSTEM_READLINE)
- FIND_PATH(READLINE_INCLUDE_DIR readline/readline.h )
+ FIND_PATH(READLINE_INCLUDE_DIR readline.h PATH_SUFFIXES readline)
FIND_LIBRARY(READLINE_LIBRARY NAMES readline)
MARK_AS_ADVANCED(READLINE_INCLUDE_DIR READLINE_LIBRARY)
- SET(CMAKE_REQUIRES_LIBRARIES ${READLINE_LIBRARY} ${CURSES_LIBRARY})
-
IF(READLINE_LIBRARY AND READLINE_INCLUDE_DIR)
SET(CMAKE_REQUIRED_LIBRARIES ${READLINE_LIBRARY} ${CURSES_LIBRARY})
+ SET(CMAKE_REQUIRED_INCLUDES ${READLINE_INCLUDE_DIR})
CHECK_CXX_SOURCE_COMPILES("
#include <stdio.h>
- #include <readline/readline.h>
+ #include <readline.h>
int main(int argc, char **argv)
{
rl_completion_func_t *func1= (rl_completion_func_t*)0;
@@ -141,19 +140,9 @@ MACRO (MYSQL_FIND_SYSTEM_READLINE)
}"
NEW_READLINE_INTERFACE)
- CHECK_CXX_SOURCE_COMPILES("
- #include <stdio.h>
- #include <readline/readline.h>
- int main(int argc, char **argv)
- {
- HIST_ENTRY entry;
- return 0;
- }"
- HAVE_HIST_ENTRY)
-
CHECK_C_SOURCE_COMPILES("
#include <stdio.h>
- #include <readline/readline.h>
+ #include <readline.h>
#if RL_VERSION_MAJOR > 5
#error
#endif
@@ -176,30 +165,27 @@ MACRO (MYSQL_FIND_SYSTEM_READLINE)
ENDIF(READLINE_V5)
ENDIF(NEW_READLINE_INTERFACE)
ENDIF()
- SET(CMAKE_REQUIRES_LIBRARIES )
ENDMACRO()
MACRO (MYSQL_FIND_SYSTEM_LIBEDIT)
-
- FIND_PATH(READLINE_INCLUDE_DIR readline/readline.h )
- FIND_LIBRARY(READLINE_LIBRARY NAMES readline)
- MARK_AS_ADVANCED(READLINE_INCLUDE_DIR READLINE_LIBRARY)
-
- SET(CMAKE_REQUIRES_LIBRARIES ${READLINE_LIBRARY})
+ FIND_PATH(LIBEDIT_INCLUDE_DIR readline.h PATH_SUFFIXES editline edit/readline)
+ FIND_LIBRARY(LIBEDIT_LIBRARY edit)
+ MARK_AS_ADVANCED(LIBEDIT_INCLUDE_DIR LIBEDIT_LIBRARY)
- IF(READLINE_LIBRARY AND READLINE_INCLUDE_DIR)
+ IF(LIBEDIT_LIBRARY AND LIBEDIT_INCLUDE_DIR)
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBEDIT_LIBRARY})
+ SET(CMAKE_REQUIRED_INCLUDES ${LIBEDIT_INCLUDE_DIR})
CHECK_CXX_SOURCE_COMPILES("
#include <stdio.h>
- #include <readline/readline.h>
+ #include <readline.h>
int main(int argc, char **argv)
{
- char res= *(*rl_completion_entry_function)(0,0);
+ int res= (*rl_completion_entry_function)(0,0);
completion_matches(0,0);
}"
LIBEDIT_INTERFACE)
SET(USE_LIBEDIT_INTERFACE ${LIBEDIT_INTERFACE})
ENDIF()
- SET(CMAKE_REQUIRES_LIBRARIES)
ENDMACRO()
@@ -216,15 +202,33 @@ MACRO (MYSQL_CHECK_READLINE)
IF (NOT APPLE)
MYSQL_FIND_SYSTEM_READLINE()
ENDIF()
- IF(NOT USE_NEW_READLINE_INTERFACE)
+ IF(USE_NEW_READLINE_INTERFACE)
+ SET(MY_READLINE_INCLUDE_DIR ${READLINE_INCLUDE_DIR})
+ SET(MY_READLINE_LIBRARY ${READLINE_LIBRARY} ${CURSES_LIBRARY})
+ ELSE()
MYSQL_FIND_SYSTEM_LIBEDIT()
- IF(NOT USE_LIBEDIT_INTERFACE)
+ IF(USE_LIBEDIT_INTERFACE)
+ SET(MY_READLINE_INCLUDE_DIR ${LIBEDIT_INCLUDE_DIR})
+ SET(MY_READLINE_LIBRARY ${LIBEDIT_LIBRARY} ${CURSES_LIBRARY})
+ ELSE()
MYSQL_USE_BUNDLED_READLINE()
ENDIF()
ENDIF()
ENDIF()
- SET(MY_READLINE_INCLUDE_DIR ${READLINE_INCLUDE_DIR})
- SET(MY_READLINE_LIBRARY ${READLINE_LIBRARY} ${CURSES_LIBRARY})
+
+ SET(CMAKE_REQUIRED_LIBRARIES ${MY_READLINE_LIBRARY})
+ SET(CMAKE_REQUIRED_INCLUDES ${MY_READLINE_INCLUDE_DIR})
+ CHECK_CXX_SOURCE_COMPILES("
+ #include <stdio.h>
+ #include <readline.h>
+ int main(int argc, char **argv)
+ {
+ HIST_ENTRY entry;
+ return 0;
+ }"
+ HAVE_HIST_ENTRY)
+ SET(CMAKE_REQUIRED_LIBRARIES)
+ SET(CMAKE_REQUIRED_INCLUDES)
ENDIF(NOT WIN32)
ENDMACRO()
diff --git a/cmd-line-utils/readline/CMakeLists.txt b/cmd-line-utils/readline/CMakeLists.txt
index c06b9c08c47..bdecdd1fcce 100644
--- a/cmd-line-utils/readline/CMakeLists.txt
+++ b/cmd-line-utils/readline/CMakeLists.txt
@@ -13,8 +13,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
- ${CMAKE_SOURCE_DIR}/cmd-line-utils)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR})
ADD_DEFINITIONS(-DHAVE_CONFIG_H -DNO_KILL_INTR)
diff --git a/cmd-line-utils/readline/history.h b/cmd-line-utils/readline/history.h
index 59aad6a4e20..c196b0361e3 100644
--- a/cmd-line-utils/readline/history.h
+++ b/cmd-line-utils/readline/history.h
@@ -32,8 +32,8 @@ extern "C" {
# include "rlstdc.h"
# include "rltypedefs.h"
#else
-# include <readline/rlstdc.h>
-# include <readline/rltypedefs.h>
+# include <rlstdc.h>
+# include <rltypedefs.h>
#endif
#ifdef __STDC__
diff --git a/cmd-line-utils/readline/keymaps.h b/cmd-line-utils/readline/keymaps.h
index eb28a8ecc33..1de567ddc1e 100644
--- a/cmd-line-utils/readline/keymaps.h
+++ b/cmd-line-utils/readline/keymaps.h
@@ -32,9 +32,9 @@ extern "C" {
# include "chardefs.h"
# include "rltypedefs.h"
#else
-# include <readline/rlstdc.h>
-# include <readline/chardefs.h>
-# include <readline/rltypedefs.h>
+# include <rlstdc.h>
+# include <chardefs.h>
+# include <rltypedefs.h>
#endif
/* A keymap contains one entry for each key in the ASCII set.
diff --git a/cmd-line-utils/readline/readline.h b/cmd-line-utils/readline/readline.h
index 8ed1b84172e..867b2e71641 100644
--- a/cmd-line-utils/readline/readline.h
+++ b/cmd-line-utils/readline/readline.h
@@ -33,10 +33,10 @@ extern "C" {
# include "keymaps.h"
# include "tilde.h"
#else
-# include <readline/rlstdc.h>
-# include <readline/rltypedefs.h>
-# include <readline/keymaps.h>
-# include <readline/tilde.h>
+# include <rlstdc.h>
+# include <rltypedefs.h>
+# include <keymaps.h>
+# include <tilde.h>
#endif
/* Hex-encoded Readline version number. */
diff --git a/cmd-line-utils/readline/xmalloc.h b/cmd-line-utils/readline/xmalloc.h
index fafb44fcffd..58b17f39f3d 100644
--- a/cmd-line-utils/readline/xmalloc.h
+++ b/cmd-line-utils/readline/xmalloc.h
@@ -26,7 +26,7 @@
#if defined (READLINE_LIBRARY)
# include "rlstdc.h"
#else
-# include <readline/rlstdc.h>
+# include <rlstdc.h>
#endif
#ifndef PTR_T
diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control
index 2fa195b6367..2de53c58e25 100644
--- a/debian/dist/Debian/control
+++ b/debian/dist/Debian/control
@@ -4,7 +4,7 @@ Priority: optional
Maintainer: MariaDB Developers <maria-developers@lists.launchpad.net>
XSBC-Original-Maintainer: Maria Developers <maria-developers@lists.launchpad.net>
Uploaders: MariaDB Developers <maria-developers@lists.launchpad.net>
-Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev
+Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev, libjemalloc-dev (>= 3.0.0)
Standards-Version: 3.8.3
Homepage: http://mariadb.org/
Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/10.0/files
@@ -147,7 +147,7 @@ Description: MariaDB database client binaries
Package: mariadb-server-core-10.0
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libmariadbclient18 (>= ${binary:Version})
+Depends: ${shlibs:Depends}, ${misc:Depends}, libmariadbclient18 (>= ${binary:Version}), libjemalloc1 (>= 3.0.0)
Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5
Conflicts: mariadb-server-5.1 (<< 5.1.60),
mariadb-server-5.2 (<< 5.2.10),
@@ -192,7 +192,7 @@ Architecture: any
Suggests: tinyca, mailx, mariadb-test
Recommends: libhtml-template-perl
Pre-Depends: mariadb-common, adduser (>= 3.40), debconf
-Depends: mariadb-client-10.0 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-10.0 (>= ${binary:Version})
+Depends: mariadb-client-10.0 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-10.0 (>= ${binary:Version}), libjemalloc1 (>= 3.0.0)
Provides: mariadb-server, mysql-server, virtual-mysql-server
Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}),
mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5,
diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control
index 33facc2d8bd..87b4ff936e5 100644
--- a/debian/dist/Ubuntu/control
+++ b/debian/dist/Ubuntu/control
@@ -4,7 +4,7 @@ Priority: optional
Maintainer: MariaDB Developers <maria-developers@lists.launchpad.net>
XSBC-Original-Maintainer: Maria Developers <maria-developers@lists.launchpad.net>
Uploaders: MariaDB Developers <maria-developers@lists.launchpad.net>
-Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev
+Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev, libjemalloc-dev (>= 3.0.0)
Standards-Version: 3.8.2
Homepage: http://mariadb.org/
Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/10.0/files
@@ -147,7 +147,7 @@ Description: MariaDB database client binaries
Package: mariadb-server-core-10.0
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libmariadbclient18 (>= ${binary:Version})
+Depends: ${shlibs:Depends}, ${misc:Depends}, libmariadbclient18 (>= ${binary:Version}), libjemalloc1 (>= 3.0.0)
Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5
Conflicts: mysql-server-5.0,
mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5,
@@ -186,7 +186,7 @@ Architecture: any
Suggests: tinyca, mailx, mariadb-test
Recommends: libhtml-template-perl
Pre-Depends: mariadb-common, adduser (>= 3.40), debconf
-Depends: mariadb-client-10.0 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-10.0 (>= ${binary:Version})
+Depends: mariadb-client-10.0 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-10.0 (>= ${binary:Version}), libjemalloc1 (>= 3.0.0)
Provides: mariadb-server, mysql-server, virtual-mysql-server
Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}),
mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5,
diff --git a/extra/jemalloc/COPYING b/extra/jemalloc/COPYING
deleted file mode 100644
index 019e8132275..00000000000
--- a/extra/jemalloc/COPYING
+++ /dev/null
@@ -1,27 +0,0 @@
-Unless otherwise specified, files in the jemalloc source distribution are
-subject to the following license:
---------------------------------------------------------------------------------
-Copyright (C) 2002-2013 Jason Evans <jasone@canonware.com>.
-All rights reserved.
-Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved.
-Copyright (C) 2009-2013 Facebook, Inc. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-1. Redistributions of source code must retain the above copyright notice(s),
- this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice(s),
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
-OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------------
diff --git a/extra/jemalloc/ChangeLog b/extra/jemalloc/ChangeLog
deleted file mode 100644
index 4f03fc141cb..00000000000
--- a/extra/jemalloc/ChangeLog
+++ /dev/null
@@ -1,434 +0,0 @@
-Following are change highlights associated with official releases. Important
-bug fixes are all mentioned, but internal enhancements are omitted here for
-brevity (even though they are more fun to write about). Much more detail can be
-found in the git revision history:
-
- http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git
- git://canonware.com/jemalloc.git
-
-* 3.3.1a (December 27, 2013)
-
- Bug fixes from 3.4.1
- - Fix Valgrind integration flaws that caused Valgrind warnings about reads of
- uninitialized memory in:
- + arena chunk headers
- + internal zero-initialized data structures (relevant to tcache and prof
- code)
-
-* 3.3.1 (March 6, 2013)
-
- This version fixes bugs that are typically encountered only when utilizing
- custom run-time options.
-
- Bug fixes:
- - Fix a locking order bug that could cause deadlock during fork if heap
- profiling were enabled.
- - Fix a chunk recycling bug that could cause the allocator to lose track of
- whether a chunk was zeroed. On FreeBSD, NetBSD, and OS X, it could cause
- corruption if allocating via sbrk(2) (unlikely unless running with the
- "dss:primary" option specified). This was completely harmless on Linux
- unless using mlockall(2) (and unlikely even then, unless the
- --disable-munmap configure option or the "dss:primary" option was
- specified). This regression was introduced in 3.1.0 by the
- mlockall(2)/madvise(2) interaction fix.
- - Fix TLS-related memory corruption that could occur during thread exit if the
- thread never allocated memory. Only the quarantine and prof facilities were
- susceptible.
- - Fix two quarantine bugs:
- + Internal reallocation of the quarantined object array leaked the old
- array.
- + Reallocation failure for internal reallocation of the quarantined object
- array (very unlikely) resulted in memory corruption.
- - Fix Valgrind integration to annotate all internally allocated memory in a
- way that keeps Valgrind happy about internal data structure access.
- - Fix building for s390 systems.
-
-* 3.3.0 (January 23, 2013)
-
- This version includes a few minor performance improvements in addition to the
- listed new features and bug fixes.
-
- New features:
- - Add clipping support to lg_chunk option processing.
- - Add the --enable-ivsalloc option.
- - Add the --without-export option.
- - Add the --disable-zone-allocator option.
-
- Bug fixes:
- - Fix "arenas.extend" mallctl to output the number of arenas.
- - Fix chunk_recycyle() to unconditionally inform Valgrind that returned memory
- is undefined.
- - Fix build break on FreeBSD related to alloca.h.
-
-* 3.2.0 (November 9, 2012)
-
- In addition to a couple of bug fixes, this version modifies page run
- allocation and dirty page purging algorithms in order to better control
- page-level virtual memory fragmentation.
-
- Incompatible changes:
- - Change the "opt.lg_dirty_mult" default from 5 to 3 (32:1 to 8:1).
-
- Bug fixes:
- - Fix dss/mmap allocation precedence code to use recyclable mmap memory only
- after primary dss allocation fails.
- - Fix deadlock in the "arenas.purge" mallctl. This regression was introduced
- in 3.1.0 by the addition of the "arena.<i>.purge" mallctl.
-
-* 3.1.0 (October 16, 2012)
-
- New features:
- - Auto-detect whether running inside Valgrind, thus removing the need to
- manually specify MALLOC_CONF=valgrind:true.
- - Add the "arenas.extend" mallctl, which allows applications to create
- manually managed arenas.
- - Add the ALLOCM_ARENA() flag for {,r,d}allocm().
- - Add the "opt.dss", "arena.<i>.dss", and "stats.arenas.<i>.dss" mallctls,
- which provide control over dss/mmap precedence.
- - Add the "arena.<i>.purge" mallctl, which obsoletes "arenas.purge".
- - Define LG_QUANTUM for hppa.
-
- Incompatible changes:
- - Disable tcache by default if running inside Valgrind, in order to avoid
- making unallocated objects appear reachable to Valgrind.
- - Drop const from malloc_usable_size() argument on Linux.
-
- Bug fixes:
- - Fix heap profiling crash if sampled object is freed via realloc(p, 0).
- - Remove const from __*_hook variable declarations, so that glibc can modify
- them during process forking.
- - Fix mlockall(2)/madvise(2) interaction.
- - Fix fork(2)-related deadlocks.
- - Fix error return value for "thread.tcache.enabled" mallctl.
-
-* 3.0.0 (May 11, 2012)
-
- Although this version adds some major new features, the primary focus is on
- internal code cleanup that facilitates maintainability and portability, most
- of which is not reflected in the ChangeLog. This is the first release to
- incorporate substantial contributions from numerous other developers, and the
- result is a more broadly useful allocator (see the git revision history for
- contribution details). Note that the license has been unified, thanks to
- Facebook granting a license under the same terms as the other copyright
- holders (see COPYING).
-
- New features:
- - Implement Valgrind support, redzones, and quarantine.
- - Add support for additional platforms:
- + FreeBSD
- + Mac OS X Lion
- + MinGW
- + Windows (no support yet for replacing the system malloc)
- - Add support for additional architectures:
- + MIPS
- + SH4
- + Tilera
- - Add support for cross compiling.
- - Add nallocm(), which rounds a request size up to the nearest size class
- without actually allocating.
- - Implement aligned_alloc() (blame C11).
- - Add the "thread.tcache.enabled" mallctl.
- - Add the "opt.prof_final" mallctl.
- - Update pprof (from gperftools 2.0).
- - Add the --with-mangling option.
- - Add the --disable-experimental option.
- - Add the --disable-munmap option, and make it the default on Linux.
- - Add the --enable-mremap option, which disables use of mremap(2) by default.
-
- Incompatible changes:
- - Enable stats by default.
- - Enable fill by default.
- - Disable lazy locking by default.
- - Rename the "tcache.flush" mallctl to "thread.tcache.flush".
- - Rename the "arenas.pagesize" mallctl to "arenas.page".
- - Change the "opt.lg_prof_sample" default from 0 to 19 (1 B to 512 KiB).
- - Change the "opt.prof_accum" default from true to false.
-
- Removed features:
- - Remove the swap feature, including the "config.swap", "swap.avail",
- "swap.prezeroed", "swap.nfds", and "swap.fds" mallctls.
- - Remove highruns statistics, including the
- "stats.arenas.<i>.bins.<j>.highruns" and
- "stats.arenas.<i>.lruns.<j>.highruns" mallctls.
- - As part of small size class refactoring, remove the "opt.lg_[qc]space_max",
- "arenas.cacheline", "arenas.subpage", "arenas.[tqcs]space_{min,max}", and
- "arenas.[tqcs]bins" mallctls.
- - Remove the "arenas.chunksize" mallctl.
- - Remove the "opt.lg_prof_tcmax" option.
- - Remove the "opt.lg_prof_bt_max" option.
- - Remove the "opt.lg_tcache_gc_sweep" option.
- - Remove the --disable-tiny option, including the "config.tiny" mallctl.
- - Remove the --enable-dynamic-page-shift configure option.
- - Remove the --enable-sysv configure option.
-
- Bug fixes:
- - Fix a statistics-related bug in the "thread.arena" mallctl that could cause
- invalid statistics and crashes.
- - Work around TLS deallocation via free() on Linux. This bug could cause
- write-after-free memory corruption.
- - Fix a potential deadlock that could occur during interval- and
- growth-triggered heap profile dumps.
- - Fix large calloc() zeroing bugs due to dropping chunk map unzeroed flags.
- - Fix chunk_alloc_dss() to stop claiming memory is zeroed. This bug could
- cause memory corruption and crashes with --enable-dss specified.
- - Fix fork-related bugs that could cause deadlock in children between fork
- and exec.
- - Fix malloc_stats_print() to honor 'b' and 'l' in the opts parameter.
- - Fix realloc(p, 0) to act like free(p).
- - Do not enforce minimum alignment in memalign().
- - Check for NULL pointer in malloc_usable_size().
- - Fix an off-by-one heap profile statistics bug that could be observed in
- interval- and growth-triggered heap profiles.
- - Fix the "epoch" mallctl to update cached stats even if the passed in epoch
- is 0.
- - Fix bin->runcur management to fix a layout policy bug. This bug did not
- affect correctness.
- - Fix a bug in choose_arena_hard() that potentially caused more arenas to be
- initialized than necessary.
- - Add missing "opt.lg_tcache_max" mallctl implementation.
- - Use glibc allocator hooks to make mixed allocator usage less likely.
- - Fix build issues for --disable-tcache.
- - Don't mangle pthread_create() when --with-private-namespace is specified.
-
-* 2.2.5 (November 14, 2011)
-
- Bug fixes:
- - Fix huge_ralloc() race when using mremap(2). This is a serious bug that
- could cause memory corruption and/or crashes.
- - Fix huge_ralloc() to maintain chunk statistics.
- - Fix malloc_stats_print(..., "a") output.
-
-* 2.2.4 (November 5, 2011)
-
- Bug fixes:
- - Initialize arenas_tsd before using it. This bug existed for 2.2.[0-3], as
- well as for --disable-tls builds in earlier releases.
- - Do not assume a 4 KiB page size in test/rallocm.c.
-
-* 2.2.3 (August 31, 2011)
-
- This version fixes numerous bugs related to heap profiling.
-
- Bug fixes:
- - Fix a prof-related race condition. This bug could cause memory corruption,
- but only occurred in non-default configurations (prof_accum:false).
- - Fix off-by-one backtracing issues (make sure that prof_alloc_prep() is
- excluded from backtraces).
- - Fix a prof-related bug in realloc() (only triggered by OOM errors).
- - Fix prof-related bugs in allocm() and rallocm().
- - Fix prof_tdata_cleanup() for --disable-tls builds.
- - Fix a relative include path, to fix objdir builds.
-
-* 2.2.2 (July 30, 2011)
-
- Bug fixes:
- - Fix a build error for --disable-tcache.
- - Fix assertions in arena_purge() (for real this time).
- - Add the --with-private-namespace option. This is a workaround for symbol
- conflicts that can inadvertently arise when using static libraries.
-
-* 2.2.1 (March 30, 2011)
-
- Bug fixes:
- - Implement atomic operations for x86/x64. This fixes compilation failures
- for versions of gcc that are still in wide use.
- - Fix an assertion in arena_purge().
-
-* 2.2.0 (March 22, 2011)
-
- This version incorporates several improvements to algorithms and data
- structures that tend to reduce fragmentation and increase speed.
-
- New features:
- - Add the "stats.cactive" mallctl.
- - Update pprof (from google-perftools 1.7).
- - Improve backtracing-related configuration logic, and add the
- --disable-prof-libgcc option.
-
- Bug fixes:
- - Change default symbol visibility from "internal", to "hidden", which
- decreases the overhead of library-internal function calls.
- - Fix symbol visibility so that it is also set on OS X.
- - Fix a build dependency regression caused by the introduction of the .pic.o
- suffix for PIC object files.
- - Add missing checks for mutex initialization failures.
- - Don't use libgcc-based backtracing except on x64, where it is known to work.
- - Fix deadlocks on OS X that were due to memory allocation in
- pthread_mutex_lock().
- - Heap profiling-specific fixes:
- + Fix memory corruption due to integer overflow in small region index
- computation, when using a small enough sample interval that profiling
- context pointers are stored in small run headers.
- + Fix a bootstrap ordering bug that only occurred with TLS disabled.
- + Fix a rallocm() rsize bug.
- + Fix error detection bugs for aligned memory allocation.
-
-* 2.1.3 (March 14, 2011)
-
- Bug fixes:
- - Fix a cpp logic regression (due to the "thread.{de,}allocatedp" mallctl fix
- for OS X in 2.1.2).
- - Fix a "thread.arena" mallctl bug.
- - Fix a thread cache stats merging bug.
-
-* 2.1.2 (March 2, 2011)
-
- Bug fixes:
- - Fix "thread.{de,}allocatedp" mallctl for OS X.
- - Add missing jemalloc.a to build system.
-
-* 2.1.1 (January 31, 2011)
-
- Bug fixes:
- - Fix aligned huge reallocation (affected allocm()).
- - Fix the ALLOCM_LG_ALIGN macro definition.
- - Fix a heap dumping deadlock.
- - Fix a "thread.arena" mallctl bug.
-
-* 2.1.0 (December 3, 2010)
-
- This version incorporates some optimizations that can't quite be considered
- bug fixes.
-
- New features:
- - Use Linux's mremap(2) for huge object reallocation when possible.
- - Avoid locking in mallctl*() when possible.
- - Add the "thread.[de]allocatedp" mallctl's.
- - Convert the manual page source from roff to DocBook, and generate both roff
- and HTML manuals.
-
- Bug fixes:
- - Fix a crash due to incorrect bootstrap ordering. This only impacted
- --enable-debug --enable-dss configurations.
- - Fix a minor statistics bug for mallctl("swap.avail", ...).
-
-* 2.0.1 (October 29, 2010)
-
- Bug fixes:
- - Fix a race condition in heap profiling that could cause undefined behavior
- if "opt.prof_accum" were disabled.
- - Add missing mutex unlocks for some OOM error paths in the heap profiling
- code.
- - Fix a compilation error for non-C99 builds.
-
-* 2.0.0 (October 24, 2010)
-
- This version focuses on the experimental *allocm() API, and on improved
- run-time configuration/introspection. Nonetheless, numerous performance
- improvements are also included.
-
- New features:
- - Implement the experimental {,r,s,d}allocm() API, which provides a superset
- of the functionality available via malloc(), calloc(), posix_memalign(),
- realloc(), malloc_usable_size(), and free(). These functions can be used to
- allocate/reallocate aligned zeroed memory, ask for optional extra memory
- during reallocation, prevent object movement during reallocation, etc.
- - Replace JEMALLOC_OPTIONS/JEMALLOC_PROF_PREFIX with MALLOC_CONF, which is
- more human-readable, and more flexible. For example:
- JEMALLOC_OPTIONS=AJP
- is now:
- MALLOC_CONF=abort:true,fill:true,stats_print:true
- - Port to Apple OS X. Sponsored by Mozilla.
- - Make it possible for the application to control thread-->arena mappings via
- the "thread.arena" mallctl.
- - Add compile-time support for all TLS-related functionality via pthreads TSD.
- This is mainly of interest for OS X, which does not support TLS, but has a
- TSD implementation with similar performance.
- - Override memalign() and valloc() if they are provided by the system.
- - Add the "arenas.purge" mallctl, which can be used to synchronously purge all
- dirty unused pages.
- - Make cumulative heap profiling data optional, so that it is possible to
- limit the amount of memory consumed by heap profiling data structures.
- - Add per thread allocation counters that can be accessed via the
- "thread.allocated" and "thread.deallocated" mallctls.
-
- Incompatible changes:
- - Remove JEMALLOC_OPTIONS and malloc_options (see MALLOC_CONF above).
- - Increase default backtrace depth from 4 to 128 for heap profiling.
- - Disable interval-based profile dumps by default.
-
- Bug fixes:
- - Remove bad assertions in fork handler functions. These assertions could
- cause aborts for some combinations of configure settings.
- - Fix strerror_r() usage to deal with non-standard semantics in GNU libc.
- - Fix leak context reporting. This bug tended to cause the number of contexts
- to be underreported (though the reported number of objects and bytes were
- correct).
- - Fix a realloc() bug for large in-place growing reallocation. This bug could
- cause memory corruption, but it was hard to trigger.
- - Fix an allocation bug for small allocations that could be triggered if
- multiple threads raced to create a new run of backing pages.
- - Enhance the heap profiler to trigger samples based on usable size, rather
- than request size.
- - Fix a heap profiling bug due to sometimes losing track of requested object
- size for sampled objects.
-
-* 1.0.3 (August 12, 2010)
-
- Bug fixes:
- - Fix the libunwind-based implementation of stack backtracing (used for heap
- profiling). This bug could cause zero-length backtraces to be reported.
- - Add a missing mutex unlock in library initialization code. If multiple
- threads raced to initialize malloc, some of them could end up permanently
- blocked.
-
-* 1.0.2 (May 11, 2010)
-
- Bug fixes:
- - Fix junk filling of large objects, which could cause memory corruption.
- - Add MAP_NORESERVE support for chunk mapping, because otherwise virtual
- memory limits could cause swap file configuration to fail. Contributed by
- Jordan DeLong.
-
-* 1.0.1 (April 14, 2010)
-
- Bug fixes:
- - Fix compilation when --enable-fill is specified.
- - Fix threads-related profiling bugs that affected accuracy and caused memory
- to be leaked during thread exit.
- - Fix dirty page purging race conditions that could cause crashes.
- - Fix crash in tcache flushing code during thread destruction.
-
-* 1.0.0 (April 11, 2010)
-
- This release focuses on speed and run-time introspection. Numerous
- algorithmic improvements make this release substantially faster than its
- predecessors.
-
- New features:
- - Implement autoconf-based configuration system.
- - Add mallctl*(), for the purposes of introspection and run-time
- configuration.
- - Make it possible for the application to manually flush a thread's cache, via
- the "tcache.flush" mallctl.
- - Base maximum dirty page count on proportion of active memory.
- - Compute various addtional run-time statistics, including per size class
- statistics for large objects.
- - Expose malloc_stats_print(), which can be called repeatedly by the
- application.
- - Simplify the malloc_message() signature to only take one string argument,
- and incorporate an opaque data pointer argument for use by the application
- in combination with malloc_stats_print().
- - Add support for allocation backed by one or more swap files, and allow the
- application to disable over-commit if swap files are in use.
- - Implement allocation profiling and leak checking.
-
- Removed features:
- - Remove the dynamic arena rebalancing code, since thread-specific caching
- reduces its utility.
-
- Bug fixes:
- - Modify chunk allocation to work when address space layout randomization
- (ASLR) is in use.
- - Fix thread cleanup bugs related to TLS destruction.
- - Handle 0-size allocation requests in posix_memalign().
- - Fix a chunk leak. The leaked chunks were never touched, so this impacted
- virtual memory usage, but not physical memory usage.
-
-* linux_2008082[78]a (August 27/28, 2008)
-
- These snapshot releases are the simple result of incorporating Linux-specific
- support into the FreeBSD malloc sources.
-
---------------------------------------------------------------------------------
-vim:filetype=text:textwidth=80
diff --git a/extra/jemalloc/INSTALL b/extra/jemalloc/INSTALL
deleted file mode 100644
index 6e371ce5095..00000000000
--- a/extra/jemalloc/INSTALL
+++ /dev/null
@@ -1,293 +0,0 @@
-Building and installing jemalloc can be as simple as typing the following while
-in the root directory of the source tree:
-
- ./configure
- make
- make install
-
-=== Advanced configuration =====================================================
-
-The 'configure' script supports numerous options that allow control of which
-functionality is enabled, where jemalloc is installed, etc. Optionally, pass
-any of the following arguments (not a definitive list) to 'configure':
-
---help
- Print a definitive list of options.
-
---prefix=<install-root-dir>
- Set the base directory in which to install. For example:
-
- ./configure --prefix=/usr/local
-
- will cause files to be installed into /usr/local/include, /usr/local/lib,
- and /usr/local/man.
-
---with-rpath=<colon-separated-rpath>
- Embed one or more library paths, so that libjemalloc can find the libraries
- it is linked to. This works only on ELF-based systems.
-
---with-mangling=<map>
- Mangle public symbols specified in <map> which is a comma-separated list of
- name:mangled pairs.
-
- For example, to use ld's --wrap option as an alternative method for
- overriding libc's malloc implementation, specify something like:
-
- --with-mangling=malloc:__wrap_malloc,free:__wrap_free[...]
-
- Note that mangling happens prior to application of the prefix specified by
- --with-jemalloc-prefix, and mangled symbols are then ignored when applying
- the prefix.
-
---with-jemalloc-prefix=<prefix>
- Prefix all public APIs with <prefix>. For example, if <prefix> is
- "prefix_", API changes like the following occur:
-
- malloc() --> prefix_malloc()
- malloc_conf --> prefix_malloc_conf
- /etc/malloc.conf --> /etc/prefix_malloc.conf
- MALLOC_CONF --> PREFIX_MALLOC_CONF
-
- This makes it possible to use jemalloc at the same time as the system
- allocator, or even to use multiple copies of jemalloc simultaneously.
-
- By default, the prefix is "", except on OS X, where it is "je_". On OS X,
- jemalloc overlays the default malloc zone, but makes no attempt to actually
- replace the "malloc", "calloc", etc. symbols.
-
---without-export
- Don't export public APIs. This can be useful when building jemalloc as a
- static library, or to avoid exporting public APIs when using the zone
- allocator on OSX.
-
---with-private-namespace=<prefix>
- Prefix all library-private APIs with <prefix>. For shared libraries,
- symbol visibility mechanisms prevent these symbols from being exported, but
- for static libraries, naming collisions are a real possibility. By
- default, the prefix is "" (empty string).
-
---with-install-suffix=<suffix>
- Append <suffix> to the base name of all installed files, such that multiple
- versions of jemalloc can coexist in the same installation directory. For
- example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0.
-
---enable-cc-silence
- Enable code that silences non-useful compiler warnings. This is helpful
- when trying to tell serious warnings from those due to compiler
- limitations, but it potentially incurs a performance penalty.
-
---enable-debug
- Enable assertions and validation code. This incurs a substantial
- performance hit, but is very useful during application development.
- Implies --enable-ivsalloc.
-
---enable-ivsalloc
- Enable validation code, which verifies that pointers reside within
- jemalloc-owned chunks before dereferencing them. This incurs a substantial
- performance hit.
-
---disable-stats
- Disable statistics gathering functionality. See the "opt.stats_print"
- option documentation for usage details.
-
---enable-prof
- Enable heap profiling and leak detection functionality. See the "opt.prof"
- option documentation for usage details. When enabled, there are several
- approaches to backtracing, and the configure script chooses the first one
- in the following list that appears to function correctly:
-
- + libunwind (requires --enable-prof-libunwind)
- + libgcc (unless --disable-prof-libgcc)
- + gcc intrinsics (unless --disable-prof-gcc)
-
---enable-prof-libunwind
- Use the libunwind library (http://www.nongnu.org/libunwind/) for stack
- backtracing.
-
---disable-prof-libgcc
- Disable the use of libgcc's backtracing functionality.
-
---disable-prof-gcc
- Disable the use of gcc intrinsics for backtracing.
-
---with-static-libunwind=<libunwind.a>
- Statically link against the specified libunwind.a rather than dynamically
- linking with -lunwind.
-
---disable-tcache
- Disable thread-specific caches for small objects. Objects are cached and
- released in bulk, thus reducing the total number of mutex operations. See
- the "opt.tcache" option for usage details.
-
---enable-mremap
- Enable huge realloc() via mremap(2). mremap() is disabled by default
- because the flavor used is specific to Linux, which has a quirk in its
- virtual memory allocation algorithm that causes semi-permanent VM map holes
- under normal jemalloc operation.
-
---disable-munmap
- Disable virtual memory deallocation via munmap(2); instead keep track of
- the virtual memory for later use. munmap() is disabled by default (i.e.
- --disable-munmap is implied) on Linux, which has a quirk in its virtual
- memory allocation algorithm that causes semi-permanent VM map holes under
- normal jemalloc operation.
-
---enable-dss
- Enable support for page allocation/deallocation via sbrk(2), in addition to
- mmap(2).
-
---disable-fill
- Disable support for junk/zero filling of memory, quarantine, and redzones.
- See the "opt.junk", "opt.zero", "opt.quarantine", and "opt.redzone" option
- documentation for usage details.
-
---disable-valgrind
- Disable support for Valgrind.
-
---disable-experimental
- Disable support for the experimental API (*allocm()).
-
---disable-zone-allocator
- Disable zone allocator for Darwin. This means jemalloc won't be hooked as
- the default allocator on OSX/iOS.
-
---enable-utrace
- Enable utrace(2)-based allocation tracing. This feature is not broadly
- portable (FreeBSD has it, but Linux and OS X do not).
-
---enable-xmalloc
- Enable support for optional immediate termination due to out-of-memory
- errors, as is commonly implemented by "xmalloc" wrapper function for malloc.
- See the "opt.xmalloc" option documentation for usage details.
-
---enable-lazy-lock
- Enable code that wraps pthread_create() to detect when an application
- switches from single-threaded to multi-threaded mode, so that it can avoid
- mutex locking/unlocking operations while in single-threaded mode. In
- practice, this feature usually has little impact on performance unless
- thread-specific caching is disabled.
-
---disable-tls
- Disable thread-local storage (TLS), which allows for fast access to
- thread-local variables via the __thread keyword. If TLS is available,
- jemalloc uses it for several purposes.
-
---with-xslroot=<path>
- Specify where to find DocBook XSL stylesheets when building the
- documentation.
-
-The following environment variables (not a definitive list) impact configure's
-behavior:
-
-CFLAGS="?"
- Pass these flags to the compiler. You probably shouldn't define this unless
- you know what you are doing. (Use EXTRA_CFLAGS instead.)
-
-EXTRA_CFLAGS="?"
- Append these flags to CFLAGS. This makes it possible to add flags such as
- -Werror, while allowing the configure script to determine what other flags
- are appropriate for the specified configuration.
-
- The configure script specifically checks whether an optimization flag (-O*)
- is specified in EXTRA_CFLAGS, and refrains from specifying an optimization
- level if it finds that one has already been specified.
-
-CPPFLAGS="?"
- Pass these flags to the C preprocessor. Note that CFLAGS is not passed to
- 'cpp' when 'configure' is looking for include files, so you must use
- CPPFLAGS instead if you need to help 'configure' find header files.
-
-LD_LIBRARY_PATH="?"
- 'ld' uses this colon-separated list to find libraries.
-
-LDFLAGS="?"
- Pass these flags when linking.
-
-PATH="?"
- 'configure' uses this to find programs.
-
-=== Advanced compilation =======================================================
-
-To build only parts of jemalloc, use the following targets:
-
- build_lib_shared
- build_lib_static
- build_lib
- build_doc_html
- build_doc_man
- build_doc
-
-To install only parts of jemalloc, use the following targets:
-
- install_bin
- install_include
- install_lib_shared
- install_lib_static
- install_lib
- install_doc_html
- install_doc_man
- install_doc
-
-To clean up build results to varying degrees, use the following make targets:
-
- clean
- distclean
- relclean
-
-=== Advanced installation ======================================================
-
-Optionally, define make variables when invoking make, including (not
-exclusively):
-
-INCLUDEDIR="?"
- Use this as the installation prefix for header files.
-
-LIBDIR="?"
- Use this as the installation prefix for libraries.
-
-MANDIR="?"
- Use this as the installation prefix for man pages.
-
-DESTDIR="?"
- Prepend DESTDIR to INCLUDEDIR, LIBDIR, DATADIR, and MANDIR. This is useful
- when installing to a different path than was specified via --prefix.
-
-CC="?"
- Use this to invoke the C compiler.
-
-CFLAGS="?"
- Pass these flags to the compiler.
-
-CPPFLAGS="?"
- Pass these flags to the C preprocessor.
-
-LDFLAGS="?"
- Pass these flags when linking.
-
-PATH="?"
- Use this to search for programs used during configuration and building.
-
-=== Development ================================================================
-
-If you intend to make non-trivial changes to jemalloc, use the 'autogen.sh'
-script rather than 'configure'. This re-generates 'configure', enables
-configuration dependency rules, and enables re-generation of automatically
-generated source files.
-
-The build system supports using an object directory separate from the source
-tree. For example, you can create an 'obj' directory, and from within that
-directory, issue configuration and build commands:
-
- autoconf
- mkdir obj
- cd obj
- ../configure --enable-autogen
- make
-
-=== Documentation ==============================================================
-
-The manual page is generated in both html and roff formats. Any web browser
-can be used to view the html manual. The roff manual page can be formatted
-prior to installation via the following command:
-
- nroff -man -t doc/jemalloc.3
diff --git a/extra/jemalloc/Makefile.in b/extra/jemalloc/Makefile.in
deleted file mode 100644
index 74810472d11..00000000000
--- a/extra/jemalloc/Makefile.in
+++ /dev/null
@@ -1,324 +0,0 @@
-# Clear out all vpaths, then set just one (default vpath) for the main build
-# directory.
-vpath
-vpath % .
-
-# Clear the default suffixes, so that built-in rules are not used.
-.SUFFIXES :
-
-SHELL := /bin/sh
-
-CC := @CC@
-
-# Configuration parameters.
-DESTDIR =
-BINDIR := $(DESTDIR)@BINDIR@
-INCLUDEDIR := $(DESTDIR)@INCLUDEDIR@
-LIBDIR := $(DESTDIR)@LIBDIR@
-DATADIR := $(DESTDIR)@DATADIR@
-MANDIR := $(DESTDIR)@MANDIR@
-srcroot := @srcroot@
-objroot := @objroot@
-abs_srcroot := @abs_srcroot@
-abs_objroot := @abs_objroot@
-
-# Build parameters.
-CPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include
-CFLAGS := @CFLAGS@
-LDFLAGS := @LDFLAGS@
-EXTRA_LDFLAGS := @EXTRA_LDFLAGS@
-LIBS := @LIBS@
-RPATH_EXTRA := @RPATH_EXTRA@
-SO := @so@
-IMPORTLIB := @importlib@
-O := @o@
-A := @a@
-EXE := @exe@
-LIBPREFIX := @libprefix@
-REV := @rev@
-install_suffix := @install_suffix@
-ABI := @abi@
-XSLTPROC := @XSLTPROC@
-AUTOCONF := @AUTOCONF@
-_RPATH = @RPATH@
-RPATH = $(if $(1),$(call _RPATH,$(1)))
-cfghdrs_in := @cfghdrs_in@
-cfghdrs_out := @cfghdrs_out@
-cfgoutputs_in := @cfgoutputs_in@
-cfgoutputs_out := @cfgoutputs_out@
-enable_autogen := @enable_autogen@
-enable_experimental := @enable_experimental@
-enable_zone_allocator := @enable_zone_allocator@
-DSO_LDFLAGS = @DSO_LDFLAGS@
-SOREV = @SOREV@
-PIC_CFLAGS = @PIC_CFLAGS@
-CTARGET = @CTARGET@
-LDTARGET = @LDTARGET@
-MKLIB = @MKLIB@
-CC_MM = @CC_MM@
-
-ifeq (macho, $(ABI))
-TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH="$(objroot)lib"
-else
-ifeq (pecoff, $(ABI))
-TEST_LIBRARY_PATH := PATH="$(PATH):$(objroot)lib"
-else
-TEST_LIBRARY_PATH :=
-endif
-endif
-
-LIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix)
-
-# Lists of files.
-BINS := $(srcroot)bin/pprof $(objroot)bin/jemalloc.sh
-CHDRS := $(objroot)include/jemalloc/jemalloc$(install_suffix).h \
- $(objroot)include/jemalloc/jemalloc_defs$(install_suffix).h
-CSRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c $(srcroot)src/atomic.c \
- $(srcroot)src/base.c $(srcroot)src/bitmap.c $(srcroot)src/chunk.c \
- $(srcroot)src/chunk_dss.c $(srcroot)src/chunk_mmap.c \
- $(srcroot)src/ckh.c $(srcroot)src/ctl.c $(srcroot)src/extent.c \
- $(srcroot)src/hash.c $(srcroot)src/huge.c $(srcroot)src/mb.c \
- $(srcroot)src/mutex.c $(srcroot)src/prof.c $(srcroot)src/quarantine.c \
- $(srcroot)src/rtree.c $(srcroot)src/stats.c $(srcroot)src/tcache.c \
- $(srcroot)src/util.c $(srcroot)src/tsd.c
-ifeq ($(enable_zone_allocator), 1)
-CSRCS += $(srcroot)src/zone.c
-endif
-ifeq ($(IMPORTLIB),$(SO))
-STATIC_LIBS := $(objroot)lib/$(LIBJEMALLOC).$(A)
-endif
-ifdef PIC_CFLAGS
-STATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_pic.$(A)
-else
-STATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_s.$(A)
-endif
-DSOS := $(objroot)lib/$(LIBJEMALLOC).$(SOREV)
-ifneq ($(SOREV),$(SO))
-DSOS += $(objroot)lib/$(LIBJEMALLOC).$(SO)
-endif
-MAN3 := $(objroot)doc/jemalloc$(install_suffix).3
-DOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml
-DOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.html)
-DOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.3)
-DOCS := $(DOCS_HTML) $(DOCS_MAN3)
-CTESTS := $(srcroot)test/aligned_alloc.c $(srcroot)test/allocated.c \
- $(srcroot)test/ALLOCM_ARENA.c $(srcroot)test/bitmap.c \
- $(srcroot)test/mremap.c $(srcroot)test/posix_memalign.c \
- $(srcroot)test/thread_arena.c $(srcroot)test/thread_tcache_enabled.c
-ifeq ($(enable_experimental), 1)
-CTESTS += $(srcroot)test/allocm.c $(srcroot)test/rallocm.c
-endif
-
-COBJS := $(CSRCS:$(srcroot)%.c=$(objroot)%.$(O))
-CPICOBJS := $(CSRCS:$(srcroot)%.c=$(objroot)%.pic.$(O))
-CTESTOBJS := $(CTESTS:$(srcroot)%.c=$(objroot)%.$(O))
-
-.PHONY: all dist build_doc_html build_doc_man build_doc
-.PHONY: install_bin install_include install_lib
-.PHONY: install_doc_html install_doc_man install_doc install
-.PHONY: tests check clean distclean relclean
-
-.SECONDARY : $(CTESTOBJS)
-
-# Default target.
-all: build
-
-dist: build_doc
-
-$(srcroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl
- $(XSLTPROC) -o $@ $(objroot)doc/html.xsl $<
-
-$(srcroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl
- $(XSLTPROC) -o $@ $(objroot)doc/manpages.xsl $<
-
-build_doc_html: $(DOCS_HTML)
-build_doc_man: $(DOCS_MAN3)
-build_doc: $(DOCS)
-
-#
-# Include generated dependency files.
-#
-ifdef CC_MM
--include $(COBJS:%.$(O)=%.d)
--include $(CPICOBJS:%.$(O)=%.d)
--include $(CTESTOBJS:%.$(O)=%.d)
-endif
-
-$(COBJS): $(objroot)src/%.$(O): $(srcroot)src/%.c
-$(CPICOBJS): $(objroot)src/%.pic.$(O): $(srcroot)src/%.c
-$(CPICOBJS): CFLAGS += $(PIC_CFLAGS)
-$(CTESTOBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c
-$(CTESTOBJS): CPPFLAGS += -I$(objroot)test
-ifneq ($(IMPORTLIB),$(SO))
-$(COBJS): CPPFLAGS += -DDLLEXPORT
-endif
-
-ifndef CC_MM
-# Dependencies
-HEADER_DIRS = $(srcroot)include/jemalloc/internal \
- $(objroot)include/jemalloc $(objroot)include/jemalloc/internal
-HEADERS = $(wildcard $(foreach dir,$(HEADER_DIRS),$(dir)/*.h))
-$(COBJS) $(CPICOBJS) $(CTESTOBJS): $(HEADERS)
-$(CTESTOBJS): $(objroot)test/jemalloc_test.h
-endif
-
-$(COBJS) $(CPICOBJS) $(CTESTOBJS): %.$(O):
- @mkdir -p $(@D)
- $(CC) $(CFLAGS) -c $(CPPFLAGS) $(CTARGET) $<
-ifdef CC_MM
- @$(CC) -MM $(CPPFLAGS) -MT $@ -o $(@:%.$(O)=%.d) $<
-endif
-
-ifneq ($(SOREV),$(SO))
-%.$(SO) : %.$(SOREV)
- @mkdir -p $(@D)
- ln -sf $(<F) $@
-endif
-
-$(objroot)lib/$(LIBJEMALLOC).$(SOREV) : $(if $(PIC_CFLAGS),$(CPICOBJS),$(COBJS))
- @mkdir -p $(@D)
- $(CC) $(DSO_LDFLAGS) $(call RPATH,$(RPATH_EXTRA)) $(LDTARGET) $+ $(LDFLAGS) $(LIBS) $(EXTRA_LDFLAGS)
-
-$(objroot)lib/$(LIBJEMALLOC)_pic.$(A) : $(CPICOBJS)
-$(objroot)lib/$(LIBJEMALLOC).$(A) : $(COBJS)
-$(objroot)lib/$(LIBJEMALLOC)_s.$(A) : $(COBJS)
-
-$(STATIC_LIBS):
- @mkdir -p $(@D)
- $(MKLIB) $+
-
-$(objroot)test/bitmap$(EXE): $(objroot)src/bitmap.$(O)
-
-$(objroot)test/%$(EXE): $(objroot)test/%.$(O) $(objroot)src/util.$(O) $(DSOS)
- @mkdir -p $(@D)
- $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(filter -lpthread,$(LIBS)) $(EXTRA_LDFLAGS)
-
-build_lib_shared: $(DSOS)
-build_lib_static: $(STATIC_LIBS)
-build: build_lib_shared build_lib_static
-
-install_bin:
- install -d $(BINDIR)
- @for b in $(BINS); do \
- echo "install -m 755 $$b $(BINDIR)"; \
- install -m 755 $$b $(BINDIR); \
-done
-
-install_include:
- install -d $(INCLUDEDIR)/jemalloc
- @for h in $(CHDRS); do \
- echo "install -m 644 $$h $(INCLUDEDIR)/jemalloc"; \
- install -m 644 $$h $(INCLUDEDIR)/jemalloc; \
-done
-
-install_lib_shared: $(DSOS)
- install -d $(LIBDIR)
- install -m 755 $(objroot)lib/$(LIBJEMALLOC).$(SOREV) $(LIBDIR)
-ifneq ($(SOREV),$(SO))
- ln -sf $(LIBJEMALLOC).$(SOREV) $(LIBDIR)/$(LIBJEMALLOC).$(SO)
-endif
-
-install_lib_static: $(STATIC_LIBS)
- install -d $(LIBDIR)
- @for l in $(STATIC_LIBS); do \
- echo "install -m 755 $$l $(LIBDIR)"; \
- install -m 755 $$l $(LIBDIR); \
-done
-
-install_lib: install_lib_shared install_lib_static
-
-install_doc_html:
- install -d $(DATADIR)/doc/jemalloc$(install_suffix)
- @for d in $(DOCS_HTML); do \
- echo "install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix)"; \
- install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix); \
-done
-
-install_doc_man:
- install -d $(MANDIR)/man3
- @for d in $(DOCS_MAN3); do \
- echo "install -m 644 $$d $(MANDIR)/man3"; \
- install -m 644 $$d $(MANDIR)/man3; \
-done
-
-install_doc: install_doc_html install_doc_man
-
-install: install_bin install_include install_lib install_doc
-
-tests: $(CTESTS:$(srcroot)%.c=$(objroot)%$(EXE))
-
-check: tests
- @mkdir -p $(objroot)test
- @$(SHELL) -c 'total=0; \
- failures=0; \
- echo "========================================="; \
- for t in $(CTESTS:$(srcroot)%.c=$(objroot)%); do \
- total=`expr $$total + 1`; \
- /bin/echo -n "$${t} ... "; \
- $(TEST_LIBRARY_PATH) $${t}$(EXE) $(abs_srcroot) \
- $(abs_objroot) > $(objroot)$${t}.out 2>&1; \
- if test -e "$(srcroot)$${t}.exp"; then \
- diff -w -u $(srcroot)$${t}.exp \
- $(objroot)$${t}.out >/dev/null 2>&1; \
- fail=$$?; \
- if test "$${fail}" -eq "1" ; then \
- failures=`expr $${failures} + 1`; \
- echo "*** FAIL ***"; \
- else \
- echo "pass"; \
- fi; \
- else \
- echo "*** FAIL *** (.exp file is missing)"; \
- failures=`expr $${failures} + 1`; \
- fi; \
- done; \
- echo "========================================="; \
- echo "Failures: $${failures}/$${total}"'
-
-clean:
- rm -f $(COBJS)
- rm -f $(CPICOBJS)
- rm -f $(COBJS:%.$(O)=%.d)
- rm -f $(CPICOBJS:%.$(O)=%.d)
- rm -f $(CTESTOBJS:%.$(O)=%$(EXE))
- rm -f $(CTESTOBJS)
- rm -f $(CTESTOBJS:%.$(O)=%.d)
- rm -f $(CTESTOBJS:%.$(O)=%.out)
- rm -f $(DSOS) $(STATIC_LIBS)
-
-distclean: clean
- rm -rf $(objroot)autom4te.cache
- rm -f $(objroot)config.log
- rm -f $(objroot)config.status
- rm -f $(objroot)config.stamp
- rm -f $(cfghdrs_out)
- rm -f $(cfgoutputs_out)
-
-relclean: distclean
- rm -f $(objroot)configure
- rm -f $(srcroot)VERSION
- rm -f $(DOCS_HTML)
- rm -f $(DOCS_MAN3)
-
-#===============================================================================
-# Re-configuration rules.
-
-ifeq ($(enable_autogen), 1)
-$(srcroot)configure : $(srcroot)configure.ac
- cd ./$(srcroot) && $(AUTOCONF)
-
-$(objroot)config.status : $(srcroot)configure
- ./$(objroot)config.status --recheck
-
-$(srcroot)config.stamp.in : $(srcroot)configure.ac
- echo stamp > $(srcroot)config.stamp.in
-
-$(objroot)config.stamp : $(cfgoutputs_in) $(cfghdrs_in) $(srcroot)configure
- ./$(objroot)config.status
- @touch $@
-
-# There must be some action in order for make to re-read Makefile when it is
-# out of date.
-$(cfgoutputs_out) $(cfghdrs_out) : $(objroot)config.stamp
- @true
-endif
diff --git a/extra/jemalloc/README b/extra/jemalloc/README
deleted file mode 100644
index 7661683bae7..00000000000
--- a/extra/jemalloc/README
+++ /dev/null
@@ -1,16 +0,0 @@
-jemalloc is a general-purpose scalable concurrent malloc(3) implementation.
-This distribution is a "portable" implementation that currently targets
-FreeBSD, Linux, Apple OS X, and MinGW. jemalloc is included as the default
-allocator in the FreeBSD and NetBSD operating systems, and it is used by the
-Mozilla Firefox web browser on Microsoft Windows-related platforms. Depending
-on your needs, one of the other divergent versions may suit your needs better
-than this distribution.
-
-The COPYING file contains copyright and licensing information.
-
-The INSTALL file contains information on how to configure, build, and install
-jemalloc.
-
-The ChangeLog file contains a brief summary of changes for each release.
-
-URL: http://www.canonware.com/jemalloc/
diff --git a/extra/jemalloc/VERSION b/extra/jemalloc/VERSION
deleted file mode 100644
index 900c82d1043..00000000000
--- a/extra/jemalloc/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-3.3.1-0-g9ef9d9e8c271cdf14f664b871a8f98c827714784
diff --git a/extra/jemalloc/autogen.sh b/extra/jemalloc/autogen.sh
deleted file mode 100755
index 75f32da6873..00000000000
--- a/extra/jemalloc/autogen.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-for i in autoconf; do
- echo "$i"
- $i
- if [ $? -ne 0 ]; then
- echo "Error $? in $i"
- exit 1
- fi
-done
-
-echo "./configure --enable-autogen $@"
-./configure --enable-autogen $@
-if [ $? -ne 0 ]; then
- echo "Error $? in ./configure"
- exit 1
-fi
diff --git a/extra/jemalloc/bin/jemalloc.sh b/extra/jemalloc/bin/jemalloc.sh
deleted file mode 100644
index 7c9f1b530da..00000000000
--- a/extra/jemalloc/bin/jemalloc.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-prefix=/usr/local
-exec_prefix=/usr/local
-libdir=${exec_prefix}/lib
-
-LD_PRELOAD=${libdir}/libjemalloc.so.1
-export LD_PRELOAD
-exec "$@"
diff --git a/extra/jemalloc/bin/jemalloc.sh.in b/extra/jemalloc/bin/jemalloc.sh.in
deleted file mode 100644
index cdf36737591..00000000000
--- a/extra/jemalloc/bin/jemalloc.sh.in
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-
-@LD_PRELOAD_VAR@=${libdir}/libjemalloc.@SOREV@
-export @LD_PRELOAD_VAR@
-exec "$@"
diff --git a/extra/jemalloc/bin/pprof b/extra/jemalloc/bin/pprof
deleted file mode 100755
index 727eb43704f..00000000000
--- a/extra/jemalloc/bin/pprof
+++ /dev/null
@@ -1,5348 +0,0 @@
-#! /usr/bin/env perl
-
-# Copyright (c) 1998-2007, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# ---
-# Program for printing the profile generated by common/profiler.cc,
-# or by the heap profiler (common/debugallocation.cc)
-#
-# The profile contains a sequence of entries of the form:
-# <count> <stack trace>
-# This program parses the profile, and generates user-readable
-# output.
-#
-# Examples:
-#
-# % tools/pprof "program" "profile"
-# Enters "interactive" mode
-#
-# % tools/pprof --text "program" "profile"
-# Generates one line per procedure
-#
-# % tools/pprof --gv "program" "profile"
-# Generates annotated call-graph and displays via "gv"
-#
-# % tools/pprof --gv --focus=Mutex "program" "profile"
-# Restrict to code paths that involve an entry that matches "Mutex"
-#
-# % tools/pprof --gv --focus=Mutex --ignore=string "program" "profile"
-# Restrict to code paths that involve an entry that matches "Mutex"
-# and does not match "string"
-#
-# % tools/pprof --list=IBF_CheckDocid "program" "profile"
-# Generates disassembly listing of all routines with at least one
-# sample that match the --list=<regexp> pattern. The listing is
-# annotated with the flat and cumulative sample counts at each line.
-#
-# % tools/pprof --disasm=IBF_CheckDocid "program" "profile"
-# Generates disassembly listing of all routines with at least one
-# sample that match the --disasm=<regexp> pattern. The listing is
-# annotated with the flat and cumulative sample counts at each PC value.
-#
-# TODO: Use color to indicate files?
-
-use strict;
-use warnings;
-use Getopt::Long;
-
-my $PPROF_VERSION = "2.0";
-
-# These are the object tools we use which can come from a
-# user-specified location using --tools, from the PPROF_TOOLS
-# environment variable, or from the environment.
-my %obj_tool_map = (
- "objdump" => "objdump",
- "nm" => "nm",
- "addr2line" => "addr2line",
- "c++filt" => "c++filt",
- ## ConfigureObjTools may add architecture-specific entries:
- #"nm_pdb" => "nm-pdb", # for reading windows (PDB-format) executables
- #"addr2line_pdb" => "addr2line-pdb", # ditto
- #"otool" => "otool", # equivalent of objdump on OS X
-);
-# NOTE: these are lists, so you can put in commandline flags if you want.
-my @DOT = ("dot"); # leave non-absolute, since it may be in /usr/local
-my @GV = ("gv");
-my @EVINCE = ("evince"); # could also be xpdf or perhaps acroread
-my @KCACHEGRIND = ("kcachegrind");
-my @PS2PDF = ("ps2pdf");
-# These are used for dynamic profiles
-my @URL_FETCHER = ("curl", "-s");
-
-# These are the web pages that servers need to support for dynamic profiles
-my $HEAP_PAGE = "/pprof/heap";
-my $PROFILE_PAGE = "/pprof/profile"; # must support cgi-param "?seconds=#"
-my $PMUPROFILE_PAGE = "/pprof/pmuprofile(?:\\?.*)?"; # must support cgi-param
- # ?seconds=#&event=x&period=n
-my $GROWTH_PAGE = "/pprof/growth";
-my $CONTENTION_PAGE = "/pprof/contention";
-my $WALL_PAGE = "/pprof/wall(?:\\?.*)?"; # accepts options like namefilter
-my $FILTEREDPROFILE_PAGE = "/pprof/filteredprofile(?:\\?.*)?";
-my $CENSUSPROFILE_PAGE = "/pprof/censusprofile(?:\\?.*)?"; # must support cgi-param
- # "?seconds=#",
- # "?tags_regexp=#" and
- # "?type=#".
-my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST
-my $PROGRAM_NAME_PAGE = "/pprof/cmdline";
-
-# These are the web pages that can be named on the command line.
-# All the alternatives must begin with /.
-my $PROFILES = "($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|" .
- "$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|" .
- "$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)";
-
-# default binary name
-my $UNKNOWN_BINARY = "(unknown)";
-
-# There is a pervasive dependency on the length (in hex characters,
-# i.e., nibbles) of an address, distinguishing between 32-bit and
-# 64-bit profiles. To err on the safe size, default to 64-bit here:
-my $address_length = 16;
-
-my $dev_null = "/dev/null";
-if (! -e $dev_null && $^O =~ /MSWin/) { # $^O is the OS perl was built for
- $dev_null = "nul";
-}
-
-# A list of paths to search for shared object files
-my @prefix_list = ();
-
-# Special routine name that should not have any symbols.
-# Used as separator to parse "addr2line -i" output.
-my $sep_symbol = '_fini';
-my $sep_address = undef;
-
-##### Argument parsing #####
-
-sub usage_string {
- return <<EOF;
-Usage:
-pprof [options] <program> <profiles>
- <profiles> is a space separated list of profile names.
-pprof [options] <symbolized-profiles>
- <symbolized-profiles> is a list of profile files where each file contains
- the necessary symbol mappings as well as profile data (likely generated
- with --raw).
-pprof [options] <profile>
- <profile> is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE
-
- Each name can be:
- /path/to/profile - a path to a profile file
- host:port[/<service>] - a location of a service to get profile from
-
- The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,
- $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,
- $CENSUSPROFILE_PAGE, or /pprof/filteredprofile.
- For instance:
- pprof http://myserver.com:80$HEAP_PAGE
- If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).
-pprof --symbols <program>
- Maps addresses to symbol names. In this mode, stdin should be a
- list of library mappings, in the same format as is found in the heap-
- and cpu-profile files (this loosely matches that of /proc/self/maps
- on linux), followed by a list of hex addresses to map, one per line.
-
- For more help with querying remote servers, including how to add the
- necessary server-side support code, see this filename (or one like it):
-
- /usr/doc/gperftools-$PPROF_VERSION/pprof_remote_servers.html
-
-Options:
- --cum Sort by cumulative data
- --base=<base> Subtract <base> from <profile> before display
- --interactive Run in interactive mode (interactive "help" gives help) [default]
- --seconds=<n> Length of time for dynamic profiles [default=30 secs]
- --add_lib=<file> Read additional symbols and line info from the given library
- --lib_prefix=<dir> Comma separated list of library path prefixes
-
-Reporting Granularity:
- --addresses Report at address level
- --lines Report at source line level
- --functions Report at function level [default]
- --files Report at source file level
-
-Output type:
- --text Generate text report
- --callgrind Generate callgrind format to stdout
- --gv Generate Postscript and display
- --evince Generate PDF and display
- --web Generate SVG and display
- --list=<regexp> Generate source listing of matching routines
- --disasm=<regexp> Generate disassembly of matching routines
- --symbols Print demangled symbol names found at given addresses
- --dot Generate DOT file to stdout
- --ps Generate Postcript to stdout
- --pdf Generate PDF to stdout
- --svg Generate SVG to stdout
- --gif Generate GIF to stdout
- --raw Generate symbolized pprof data (useful with remote fetch)
-
-Heap-Profile Options:
- --inuse_space Display in-use (mega)bytes [default]
- --inuse_objects Display in-use objects
- --alloc_space Display allocated (mega)bytes
- --alloc_objects Display allocated objects
- --show_bytes Display space in bytes
- --drop_negative Ignore negative differences
-
-Contention-profile options:
- --total_delay Display total delay at each region [default]
- --contentions Display number of delays at each region
- --mean_delay Display mean delay at each region
-
-Call-graph Options:
- --nodecount=<n> Show at most so many nodes [default=80]
- --nodefraction=<f> Hide nodes below <f>*total [default=.005]
- --edgefraction=<f> Hide edges below <f>*total [default=.001]
- --maxdegree=<n> Max incoming/outgoing edges per node [default=8]
- --focus=<regexp> Focus on nodes matching <regexp>
- --ignore=<regexp> Ignore nodes matching <regexp>
- --scale=<n> Set GV scaling [default=0]
- --heapcheck Make nodes with non-0 object counts
- (i.e. direct leak generators) more visible
-
-Miscellaneous:
- --tools=<prefix or binary:fullpath>[,...] \$PATH for object tool pathnames
- --test Run unit tests
- --help This message
- --version Version information
-
-Environment Variables:
- PPROF_TMPDIR Profiles directory. Defaults to \$HOME/pprof
- PPROF_TOOLS Prefix for object tools pathnames
-
-Examples:
-
-pprof /bin/ls ls.prof
- Enters "interactive" mode
-pprof --text /bin/ls ls.prof
- Outputs one line per procedure
-pprof --web /bin/ls ls.prof
- Displays annotated call-graph in web browser
-pprof --gv /bin/ls ls.prof
- Displays annotated call-graph via 'gv'
-pprof --gv --focus=Mutex /bin/ls ls.prof
- Restricts to code paths including a .*Mutex.* entry
-pprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof
- Code paths including Mutex but not string
-pprof --list=getdir /bin/ls ls.prof
- (Per-line) annotated source listing for getdir()
-pprof --disasm=getdir /bin/ls ls.prof
- (Per-PC) annotated disassembly for getdir()
-
-pprof http://localhost:1234/
- Enters "interactive" mode
-pprof --text localhost:1234
- Outputs one line per procedure for localhost:1234
-pprof --raw localhost:1234 > ./local.raw
-pprof --text ./local.raw
- Fetches a remote profile for later analysis and then
- analyzes it in text mode.
-EOF
-}
-
-sub version_string {
- return <<EOF
-pprof (part of gperftools $PPROF_VERSION)
-
-Copyright 1998-2007 Google Inc.
-
-This is BSD licensed software; see the source for copying conditions
-and license information.
-There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE.
-EOF
-}
-
-sub usage {
- my $msg = shift;
- print STDERR "$msg\n\n";
- print STDERR usage_string();
- print STDERR "\nFATAL ERROR: $msg\n"; # just as a reminder
- exit(1);
-}
-
-sub Init() {
- # Setup tmp-file name and handler to clean it up.
- # We do this in the very beginning so that we can use
- # error() and cleanup() function anytime here after.
- $main::tmpfile_sym = "/tmp/pprof$$.sym";
- $main::tmpfile_ps = "/tmp/pprof$$";
- $main::next_tmpfile = 0;
- $SIG{'INT'} = \&sighandler;
-
- # Cache from filename/linenumber to source code
- $main::source_cache = ();
-
- $main::opt_help = 0;
- $main::opt_version = 0;
-
- $main::opt_cum = 0;
- $main::opt_base = '';
- $main::opt_addresses = 0;
- $main::opt_lines = 0;
- $main::opt_functions = 0;
- $main::opt_files = 0;
- $main::opt_lib_prefix = "";
-
- $main::opt_text = 0;
- $main::opt_callgrind = 0;
- $main::opt_list = "";
- $main::opt_disasm = "";
- $main::opt_symbols = 0;
- $main::opt_gv = 0;
- $main::opt_evince = 0;
- $main::opt_web = 0;
- $main::opt_dot = 0;
- $main::opt_ps = 0;
- $main::opt_pdf = 0;
- $main::opt_gif = 0;
- $main::opt_svg = 0;
- $main::opt_raw = 0;
-
- $main::opt_nodecount = 80;
- $main::opt_nodefraction = 0.005;
- $main::opt_edgefraction = 0.001;
- $main::opt_maxdegree = 8;
- $main::opt_focus = '';
- $main::opt_ignore = '';
- $main::opt_scale = 0;
- $main::opt_heapcheck = 0;
- $main::opt_seconds = 30;
- $main::opt_lib = "";
-
- $main::opt_inuse_space = 0;
- $main::opt_inuse_objects = 0;
- $main::opt_alloc_space = 0;
- $main::opt_alloc_objects = 0;
- $main::opt_show_bytes = 0;
- $main::opt_drop_negative = 0;
- $main::opt_interactive = 0;
-
- $main::opt_total_delay = 0;
- $main::opt_contentions = 0;
- $main::opt_mean_delay = 0;
-
- $main::opt_tools = "";
- $main::opt_debug = 0;
- $main::opt_test = 0;
-
- # These are undocumented flags used only by unittests.
- $main::opt_test_stride = 0;
-
- # Are we using $SYMBOL_PAGE?
- $main::use_symbol_page = 0;
-
- # Files returned by TempName.
- %main::tempnames = ();
-
- # Type of profile we are dealing with
- # Supported types:
- # cpu
- # heap
- # growth
- # contention
- $main::profile_type = ''; # Empty type means "unknown"
-
- GetOptions("help!" => \$main::opt_help,
- "version!" => \$main::opt_version,
- "cum!" => \$main::opt_cum,
- "base=s" => \$main::opt_base,
- "seconds=i" => \$main::opt_seconds,
- "add_lib=s" => \$main::opt_lib,
- "lib_prefix=s" => \$main::opt_lib_prefix,
- "functions!" => \$main::opt_functions,
- "lines!" => \$main::opt_lines,
- "addresses!" => \$main::opt_addresses,
- "files!" => \$main::opt_files,
- "text!" => \$main::opt_text,
- "callgrind!" => \$main::opt_callgrind,
- "list=s" => \$main::opt_list,
- "disasm=s" => \$main::opt_disasm,
- "symbols!" => \$main::opt_symbols,
- "gv!" => \$main::opt_gv,
- "evince!" => \$main::opt_evince,
- "web!" => \$main::opt_web,
- "dot!" => \$main::opt_dot,
- "ps!" => \$main::opt_ps,
- "pdf!" => \$main::opt_pdf,
- "svg!" => \$main::opt_svg,
- "gif!" => \$main::opt_gif,
- "raw!" => \$main::opt_raw,
- "interactive!" => \$main::opt_interactive,
- "nodecount=i" => \$main::opt_nodecount,
- "nodefraction=f" => \$main::opt_nodefraction,
- "edgefraction=f" => \$main::opt_edgefraction,
- "maxdegree=i" => \$main::opt_maxdegree,
- "focus=s" => \$main::opt_focus,
- "ignore=s" => \$main::opt_ignore,
- "scale=i" => \$main::opt_scale,
- "heapcheck" => \$main::opt_heapcheck,
- "inuse_space!" => \$main::opt_inuse_space,
- "inuse_objects!" => \$main::opt_inuse_objects,
- "alloc_space!" => \$main::opt_alloc_space,
- "alloc_objects!" => \$main::opt_alloc_objects,
- "show_bytes!" => \$main::opt_show_bytes,
- "drop_negative!" => \$main::opt_drop_negative,
- "total_delay!" => \$main::opt_total_delay,
- "contentions!" => \$main::opt_contentions,
- "mean_delay!" => \$main::opt_mean_delay,
- "tools=s" => \$main::opt_tools,
- "test!" => \$main::opt_test,
- "debug!" => \$main::opt_debug,
- # Undocumented flags used only by unittests:
- "test_stride=i" => \$main::opt_test_stride,
- ) || usage("Invalid option(s)");
-
- # Deal with the standard --help and --version
- if ($main::opt_help) {
- print usage_string();
- exit(0);
- }
-
- if ($main::opt_version) {
- print version_string();
- exit(0);
- }
-
- # Disassembly/listing/symbols mode requires address-level info
- if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) {
- $main::opt_functions = 0;
- $main::opt_lines = 0;
- $main::opt_addresses = 1;
- $main::opt_files = 0;
- }
-
- # Check heap-profiling flags
- if ($main::opt_inuse_space +
- $main::opt_inuse_objects +
- $main::opt_alloc_space +
- $main::opt_alloc_objects > 1) {
- usage("Specify at most on of --inuse/--alloc options");
- }
-
- # Check output granularities
- my $grains =
- $main::opt_functions +
- $main::opt_lines +
- $main::opt_addresses +
- $main::opt_files +
- 0;
- if ($grains > 1) {
- usage("Only specify one output granularity option");
- }
- if ($grains == 0) {
- $main::opt_functions = 1;
- }
-
- # Check output modes
- my $modes =
- $main::opt_text +
- $main::opt_callgrind +
- ($main::opt_list eq '' ? 0 : 1) +
- ($main::opt_disasm eq '' ? 0 : 1) +
- ($main::opt_symbols == 0 ? 0 : 1) +
- $main::opt_gv +
- $main::opt_evince +
- $main::opt_web +
- $main::opt_dot +
- $main::opt_ps +
- $main::opt_pdf +
- $main::opt_svg +
- $main::opt_gif +
- $main::opt_raw +
- $main::opt_interactive +
- 0;
- if ($modes > 1) {
- usage("Only specify one output mode");
- }
- if ($modes == 0) {
- if (-t STDOUT) { # If STDOUT is a tty, activate interactive mode
- $main::opt_interactive = 1;
- } else {
- $main::opt_text = 1;
- }
- }
-
- if ($main::opt_test) {
- RunUnitTests();
- # Should not return
- exit(1);
- }
-
- # Binary name and profile arguments list
- $main::prog = "";
- @main::pfile_args = ();
-
- # Remote profiling without a binary (using $SYMBOL_PAGE instead)
- if (@ARGV > 0) {
- if (IsProfileURL($ARGV[0])) {
- $main::use_symbol_page = 1;
- } elsif (IsSymbolizedProfileFile($ARGV[0])) {
- $main::use_symbolized_profile = 1;
- $main::prog = $UNKNOWN_BINARY; # will be set later from the profile file
- }
- }
-
- if ($main::use_symbol_page || $main::use_symbolized_profile) {
- # We don't need a binary!
- my %disabled = ('--lines' => $main::opt_lines,
- '--disasm' => $main::opt_disasm);
- for my $option (keys %disabled) {
- usage("$option cannot be used without a binary") if $disabled{$option};
- }
- # Set $main::prog later...
- scalar(@ARGV) || usage("Did not specify profile file");
- } elsif ($main::opt_symbols) {
- # --symbols needs a binary-name (to run nm on, etc) but not profiles
- $main::prog = shift(@ARGV) || usage("Did not specify program");
- } else {
- $main::prog = shift(@ARGV) || usage("Did not specify program");
- scalar(@ARGV) || usage("Did not specify profile file");
- }
-
- # Parse profile file/location arguments
- foreach my $farg (@ARGV) {
- if ($farg =~ m/(.*)\@([0-9]+)(|\/.*)$/ ) {
- my $machine = $1;
- my $num_machines = $2;
- my $path = $3;
- for (my $i = 0; $i < $num_machines; $i++) {
- unshift(@main::pfile_args, "$i.$machine$path");
- }
- } else {
- unshift(@main::pfile_args, $farg);
- }
- }
-
- if ($main::use_symbol_page) {
- unless (IsProfileURL($main::pfile_args[0])) {
- error("The first profile should be a remote form to use $SYMBOL_PAGE\n");
- }
- CheckSymbolPage();
- $main::prog = FetchProgramName();
- } elsif (!$main::use_symbolized_profile) { # may not need objtools!
- ConfigureObjTools($main::prog)
- }
-
- # Break the opt_lib_prefix into the prefix_list array
- @prefix_list = split (',', $main::opt_lib_prefix);
-
- # Remove trailing / from the prefixes, in the list to prevent
- # searching things like /my/path//lib/mylib.so
- foreach (@prefix_list) {
- s|/+$||;
- }
-}
-
-sub Main() {
- Init();
- $main::collected_profile = undef;
- @main::profile_files = ();
- $main::op_time = time();
-
- # Printing symbols is special and requires a lot less info that most.
- if ($main::opt_symbols) {
- PrintSymbols(*STDIN); # Get /proc/maps and symbols output from stdin
- return;
- }
-
- # Fetch all profile data
- FetchDynamicProfiles();
-
- # this will hold symbols that we read from the profile files
- my $symbol_map = {};
-
- # Read one profile, pick the last item on the list
- my $data = ReadProfile($main::prog, pop(@main::profile_files));
- my $profile = $data->{profile};
- my $pcs = $data->{pcs};
- my $libs = $data->{libs}; # Info about main program and shared libraries
- $symbol_map = MergeSymbols($symbol_map, $data->{symbols});
-
- # Add additional profiles, if available.
- if (scalar(@main::profile_files) > 0) {
- foreach my $pname (@main::profile_files) {
- my $data2 = ReadProfile($main::prog, $pname);
- $profile = AddProfile($profile, $data2->{profile});
- $pcs = AddPcs($pcs, $data2->{pcs});
- $symbol_map = MergeSymbols($symbol_map, $data2->{symbols});
- }
- }
-
- # Subtract base from profile, if specified
- if ($main::opt_base ne '') {
- my $base = ReadProfile($main::prog, $main::opt_base);
- $profile = SubtractProfile($profile, $base->{profile});
- $pcs = AddPcs($pcs, $base->{pcs});
- $symbol_map = MergeSymbols($symbol_map, $base->{symbols});
- }
-
- # Get total data in profile
- my $total = TotalProfile($profile);
-
- # Collect symbols
- my $symbols;
- if ($main::use_symbolized_profile) {
- $symbols = FetchSymbols($pcs, $symbol_map);
- } elsif ($main::use_symbol_page) {
- $symbols = FetchSymbols($pcs);
- } else {
- # TODO(csilvers): $libs uses the /proc/self/maps data from profile1,
- # which may differ from the data from subsequent profiles, especially
- # if they were run on different machines. Use appropriate libs for
- # each pc somehow.
- $symbols = ExtractSymbols($libs, $pcs);
- }
-
- # Remove uniniteresting stack items
- $profile = RemoveUninterestingFrames($symbols, $profile);
-
- # Focus?
- if ($main::opt_focus ne '') {
- $profile = FocusProfile($symbols, $profile, $main::opt_focus);
- }
-
- # Ignore?
- if ($main::opt_ignore ne '') {
- $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore);
- }
-
- my $calls = ExtractCalls($symbols, $profile);
-
- # Reduce profiles to required output granularity, and also clean
- # each stack trace so a given entry exists at most once.
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- # Print
- if (!$main::opt_interactive) {
- if ($main::opt_disasm) {
- PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm);
- } elsif ($main::opt_list) {
- PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0);
- } elsif ($main::opt_text) {
- # Make sure the output is empty when have nothing to report
- # (only matters when --heapcheck is given but we must be
- # compatible with old branches that did not pass --heapcheck always):
- if ($total != 0) {
- printf("Total: %s %s\n", Unparse($total), Units());
- }
- PrintText($symbols, $flat, $cumulative, -1);
- } elsif ($main::opt_raw) {
- PrintSymbolizedProfile($symbols, $profile, $main::prog);
- } elsif ($main::opt_callgrind) {
- PrintCallgrind($calls);
- } else {
- if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
- if ($main::opt_gv) {
- RunGV(TempName($main::next_tmpfile, "ps"), "");
- } elsif ($main::opt_evince) {
- RunEvince(TempName($main::next_tmpfile, "pdf"), "");
- } elsif ($main::opt_web) {
- my $tmp = TempName($main::next_tmpfile, "svg");
- RunWeb($tmp);
- # The command we run might hand the file name off
- # to an already running browser instance and then exit.
- # Normally, we'd remove $tmp on exit (right now),
- # but fork a child to remove $tmp a little later, so that the
- # browser has time to load it first.
- delete $main::tempnames{$tmp};
- if (fork() == 0) {
- sleep 5;
- unlink($tmp);
- exit(0);
- }
- }
- } else {
- cleanup();
- exit(1);
- }
- }
- } else {
- InteractiveMode($profile, $symbols, $libs, $total);
- }
-
- cleanup();
- exit(0);
-}
-
-##### Entry Point #####
-
-Main();
-
-# Temporary code to detect if we're running on a Goobuntu system.
-# These systems don't have the right stuff installed for the special
-# Readline libraries to work, so as a temporary workaround, we default
-# to using the normal stdio code, rather than the fancier readline-based
-# code
-sub ReadlineMightFail {
- if (-e '/lib/libtermcap.so.2') {
- return 0; # libtermcap exists, so readline should be okay
- } else {
- return 1;
- }
-}
-
-sub RunGV {
- my $fname = shift;
- my $bg = shift; # "" or " &" if we should run in background
- if (!system(ShellEscape(@GV, "--version") . " >$dev_null 2>&1")) {
- # Options using double dash are supported by this gv version.
- # Also, turn on noantialias to better handle bug in gv for
- # postscript files with large dimensions.
- # TODO: Maybe we should not pass the --noantialias flag
- # if the gv version is known to work properly without the flag.
- system(ShellEscape(@GV, "--scale=$main::opt_scale", "--noantialias", $fname)
- . $bg);
- } else {
- # Old gv version - only supports options that use single dash.
- print STDERR ShellEscape(@GV, "-scale", $main::opt_scale) . "\n";
- system(ShellEscape(@GV, "-scale", "$main::opt_scale", $fname) . $bg);
- }
-}
-
-sub RunEvince {
- my $fname = shift;
- my $bg = shift; # "" or " &" if we should run in background
- system(ShellEscape(@EVINCE, $fname) . $bg);
-}
-
-sub RunWeb {
- my $fname = shift;
- print STDERR "Loading web page file:///$fname\n";
-
- if (`uname` =~ /Darwin/) {
- # OS X: open will use standard preference for SVG files.
- system("/usr/bin/open", $fname);
- return;
- }
-
- # Some kind of Unix; try generic symlinks, then specific browsers.
- # (Stop once we find one.)
- # Works best if the browser is already running.
- my @alt = (
- "/etc/alternatives/gnome-www-browser",
- "/etc/alternatives/x-www-browser",
- "google-chrome",
- "firefox",
- );
- foreach my $b (@alt) {
- if (system($b, $fname) == 0) {
- return;
- }
- }
-
- print STDERR "Could not load web browser.\n";
-}
-
-sub RunKcachegrind {
- my $fname = shift;
- my $bg = shift; # "" or " &" if we should run in background
- print STDERR "Starting '@KCACHEGRIND " . $fname . $bg . "'\n";
- system(ShellEscape(@KCACHEGRIND, $fname) . $bg);
-}
-
-
-##### Interactive helper routines #####
-
-sub InteractiveMode {
- $| = 1; # Make output unbuffered for interactive mode
- my ($orig_profile, $symbols, $libs, $total) = @_;
-
- print STDERR "Welcome to pprof! For help, type 'help'.\n";
-
- # Use ReadLine if it's installed and input comes from a console.
- if ( -t STDIN &&
- !ReadlineMightFail() &&
- defined(eval {require Term::ReadLine}) ) {
- my $term = new Term::ReadLine 'pprof';
- while ( defined ($_ = $term->readline('(pprof) '))) {
- $term->addhistory($_) if /\S/;
- if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {
- last; # exit when we get an interactive command to quit
- }
- }
- } else { # don't have readline
- while (1) {
- print STDERR "(pprof) ";
- $_ = <STDIN>;
- last if ! defined $_ ;
- s/\r//g; # turn windows-looking lines into unix-looking lines
-
- # Save some flags that might be reset by InteractiveCommand()
- my $save_opt_lines = $main::opt_lines;
-
- if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) {
- last; # exit when we get an interactive command to quit
- }
-
- # Restore flags
- $main::opt_lines = $save_opt_lines;
- }
- }
-}
-
-# Takes two args: orig profile, and command to run.
-# Returns 1 if we should keep going, or 0 if we were asked to quit
-sub InteractiveCommand {
- my($orig_profile, $symbols, $libs, $total, $command) = @_;
- $_ = $command; # just to make future m//'s easier
- if (!defined($_)) {
- print STDERR "\n";
- return 0;
- }
- if (m/^\s*quit/) {
- return 0;
- }
- if (m/^\s*help/) {
- InteractiveHelpMessage();
- return 1;
- }
- # Clear all the mode options -- mode is controlled by "$command"
- $main::opt_text = 0;
- $main::opt_callgrind = 0;
- $main::opt_disasm = 0;
- $main::opt_list = 0;
- $main::opt_gv = 0;
- $main::opt_evince = 0;
- $main::opt_cum = 0;
-
- if (m/^\s*(text|top)(\d*)\s*(.*)/) {
- $main::opt_text = 1;
-
- my $line_limit = ($2 ne "") ? int($2) : 10;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($3);
-
- my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- PrintText($symbols, $flat, $cumulative, $line_limit);
- return 1;
- }
- if (m/^\s*callgrind\s*([^ \n]*)/) {
- $main::opt_callgrind = 1;
-
- # Get derived profiles
- my $calls = ExtractCalls($symbols, $orig_profile);
- my $filename = $1;
- if ( $1 eq '' ) {
- $filename = TempName($main::next_tmpfile, "callgrind");
- }
- PrintCallgrind($calls, $filename);
- if ( $1 eq '' ) {
- RunKcachegrind($filename, " & ");
- $main::next_tmpfile++;
- }
-
- return 1;
- }
- if (m/^\s*(web)?list\s*(.+)/) {
- my $html = (defined($1) && ($1 eq "web"));
- $main::opt_list = 1;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($2);
-
- my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- PrintListing($total, $libs, $flat, $cumulative, $routine, $html);
- return 1;
- }
- if (m/^\s*disasm\s*(.+)/) {
- $main::opt_disasm = 1;
-
- my $routine;
- my $ignore;
- ($routine, $ignore) = ParseInteractiveArgs($1);
-
- # Process current profile to account for various settings
- my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- PrintDisassembly($libs, $flat, $cumulative, $routine);
- return 1;
- }
- if (m/^\s*(gv|web|evince)\s*(.*)/) {
- $main::opt_gv = 0;
- $main::opt_evince = 0;
- $main::opt_web = 0;
- if ($1 eq "gv") {
- $main::opt_gv = 1;
- } elsif ($1 eq "evince") {
- $main::opt_evince = 1;
- } elsif ($1 eq "web") {
- $main::opt_web = 1;
- }
-
- my $focus;
- my $ignore;
- ($focus, $ignore) = ParseInteractiveArgs($2);
-
- # Process current profile to account for various settings
- my $profile = ProcessProfile($total, $orig_profile, $symbols,
- $focus, $ignore);
- my $reduced = ReduceProfile($symbols, $profile);
-
- # Get derived profiles
- my $flat = FlatProfile($reduced);
- my $cumulative = CumulativeProfile($reduced);
-
- if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) {
- if ($main::opt_gv) {
- RunGV(TempName($main::next_tmpfile, "ps"), " &");
- } elsif ($main::opt_evince) {
- RunEvince(TempName($main::next_tmpfile, "pdf"), " &");
- } elsif ($main::opt_web) {
- RunWeb(TempName($main::next_tmpfile, "svg"));
- }
- $main::next_tmpfile++;
- }
- return 1;
- }
- if (m/^\s*$/) {
- return 1;
- }
- print STDERR "Unknown command: try 'help'.\n";
- return 1;
-}
-
-
-sub ProcessProfile {
- my $total_count = shift;
- my $orig_profile = shift;
- my $symbols = shift;
- my $focus = shift;
- my $ignore = shift;
-
- # Process current profile to account for various settings
- my $profile = $orig_profile;
- printf("Total: %s %s\n", Unparse($total_count), Units());
- if ($focus ne '') {
- $profile = FocusProfile($symbols, $profile, $focus);
- my $focus_count = TotalProfile($profile);
- printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
- $focus,
- Unparse($focus_count), Units(),
- Unparse($total_count), ($focus_count*100.0) / $total_count);
- }
- if ($ignore ne '') {
- $profile = IgnoreProfile($symbols, $profile, $ignore);
- my $ignore_count = TotalProfile($profile);
- printf("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
- $ignore,
- Unparse($ignore_count), Units(),
- Unparse($total_count),
- ($ignore_count*100.0) / $total_count);
- }
-
- return $profile;
-}
-
-sub InteractiveHelpMessage {
- print STDERR <<ENDOFHELP;
-Interactive pprof mode
-
-Commands:
- gv
- gv [focus] [-ignore1] [-ignore2]
- Show graphical hierarchical display of current profile. Without
- any arguments, shows all samples in the profile. With the optional
- "focus" argument, restricts the samples shown to just those where
- the "focus" regular expression matches a routine name on the stack
- trace.
-
- web
- web [focus] [-ignore1] [-ignore2]
- Like GV, but displays profile in your web browser instead of using
- Ghostview. Works best if your web browser is already running.
- To change the browser that gets used:
- On Linux, set the /etc/alternatives/gnome-www-browser symlink.
- On OS X, change the Finder association for SVG files.
-
- list [routine_regexp] [-ignore1] [-ignore2]
- Show source listing of routines whose names match "routine_regexp"
-
- weblist [routine_regexp] [-ignore1] [-ignore2]
- Displays a source listing of routines whose names match "routine_regexp"
- in a web browser. You can click on source lines to view the
- corresponding disassembly.
-
- top [--cum] [-ignore1] [-ignore2]
- top20 [--cum] [-ignore1] [-ignore2]
- top37 [--cum] [-ignore1] [-ignore2]
- Show top lines ordered by flat profile count, or cumulative count
- if --cum is specified. If a number is present after 'top', the
- top K routines will be shown (defaults to showing the top 10)
-
- disasm [routine_regexp] [-ignore1] [-ignore2]
- Show disassembly of routines whose names match "routine_regexp",
- annotated with sample counts.
-
- callgrind
- callgrind [filename]
- Generates callgrind file. If no filename is given, kcachegrind is called.
-
- help - This listing
- quit or ^D - End pprof
-
-For commands that accept optional -ignore tags, samples where any routine in
-the stack trace matches the regular expression in any of the -ignore
-parameters will be ignored.
-
-Further pprof details are available at this location (or one similar):
-
- /usr/doc/gperftools-$PPROF_VERSION/cpu_profiler.html
- /usr/doc/gperftools-$PPROF_VERSION/heap_profiler.html
-
-ENDOFHELP
-}
-sub ParseInteractiveArgs {
- my $args = shift;
- my $focus = "";
- my $ignore = "";
- my @x = split(/ +/, $args);
- foreach $a (@x) {
- if ($a =~ m/^(--|-)lines$/) {
- $main::opt_lines = 1;
- } elsif ($a =~ m/^(--|-)cum$/) {
- $main::opt_cum = 1;
- } elsif ($a =~ m/^-(.*)/) {
- $ignore .= (($ignore ne "") ? "|" : "" ) . $1;
- } else {
- $focus .= (($focus ne "") ? "|" : "" ) . $a;
- }
- }
- if ($ignore ne "") {
- print STDERR "Ignoring samples in call stacks that match '$ignore'\n";
- }
- return ($focus, $ignore);
-}
-
-##### Output code #####
-
-sub TempName {
- my $fnum = shift;
- my $ext = shift;
- my $file = "$main::tmpfile_ps.$fnum.$ext";
- $main::tempnames{$file} = 1;
- return $file;
-}
-
-# Print profile data in packed binary format (64-bit) to standard out
-sub PrintProfileData {
- my $profile = shift;
-
- # print header (64-bit style)
- # (zero) (header-size) (version) (sample-period) (zero)
- print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);
-
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- if ($#addrs >= 0) {
- my $depth = $#addrs + 1;
- # int(foo / 2**32) is the only reliable way to get rid of bottom
- # 32 bits on both 32- and 64-bit systems.
- print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32));
- print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32));
-
- foreach my $full_addr (@addrs) {
- my $addr = $full_addr;
- $addr =~ s/0x0*//; # strip off leading 0x, zeroes
- if (length($addr) > 16) {
- print STDERR "Invalid address in profile: $full_addr\n";
- next;
- }
- my $low_addr = substr($addr, -8); # get last 8 hex chars
- my $high_addr = substr($addr, -16, 8); # get up to 8 more hex chars
- print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr));
- }
- }
- }
-}
-
-# Print symbols and profile data
-sub PrintSymbolizedProfile {
- my $symbols = shift;
- my $profile = shift;
- my $prog = shift;
-
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
-
- print '--- ', $symbol_marker, "\n";
- if (defined($prog)) {
- print 'binary=', $prog, "\n";
- }
- while (my ($pc, $name) = each(%{$symbols})) {
- my $sep = ' ';
- print '0x', $pc;
- # We have a list of function names, which include the inlined
- # calls. They are separated (and terminated) by --, which is
- # illegal in function names.
- for (my $j = 2; $j <= $#{$name}; $j += 3) {
- print $sep, $name->[$j];
- $sep = '--';
- }
- print "\n";
- }
- print '---', "\n";
-
- $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $profile_marker = $&;
- print '--- ', $profile_marker, "\n";
- if (defined($main::collected_profile)) {
- # if used with remote fetch, simply dump the collected profile to output.
- open(SRC, "<$main::collected_profile");
- while (<SRC>) {
- print $_;
- }
- close(SRC);
- } else {
- # dump a cpu-format profile to standard out
- PrintProfileData($profile);
- }
-}
-
-# Print text output
-sub PrintText {
- my $symbols = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $line_limit = shift;
-
- my $total = TotalProfile($flat);
-
- # Which profile to sort by?
- my $s = $main::opt_cum ? $cumulative : $flat;
-
- my $running_sum = 0;
- my $lines = 0;
- foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b }
- keys(%{$cumulative})) {
- my $f = GetEntry($flat, $k);
- my $c = GetEntry($cumulative, $k);
- $running_sum += $f;
-
- my $sym = $k;
- if (exists($symbols->{$k})) {
- $sym = $symbols->{$k}->[0] . " " . $symbols->{$k}->[1];
- if ($main::opt_addresses) {
- $sym = $k . " " . $sym;
- }
- }
-
- if ($f != 0 || $c != 0) {
- printf("%8s %6s %6s %8s %6s %s\n",
- Unparse($f),
- Percent($f, $total),
- Percent($running_sum, $total),
- Unparse($c),
- Percent($c, $total),
- $sym);
- }
- $lines++;
- last if ($line_limit >= 0 && $lines >= $line_limit);
- }
-}
-
-# Callgrind format has a compression for repeated function and file
-# names. You show the name the first time, and just use its number
-# subsequently. This can cut down the file to about a third or a
-# quarter of its uncompressed size. $key and $val are the key/value
-# pair that would normally be printed by callgrind; $map is a map from
-# value to number.
-sub CompressedCGName {
- my($key, $val, $map) = @_;
- my $idx = $map->{$val};
- # For very short keys, providing an index hurts rather than helps.
- if (length($val) <= 3) {
- return "$key=$val\n";
- } elsif (defined($idx)) {
- return "$key=($idx)\n";
- } else {
- # scalar(keys $map) gives the number of items in the map.
- $idx = scalar(keys(%{$map})) + 1;
- $map->{$val} = $idx;
- return "$key=($idx) $val\n";
- }
-}
-
-# Print the call graph in a way that's suiteable for callgrind.
-sub PrintCallgrind {
- my $calls = shift;
- my $filename;
- my %filename_to_index_map;
- my %fnname_to_index_map;
-
- if ($main::opt_interactive) {
- $filename = shift;
- print STDERR "Writing callgrind file to '$filename'.\n"
- } else {
- $filename = "&STDOUT";
- }
- open(CG, ">$filename");
- printf CG ("events: Hits\n\n");
- foreach my $call ( map { $_->[0] }
- sort { $a->[1] cmp $b ->[1] ||
- $a->[2] <=> $b->[2] }
- map { /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/;
- [$_, $1, $2] }
- keys %$calls ) {
- my $count = int($calls->{$call});
- $call =~ /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/;
- my ( $caller_file, $caller_line, $caller_function,
- $callee_file, $callee_line, $callee_function ) =
- ( $1, $2, $3, $5, $6, $7 );
-
- # TODO(csilvers): for better compression, collect all the
- # caller/callee_files and functions first, before printing
- # anything, and only compress those referenced more than once.
- printf CG CompressedCGName("fl", $caller_file, \%filename_to_index_map);
- printf CG CompressedCGName("fn", $caller_function, \%fnname_to_index_map);
- if (defined $6) {
- printf CG CompressedCGName("cfl", $callee_file, \%filename_to_index_map);
- printf CG CompressedCGName("cfn", $callee_function, \%fnname_to_index_map);
- printf CG ("calls=$count $callee_line\n");
- }
- printf CG ("$caller_line $count\n\n");
- }
-}
-
-# Print disassembly for all all routines that match $main::opt_disasm
-sub PrintDisassembly {
- my $libs = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $disasm_opts = shift;
-
- my $total = TotalProfile($flat);
-
- foreach my $lib (@{$libs}) {
- my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts);
- my $offset = AddressSub($lib->[1], $lib->[3]);
- foreach my $routine (sort ByName keys(%{$symbol_table})) {
- my $start_addr = $symbol_table->{$routine}->[0];
- my $end_addr = $symbol_table->{$routine}->[1];
- # See if there are any samples in this routine
- my $length = hex(AddressSub($end_addr, $start_addr));
- my $addr = AddressAdd($start_addr, $offset);
- for (my $i = 0; $i < $length; $i++) {
- if (defined($cumulative->{$addr})) {
- PrintDisassembledFunction($lib->[0], $offset,
- $routine, $flat, $cumulative,
- $start_addr, $end_addr, $total);
- last;
- }
- $addr = AddressInc($addr);
- }
- }
- }
-}
-
-# Return reference to array of tuples of the form:
-# [start_address, filename, linenumber, instruction, limit_address]
-# E.g.,
-# ["0x806c43d", "/foo/bar.cc", 131, "ret", "0x806c440"]
-sub Disassemble {
- my $prog = shift;
- my $offset = shift;
- my $start_addr = shift;
- my $end_addr = shift;
-
- my $objdump = $obj_tool_map{"objdump"};
- my $cmd = ShellEscape($objdump, "-C", "-d", "-l", "--no-show-raw-insn",
- "--start-address=0x$start_addr",
- "--stop-address=0x$end_addr", $prog);
- open(OBJDUMP, "$cmd |") || error("$cmd: $!\n");
- my @result = ();
- my $filename = "";
- my $linenumber = -1;
- my $last = ["", "", "", ""];
- while (<OBJDUMP>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- chop;
- if (m|\s*([^:\s]+):(\d+)\s*$|) {
- # Location line of the form:
- # <filename>:<linenumber>
- $filename = $1;
- $linenumber = $2;
- } elsif (m/^ +([0-9a-f]+):\s*(.*)/) {
- # Disassembly line -- zero-extend address to full length
- my $addr = HexExtend($1);
- my $k = AddressAdd($addr, $offset);
- $last->[4] = $k; # Store ending address for previous instruction
- $last = [$k, $filename, $linenumber, $2, $end_addr];
- push(@result, $last);
- }
- }
- close(OBJDUMP);
- return @result;
-}
-
-# The input file should contain lines of the form /proc/maps-like
-# output (same format as expected from the profiles) or that looks
-# like hex addresses (like "0xDEADBEEF"). We will parse all
-# /proc/maps output, and for all the hex addresses, we will output
-# "short" symbol names, one per line, in the same order as the input.
-sub PrintSymbols {
- my $maps_and_symbols_file = shift;
-
- # ParseLibraries expects pcs to be in a set. Fine by us...
- my @pclist = (); # pcs in sorted order
- my $pcs = {};
- my $map = "";
- foreach my $line (<$maps_and_symbols_file>) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- if ($line =~ /\b(0x[0-9a-f]+)\b/i) {
- push(@pclist, HexExtend($1));
- $pcs->{$pclist[-1]} = 1;
- } else {
- $map .= $line;
- }
- }
-
- my $libs = ParseLibraries($main::prog, $map, $pcs);
- my $symbols = ExtractSymbols($libs, $pcs);
-
- foreach my $pc (@pclist) {
- # ->[0] is the shortname, ->[2] is the full name
- print(($symbols->{$pc}->[0] || "??") . "\n");
- }
-}
-
-
-# For sorting functions by name
-sub ByName {
- return ShortFunctionName($a) cmp ShortFunctionName($b);
-}
-
-# Print source-listing for all all routines that match $list_opts
-sub PrintListing {
- my $total = shift;
- my $libs = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $list_opts = shift;
- my $html = shift;
-
- my $output = \*STDOUT;
- my $fname = "";
-
- if ($html) {
- # Arrange to write the output to a temporary file
- $fname = TempName($main::next_tmpfile, "html");
- $main::next_tmpfile++;
- if (!open(TEMP, ">$fname")) {
- print STDERR "$fname: $!\n";
- return;
- }
- $output = \*TEMP;
- print $output HtmlListingHeader();
- printf $output ("<div class=\"legend\">%s<br>Total: %s %s</div>\n",
- $main::prog, Unparse($total), Units());
- }
-
- my $listed = 0;
- foreach my $lib (@{$libs}) {
- my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts);
- my $offset = AddressSub($lib->[1], $lib->[3]);
- foreach my $routine (sort ByName keys(%{$symbol_table})) {
- # Print if there are any samples in this routine
- my $start_addr = $symbol_table->{$routine}->[0];
- my $end_addr = $symbol_table->{$routine}->[1];
- my $length = hex(AddressSub($end_addr, $start_addr));
- my $addr = AddressAdd($start_addr, $offset);
- for (my $i = 0; $i < $length; $i++) {
- if (defined($cumulative->{$addr})) {
- $listed += PrintSource(
- $lib->[0], $offset,
- $routine, $flat, $cumulative,
- $start_addr, $end_addr,
- $html,
- $output);
- last;
- }
- $addr = AddressInc($addr);
- }
- }
- }
-
- if ($html) {
- if ($listed > 0) {
- print $output HtmlListingFooter();
- close($output);
- RunWeb($fname);
- } else {
- close($output);
- unlink($fname);
- }
- }
-}
-
-sub HtmlListingHeader {
- return <<'EOF';
-<DOCTYPE html>
-<html>
-<head>
-<title>Pprof listing</title>
-<style type="text/css">
-body {
- font-family: sans-serif;
-}
-h1 {
- font-size: 1.5em;
- margin-bottom: 4px;
-}
-.legend {
- font-size: 1.25em;
-}
-.line {
- color: #aaaaaa;
-}
-.nop {
- color: #aaaaaa;
-}
-.unimportant {
- color: #cccccc;
-}
-.disasmloc {
- color: #000000;
-}
-.deadsrc {
- cursor: pointer;
-}
-.deadsrc:hover {
- background-color: #eeeeee;
-}
-.livesrc {
- color: #0000ff;
- cursor: pointer;
-}
-.livesrc:hover {
- background-color: #eeeeee;
-}
-.asm {
- color: #008800;
- display: none;
-}
-</style>
-<script type="text/javascript">
-function pprof_toggle_asm(e) {
- var target;
- if (!e) e = window.event;
- if (e.target) target = e.target;
- else if (e.srcElement) target = e.srcElement;
-
- if (target) {
- var asm = target.nextSibling;
- if (asm && asm.className == "asm") {
- asm.style.display = (asm.style.display == "block" ? "" : "block");
- e.preventDefault();
- return false;
- }
- }
-}
-</script>
-</head>
-<body>
-EOF
-}
-
-sub HtmlListingFooter {
- return <<'EOF';
-</body>
-</html>
-EOF
-}
-
-sub HtmlEscape {
- my $text = shift;
- $text =~ s/&/&amp;/g;
- $text =~ s/</&lt;/g;
- $text =~ s/>/&gt;/g;
- return $text;
-}
-
-# Returns the indentation of the line, if it has any non-whitespace
-# characters. Otherwise, returns -1.
-sub Indentation {
- my $line = shift;
- if (m/^(\s*)\S/) {
- return length($1);
- } else {
- return -1;
- }
-}
-
-# If the symbol table contains inlining info, Disassemble() may tag an
-# instruction with a location inside an inlined function. But for
-# source listings, we prefer to use the location in the function we
-# are listing. So use MapToSymbols() to fetch full location
-# information for each instruction and then pick out the first
-# location from a location list (location list contains callers before
-# callees in case of inlining).
-#
-# After this routine has run, each entry in $instructions contains:
-# [0] start address
-# [1] filename for function we are listing
-# [2] line number for function we are listing
-# [3] disassembly
-# [4] limit address
-# [5] most specific filename (may be different from [1] due to inlining)
-# [6] most specific line number (may be different from [2] due to inlining)
-sub GetTopLevelLineNumbers {
- my ($lib, $offset, $instructions) = @_;
- my $pcs = [];
- for (my $i = 0; $i <= $#{$instructions}; $i++) {
- push(@{$pcs}, $instructions->[$i]->[0]);
- }
- my $symbols = {};
- MapToSymbols($lib, $offset, $pcs, $symbols);
- for (my $i = 0; $i <= $#{$instructions}; $i++) {
- my $e = $instructions->[$i];
- push(@{$e}, $e->[1]);
- push(@{$e}, $e->[2]);
- my $addr = $e->[0];
- my $sym = $symbols->{$addr};
- if (defined($sym)) {
- if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\d+)$/) {
- $e->[1] = $1; # File name
- $e->[2] = $2; # Line number
- }
- }
- }
-}
-
-# Print source-listing for one routine
-sub PrintSource {
- my $prog = shift;
- my $offset = shift;
- my $routine = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $start_addr = shift;
- my $end_addr = shift;
- my $html = shift;
- my $output = shift;
-
- # Disassemble all instructions (just to get line numbers)
- my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);
- GetTopLevelLineNumbers($prog, $offset, \@instructions);
-
- # Hack 1: assume that the first source file encountered in the
- # disassembly contains the routine
- my $filename = undef;
- for (my $i = 0; $i <= $#instructions; $i++) {
- if ($instructions[$i]->[2] >= 0) {
- $filename = $instructions[$i]->[1];
- last;
- }
- }
- if (!defined($filename)) {
- print STDERR "no filename found in $routine\n";
- return 0;
- }
-
- # Hack 2: assume that the largest line number from $filename is the
- # end of the procedure. This is typically safe since if P1 contains
- # an inlined call to P2, then P2 usually occurs earlier in the
- # source file. If this does not work, we might have to compute a
- # density profile or just print all regions we find.
- my $lastline = 0;
- for (my $i = 0; $i <= $#instructions; $i++) {
- my $f = $instructions[$i]->[1];
- my $l = $instructions[$i]->[2];
- if (($f eq $filename) && ($l > $lastline)) {
- $lastline = $l;
- }
- }
-
- # Hack 3: assume the first source location from "filename" is the start of
- # the source code.
- my $firstline = 1;
- for (my $i = 0; $i <= $#instructions; $i++) {
- if ($instructions[$i]->[1] eq $filename) {
- $firstline = $instructions[$i]->[2];
- last;
- }
- }
-
- # Hack 4: Extend last line forward until its indentation is less than
- # the indentation we saw on $firstline
- my $oldlastline = $lastline;
- {
- if (!open(FILE, "<$filename")) {
- print STDERR "$filename: $!\n";
- return 0;
- }
- my $l = 0;
- my $first_indentation = -1;
- while (<FILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $l++;
- my $indent = Indentation($_);
- if ($l >= $firstline) {
- if ($first_indentation < 0 && $indent >= 0) {
- $first_indentation = $indent;
- last if ($first_indentation == 0);
- }
- }
- if ($l >= $lastline && $indent >= 0) {
- if ($indent >= $first_indentation) {
- $lastline = $l+1;
- } else {
- last;
- }
- }
- }
- close(FILE);
- }
-
- # Assign all samples to the range $firstline,$lastline,
- # Hack 4: If an instruction does not occur in the range, its samples
- # are moved to the next instruction that occurs in the range.
- my $samples1 = {}; # Map from line number to flat count
- my $samples2 = {}; # Map from line number to cumulative count
- my $running1 = 0; # Unassigned flat counts
- my $running2 = 0; # Unassigned cumulative counts
- my $total1 = 0; # Total flat counts
- my $total2 = 0; # Total cumulative counts
- my %disasm = (); # Map from line number to disassembly
- my $running_disasm = ""; # Unassigned disassembly
- my $skip_marker = "---\n";
- if ($html) {
- $skip_marker = "";
- for (my $l = $firstline; $l <= $lastline; $l++) {
- $disasm{$l} = "";
- }
- }
- my $last_dis_filename = '';
- my $last_dis_linenum = -1;
- my $last_touched_line = -1; # To detect gaps in disassembly for a line
- foreach my $e (@instructions) {
- # Add up counts for all address that fall inside this instruction
- my $c1 = 0;
- my $c2 = 0;
- for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
- $c1 += GetEntry($flat, $a);
- $c2 += GetEntry($cumulative, $a);
- }
-
- if ($html) {
- my $dis = sprintf(" %6s %6s \t\t%8s: %s ",
- HtmlPrintNumber($c1),
- HtmlPrintNumber($c2),
- UnparseAddress($offset, $e->[0]),
- CleanDisassembly($e->[3]));
-
- # Append the most specific source line associated with this instruction
- if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) };
- $dis = HtmlEscape($dis);
- my $f = $e->[5];
- my $l = $e->[6];
- if ($f ne $last_dis_filename) {
- $dis .= sprintf("<span class=disasmloc>%s:%d</span>",
- HtmlEscape(CleanFileName($f)), $l);
- } elsif ($l ne $last_dis_linenum) {
- # De-emphasize the unchanged file name portion
- $dis .= sprintf("<span class=unimportant>%s</span>" .
- "<span class=disasmloc>:%d</span>",
- HtmlEscape(CleanFileName($f)), $l);
- } else {
- # De-emphasize the entire location
- $dis .= sprintf("<span class=unimportant>%s:%d</span>",
- HtmlEscape(CleanFileName($f)), $l);
- }
- $last_dis_filename = $f;
- $last_dis_linenum = $l;
- $running_disasm .= $dis;
- $running_disasm .= "\n";
- }
-
- $running1 += $c1;
- $running2 += $c2;
- $total1 += $c1;
- $total2 += $c2;
- my $file = $e->[1];
- my $line = $e->[2];
- if (($file eq $filename) &&
- ($line >= $firstline) &&
- ($line <= $lastline)) {
- # Assign all accumulated samples to this line
- AddEntry($samples1, $line, $running1);
- AddEntry($samples2, $line, $running2);
- $running1 = 0;
- $running2 = 0;
- if ($html) {
- if ($line != $last_touched_line && $disasm{$line} ne '') {
- $disasm{$line} .= "\n";
- }
- $disasm{$line} .= $running_disasm;
- $running_disasm = '';
- $last_touched_line = $line;
- }
- }
- }
-
- # Assign any leftover samples to $lastline
- AddEntry($samples1, $lastline, $running1);
- AddEntry($samples2, $lastline, $running2);
- if ($html) {
- if ($lastline != $last_touched_line && $disasm{$lastline} ne '') {
- $disasm{$lastline} .= "\n";
- }
- $disasm{$lastline} .= $running_disasm;
- }
-
- if ($html) {
- printf $output (
- "<h1>%s</h1>%s\n<pre onClick=\"pprof_toggle_asm()\">\n" .
- "Total:%6s %6s (flat / cumulative %s)\n",
- HtmlEscape(ShortFunctionName($routine)),
- HtmlEscape(CleanFileName($filename)),
- Unparse($total1),
- Unparse($total2),
- Units());
- } else {
- printf $output (
- "ROUTINE ====================== %s in %s\n" .
- "%6s %6s Total %s (flat / cumulative)\n",
- ShortFunctionName($routine),
- CleanFileName($filename),
- Unparse($total1),
- Unparse($total2),
- Units());
- }
- if (!open(FILE, "<$filename")) {
- print STDERR "$filename: $!\n";
- return 0;
- }
- my $l = 0;
- while (<FILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $l++;
- if ($l >= $firstline - 5 &&
- (($l <= $oldlastline + 5) || ($l <= $lastline))) {
- chop;
- my $text = $_;
- if ($l == $firstline) { print $output $skip_marker; }
- my $n1 = GetEntry($samples1, $l);
- my $n2 = GetEntry($samples2, $l);
- if ($html) {
- # Emit a span that has one of the following classes:
- # livesrc -- has samples
- # deadsrc -- has disassembly, but with no samples
- # nop -- has no matching disasembly
- # Also emit an optional span containing disassembly.
- my $dis = $disasm{$l};
- my $asm = "";
- if (defined($dis) && $dis ne '') {
- $asm = "<span class=\"asm\">" . $dis . "</span>";
- }
- my $source_class = (($n1 + $n2 > 0)
- ? "livesrc"
- : (($asm ne "") ? "deadsrc" : "nop"));
- printf $output (
- "<span class=\"line\">%5d</span> " .
- "<span class=\"%s\">%6s %6s %s</span>%s\n",
- $l, $source_class,
- HtmlPrintNumber($n1),
- HtmlPrintNumber($n2),
- HtmlEscape($text),
- $asm);
- } else {
- printf $output(
- "%6s %6s %4d: %s\n",
- UnparseAlt($n1),
- UnparseAlt($n2),
- $l,
- $text);
- }
- if ($l == $lastline) { print $output $skip_marker; }
- };
- }
- close(FILE);
- if ($html) {
- print $output "</pre>\n";
- }
- return 1;
-}
-
-# Return the source line for the specified file/linenumber.
-# Returns undef if not found.
-sub SourceLine {
- my $file = shift;
- my $line = shift;
-
- # Look in cache
- if (!defined($main::source_cache{$file})) {
- if (100 < scalar keys(%main::source_cache)) {
- # Clear the cache when it gets too big
- $main::source_cache = ();
- }
-
- # Read all lines from the file
- if (!open(FILE, "<$file")) {
- print STDERR "$file: $!\n";
- $main::source_cache{$file} = []; # Cache the negative result
- return undef;
- }
- my $lines = [];
- push(@{$lines}, ""); # So we can use 1-based line numbers as indices
- while (<FILE>) {
- push(@{$lines}, $_);
- }
- close(FILE);
-
- # Save the lines in the cache
- $main::source_cache{$file} = $lines;
- }
-
- my $lines = $main::source_cache{$file};
- if (($line < 0) || ($line > $#{$lines})) {
- return undef;
- } else {
- return $lines->[$line];
- }
-}
-
-# Print disassembly for one routine with interspersed source if available
-sub PrintDisassembledFunction {
- my $prog = shift;
- my $offset = shift;
- my $routine = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $start_addr = shift;
- my $end_addr = shift;
- my $total = shift;
-
- # Disassemble all instructions
- my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr);
-
- # Make array of counts per instruction
- my @flat_count = ();
- my @cum_count = ();
- my $flat_total = 0;
- my $cum_total = 0;
- foreach my $e (@instructions) {
- # Add up counts for all address that fall inside this instruction
- my $c1 = 0;
- my $c2 = 0;
- for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) {
- $c1 += GetEntry($flat, $a);
- $c2 += GetEntry($cumulative, $a);
- }
- push(@flat_count, $c1);
- push(@cum_count, $c2);
- $flat_total += $c1;
- $cum_total += $c2;
- }
-
- # Print header with total counts
- printf("ROUTINE ====================== %s\n" .
- "%6s %6s %s (flat, cumulative) %.1f%% of total\n",
- ShortFunctionName($routine),
- Unparse($flat_total),
- Unparse($cum_total),
- Units(),
- ($cum_total * 100.0) / $total);
-
- # Process instructions in order
- my $current_file = "";
- for (my $i = 0; $i <= $#instructions; ) {
- my $e = $instructions[$i];
-
- # Print the new file name whenever we switch files
- if ($e->[1] ne $current_file) {
- $current_file = $e->[1];
- my $fname = $current_file;
- $fname =~ s|^\./||; # Trim leading "./"
-
- # Shorten long file names
- if (length($fname) >= 58) {
- $fname = "..." . substr($fname, -55);
- }
- printf("-------------------- %s\n", $fname);
- }
-
- # TODO: Compute range of lines to print together to deal with
- # small reorderings.
- my $first_line = $e->[2];
- my $last_line = $first_line;
- my %flat_sum = ();
- my %cum_sum = ();
- for (my $l = $first_line; $l <= $last_line; $l++) {
- $flat_sum{$l} = 0;
- $cum_sum{$l} = 0;
- }
-
- # Find run of instructions for this range of source lines
- my $first_inst = $i;
- while (($i <= $#instructions) &&
- ($instructions[$i]->[2] >= $first_line) &&
- ($instructions[$i]->[2] <= $last_line)) {
- $e = $instructions[$i];
- $flat_sum{$e->[2]} += $flat_count[$i];
- $cum_sum{$e->[2]} += $cum_count[$i];
- $i++;
- }
- my $last_inst = $i - 1;
-
- # Print source lines
- for (my $l = $first_line; $l <= $last_line; $l++) {
- my $line = SourceLine($current_file, $l);
- if (!defined($line)) {
- $line = "?\n";
- next;
- } else {
- $line =~ s/^\s+//;
- }
- printf("%6s %6s %5d: %s",
- UnparseAlt($flat_sum{$l}),
- UnparseAlt($cum_sum{$l}),
- $l,
- $line);
- }
-
- # Print disassembly
- for (my $x = $first_inst; $x <= $last_inst; $x++) {
- my $e = $instructions[$x];
- printf("%6s %6s %8s: %6s\n",
- UnparseAlt($flat_count[$x]),
- UnparseAlt($cum_count[$x]),
- UnparseAddress($offset, $e->[0]),
- CleanDisassembly($e->[3]));
- }
- }
-}
-
-# Print DOT graph
-sub PrintDot {
- my $prog = shift;
- my $symbols = shift;
- my $raw = shift;
- my $flat = shift;
- my $cumulative = shift;
- my $overall_total = shift;
-
- # Get total
- my $local_total = TotalProfile($flat);
- my $nodelimit = int($main::opt_nodefraction * $local_total);
- my $edgelimit = int($main::opt_edgefraction * $local_total);
- my $nodecount = $main::opt_nodecount;
-
- # Find nodes to include
- my @list = (sort { abs(GetEntry($cumulative, $b)) <=>
- abs(GetEntry($cumulative, $a))
- || $a cmp $b }
- keys(%{$cumulative}));
- my $last = $nodecount - 1;
- if ($last > $#list) {
- $last = $#list;
- }
- while (($last >= 0) &&
- (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) {
- $last--;
- }
- if ($last < 0) {
- print STDERR "No nodes to print\n";
- return 0;
- }
-
- if ($nodelimit > 0 || $edgelimit > 0) {
- printf STDERR ("Dropping nodes with <= %s %s; edges with <= %s abs(%s)\n",
- Unparse($nodelimit), Units(),
- Unparse($edgelimit), Units());
- }
-
- # Open DOT output file
- my $output;
- my $escaped_dot = ShellEscape(@DOT);
- my $escaped_ps2pdf = ShellEscape(@PS2PDF);
- if ($main::opt_gv) {
- my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "ps"));
- $output = "| $escaped_dot -Tps2 >$escaped_outfile";
- } elsif ($main::opt_evince) {
- my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "pdf"));
- $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - $escaped_outfile";
- } elsif ($main::opt_ps) {
- $output = "| $escaped_dot -Tps2";
- } elsif ($main::opt_pdf) {
- $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - -";
- } elsif ($main::opt_web || $main::opt_svg) {
- # We need to post-process the SVG, so write to a temporary file always.
- my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "svg"));
- $output = "| $escaped_dot -Tsvg >$escaped_outfile";
- } elsif ($main::opt_gif) {
- $output = "| $escaped_dot -Tgif";
- } else {
- $output = ">&STDOUT";
- }
- open(DOT, $output) || error("$output: $!\n");
-
- # Title
- printf DOT ("digraph \"%s; %s %s\" {\n",
- $prog,
- Unparse($overall_total),
- Units());
- if ($main::opt_pdf) {
- # The output is more printable if we set the page size for dot.
- printf DOT ("size=\"8,11\"\n");
- }
- printf DOT ("node [width=0.375,height=0.25];\n");
-
- # Print legend
- printf DOT ("Legend [shape=box,fontsize=24,shape=plaintext," .
- "label=\"%s\\l%s\\l%s\\l%s\\l%s\\l\"];\n",
- $prog,
- sprintf("Total %s: %s", Units(), Unparse($overall_total)),
- sprintf("Focusing on: %s", Unparse($local_total)),
- sprintf("Dropped nodes with <= %s abs(%s)",
- Unparse($nodelimit), Units()),
- sprintf("Dropped edges with <= %s %s",
- Unparse($edgelimit), Units())
- );
-
- # Print nodes
- my %node = ();
- my $nextnode = 1;
- foreach my $a (@list[0..$last]) {
- # Pick font size
- my $f = GetEntry($flat, $a);
- my $c = GetEntry($cumulative, $a);
-
- my $fs = 8;
- if ($local_total > 0) {
- $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total)));
- }
-
- $node{$a} = $nextnode++;
- my $sym = $a;
- $sym =~ s/\s+/\\n/g;
- $sym =~ s/::/\\n/g;
-
- # Extra cumulative info to print for non-leaves
- my $extra = "";
- if ($f != $c) {
- $extra = sprintf("\\rof %s (%s)",
- Unparse($c),
- Percent($c, $local_total));
- }
- my $style = "";
- if ($main::opt_heapcheck) {
- if ($f > 0) {
- # make leak-causing nodes more visible (add a background)
- $style = ",style=filled,fillcolor=gray"
- } elsif ($f < 0) {
- # make anti-leak-causing nodes (which almost never occur)
- # stand out as well (triple border)
- $style = ",peripheries=3"
- }
- }
-
- printf DOT ("N%d [label=\"%s\\n%s (%s)%s\\r" .
- "\",shape=box,fontsize=%.1f%s];\n",
- $node{$a},
- $sym,
- Unparse($f),
- Percent($f, $local_total),
- $extra,
- $fs,
- $style,
- );
- }
-
- # Get edges and counts per edge
- my %edge = ();
- my $n;
- my $fullname_to_shortname_map = {};
- FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);
- foreach my $k (keys(%{$raw})) {
- # TODO: omit low %age edges
- $n = $raw->{$k};
- my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);
- for (my $i = 1; $i <= $#translated; $i++) {
- my $src = $translated[$i];
- my $dst = $translated[$i-1];
- #next if ($src eq $dst); # Avoid self-edges?
- if (exists($node{$src}) && exists($node{$dst})) {
- my $edge_label = "$src\001$dst";
- if (!exists($edge{$edge_label})) {
- $edge{$edge_label} = 0;
- }
- $edge{$edge_label} += $n;
- }
- }
- }
-
- # Print edges (process in order of decreasing counts)
- my %indegree = (); # Number of incoming edges added per node so far
- my %outdegree = (); # Number of outgoing edges added per node so far
- foreach my $e (sort { $edge{$b} <=> $edge{$a} } keys(%edge)) {
- my @x = split(/\001/, $e);
- $n = $edge{$e};
-
- # Initialize degree of kept incoming and outgoing edges if necessary
- my $src = $x[0];
- my $dst = $x[1];
- if (!exists($outdegree{$src})) { $outdegree{$src} = 0; }
- if (!exists($indegree{$dst})) { $indegree{$dst} = 0; }
-
- my $keep;
- if ($indegree{$dst} == 0) {
- # Keep edge if needed for reachability
- $keep = 1;
- } elsif (abs($n) <= $edgelimit) {
- # Drop if we are below --edgefraction
- $keep = 0;
- } elsif ($outdegree{$src} >= $main::opt_maxdegree ||
- $indegree{$dst} >= $main::opt_maxdegree) {
- # Keep limited number of in/out edges per node
- $keep = 0;
- } else {
- $keep = 1;
- }
-
- if ($keep) {
- $outdegree{$src}++;
- $indegree{$dst}++;
-
- # Compute line width based on edge count
- my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0);
- if ($fraction > 1) { $fraction = 1; }
- my $w = $fraction * 2;
- if ($w < 1 && ($main::opt_web || $main::opt_svg)) {
- # SVG output treats line widths < 1 poorly.
- $w = 1;
- }
-
- # Dot sometimes segfaults if given edge weights that are too large, so
- # we cap the weights at a large value
- my $edgeweight = abs($n) ** 0.7;
- if ($edgeweight > 100000) { $edgeweight = 100000; }
- $edgeweight = int($edgeweight);
-
- my $style = sprintf("setlinewidth(%f)", $w);
- if ($x[1] =~ m/\(inline\)/) {
- $style .= ",dashed";
- }
-
- # Use a slightly squashed function of the edge count as the weight
- printf DOT ("N%s -> N%s [label=%s, weight=%d, style=\"%s\"];\n",
- $node{$x[0]},
- $node{$x[1]},
- Unparse($n),
- $edgeweight,
- $style);
- }
- }
-
- print DOT ("}\n");
- close(DOT);
-
- if ($main::opt_web || $main::opt_svg) {
- # Rewrite SVG to be more usable inside web browser.
- RewriteSvg(TempName($main::next_tmpfile, "svg"));
- }
-
- return 1;
-}
-
-sub RewriteSvg {
- my $svgfile = shift;
-
- open(SVG, $svgfile) || die "open temp svg: $!";
- my @svg = <SVG>;
- close(SVG);
- unlink $svgfile;
- my $svg = join('', @svg);
-
- # Dot's SVG output is
- #
- # <svg width="___" height="___"
- # viewBox="___" xmlns=...>
- # <g id="graph0" transform="...">
- # ...
- # </g>
- # </svg>
- #
- # Change it to
- #
- # <svg width="100%" height="100%"
- # xmlns=...>
- # $svg_javascript
- # <g id="viewport" transform="translate(0,0)">
- # <g id="graph0" transform="...">
- # ...
- # </g>
- # </g>
- # </svg>
-
- # Fix width, height; drop viewBox.
- $svg =~ s/(?s)<svg width="[^"]+" height="[^"]+"(.*?)viewBox="[^"]+"/<svg width="100%" height="100%"$1/;
-
- # Insert script, viewport <g> above first <g>
- my $svg_javascript = SvgJavascript();
- my $viewport = "<g id=\"viewport\" transform=\"translate(0,0)\">\n";
- $svg =~ s/<g id="graph\d"/$svg_javascript$viewport$&/;
-
- # Insert final </g> above </svg>.
- $svg =~ s/(.*)(<\/svg>)/$1<\/g>$2/;
- $svg =~ s/<g id="graph\d"(.*?)/<g id="viewport"$1/;
-
- if ($main::opt_svg) {
- # --svg: write to standard output.
- print $svg;
- } else {
- # Write back to temporary file.
- open(SVG, ">$svgfile") || die "open $svgfile: $!";
- print SVG $svg;
- close(SVG);
- }
-}
-
-sub SvgJavascript {
- return <<'EOF';
-<script type="text/ecmascript"><![CDATA[
-// SVGPan
-// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/
-// Local modification: if(true || ...) below to force panning, never moving.
-
-/**
- * SVGPan library 1.2
- * ====================
- *
- * Given an unique existing element with id "viewport", including the
- * the library into any SVG adds the following capabilities:
- *
- * - Mouse panning
- * - Mouse zooming (using the wheel)
- * - Object dargging
- *
- * Known issues:
- *
- * - Zooming (while panning) on Safari has still some issues
- *
- * Releases:
- *
- * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
- * Fixed a bug with browser mouse handler interaction
- *
- * 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui
- * Updated the zoom code to support the mouse wheel on Safari/Chrome
- *
- * 1.0, Andrea Leofreddi
- * First release
- *
- * This code is licensed under the following BSD license:
- *
- * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of Andrea Leofreddi.
- */
-
-var root = document.documentElement;
-
-var state = 'none', stateTarget, stateOrigin, stateTf;
-
-setupHandlers(root);
-
-/**
- * Register handlers
- */
-function setupHandlers(root){
- setAttributes(root, {
- "onmouseup" : "add(evt)",
- "onmousedown" : "handleMouseDown(evt)",
- "onmousemove" : "handleMouseMove(evt)",
- "onmouseup" : "handleMouseUp(evt)",
- //"onmouseout" : "handleMouseUp(evt)", // Decomment this to stop the pan functionality when dragging out of the SVG element
- });
-
- if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
- window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
- else
- window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
-
- var g = svgDoc.getElementById("svg");
- g.width = "100%";
- g.height = "100%";
-}
-
-/**
- * Instance an SVGPoint object with given event coordinates.
- */
-function getEventPoint(evt) {
- var p = root.createSVGPoint();
-
- p.x = evt.clientX;
- p.y = evt.clientY;
-
- return p;
-}
-
-/**
- * Sets the current transform matrix of an element.
- */
-function setCTM(element, matrix) {
- var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";
-
- element.setAttribute("transform", s);
-}
-
-/**
- * Dumps a matrix to a string (useful for debug).
- */
-function dumpMatrix(matrix) {
- var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n 0, 0, 1 ]";
-
- return s;
-}
-
-/**
- * Sets attributes of an element.
- */
-function setAttributes(element, attributes){
- for (i in attributes)
- element.setAttributeNS(null, i, attributes[i]);
-}
-
-/**
- * Handle mouse move event.
- */
-function handleMouseWheel(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var delta;
-
- if(evt.wheelDelta)
- delta = evt.wheelDelta / 3600; // Chrome/Safari
- else
- delta = evt.detail / -90; // Mozilla
-
- var z = 1 + delta; // Zoom factor: 0.9/1.1
-
- var g = svgDoc.getElementById("viewport");
-
- var p = getEventPoint(evt);
-
- p = p.matrixTransform(g.getCTM().inverse());
-
- // Compute new scale matrix in current mouse position
- var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);
-
- setCTM(g, g.getCTM().multiply(k));
-
- stateTf = stateTf.multiply(k.inverse());
-}
-
-/**
- * Handle mouse move event.
- */
-function handleMouseMove(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var g = svgDoc.getElementById("viewport");
-
- if(state == 'pan') {
- // Pan mode
- var p = getEventPoint(evt).matrixTransform(stateTf);
-
- setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));
- } else if(state == 'move') {
- // Move mode
- var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());
-
- setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));
-
- stateOrigin = p;
- }
-}
-
-/**
- * Handle click event.
- */
-function handleMouseDown(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- var g = svgDoc.getElementById("viewport");
-
- if(true || evt.target.tagName == "svg") {
- // Pan mode
- state = 'pan';
-
- stateTf = g.getCTM().inverse();
-
- stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
- } else {
- // Move mode
- state = 'move';
-
- stateTarget = evt.target;
-
- stateTf = g.getCTM().inverse();
-
- stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
- }
-}
-
-/**
- * Handle mouse button release event.
- */
-function handleMouseUp(evt) {
- if(evt.preventDefault)
- evt.preventDefault();
-
- evt.returnValue = false;
-
- var svgDoc = evt.target.ownerDocument;
-
- if(state == 'pan' || state == 'move') {
- // Quit pan mode
- state = '';
- }
-}
-
-]]></script>
-EOF
-}
-
-# Provides a map from fullname to shortname for cases where the
-# shortname is ambiguous. The symlist has both the fullname and
-# shortname for all symbols, which is usually fine, but sometimes --
-# such as overloaded functions -- two different fullnames can map to
-# the same shortname. In that case, we use the address of the
-# function to disambiguate the two. This function fills in a map that
-# maps fullnames to modified shortnames in such cases. If a fullname
-# is not present in the map, the 'normal' shortname provided by the
-# symlist is the appropriate one to use.
-sub FillFullnameToShortnameMap {
- my $symbols = shift;
- my $fullname_to_shortname_map = shift;
- my $shortnames_seen_once = {};
- my $shortnames_seen_more_than_once = {};
-
- foreach my $symlist (values(%{$symbols})) {
- # TODO(csilvers): deal with inlined symbols too.
- my $shortname = $symlist->[0];
- my $fullname = $symlist->[2];
- if ($fullname !~ /<[0-9a-fA-F]+>$/) { # fullname doesn't end in an address
- next; # the only collisions we care about are when addresses differ
- }
- if (defined($shortnames_seen_once->{$shortname}) &&
- $shortnames_seen_once->{$shortname} ne $fullname) {
- $shortnames_seen_more_than_once->{$shortname} = 1;
- } else {
- $shortnames_seen_once->{$shortname} = $fullname;
- }
- }
-
- foreach my $symlist (values(%{$symbols})) {
- my $shortname = $symlist->[0];
- my $fullname = $symlist->[2];
- # TODO(csilvers): take in a list of addresses we care about, and only
- # store in the map if $symlist->[1] is in that list. Saves space.
- next if defined($fullname_to_shortname_map->{$fullname});
- if (defined($shortnames_seen_more_than_once->{$shortname})) {
- if ($fullname =~ /<0*([^>]*)>$/) { # fullname has address at end of it
- $fullname_to_shortname_map->{$fullname} = "$shortname\@$1";
- }
- }
- }
-}
-
-# Return a small number that identifies the argument.
-# Multiple calls with the same argument will return the same number.
-# Calls with different arguments will return different numbers.
-sub ShortIdFor {
- my $key = shift;
- my $id = $main::uniqueid{$key};
- if (!defined($id)) {
- $id = keys(%main::uniqueid) + 1;
- $main::uniqueid{$key} = $id;
- }
- return $id;
-}
-
-# Translate a stack of addresses into a stack of symbols
-sub TranslateStack {
- my $symbols = shift;
- my $fullname_to_shortname_map = shift;
- my $k = shift;
-
- my @addrs = split(/\n/, $k);
- my @result = ();
- for (my $i = 0; $i <= $#addrs; $i++) {
- my $a = $addrs[$i];
-
- # Skip large addresses since they sometimes show up as fake entries on RH9
- if (length($a) > 8 && $a gt "7fffffffffffffff") {
- next;
- }
-
- if ($main::opt_disasm || $main::opt_list) {
- # We want just the address for the key
- push(@result, $a);
- next;
- }
-
- my $symlist = $symbols->{$a};
- if (!defined($symlist)) {
- $symlist = [$a, "", $a];
- }
-
- # We can have a sequence of symbols for a particular entry
- # (more than one symbol in the case of inlining). Callers
- # come before callees in symlist, so walk backwards since
- # the translated stack should contain callees before callers.
- for (my $j = $#{$symlist}; $j >= 2; $j -= 3) {
- my $func = $symlist->[$j-2];
- my $fileline = $symlist->[$j-1];
- my $fullfunc = $symlist->[$j];
- if (defined($fullname_to_shortname_map->{$fullfunc})) {
- $func = $fullname_to_shortname_map->{$fullfunc};
- }
- if ($j > 2) {
- $func = "$func (inline)";
- }
-
- # Do not merge nodes corresponding to Callback::Run since that
- # causes confusing cycles in dot display. Instead, we synthesize
- # a unique name for this frame per caller.
- if ($func =~ m/Callback.*::Run$/) {
- my $caller = ($i > 0) ? $addrs[$i-1] : 0;
- $func = "Run#" . ShortIdFor($caller);
- }
-
- if ($main::opt_addresses) {
- push(@result, "$a $func $fileline");
- } elsif ($main::opt_lines) {
- if ($func eq '??' && $fileline eq '??:0') {
- push(@result, "$a");
- } else {
- push(@result, "$func $fileline");
- }
- } elsif ($main::opt_functions) {
- if ($func eq '??') {
- push(@result, "$a");
- } else {
- push(@result, $func);
- }
- } elsif ($main::opt_files) {
- if ($fileline eq '??:0' || $fileline eq '') {
- push(@result, "$a");
- } else {
- my $f = $fileline;
- $f =~ s/:\d+$//;
- push(@result, $f);
- }
- } else {
- push(@result, $a);
- last; # Do not print inlined info
- }
- }
- }
-
- # print join(",", @addrs), " => ", join(",", @result), "\n";
- return @result;
-}
-
-# Generate percent string for a number and a total
-sub Percent {
- my $num = shift;
- my $tot = shift;
- if ($tot != 0) {
- return sprintf("%.1f%%", $num * 100.0 / $tot);
- } else {
- return ($num == 0) ? "nan" : (($num > 0) ? "+inf" : "-inf");
- }
-}
-
-# Generate pretty-printed form of number
-sub Unparse {
- my $num = shift;
- if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
- if ($main::opt_inuse_objects || $main::opt_alloc_objects) {
- return sprintf("%d", $num);
- } else {
- if ($main::opt_show_bytes) {
- return sprintf("%d", $num);
- } else {
- return sprintf("%.1f", $num / 1048576.0);
- }
- }
- } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {
- return sprintf("%.3f", $num / 1e9); # Convert nanoseconds to seconds
- } else {
- return sprintf("%d", $num);
- }
-}
-
-# Alternate pretty-printed form: 0 maps to "."
-sub UnparseAlt {
- my $num = shift;
- if ($num == 0) {
- return ".";
- } else {
- return Unparse($num);
- }
-}
-
-# Alternate pretty-printed form: 0 maps to ""
-sub HtmlPrintNumber {
- my $num = shift;
- if ($num == 0) {
- return "";
- } else {
- return Unparse($num);
- }
-}
-
-# Return output units
-sub Units {
- if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
- if ($main::opt_inuse_objects || $main::opt_alloc_objects) {
- return "objects";
- } else {
- if ($main::opt_show_bytes) {
- return "B";
- } else {
- return "MB";
- }
- }
- } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) {
- return "seconds";
- } else {
- return "samples";
- }
-}
-
-##### Profile manipulation code #####
-
-# Generate flattened profile:
-# If count is charged to stack [a,b,c,d], in generated profile,
-# it will be charged to [a]
-sub FlatProfile {
- my $profile = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- if ($#addrs >= 0) {
- AddEntry($result, $addrs[0], $count);
- }
- }
- return $result;
-}
-
-# Generate cumulative profile:
-# If count is charged to stack [a,b,c,d], in generated profile,
-# it will be charged to [a], [b], [c], [d]
-sub CumulativeProfile {
- my $profile = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- foreach my $a (@addrs) {
- AddEntry($result, $a, $count);
- }
- }
- return $result;
-}
-
-# If the second-youngest PC on the stack is always the same, returns
-# that pc. Otherwise, returns undef.
-sub IsSecondPcAlwaysTheSame {
- my $profile = shift;
-
- my $second_pc = undef;
- foreach my $k (keys(%{$profile})) {
- my @addrs = split(/\n/, $k);
- if ($#addrs < 1) {
- return undef;
- }
- if (not defined $second_pc) {
- $second_pc = $addrs[1];
- } else {
- if ($second_pc ne $addrs[1]) {
- return undef;
- }
- }
- }
- return $second_pc;
-}
-
-sub ExtractSymbolLocation {
- my $symbols = shift;
- my $address = shift;
- # 'addr2line' outputs "??:0" for unknown locations; we do the
- # same to be consistent.
- my $location = "??:0:unknown";
- if (exists $symbols->{$address}) {
- my $file = $symbols->{$address}->[1];
- if ($file eq "?") {
- $file = "??:0"
- }
- $location = $file . ":" . $symbols->{$address}->[0];
- }
- return $location;
-}
-
-# Extracts a graph of calls.
-sub ExtractCalls {
- my $symbols = shift;
- my $profile = shift;
-
- my $calls = {};
- while( my ($stack_trace, $count) = each %$profile ) {
- my @address = split(/\n/, $stack_trace);
- my $destination = ExtractSymbolLocation($symbols, $address[0]);
- AddEntry($calls, $destination, $count);
- for (my $i = 1; $i <= $#address; $i++) {
- my $source = ExtractSymbolLocation($symbols, $address[$i]);
- my $call = "$source -> $destination";
- AddEntry($calls, $call, $count);
- $destination = $source;
- }
- }
-
- return $calls;
-}
-
-sub RemoveUninterestingFrames {
- my $symbols = shift;
- my $profile = shift;
-
- # List of function names to skip
- my %skip = ();
- my $skip_regexp = 'NOMATCH';
- if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') {
- foreach my $name ('calloc',
- 'cfree',
- 'malloc',
- 'free',
- 'memalign',
- 'posix_memalign',
- 'pvalloc',
- 'valloc',
- 'realloc',
- 'tc_calloc',
- 'tc_cfree',
- 'tc_malloc',
- 'tc_free',
- 'tc_memalign',
- 'tc_posix_memalign',
- 'tc_pvalloc',
- 'tc_valloc',
- 'tc_realloc',
- 'tc_new',
- 'tc_delete',
- 'tc_newarray',
- 'tc_deletearray',
- 'tc_new_nothrow',
- 'tc_newarray_nothrow',
- 'do_malloc',
- '::do_malloc', # new name -- got moved to an unnamed ns
- '::do_malloc_or_cpp_alloc',
- 'DoSampledAllocation',
- 'simple_alloc::allocate',
- '__malloc_alloc_template::allocate',
- '__builtin_delete',
- '__builtin_new',
- '__builtin_vec_delete',
- '__builtin_vec_new',
- 'operator new',
- 'operator new[]',
- # The entry to our memory-allocation routines on OS X
- 'malloc_zone_malloc',
- 'malloc_zone_calloc',
- 'malloc_zone_valloc',
- 'malloc_zone_realloc',
- 'malloc_zone_memalign',
- 'malloc_zone_free',
- # These mark the beginning/end of our custom sections
- '__start_google_malloc',
- '__stop_google_malloc',
- '__start_malloc_hook',
- '__stop_malloc_hook') {
- $skip{$name} = 1;
- $skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything
- }
- # TODO: Remove TCMalloc once everything has been
- # moved into the tcmalloc:: namespace and we have flushed
- # old code out of the system.
- $skip_regexp = "TCMalloc|^tcmalloc::";
- } elsif ($main::profile_type eq 'contention') {
- foreach my $vname ('base::RecordLockProfileData',
- 'base::SubmitMutexProfileData',
- 'base::SubmitSpinLockProfileData',
- 'Mutex::Unlock',
- 'Mutex::UnlockSlow',
- 'Mutex::ReaderUnlock',
- 'MutexLock::~MutexLock',
- 'SpinLock::Unlock',
- 'SpinLock::SlowUnlock',
- 'SpinLockHolder::~SpinLockHolder') {
- $skip{$vname} = 1;
- }
- } elsif ($main::profile_type eq 'cpu') {
- # Drop signal handlers used for CPU profile collection
- # TODO(dpeng): this should not be necessary; it's taken
- # care of by the general 2nd-pc mechanism below.
- foreach my $name ('ProfileData::Add', # historical
- 'ProfileData::prof_handler', # historical
- 'CpuProfiler::prof_handler',
- '__FRAME_END__',
- '__pthread_sighandler',
- '__restore') {
- $skip{$name} = 1;
- }
- } else {
- # Nothing skipped for unknown types
- }
-
- if ($main::profile_type eq 'cpu') {
- # If all the second-youngest program counters are the same,
- # this STRONGLY suggests that it is an artifact of measurement,
- # i.e., stack frames pushed by the CPU profiler signal handler.
- # Hence, we delete them.
- # (The topmost PC is read from the signal structure, not from
- # the stack, so it does not get involved.)
- while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) {
- my $result = {};
- my $func = '';
- if (exists($symbols->{$second_pc})) {
- $second_pc = $symbols->{$second_pc}->[0];
- }
- print STDERR "Removing $second_pc from all stack traces.\n";
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- splice @addrs, 1, 1;
- my $reduced_path = join("\n", @addrs);
- AddEntry($result, $reduced_path, $count);
- }
- $profile = $result;
- }
- }
-
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- my @path = ();
- foreach my $a (@addrs) {
- if (exists($symbols->{$a})) {
- my $func = $symbols->{$a}->[0];
- if ($skip{$func} || ($func =~ m/$skip_regexp/)) {
- next;
- }
- }
- push(@path, $a);
- }
- my $reduced_path = join("\n", @path);
- AddEntry($result, $reduced_path, $count);
- }
- return $result;
-}
-
-# Reduce profile to granularity given by user
-sub ReduceProfile {
- my $symbols = shift;
- my $profile = shift;
- my $result = {};
- my $fullname_to_shortname_map = {};
- FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map);
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k);
- my @path = ();
- my %seen = ();
- $seen{''} = 1; # So that empty keys are skipped
- foreach my $e (@translated) {
- # To avoid double-counting due to recursion, skip a stack-trace
- # entry if it has already been seen
- if (!$seen{$e}) {
- $seen{$e} = 1;
- push(@path, $e);
- }
- }
- my $reduced_path = join("\n", @path);
- AddEntry($result, $reduced_path, $count);
- }
- return $result;
-}
-
-# Does the specified symbol array match the regexp?
-sub SymbolMatches {
- my $sym = shift;
- my $re = shift;
- if (defined($sym)) {
- for (my $i = 0; $i < $#{$sym}; $i += 3) {
- if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-# Focus only on paths involving specified regexps
-sub FocusProfile {
- my $symbols = shift;
- my $profile = shift;
- my $focus = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- foreach my $a (@addrs) {
- # Reply if it matches either the address/shortname/fileline
- if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) {
- AddEntry($result, $k, $count);
- last;
- }
- }
- }
- return $result;
-}
-
-# Focus only on paths not involving specified regexps
-sub IgnoreProfile {
- my $symbols = shift;
- my $profile = shift;
- my $ignore = shift;
- my $result = {};
- foreach my $k (keys(%{$profile})) {
- my $count = $profile->{$k};
- my @addrs = split(/\n/, $k);
- my $matched = 0;
- foreach my $a (@addrs) {
- # Reply if it matches either the address/shortname/fileline
- if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) {
- $matched = 1;
- last;
- }
- }
- if (!$matched) {
- AddEntry($result, $k, $count);
- }
- }
- return $result;
-}
-
-# Get total count in profile
-sub TotalProfile {
- my $profile = shift;
- my $result = 0;
- foreach my $k (keys(%{$profile})) {
- $result += $profile->{$k};
- }
- return $result;
-}
-
-# Add A to B
-sub AddProfile {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- # add all keys in A
- foreach my $k (keys(%{$A})) {
- my $v = $A->{$k};
- AddEntry($R, $k, $v);
- }
- # add all keys in B
- foreach my $k (keys(%{$B})) {
- my $v = $B->{$k};
- AddEntry($R, $k, $v);
- }
- return $R;
-}
-
-# Merges symbol maps
-sub MergeSymbols {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- foreach my $k (keys(%{$A})) {
- $R->{$k} = $A->{$k};
- }
- if (defined($B)) {
- foreach my $k (keys(%{$B})) {
- $R->{$k} = $B->{$k};
- }
- }
- return $R;
-}
-
-
-# Add A to B
-sub AddPcs {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- # add all keys in A
- foreach my $k (keys(%{$A})) {
- $R->{$k} = 1
- }
- # add all keys in B
- foreach my $k (keys(%{$B})) {
- $R->{$k} = 1
- }
- return $R;
-}
-
-# Subtract B from A
-sub SubtractProfile {
- my $A = shift;
- my $B = shift;
-
- my $R = {};
- foreach my $k (keys(%{$A})) {
- my $v = $A->{$k} - GetEntry($B, $k);
- if ($v < 0 && $main::opt_drop_negative) {
- $v = 0;
- }
- AddEntry($R, $k, $v);
- }
- if (!$main::opt_drop_negative) {
- # Take care of when subtracted profile has more entries
- foreach my $k (keys(%{$B})) {
- if (!exists($A->{$k})) {
- AddEntry($R, $k, 0 - $B->{$k});
- }
- }
- }
- return $R;
-}
-
-# Get entry from profile; zero if not present
-sub GetEntry {
- my $profile = shift;
- my $k = shift;
- if (exists($profile->{$k})) {
- return $profile->{$k};
- } else {
- return 0;
- }
-}
-
-# Add entry to specified profile
-sub AddEntry {
- my $profile = shift;
- my $k = shift;
- my $n = shift;
- if (!exists($profile->{$k})) {
- $profile->{$k} = 0;
- }
- $profile->{$k} += $n;
-}
-
-# Add a stack of entries to specified profile, and add them to the $pcs
-# list.
-sub AddEntries {
- my $profile = shift;
- my $pcs = shift;
- my $stack = shift;
- my $count = shift;
- my @k = ();
-
- foreach my $e (split(/\s+/, $stack)) {
- my $pc = HexExtend($e);
- $pcs->{$pc} = 1;
- push @k, $pc;
- }
- AddEntry($profile, (join "\n", @k), $count);
-}
-
-##### Code to profile a server dynamically #####
-
-sub CheckSymbolPage {
- my $url = SymbolPageURL();
- my $command = ShellEscape(@URL_FETCHER, $url);
- open(SYMBOL, "$command |") or error($command);
- my $line = <SYMBOL>;
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- close(SYMBOL);
- unless (defined($line)) {
- error("$url doesn't exist\n");
- }
-
- if ($line =~ /^num_symbols:\s+(\d+)$/) {
- if ($1 == 0) {
- error("Stripped binary. No symbols available.\n");
- }
- } else {
- error("Failed to get the number of symbols from $url\n");
- }
-}
-
-sub IsProfileURL {
- my $profile_name = shift;
- if (-f $profile_name) {
- printf STDERR "Using local file $profile_name.\n";
- return 0;
- }
- return 1;
-}
-
-sub ParseProfileURL {
- my $profile_name = shift;
-
- if (!defined($profile_name) || $profile_name eq "") {
- return ();
- }
-
- # Split profile URL - matches all non-empty strings, so no test.
- $profile_name =~ m,^(https?://)?([^/]+)(.*?)(/|$PROFILES)?$,;
-
- my $proto = $1 || "http://";
- my $hostport = $2;
- my $prefix = $3;
- my $profile = $4 || "/";
-
- my $host = $hostport;
- $host =~ s/:.*//;
-
- my $baseurl = "$proto$hostport$prefix";
- return ($host, $baseurl, $profile);
-}
-
-# We fetch symbols from the first profile argument.
-sub SymbolPageURL {
- my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);
- return "$baseURL$SYMBOL_PAGE";
-}
-
-sub FetchProgramName() {
- my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]);
- my $url = "$baseURL$PROGRAM_NAME_PAGE";
- my $command_line = ShellEscape(@URL_FETCHER, $url);
- open(CMDLINE, "$command_line |") or error($command_line);
- my $cmdline = <CMDLINE>;
- $cmdline =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- close(CMDLINE);
- error("Failed to get program name from $url\n") unless defined($cmdline);
- $cmdline =~ s/\x00.+//; # Remove argv[1] and latters.
- $cmdline =~ s!\n!!g; # Remove LFs.
- return $cmdline;
-}
-
-# Gee, curl's -L (--location) option isn't reliable at least
-# with its 7.12.3 version. Curl will forget to post data if
-# there is a redirection. This function is a workaround for
-# curl. Redirection happens on borg hosts.
-sub ResolveRedirectionForCurl {
- my $url = shift;
- my $command_line = ShellEscape(@URL_FETCHER, "--head", $url);
- open(CMDLINE, "$command_line |") or error($command_line);
- while (<CMDLINE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (/^Location: (.*)/) {
- $url = $1;
- }
- }
- close(CMDLINE);
- return $url;
-}
-
-# Add a timeout flat to URL_FETCHER. Returns a new list.
-sub AddFetchTimeout {
- my $timeout = shift;
- my @fetcher = shift;
- if (defined($timeout)) {
- if (join(" ", @fetcher) =~ m/\bcurl -s/) {
- push(@fetcher, "--max-time", sprintf("%d", $timeout));
- } elsif (join(" ", @fetcher) =~ m/\brpcget\b/) {
- push(@fetcher, sprintf("--deadline=%d", $timeout));
- }
- }
- return @fetcher;
-}
-
-# Reads a symbol map from the file handle name given as $1, returning
-# the resulting symbol map. Also processes variables relating to symbols.
-# Currently, the only variable processed is 'binary=<value>' which updates
-# $main::prog to have the correct program name.
-sub ReadSymbols {
- my $in = shift;
- my $map = {};
- while (<$in>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Removes all the leading zeroes from the symbols, see comment below.
- if (m/^0x0*([0-9a-f]+)\s+(.+)/) {
- $map->{$1} = $2;
- } elsif (m/^---/) {
- last;
- } elsif (m/^([a-z][^=]*)=(.*)$/ ) {
- my ($variable, $value) = ($1, $2);
- for ($variable, $value) {
- s/^\s+//;
- s/\s+$//;
- }
- if ($variable eq "binary") {
- if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) {
- printf STDERR ("Warning: Mismatched binary name '%s', using '%s'.\n",
- $main::prog, $value);
- }
- $main::prog = $value;
- } else {
- printf STDERR ("Ignoring unknown variable in symbols list: " .
- "'%s' = '%s'\n", $variable, $value);
- }
- }
- }
- return $map;
-}
-
-# Fetches and processes symbols to prepare them for use in the profile output
-# code. If the optional 'symbol_map' arg is not given, fetches symbols from
-# $SYMBOL_PAGE for all PC values found in profile. Otherwise, the raw symbols
-# are assumed to have already been fetched into 'symbol_map' and are simply
-# extracted and processed.
-sub FetchSymbols {
- my $pcset = shift;
- my $symbol_map = shift;
-
- my %seen = ();
- my @pcs = grep { !$seen{$_}++ } keys(%$pcset); # uniq
-
- if (!defined($symbol_map)) {
- my $post_data = join("+", sort((map {"0x" . "$_"} @pcs)));
-
- open(POSTFILE, ">$main::tmpfile_sym");
- print POSTFILE $post_data;
- close(POSTFILE);
-
- my $url = SymbolPageURL();
-
- my $command_line;
- if (join(" ", @URL_FETCHER) =~ m/\bcurl -s/) {
- $url = ResolveRedirectionForCurl($url);
- $command_line = ShellEscape(@URL_FETCHER, "-d", "\@$main::tmpfile_sym",
- $url);
- } else {
- $command_line = (ShellEscape(@URL_FETCHER, "--post", $url)
- . " < " . ShellEscape($main::tmpfile_sym));
- }
- # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.
- my $escaped_cppfilt = ShellEscape($obj_tool_map{"c++filt"});
- open(SYMBOL, "$command_line | $escaped_cppfilt |") or error($command_line);
- $symbol_map = ReadSymbols(*SYMBOL{IO});
- close(SYMBOL);
- }
-
- my $symbols = {};
- foreach my $pc (@pcs) {
- my $fullname;
- # For 64 bits binaries, symbols are extracted with 8 leading zeroes.
- # Then /symbol reads the long symbols in as uint64, and outputs
- # the result with a "0x%08llx" format which get rid of the zeroes.
- # By removing all the leading zeroes in both $pc and the symbols from
- # /symbol, the symbols match and are retrievable from the map.
- my $shortpc = $pc;
- $shortpc =~ s/^0*//;
- # Each line may have a list of names, which includes the function
- # and also other functions it has inlined. They are separated (in
- # PrintSymbolizedProfile), by --, which is illegal in function names.
- my $fullnames;
- if (defined($symbol_map->{$shortpc})) {
- $fullnames = $symbol_map->{$shortpc};
- } else {
- $fullnames = "0x" . $pc; # Just use addresses
- }
- my $sym = [];
- $symbols->{$pc} = $sym;
- foreach my $fullname (split("--", $fullnames)) {
- my $name = ShortFunctionName($fullname);
- push(@{$sym}, $name, "?", $fullname);
- }
- }
- return $symbols;
-}
-
-sub BaseName {
- my $file_name = shift;
- $file_name =~ s!^.*/!!; # Remove directory name
- return $file_name;
-}
-
-sub MakeProfileBaseName {
- my ($binary_name, $profile_name) = @_;
- my ($host, $baseURL, $path) = ParseProfileURL($profile_name);
- my $binary_shortname = BaseName($binary_name);
- return sprintf("%s.%s.%s",
- $binary_shortname, $main::op_time, $host);
-}
-
-sub FetchDynamicProfile {
- my $binary_name = shift;
- my $profile_name = shift;
- my $fetch_name_only = shift;
- my $encourage_patience = shift;
-
- if (!IsProfileURL($profile_name)) {
- return $profile_name;
- } else {
- my ($host, $baseURL, $path) = ParseProfileURL($profile_name);
- if ($path eq "" || $path eq "/") {
- # Missing type specifier defaults to cpu-profile
- $path = $PROFILE_PAGE;
- }
-
- my $profile_file = MakeProfileBaseName($binary_name, $profile_name);
-
- my $url = "$baseURL$path";
- my $fetch_timeout = undef;
- if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/) {
- if ($path =~ m/[?]/) {
- $url .= "&";
- } else {
- $url .= "?";
- }
- $url .= sprintf("seconds=%d", $main::opt_seconds);
- $fetch_timeout = $main::opt_seconds * 1.01 + 60;
- } else {
- # For non-CPU profiles, we add a type-extension to
- # the target profile file name.
- my $suffix = $path;
- $suffix =~ s,/,.,g;
- $profile_file .= $suffix;
- }
-
- my $profile_dir = $ENV{"PPROF_TMPDIR"} || ($ENV{HOME} . "/pprof");
- if (! -d $profile_dir) {
- mkdir($profile_dir)
- || die("Unable to create profile directory $profile_dir: $!\n");
- }
- my $tmp_profile = "$profile_dir/.tmp.$profile_file";
- my $real_profile = "$profile_dir/$profile_file";
-
- if ($fetch_name_only > 0) {
- return $real_profile;
- }
-
- my @fetcher = AddFetchTimeout($fetch_timeout, @URL_FETCHER);
- my $cmd = ShellEscape(@fetcher, $url) . " > " . ShellEscape($tmp_profile);
- if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){
- print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n";
- if ($encourage_patience) {
- print STDERR "Be patient...\n";
- }
- } else {
- print STDERR "Fetching $path profile from $url to\n ${real_profile}\n";
- }
-
- (system($cmd) == 0) || error("Failed to get profile: $cmd: $!\n");
- (system("mv", $tmp_profile, $real_profile) == 0) || error("Unable to rename profile\n");
- print STDERR "Wrote profile to $real_profile\n";
- $main::collected_profile = $real_profile;
- return $main::collected_profile;
- }
-}
-
-# Collect profiles in parallel
-sub FetchDynamicProfiles {
- my $items = scalar(@main::pfile_args);
- my $levels = log($items) / log(2);
-
- if ($items == 1) {
- $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1);
- } else {
- # math rounding issues
- if ((2 ** $levels) < $items) {
- $levels++;
- }
- my $count = scalar(@main::pfile_args);
- for (my $i = 0; $i < $count; $i++) {
- $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0);
- }
- print STDERR "Fetching $count profiles, Be patient...\n";
- FetchDynamicProfilesRecurse($levels, 0, 0);
- $main::collected_profile = join(" \\\n ", @main::profile_files);
- }
-}
-
-# Recursively fork a process to get enough processes
-# collecting profiles
-sub FetchDynamicProfilesRecurse {
- my $maxlevel = shift;
- my $level = shift;
- my $position = shift;
-
- if (my $pid = fork()) {
- $position = 0 | ($position << 1);
- TryCollectProfile($maxlevel, $level, $position);
- wait;
- } else {
- $position = 1 | ($position << 1);
- TryCollectProfile($maxlevel, $level, $position);
- cleanup();
- exit(0);
- }
-}
-
-# Collect a single profile
-sub TryCollectProfile {
- my $maxlevel = shift;
- my $level = shift;
- my $position = shift;
-
- if ($level >= ($maxlevel - 1)) {
- if ($position < scalar(@main::pfile_args)) {
- FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0);
- }
- } else {
- FetchDynamicProfilesRecurse($maxlevel, $level+1, $position);
- }
-}
-
-##### Parsing code #####
-
-# Provide a small streaming-read module to handle very large
-# cpu-profile files. Stream in chunks along a sliding window.
-# Provides an interface to get one 'slot', correctly handling
-# endian-ness differences. A slot is one 32-bit or 64-bit word
-# (depending on the input profile). We tell endianness and bit-size
-# for the profile by looking at the first 8 bytes: in cpu profiles,
-# the second slot is always 3 (we'll accept anything that's not 0).
-BEGIN {
- package CpuProfileStream;
-
- sub new {
- my ($class, $file, $fname) = @_;
- my $self = { file => $file,
- base => 0,
- stride => 512 * 1024, # must be a multiple of bitsize/8
- slots => [],
- unpack_code => "", # N for big-endian, V for little
- perl_is_64bit => 1, # matters if profile is 64-bit
- };
- bless $self, $class;
- # Let unittests adjust the stride
- if ($main::opt_test_stride > 0) {
- $self->{stride} = $main::opt_test_stride;
- }
- # Read the first two slots to figure out bitsize and endianness.
- my $slots = $self->{slots};
- my $str;
- read($self->{file}, $str, 8);
- # Set the global $address_length based on what we see here.
- # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars).
- $address_length = ($str eq (chr(0)x8)) ? 16 : 8;
- if ($address_length == 8) {
- if (substr($str, 6, 2) eq chr(0)x2) {
- $self->{unpack_code} = 'V'; # Little-endian.
- } elsif (substr($str, 4, 2) eq chr(0)x2) {
- $self->{unpack_code} = 'N'; # Big-endian
- } else {
- ::error("$fname: header size >= 2**16\n");
- }
- @$slots = unpack($self->{unpack_code} . "*", $str);
- } else {
- # If we're a 64-bit profile, check if we're a 64-bit-capable
- # perl. Otherwise, each slot will be represented as a float
- # instead of an int64, losing precision and making all the
- # 64-bit addresses wrong. We won't complain yet, but will
- # later if we ever see a value that doesn't fit in 32 bits.
- my $has_q = 0;
- eval { $has_q = pack("Q", "1") ? 1 : 1; };
- if (!$has_q) {
- $self->{perl_is_64bit} = 0;
- }
- read($self->{file}, $str, 8);
- if (substr($str, 4, 4) eq chr(0)x4) {
- # We'd love to use 'Q', but it's a) not universal, b) not endian-proof.
- $self->{unpack_code} = 'V'; # Little-endian.
- } elsif (substr($str, 0, 4) eq chr(0)x4) {
- $self->{unpack_code} = 'N'; # Big-endian
- } else {
- ::error("$fname: header size >= 2**32\n");
- }
- my @pair = unpack($self->{unpack_code} . "*", $str);
- # Since we know one of the pair is 0, it's fine to just add them.
- @$slots = (0, $pair[0] + $pair[1]);
- }
- return $self;
- }
-
- # Load more data when we access slots->get(X) which is not yet in memory.
- sub overflow {
- my ($self) = @_;
- my $slots = $self->{slots};
- $self->{base} += $#$slots + 1; # skip over data we're replacing
- my $str;
- read($self->{file}, $str, $self->{stride});
- if ($address_length == 8) { # the 32-bit case
- # This is the easy case: unpack provides 32-bit unpacking primitives.
- @$slots = unpack($self->{unpack_code} . "*", $str);
- } else {
- # We need to unpack 32 bits at a time and combine.
- my @b32_values = unpack($self->{unpack_code} . "*", $str);
- my @b64_values = ();
- for (my $i = 0; $i < $#b32_values; $i += 2) {
- # TODO(csilvers): if this is a 32-bit perl, the math below
- # could end up in a too-large int, which perl will promote
- # to a double, losing necessary precision. Deal with that.
- # Right now, we just die.
- my ($lo, $hi) = ($b32_values[$i], $b32_values[$i+1]);
- if ($self->{unpack_code} eq 'N') { # big-endian
- ($lo, $hi) = ($hi, $lo);
- }
- my $value = $lo + $hi * (2**32);
- if (!$self->{perl_is_64bit} && # check value is exactly represented
- (($value % (2**32)) != $lo || int($value / (2**32)) != $hi)) {
- ::error("Need a 64-bit perl to process this 64-bit profile.\n");
- }
- push(@b64_values, $value);
- }
- @$slots = @b64_values;
- }
- }
-
- # Access the i-th long in the file (logically), or -1 at EOF.
- sub get {
- my ($self, $idx) = @_;
- my $slots = $self->{slots};
- while ($#$slots >= 0) {
- if ($idx < $self->{base}) {
- # The only time we expect a reference to $slots[$i - something]
- # after referencing $slots[$i] is reading the very first header.
- # Since $stride > |header|, that shouldn't cause any lookback
- # errors. And everything after the header is sequential.
- print STDERR "Unexpected look-back reading CPU profile";
- return -1; # shrug, don't know what better to return
- } elsif ($idx > $self->{base} + $#$slots) {
- $self->overflow();
- } else {
- return $slots->[$idx - $self->{base}];
- }
- }
- # If we get here, $slots is [], which means we've reached EOF
- return -1; # unique since slots is supposed to hold unsigned numbers
- }
-}
-
-# Reads the top, 'header' section of a profile, and returns the last
-# line of the header, commonly called a 'header line'. The header
-# section of a profile consists of zero or more 'command' lines that
-# are instructions to pprof, which pprof executes when reading the
-# header. All 'command' lines start with a %. After the command
-# lines is the 'header line', which is a profile-specific line that
-# indicates what type of profile it is, and perhaps other global
-# information about the profile. For instance, here's a header line
-# for a heap profile:
-# heap profile: 53: 38236 [ 5525: 1284029] @ heapprofile
-# For historical reasons, the CPU profile does not contain a text-
-# readable header line. If the profile looks like a CPU profile,
-# this function returns "". If no header line could be found, this
-# function returns undef.
-#
-# The following commands are recognized:
-# %warn -- emit the rest of this line to stderr, prefixed by 'WARNING:'
-#
-# The input file should be in binmode.
-sub ReadProfileHeader {
- local *PROFILE = shift;
- my $firstchar = "";
- my $line = "";
- read(PROFILE, $firstchar, 1);
- seek(PROFILE, -1, 1); # unread the firstchar
- if ($firstchar !~ /[[:print:]]/) { # is not a text character
- return "";
- }
- while (defined($line = <PROFILE>)) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- if ($line =~ /^%warn\s+(.*)/) { # 'warn' command
- # Note this matches both '%warn blah\n' and '%warn\n'.
- print STDERR "WARNING: $1\n"; # print the rest of the line
- } elsif ($line =~ /^%/) {
- print STDERR "Ignoring unknown command from profile header: $line";
- } else {
- # End of commands, must be the header line.
- return $line;
- }
- }
- return undef; # got to EOF without seeing a header line
-}
-
-sub IsSymbolizedProfileFile {
- my $file_name = shift;
- if (!(-e $file_name) || !(-r $file_name)) {
- return 0;
- }
- # Check if the file contains a symbol-section marker.
- open(TFILE, "<$file_name");
- binmode TFILE;
- my $firstline = ReadProfileHeader(*TFILE);
- close(TFILE);
- if (!$firstline) {
- return 0;
- }
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
- return $firstline =~ /^--- *$symbol_marker/;
-}
-
-# Parse profile generated by common/profiler.cc and return a reference
-# to a map:
-# $result->{version} Version number of profile file
-# $result->{period} Sampling period (in microseconds)
-# $result->{profile} Profile object
-# $result->{map} Memory map info from profile
-# $result->{pcs} Hash of all PC values seen, key is hex address
-sub ReadProfile {
- my $prog = shift;
- my $fname = shift;
- my $result; # return value
-
- $CONTENTION_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $contention_marker = $&;
- $GROWTH_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $growth_marker = $&;
- $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $symbol_marker = $&;
- $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
- my $profile_marker = $&;
-
- # Look at first line to see if it is a heap or a CPU profile.
- # CPU profile may start with no header at all, and just binary data
- # (starting with \0\0\0\0) -- in that case, don't try to read the
- # whole firstline, since it may be gigabytes(!) of data.
- open(PROFILE, "<$fname") || error("$fname: $!\n");
- binmode PROFILE; # New perls do UTF-8 processing
- my $header = ReadProfileHeader(*PROFILE);
- if (!defined($header)) { # means "at EOF"
- error("Profile is empty.\n");
- }
-
- my $symbols;
- if ($header =~ m/^--- *$symbol_marker/o) {
- # Verify that the user asked for a symbolized profile
- if (!$main::use_symbolized_profile) {
- # we have both a binary and symbolized profiles, abort
- error("FATAL ERROR: Symbolized profile\n $fname\ncannot be used with " .
- "a binary arg. Try again without passing\n $prog\n");
- }
- # Read the symbol section of the symbolized profile file.
- $symbols = ReadSymbols(*PROFILE{IO});
- # Read the next line to get the header for the remaining profile.
- $header = ReadProfileHeader(*PROFILE) || "";
- }
-
- $main::profile_type = '';
- if ($header =~ m/^heap profile:.*$growth_marker/o) {
- $main::profile_type = 'growth';
- $result = ReadHeapProfile($prog, *PROFILE, $header);
- } elsif ($header =~ m/^heap profile:/) {
- $main::profile_type = 'heap';
- $result = ReadHeapProfile($prog, *PROFILE, $header);
- } elsif ($header =~ m/^--- *$contention_marker/o) {
- $main::profile_type = 'contention';
- $result = ReadSynchProfile($prog, *PROFILE);
- } elsif ($header =~ m/^--- *Stacks:/) {
- print STDERR
- "Old format contention profile: mistakenly reports " .
- "condition variable signals as lock contentions.\n";
- $main::profile_type = 'contention';
- $result = ReadSynchProfile($prog, *PROFILE);
- } elsif ($header =~ m/^--- *$profile_marker/) {
- # the binary cpu profile data starts immediately after this line
- $main::profile_type = 'cpu';
- $result = ReadCPUProfile($prog, $fname, *PROFILE);
- } else {
- if (defined($symbols)) {
- # a symbolized profile contains a format we don't recognize, bail out
- error("$fname: Cannot recognize profile section after symbols.\n");
- }
- # no ascii header present -- must be a CPU profile
- $main::profile_type = 'cpu';
- $result = ReadCPUProfile($prog, $fname, *PROFILE);
- }
-
- close(PROFILE);
-
- # if we got symbols along with the profile, return those as well
- if (defined($symbols)) {
- $result->{symbols} = $symbols;
- }
-
- return $result;
-}
-
-# Subtract one from caller pc so we map back to call instr.
-# However, don't do this if we're reading a symbolized profile
-# file, in which case the subtract-one was done when the file
-# was written.
-#
-# We apply the same logic to all readers, though ReadCPUProfile uses an
-# independent implementation.
-sub FixCallerAddresses {
- my $stack = shift;
- if ($main::use_symbolized_profile) {
- return $stack;
- } else {
- $stack =~ /(\s)/;
- my $delimiter = $1;
- my @addrs = split(' ', $stack);
- my @fixedaddrs;
- $#fixedaddrs = $#addrs;
- if ($#addrs >= 0) {
- $fixedaddrs[0] = $addrs[0];
- }
- for (my $i = 1; $i <= $#addrs; $i++) {
- $fixedaddrs[$i] = AddressSub($addrs[$i], "0x1");
- }
- return join $delimiter, @fixedaddrs;
- }
-}
-
-# CPU profile reader
-sub ReadCPUProfile {
- my $prog = shift;
- my $fname = shift; # just used for logging
- local *PROFILE = shift;
- my $version;
- my $period;
- my $i;
- my $profile = {};
- my $pcs = {};
-
- # Parse string into array of slots.
- my $slots = CpuProfileStream->new(*PROFILE, $fname);
-
- # Read header. The current header version is a 5-element structure
- # containing:
- # 0: header count (always 0)
- # 1: header "words" (after this one: 3)
- # 2: format version (0)
- # 3: sampling period (usec)
- # 4: unused padding (always 0)
- if ($slots->get(0) != 0 ) {
- error("$fname: not a profile file, or old format profile file\n");
- }
- $i = 2 + $slots->get(1);
- $version = $slots->get(2);
- $period = $slots->get(3);
- # Do some sanity checking on these header values.
- if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) {
- error("$fname: not a profile file, or corrupted profile file\n");
- }
-
- # Parse profile
- while ($slots->get($i) != -1) {
- my $n = $slots->get($i++);
- my $d = $slots->get($i++);
- if ($d > (2**16)) { # TODO(csilvers): what's a reasonable max-stack-depth?
- my $addr = sprintf("0%o", $i * ($address_length == 8 ? 4 : 8));
- print STDERR "At index $i (address $addr):\n";
- error("$fname: stack trace depth >= 2**32\n");
- }
- if ($slots->get($i) == 0) {
- # End of profile data marker
- $i += $d;
- last;
- }
-
- # Make key out of the stack entries
- my @k = ();
- for (my $j = 0; $j < $d; $j++) {
- my $pc = $slots->get($i+$j);
- # Subtract one from caller pc so we map back to call instr.
- # However, don't do this if we're reading a symbolized profile
- # file, in which case the subtract-one was done when the file
- # was written.
- if ($j > 0 && !$main::use_symbolized_profile) {
- $pc--;
- }
- $pc = sprintf("%0*x", $address_length, $pc);
- $pcs->{$pc} = 1;
- push @k, $pc;
- }
-
- AddEntry($profile, (join "\n", @k), $n);
- $i += $d;
- }
-
- # Parse map
- my $map = '';
- seek(PROFILE, $i * 4, 0);
- read(PROFILE, $map, (stat PROFILE)[7]);
-
- my $r = {};
- $r->{version} = $version;
- $r->{period} = $period;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
-
- return $r;
-}
-
-sub ReadHeapProfile {
- my $prog = shift;
- local *PROFILE = shift;
- my $header = shift;
-
- my $index = 1;
- if ($main::opt_inuse_space) {
- $index = 1;
- } elsif ($main::opt_inuse_objects) {
- $index = 0;
- } elsif ($main::opt_alloc_space) {
- $index = 3;
- } elsif ($main::opt_alloc_objects) {
- $index = 2;
- }
-
- # Find the type of this profile. The header line looks like:
- # heap profile: 1246: 8800744 [ 1246: 8800744] @ <heap-url>/266053
- # There are two pairs <count: size>, the first inuse objects/space, and the
- # second allocated objects/space. This is followed optionally by a profile
- # type, and if that is present, optionally by a sampling frequency.
- # For remote heap profiles (v1):
- # The interpretation of the sampling frequency is that the profiler, for
- # each sample, calculates a uniformly distributed random integer less than
- # the given value, and records the next sample after that many bytes have
- # been allocated. Therefore, the expected sample interval is half of the
- # given frequency. By default, if not specified, the expected sample
- # interval is 128KB. Only remote-heap-page profiles are adjusted for
- # sample size.
- # For remote heap profiles (v2):
- # The sampling frequency is the rate of a Poisson process. This means that
- # the probability of sampling an allocation of size X with sampling rate Y
- # is 1 - exp(-X/Y)
- # For version 2, a typical header line might look like this:
- # heap profile: 1922: 127792360 [ 1922: 127792360] @ <heap-url>_v2/524288
- # the trailing number (524288) is the sampling rate. (Version 1 showed
- # double the 'rate' here)
- my $sampling_algorithm = 0;
- my $sample_adjustment = 0;
- chomp($header);
- my $type = "unknown";
- if ($header =~ m"^heap profile:\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\](\s*@\s*([^/]*)(/(\d+))?)?") {
- if (defined($6) && ($6 ne '')) {
- $type = $6;
- my $sample_period = $8;
- # $type is "heapprofile" for profiles generated by the
- # heap-profiler, and either "heap" or "heap_v2" for profiles
- # generated by sampling directly within tcmalloc. It can also
- # be "growth" for heap-growth profiles. The first is typically
- # found for profiles generated locally, and the others for
- # remote profiles.
- if (($type eq "heapprofile") || ($type !~ /heap/) ) {
- # No need to adjust for the sampling rate with heap-profiler-derived data
- $sampling_algorithm = 0;
- } elsif ($type =~ /_v2/) {
- $sampling_algorithm = 2; # version 2 sampling
- if (defined($sample_period) && ($sample_period ne '')) {
- $sample_adjustment = int($sample_period);
- }
- } else {
- $sampling_algorithm = 1; # version 1 sampling
- if (defined($sample_period) && ($sample_period ne '')) {
- $sample_adjustment = int($sample_period)/2;
- }
- }
- } else {
- # We detect whether or not this is a remote-heap profile by checking
- # that the total-allocated stats ($n2,$s2) are exactly the
- # same as the in-use stats ($n1,$s1). It is remotely conceivable
- # that a non-remote-heap profile may pass this check, but it is hard
- # to imagine how that could happen.
- # In this case it's so old it's guaranteed to be remote-heap version 1.
- my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);
- if (($n1 == $n2) && ($s1 == $s2)) {
- # This is likely to be a remote-heap based sample profile
- $sampling_algorithm = 1;
- }
- }
- }
-
- if ($sampling_algorithm > 0) {
- # For remote-heap generated profiles, adjust the counts and sizes to
- # account for the sample rate (we sample once every 128KB by default).
- if ($sample_adjustment == 0) {
- # Turn on profile adjustment.
- $sample_adjustment = 128*1024;
- print STDERR "Adjusting heap profiles for 1-in-128KB sampling rate\n";
- } else {
- printf STDERR ("Adjusting heap profiles for 1-in-%d sampling rate\n",
- $sample_adjustment);
- }
- if ($sampling_algorithm > 1) {
- # We don't bother printing anything for the original version (version 1)
- printf STDERR "Heap version $sampling_algorithm\n";
- }
- }
-
- my $profile = {};
- my $pcs = {};
- my $map = "";
-
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (/^MAPPED_LIBRARIES:/) {
- # Read the /proc/self/maps data
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- $map .= $_;
- }
- last;
- }
-
- if (/^--- Memory map:/) {
- # Read /proc/self/maps data as formatted by DumpAddressMap()
- my $buildvar = "";
- while (<PROFILE>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Parse "build=<dir>" specification if supplied
- if (m/^\s*build=(.*)\n/) {
- $buildvar = $1;
- }
-
- # Expand "$build" variable if available
- $_ =~ s/\$build\b/$buildvar/g;
-
- $map .= $_;
- }
- last;
- }
-
- # Read entry of the form:
- # <count1>: <bytes1> [<count2>: <bytes2>] @ a1 a2 a3 ... an
- s/^\s*//;
- s/\s*$//;
- if (m/^\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\]\s+@\s+(.*)$/) {
- my $stack = $5;
- my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4);
-
- if ($sample_adjustment) {
- if ($sampling_algorithm == 2) {
- # Remote-heap version 2
- # The sampling frequency is the rate of a Poisson process.
- # This means that the probability of sampling an allocation of
- # size X with sampling rate Y is 1 - exp(-X/Y)
- if ($n1 != 0) {
- my $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
- my $scale_factor = 1/(1 - exp(-$ratio));
- $n1 *= $scale_factor;
- $s1 *= $scale_factor;
- }
- if ($n2 != 0) {
- my $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
- my $scale_factor = 1/(1 - exp(-$ratio));
- $n2 *= $scale_factor;
- $s2 *= $scale_factor;
- }
- } else {
- # Remote-heap version 1
- my $ratio;
- $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
- if ($ratio < 1) {
- $n1 /= $ratio;
- $s1 /= $ratio;
- }
- $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
- if ($ratio < 1) {
- $n2 /= $ratio;
- $s2 /= $ratio;
- }
- }
- }
-
- my @counts = ($n1, $s1, $n2, $s2);
- AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]);
- }
- }
-
- my $r = {};
- $r->{version} = "heap";
- $r->{period} = 1;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
- return $r;
-}
-
-sub ReadSynchProfile {
- my $prog = shift;
- local *PROFILE = shift;
- my $header = shift;
-
- my $map = '';
- my $profile = {};
- my $pcs = {};
- my $sampling_period = 1;
- my $cyclespernanosec = 2.8; # Default assumption for old binaries
- my $seen_clockrate = 0;
- my $line;
-
- my $index = 0;
- if ($main::opt_total_delay) {
- $index = 0;
- } elsif ($main::opt_contentions) {
- $index = 1;
- } elsif ($main::opt_mean_delay) {
- $index = 2;
- }
-
- while ( $line = <PROFILE> ) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- if ( $line =~ /^\s*(\d+)\s+(\d+) \@\s*(.*?)\s*$/ ) {
- my ($cycles, $count, $stack) = ($1, $2, $3);
-
- # Convert cycles to nanoseconds
- $cycles /= $cyclespernanosec;
-
- # Adjust for sampling done by application
- $cycles *= $sampling_period;
- $count *= $sampling_period;
-
- my @values = ($cycles, $count, $cycles / $count);
- AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]);
-
- } elsif ( $line =~ /^(slow release).*thread \d+ \@\s*(.*?)\s*$/ ||
- $line =~ /^\s*(\d+) \@\s*(.*?)\s*$/ ) {
- my ($cycles, $stack) = ($1, $2);
- if ($cycles !~ /^\d+$/) {
- next;
- }
-
- # Convert cycles to nanoseconds
- $cycles /= $cyclespernanosec;
-
- # Adjust for sampling done by application
- $cycles *= $sampling_period;
-
- AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles);
-
- } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) {
- my ($variable, $value) = ($1,$2);
- for ($variable, $value) {
- s/^\s+//;
- s/\s+$//;
- }
- if ($variable eq "cycles/second") {
- $cyclespernanosec = $value / 1e9;
- $seen_clockrate = 1;
- } elsif ($variable eq "sampling period") {
- $sampling_period = $value;
- } elsif ($variable eq "ms since reset") {
- # Currently nothing is done with this value in pprof
- # So we just silently ignore it for now
- } elsif ($variable eq "discarded samples") {
- # Currently nothing is done with this value in pprof
- # So we just silently ignore it for now
- } else {
- printf STDERR ("Ignoring unnknown variable in /contention output: " .
- "'%s' = '%s'\n",$variable,$value);
- }
- } else {
- # Memory map entry
- $map .= $line;
- }
- }
-
- if (!$seen_clockrate) {
- printf STDERR ("No cycles/second entry in profile; Guessing %.1f GHz\n",
- $cyclespernanosec);
- }
-
- my $r = {};
- $r->{version} = 0;
- $r->{period} = $sampling_period;
- $r->{profile} = $profile;
- $r->{libs} = ParseLibraries($prog, $map, $pcs);
- $r->{pcs} = $pcs;
- return $r;
-}
-
-# Given a hex value in the form "0x1abcd" or "1abcd", return either
-# "0001abcd" or "000000000001abcd", depending on the current (global)
-# address length.
-sub HexExtend {
- my $addr = shift;
-
- $addr =~ s/^(0x)?0*//;
- my $zeros_needed = $address_length - length($addr);
- if ($zeros_needed < 0) {
- printf STDERR "Warning: address $addr is longer than address length $address_length\n";
- return $addr;
- }
- return ("0" x $zeros_needed) . $addr;
-}
-
-##### Symbol extraction #####
-
-# Aggressively search the lib_prefix values for the given library
-# If all else fails, just return the name of the library unmodified.
-# If the lib_prefix is "/my/path,/other/path" and $file is "/lib/dir/mylib.so"
-# it will search the following locations in this order, until it finds a file:
-# /my/path/lib/dir/mylib.so
-# /other/path/lib/dir/mylib.so
-# /my/path/dir/mylib.so
-# /other/path/dir/mylib.so
-# /my/path/mylib.so
-# /other/path/mylib.so
-# /lib/dir/mylib.so (returned as last resort)
-sub FindLibrary {
- my $file = shift;
- my $suffix = $file;
-
- # Search for the library as described above
- do {
- foreach my $prefix (@prefix_list) {
- my $fullpath = $prefix . $suffix;
- if (-e $fullpath) {
- return $fullpath;
- }
- }
- } while ($suffix =~ s|^/[^/]+/|/|);
- return $file;
-}
-
-# Return path to library with debugging symbols.
-# For libc libraries, the copy in /usr/lib/debug contains debugging symbols
-sub DebuggingLibrary {
- my $file = shift;
- if ($file =~ m|^/| && -f "/usr/lib/debug$file") {
- return "/usr/lib/debug$file";
- }
- return undef;
-}
-
-# Parse text section header of a library using objdump
-sub ParseTextSectionHeaderFromObjdump {
- my $lib = shift;
-
- my $size = undef;
- my $vma;
- my $file_offset;
- # Get objdump output from the library file to figure out how to
- # map between mapped addresses and addresses in the library.
- my $cmd = ShellEscape($obj_tool_map{"objdump"}, "-h", $lib);
- open(OBJDUMP, "$cmd |") || error("$cmd: $!\n");
- while (<OBJDUMP>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Idx Name Size VMA LMA File off Algn
- # 10 .text 00104b2c 420156f0 420156f0 000156f0 2**4
- # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file
- # offset may still be 8. But AddressSub below will still handle that.
- my @x = split;
- if (($#x >= 6) && ($x[1] eq '.text')) {
- $size = $x[2];
- $vma = $x[3];
- $file_offset = $x[5];
- last;
- }
- }
- close(OBJDUMP);
-
- if (!defined($size)) {
- return undef;
- }
-
- my $r = {};
- $r->{size} = $size;
- $r->{vma} = $vma;
- $r->{file_offset} = $file_offset;
-
- return $r;
-}
-
-# Parse text section header of a library using otool (on OS X)
-sub ParseTextSectionHeaderFromOtool {
- my $lib = shift;
-
- my $size = undef;
- my $vma = undef;
- my $file_offset = undef;
- # Get otool output from the library file to figure out how to
- # map between mapped addresses and addresses in the library.
- my $command = ShellEscape($obj_tool_map{"otool"}, "-l", $lib);
- open(OTOOL, "$command |") || error("$command: $!\n");
- my $cmd = "";
- my $sectname = "";
- my $segname = "";
- foreach my $line (<OTOOL>) {
- $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines
- # Load command <#>
- # cmd LC_SEGMENT
- # [...]
- # Section
- # sectname __text
- # segname __TEXT
- # addr 0x000009f8
- # size 0x00018b9e
- # offset 2552
- # align 2^2 (4)
- # We will need to strip off the leading 0x from the hex addresses,
- # and convert the offset into hex.
- if ($line =~ /Load command/) {
- $cmd = "";
- $sectname = "";
- $segname = "";
- } elsif ($line =~ /Section/) {
- $sectname = "";
- $segname = "";
- } elsif ($line =~ /cmd (\w+)/) {
- $cmd = $1;
- } elsif ($line =~ /sectname (\w+)/) {
- $sectname = $1;
- } elsif ($line =~ /segname (\w+)/) {
- $segname = $1;
- } elsif (!(($cmd eq "LC_SEGMENT" || $cmd eq "LC_SEGMENT_64") &&
- $sectname eq "__text" &&
- $segname eq "__TEXT")) {
- next;
- } elsif ($line =~ /\baddr 0x([0-9a-fA-F]+)/) {
- $vma = $1;
- } elsif ($line =~ /\bsize 0x([0-9a-fA-F]+)/) {
- $size = $1;
- } elsif ($line =~ /\boffset ([0-9]+)/) {
- $file_offset = sprintf("%016x", $1);
- }
- if (defined($vma) && defined($size) && defined($file_offset)) {
- last;
- }
- }
- close(OTOOL);
-
- if (!defined($vma) || !defined($size) || !defined($file_offset)) {
- return undef;
- }
-
- my $r = {};
- $r->{size} = $size;
- $r->{vma} = $vma;
- $r->{file_offset} = $file_offset;
-
- return $r;
-}
-
-sub ParseTextSectionHeader {
- # obj_tool_map("otool") is only defined if we're in a Mach-O environment
- if (defined($obj_tool_map{"otool"})) {
- my $r = ParseTextSectionHeaderFromOtool(@_);
- if (defined($r)){
- return $r;
- }
- }
- # If otool doesn't work, or we don't have it, fall back to objdump
- return ParseTextSectionHeaderFromObjdump(@_);
-}
-
-# Split /proc/pid/maps dump into a list of libraries
-sub ParseLibraries {
- return if $main::use_symbol_page; # We don't need libraries info.
- my $prog = shift;
- my $map = shift;
- my $pcs = shift;
-
- my $result = [];
- my $h = "[a-f0-9]+";
- my $zero_offset = HexExtend("0");
-
- my $buildvar = "";
- foreach my $l (split("\n", $map)) {
- if ($l =~ m/^\s*build=(.*)$/) {
- $buildvar = $1;
- }
-
- my $start;
- my $finish;
- my $offset;
- my $lib;
- if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+\.(so|dll|dylib|bundle)((\.\d+)+\w*(\.\d+){0,3})?)$/i) {
- # Full line from /proc/self/maps. Example:
- # 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so
- $start = HexExtend($1);
- $finish = HexExtend($2);
- $offset = HexExtend($3);
- $lib = $4;
- $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths
- } elsif ($l =~ /^\s*($h)-($h):\s*(\S+\.so(\.\d+)*)/) {
- # Cooked line from DumpAddressMap. Example:
- # 40000000-40015000: /lib/ld-2.3.2.so
- $start = HexExtend($1);
- $finish = HexExtend($2);
- $offset = $zero_offset;
- $lib = $3;
- } else {
- next;
- }
-
- # Expand "$build" variable if available
- $lib =~ s/\$build\b/$buildvar/g;
-
- $lib = FindLibrary($lib);
-
- # Check for pre-relocated libraries, which use pre-relocated symbol tables
- # and thus require adjusting the offset that we'll use to translate
- # VM addresses into symbol table addresses.
- # Only do this if we're not going to fetch the symbol table from a
- # debugging copy of the library.
- if (!DebuggingLibrary($lib)) {
- my $text = ParseTextSectionHeader($lib);
- if (defined($text)) {
- my $vma_offset = AddressSub($text->{vma}, $text->{file_offset});
- $offset = AddressAdd($offset, $vma_offset);
- }
- }
-
- push(@{$result}, [$lib, $start, $finish, $offset]);
- }
-
- # Append special entry for additional library (not relocated)
- if ($main::opt_lib ne "") {
- my $text = ParseTextSectionHeader($main::opt_lib);
- if (defined($text)) {
- my $start = $text->{vma};
- my $finish = AddressAdd($start, $text->{size});
-
- push(@{$result}, [$main::opt_lib, $start, $finish, $start]);
- }
- }
-
- # Append special entry for the main program. This covers
- # 0..max_pc_value_seen, so that we assume pc values not found in one
- # of the library ranges will be treated as coming from the main
- # program binary.
- my $min_pc = HexExtend("0");
- my $max_pc = $min_pc; # find the maximal PC value in any sample
- foreach my $pc (keys(%{$pcs})) {
- if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); }
- }
- push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]);
-
- return $result;
-}
-
-# Add two hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressAdd {
- my $addr1 = shift;
- my $addr2 = shift;
- my $sum;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16);
- return sprintf("%08x", $sum);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize carry handling.
-
- if ($main::opt_debug and $main::opt_test) {
- print STDERR "AddressAdd $addr1 + $addr2 = ";
- }
-
- my $a1 = substr($addr1,-7);
- $addr1 = substr($addr1,0,-7);
- my $a2 = substr($addr2,-7);
- $addr2 = substr($addr2,0,-7);
- $sum = hex($a1) + hex($a2);
- my $c = 0;
- if ($sum > 0xfffffff) {
- $c = 1;
- $sum -= 0x10000000;
- }
- my $r = sprintf("%07x", $sum);
-
- $a1 = substr($addr1,-7);
- $addr1 = substr($addr1,0,-7);
- $a2 = substr($addr2,-7);
- $addr2 = substr($addr2,0,-7);
- $sum = hex($a1) + hex($a2) + $c;
- $c = 0;
- if ($sum > 0xfffffff) {
- $c = 1;
- $sum -= 0x10000000;
- }
- $r = sprintf("%07x", $sum) . $r;
-
- $sum = hex($addr1) + hex($addr2) + $c;
- if ($sum > 0xff) { $sum -= 0x100; }
- $r = sprintf("%02x", $sum) . $r;
-
- if ($main::opt_debug and $main::opt_test) { print STDERR "$r\n"; }
-
- return $r;
- }
-}
-
-
-# Subtract two hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressSub {
- my $addr1 = shift;
- my $addr2 = shift;
- my $diff;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16);
- return sprintf("%08x", $diff);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize borrow handling.
- # if ($main::opt_debug) { print STDERR "AddressSub $addr1 - $addr2 = "; }
-
- my $a1 = hex(substr($addr1,-7));
- $addr1 = substr($addr1,0,-7);
- my $a2 = hex(substr($addr2,-7));
- $addr2 = substr($addr2,0,-7);
- my $b = 0;
- if ($a2 > $a1) {
- $b = 1;
- $a1 += 0x10000000;
- }
- $diff = $a1 - $a2;
- my $r = sprintf("%07x", $diff);
-
- $a1 = hex(substr($addr1,-7));
- $addr1 = substr($addr1,0,-7);
- $a2 = hex(substr($addr2,-7)) + $b;
- $addr2 = substr($addr2,0,-7);
- $b = 0;
- if ($a2 > $a1) {
- $b = 1;
- $a1 += 0x10000000;
- }
- $diff = $a1 - $a2;
- $r = sprintf("%07x", $diff) . $r;
-
- $a1 = hex($addr1);
- $a2 = hex($addr2) + $b;
- if ($a2 > $a1) { $a1 += 0x100; }
- $diff = $a1 - $a2;
- $r = sprintf("%02x", $diff) . $r;
-
- # if ($main::opt_debug) { print STDERR "$r\n"; }
-
- return $r;
- }
-}
-
-# Increment a hex addresses of length $address_length.
-# Run pprof --test for unit test if this is changed.
-sub AddressInc {
- my $addr = shift;
- my $sum;
-
- if ($address_length == 8) {
- # Perl doesn't cope with wraparound arithmetic, so do it explicitly:
- $sum = (hex($addr)+1) % (0x10000000 * 16);
- return sprintf("%08x", $sum);
-
- } else {
- # Do the addition in 7-nibble chunks to trivialize carry handling.
- # We are always doing this to step through the addresses in a function,
- # and will almost never overflow the first chunk, so we check for this
- # case and exit early.
-
- # if ($main::opt_debug) { print STDERR "AddressInc $addr1 = "; }
-
- my $a1 = substr($addr,-7);
- $addr = substr($addr,0,-7);
- $sum = hex($a1) + 1;
- my $r = sprintf("%07x", $sum);
- if ($sum <= 0xfffffff) {
- $r = $addr . $r;
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return HexExtend($r);
- } else {
- $r = "0000000";
- }
-
- $a1 = substr($addr,-7);
- $addr = substr($addr,0,-7);
- $sum = hex($a1) + 1;
- $r = sprintf("%07x", $sum) . $r;
- if ($sum <= 0xfffffff) {
- $r = $addr . $r;
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return HexExtend($r);
- } else {
- $r = "00000000000000";
- }
-
- $sum = hex($addr) + 1;
- if ($sum > 0xff) { $sum -= 0x100; }
- $r = sprintf("%02x", $sum) . $r;
-
- # if ($main::opt_debug) { print STDERR "$r\n"; }
- return $r;
- }
-}
-
-# Extract symbols for all PC values found in profile
-sub ExtractSymbols {
- my $libs = shift;
- my $pcset = shift;
-
- my $symbols = {};
-
- # Map each PC value to the containing library. To make this faster,
- # we sort libraries by their starting pc value (highest first), and
- # advance through the libraries as we advance the pc. Sometimes the
- # addresses of libraries may overlap with the addresses of the main
- # binary, so to make sure the libraries 'win', we iterate over the
- # libraries in reverse order (which assumes the binary doesn't start
- # in the middle of a library, which seems a fair assumption).
- my @pcs = (sort { $a cmp $b } keys(%{$pcset})); # pcset is 0-extended strings
- foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) {
- my $libname = $lib->[0];
- my $start = $lib->[1];
- my $finish = $lib->[2];
- my $offset = $lib->[3];
-
- # Get list of pcs that belong in this library.
- my $contained = [];
- my ($start_pc_index, $finish_pc_index);
- # Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index].
- for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0;
- $finish_pc_index--) {
- last if $pcs[$finish_pc_index - 1] le $finish;
- }
- # Find smallest start_pc_index such that $start <= $pc[$start_pc_index].
- for ($start_pc_index = $finish_pc_index; $start_pc_index > 0;
- $start_pc_index--) {
- last if $pcs[$start_pc_index - 1] lt $start;
- }
- # This keeps PC values higher than $pc[$finish_pc_index] in @pcs,
- # in case there are overlaps in libraries and the main binary.
- @{$contained} = splice(@pcs, $start_pc_index,
- $finish_pc_index - $start_pc_index);
- # Map to symbols
- MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols);
- }
-
- return $symbols;
-}
-
-# Map list of PC values to symbols for a given image
-sub MapToSymbols {
- my $image = shift;
- my $offset = shift;
- my $pclist = shift;
- my $symbols = shift;
-
- my $debug = 0;
-
- # Ignore empty binaries
- if ($#{$pclist} < 0) { return; }
-
- # Figure out the addr2line command to use
- my $addr2line = $obj_tool_map{"addr2line"};
- my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image);
- if (exists $obj_tool_map{"addr2line_pdb"}) {
- $addr2line = $obj_tool_map{"addr2line_pdb"};
- $cmd = ShellEscape($addr2line, "--demangle", "-f", "-C", "-e", $image);
- }
-
- # If "addr2line" isn't installed on the system at all, just use
- # nm to get what info we can (function names, but not line numbers).
- if (system(ShellEscape($addr2line, "--help") . " >$dev_null 2>&1") != 0) {
- MapSymbolsWithNM($image, $offset, $pclist, $symbols);
- return;
- }
-
- # "addr2line -i" can produce a variable number of lines per input
- # address, with no separator that allows us to tell when data for
- # the next address starts. So we find the address for a special
- # symbol (_fini) and interleave this address between all real
- # addresses passed to addr2line. The name of this special symbol
- # can then be used as a separator.
- $sep_address = undef; # May be filled in by MapSymbolsWithNM()
- my $nm_symbols = {};
- MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols);
- if (defined($sep_address)) {
- # Only add " -i" to addr2line if the binary supports it.
- # addr2line --help returns 0, but not if it sees an unknown flag first.
- if (system("$cmd -i --help >$dev_null 2>&1") == 0) {
- $cmd .= " -i";
- } else {
- $sep_address = undef; # no need for sep_address if we don't support -i
- }
- }
-
- # Make file with all PC values with intervening 'sep_address' so
- # that we can reliably detect the end of inlined function list
- open(ADDRESSES, ">$main::tmpfile_sym") || error("$main::tmpfile_sym: $!\n");
- if ($debug) { print("---- $image ---\n"); }
- for (my $i = 0; $i <= $#{$pclist}; $i++) {
- # addr2line always reads hex addresses, and does not need '0x' prefix.
- if ($debug) { printf STDERR ("%s\n", $pclist->[$i]); }
- printf ADDRESSES ("%s\n", AddressSub($pclist->[$i], $offset));
- if (defined($sep_address)) {
- printf ADDRESSES ("%s\n", $sep_address);
- }
- }
- close(ADDRESSES);
- if ($debug) {
- print("----\n");
- system("cat", $main::tmpfile_sym);
- print("----\n");
- system("$cmd < " . ShellEscape($main::tmpfile_sym));
- print("----\n");
- }
-
- open(SYMBOLS, "$cmd <" . ShellEscape($main::tmpfile_sym) . " |")
- || error("$cmd: $!\n");
- my $count = 0; # Index in pclist
- while (<SYMBOLS>) {
- # Read fullfunction and filelineinfo from next pair of lines
- s/\r?\n$//g;
- my $fullfunction = $_;
- $_ = <SYMBOLS>;
- s/\r?\n$//g;
- my $filelinenum = $_;
-
- if (defined($sep_address) && $fullfunction eq $sep_symbol) {
- # Terminating marker for data for this address
- $count++;
- next;
- }
-
- $filelinenum =~ s|\\|/|g; # turn windows-style paths into unix-style paths
-
- my $pcstr = $pclist->[$count];
- my $function = ShortFunctionName($fullfunction);
- my $nms = $nm_symbols->{$pcstr};
- if (defined($nms)) {
- if ($fullfunction eq '??') {
- # nm found a symbol for us.
- $function = $nms->[0];
- $fullfunction = $nms->[2];
- } else {
- # MapSymbolsWithNM tags each routine with its starting address,
- # useful in case the image has multiple occurrences of this
- # routine. (It uses a syntax that resembles template paramters,
- # that are automatically stripped out by ShortFunctionName().)
- # addr2line does not provide the same information. So we check
- # if nm disambiguated our symbol, and if so take the annotated
- # (nm) version of the routine-name. TODO(csilvers): this won't
- # catch overloaded, inlined symbols, which nm doesn't see.
- # Better would be to do a check similar to nm's, in this fn.
- if ($nms->[2] =~ m/^\Q$function\E/) { # sanity check it's the right fn
- $function = $nms->[0];
- $fullfunction = $nms->[2];
- }
- }
- }
-
- # Prepend to accumulated symbols for pcstr
- # (so that caller comes before callee)
- my $sym = $symbols->{$pcstr};
- if (!defined($sym)) {
- $sym = [];
- $symbols->{$pcstr} = $sym;
- }
- unshift(@{$sym}, $function, $filelinenum, $fullfunction);
- if ($debug) { printf STDERR ("%s => [%s]\n", $pcstr, join(" ", @{$sym})); }
- if (!defined($sep_address)) {
- # Inlining is off, so this entry ends immediately
- $count++;
- }
- }
- close(SYMBOLS);
-}
-
-# Use nm to map the list of referenced PCs to symbols. Return true iff we
-# are able to read procedure information via nm.
-sub MapSymbolsWithNM {
- my $image = shift;
- my $offset = shift;
- my $pclist = shift;
- my $symbols = shift;
-
- # Get nm output sorted by increasing address
- my $symbol_table = GetProcedureBoundaries($image, ".");
- if (!%{$symbol_table}) {
- return 0;
- }
- # Start addresses are already the right length (8 or 16 hex digits).
- my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] }
- keys(%{$symbol_table});
-
- if ($#names < 0) {
- # No symbols: just use addresses
- foreach my $pc (@{$pclist}) {
- my $pcstr = "0x" . $pc;
- $symbols->{$pc} = [$pcstr, "?", $pcstr];
- }
- return 0;
- }
-
- # Sort addresses so we can do a join against nm output
- my $index = 0;
- my $fullname = $names[0];
- my $name = ShortFunctionName($fullname);
- foreach my $pc (sort { $a cmp $b } @{$pclist}) {
- # Adjust for mapped offset
- my $mpc = AddressSub($pc, $offset);
- while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){
- $index++;
- $fullname = $names[$index];
- $name = ShortFunctionName($fullname);
- }
- if ($mpc lt $symbol_table->{$fullname}->[1]) {
- $symbols->{$pc} = [$name, "?", $fullname];
- } else {
- my $pcstr = "0x" . $pc;
- $symbols->{$pc} = [$pcstr, "?", $pcstr];
- }
- }
- return 1;
-}
-
-sub ShortFunctionName {
- my $function = shift;
- while ($function =~ s/\([^()]*\)(\s*const)?//g) { } # Argument types
- while ($function =~ s/<[^<>]*>//g) { } # Remove template arguments
- $function =~ s/^.*\s+(\w+::)/$1/; # Remove leading type
- return $function;
-}
-
-# Trim overly long symbols found in disassembler output
-sub CleanDisassembly {
- my $d = shift;
- while ($d =~ s/\([^()%]*\)(\s*const)?//g) { } # Argument types, not (%rax)
- while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments
- return $d;
-}
-
-# Clean file name for display
-sub CleanFileName {
- my ($f) = @_;
- $f =~ s|^/proc/self/cwd/||;
- $f =~ s|^\./||;
- return $f;
-}
-
-# Make address relative to section and clean up for display
-sub UnparseAddress {
- my ($offset, $address) = @_;
- $address = AddressSub($address, $offset);
- $address =~ s/^0x//;
- $address =~ s/^0*//;
- return $address;
-}
-
-##### Miscellaneous #####
-
-# Find the right versions of the above object tools to use. The
-# argument is the program file being analyzed, and should be an ELF
-# 32-bit or ELF 64-bit executable file. The location of the tools
-# is determined by considering the following options in this order:
-# 1) --tools option, if set
-# 2) PPROF_TOOLS environment variable, if set
-# 3) the environment
-sub ConfigureObjTools {
- my $prog_file = shift;
-
- # Check for the existence of $prog_file because /usr/bin/file does not
- # predictably return error status in prod.
- (-e $prog_file) || error("$prog_file does not exist.\n");
-
- my $file_type = undef;
- if (-e "/usr/bin/file") {
- # Follow symlinks (at least for systems where "file" supports that).
- my $escaped_prog_file = ShellEscape($prog_file);
- $file_type = `/usr/bin/file -L $escaped_prog_file 2>$dev_null ||
- /usr/bin/file $escaped_prog_file`;
- } elsif ($^O == "MSWin32") {
- $file_type = "MS Windows";
- } else {
- print STDERR "WARNING: Can't determine the file type of $prog_file";
- }
-
- if ($file_type =~ /64-bit/) {
- # Change $address_length to 16 if the program file is ELF 64-bit.
- # We can't detect this from many (most?) heap or lock contention
- # profiles, since the actual addresses referenced are generally in low
- # memory even for 64-bit programs.
- $address_length = 16;
- }
-
- if ($file_type =~ /MS Windows/) {
- # For windows, we provide a version of nm and addr2line as part of
- # the opensource release, which is capable of parsing
- # Windows-style PDB executables. It should live in the path, or
- # in the same directory as pprof.
- $obj_tool_map{"nm_pdb"} = "nm-pdb";
- $obj_tool_map{"addr2line_pdb"} = "addr2line-pdb";
- }
-
- if ($file_type =~ /Mach-O/) {
- # OS X uses otool to examine Mach-O files, rather than objdump.
- $obj_tool_map{"otool"} = "otool";
- $obj_tool_map{"addr2line"} = "false"; # no addr2line
- $obj_tool_map{"objdump"} = "false"; # no objdump
- }
-
- # Go fill in %obj_tool_map with the pathnames to use:
- foreach my $tool (keys %obj_tool_map) {
- $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool});
- }
-}
-
-# Returns the path of a caller-specified object tool. If --tools or
-# PPROF_TOOLS are specified, then returns the full path to the tool
-# with that prefix. Otherwise, returns the path unmodified (which
-# means we will look for it on PATH).
-sub ConfigureTool {
- my $tool = shift;
- my $path;
-
- # --tools (or $PPROF_TOOLS) is a comma separated list, where each
- # item is either a) a pathname prefix, or b) a map of the form
- # <tool>:<path>. First we look for an entry of type (b) for our
- # tool. If one is found, we use it. Otherwise, we consider all the
- # pathname prefixes in turn, until one yields an existing file. If
- # none does, we use a default path.
- my $tools = $main::opt_tools || $ENV{"PPROF_TOOLS"} || "";
- if ($tools =~ m/(,|^)\Q$tool\E:([^,]*)/) {
- $path = $2;
- # TODO(csilvers): sanity-check that $path exists? Hard if it's relative.
- } elsif ($tools ne '') {
- foreach my $prefix (split(',', $tools)) {
- next if ($prefix =~ /:/); # ignore "tool:fullpath" entries in the list
- if (-x $prefix . $tool) {
- $path = $prefix . $tool;
- last;
- }
- }
- if (!$path) {
- error("No '$tool' found with prefix specified by " .
- "--tools (or \$PPROF_TOOLS) '$tools'\n");
- }
- } else {
- # ... otherwise use the version that exists in the same directory as
- # pprof. If there's nothing there, use $PATH.
- $0 =~ m,[^/]*$,; # this is everything after the last slash
- my $dirname = $`; # this is everything up to and including the last slash
- if (-x "$dirname$tool") {
- $path = "$dirname$tool";
- } else {
- $path = $tool;
- }
- }
- if ($main::opt_debug) { print STDERR "Using '$path' for '$tool'.\n"; }
- return $path;
-}
-
-sub ShellEscape {
- my @escaped_words = ();
- foreach my $word (@_) {
- my $escaped_word = $word;
- if ($word =~ m![^a-zA-Z0-9/.,_=-]!) { # check for anything not in whitelist
- $escaped_word =~ s/'/'\\''/;
- $escaped_word = "'$escaped_word'";
- }
- push(@escaped_words, $escaped_word);
- }
- return join(" ", @escaped_words);
-}
-
-sub cleanup {
- unlink($main::tmpfile_sym);
- unlink(keys %main::tempnames);
-
- # We leave any collected profiles in $HOME/pprof in case the user wants
- # to look at them later. We print a message informing them of this.
- if ((scalar(@main::profile_files) > 0) &&
- defined($main::collected_profile)) {
- if (scalar(@main::profile_files) == 1) {
- print STDERR "Dynamically gathered profile is in $main::collected_profile\n";
- }
- print STDERR "If you want to investigate this profile further, you can do:\n";
- print STDERR "\n";
- print STDERR " pprof \\\n";
- print STDERR " $main::prog \\\n";
- print STDERR " $main::collected_profile\n";
- print STDERR "\n";
- }
-}
-
-sub sighandler {
- cleanup();
- exit(1);
-}
-
-sub error {
- my $msg = shift;
- print STDERR $msg;
- cleanup();
- exit(1);
-}
-
-
-# Run $nm_command and get all the resulting procedure boundaries whose
-# names match "$regexp" and returns them in a hashtable mapping from
-# procedure name to a two-element vector of [start address, end address]
-sub GetProcedureBoundariesViaNm {
- my $escaped_nm_command = shift; # shell-escaped
- my $regexp = shift;
-
- my $symbol_table = {};
- open(NM, "$escaped_nm_command |") || error("$escaped_nm_command: $!\n");
- my $last_start = "0";
- my $routine = "";
- while (<NM>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- if (m/^\s*([0-9a-f]+) (.) (..*)/) {
- my $start_val = $1;
- my $type = $2;
- my $this_routine = $3;
-
- # It's possible for two symbols to share the same address, if
- # one is a zero-length variable (like __start_google_malloc) or
- # one symbol is a weak alias to another (like __libc_malloc).
- # In such cases, we want to ignore all values except for the
- # actual symbol, which in nm-speak has type "T". The logic
- # below does this, though it's a bit tricky: what happens when
- # we have a series of lines with the same address, is the first
- # one gets queued up to be processed. However, it won't
- # *actually* be processed until later, when we read a line with
- # a different address. That means that as long as we're reading
- # lines with the same address, we have a chance to replace that
- # item in the queue, which we do whenever we see a 'T' entry --
- # that is, a line with type 'T'. If we never see a 'T' entry,
- # we'll just go ahead and process the first entry (which never
- # got touched in the queue), and ignore the others.
- if ($start_val eq $last_start && $type =~ /t/i) {
- # We are the 'T' symbol at this address, replace previous symbol.
- $routine = $this_routine;
- next;
- } elsif ($start_val eq $last_start) {
- # We're not the 'T' symbol at this address, so ignore us.
- next;
- }
-
- if ($this_routine eq $sep_symbol) {
- $sep_address = HexExtend($start_val);
- }
-
- # Tag this routine with the starting address in case the image
- # has multiple occurrences of this routine. We use a syntax
- # that resembles template paramters that are automatically
- # stripped out by ShortFunctionName()
- $this_routine .= "<$start_val>";
-
- if (defined($routine) && $routine =~ m/$regexp/) {
- $symbol_table->{$routine} = [HexExtend($last_start),
- HexExtend($start_val)];
- }
- $last_start = $start_val;
- $routine = $this_routine;
- } elsif (m/^Loaded image name: (.+)/) {
- # The win32 nm workalike emits information about the binary it is using.
- if ($main::opt_debug) { print STDERR "Using Image $1\n"; }
- } elsif (m/^PDB file name: (.+)/) {
- # The win32 nm workalike emits information about the pdb it is using.
- if ($main::opt_debug) { print STDERR "Using PDB $1\n"; }
- }
- }
- close(NM);
- # Handle the last line in the nm output. Unfortunately, we don't know
- # how big this last symbol is, because we don't know how big the file
- # is. For now, we just give it a size of 0.
- # TODO(csilvers): do better here.
- if (defined($routine) && $routine =~ m/$regexp/) {
- $symbol_table->{$routine} = [HexExtend($last_start),
- HexExtend($last_start)];
- }
- return $symbol_table;
-}
-
-# Gets the procedure boundaries for all routines in "$image" whose names
-# match "$regexp" and returns them in a hashtable mapping from procedure
-# name to a two-element vector of [start address, end address].
-# Will return an empty map if nm is not installed or not working properly.
-sub GetProcedureBoundaries {
- my $image = shift;
- my $regexp = shift;
-
- # If $image doesn't start with /, then put ./ in front of it. This works
- # around an obnoxious bug in our probing of nm -f behavior.
- # "nm -f $image" is supposed to fail on GNU nm, but if:
- #
- # a. $image starts with [BbSsPp] (for example, bin/foo/bar), AND
- # b. you have a.out in your current directory (a not uncommon occurence)
- #
- # then "nm -f $image" succeeds because -f only looks at the first letter of
- # the argument, which looks valid because it's [BbSsPp], and then since
- # there's no image provided, it looks for a.out and finds it.
- #
- # This regex makes sure that $image starts with . or /, forcing the -f
- # parsing to fail since . and / are not valid formats.
- $image =~ s#^[^/]#./$&#;
-
- # For libc libraries, the copy in /usr/lib/debug contains debugging symbols
- my $debugging = DebuggingLibrary($image);
- if ($debugging) {
- $image = $debugging;
- }
-
- my $nm = $obj_tool_map{"nm"};
- my $cppfilt = $obj_tool_map{"c++filt"};
-
- # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm
- # binary doesn't support --demangle. In addition, for OS X we need
- # to use the -f flag to get 'flat' nm output (otherwise we don't sort
- # properly and get incorrect results). Unfortunately, GNU nm uses -f
- # in an incompatible way. So first we test whether our nm supports
- # --demangle and -f.
- my $demangle_flag = "";
- my $cppfilt_flag = "";
- my $to_devnull = ">$dev_null 2>&1";
- if (system(ShellEscape($nm, "--demangle", "image") . $to_devnull) == 0) {
- # In this mode, we do "nm --demangle <foo>"
- $demangle_flag = "--demangle";
- $cppfilt_flag = "";
- } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) {
- # In this mode, we do "nm <foo> | c++filt"
- $cppfilt_flag = " | " . ShellEscape($cppfilt);
- };
- my $flatten_flag = "";
- if (system(ShellEscape($nm, "-f", $image) . $to_devnull) == 0) {
- $flatten_flag = "-f";
- }
-
- # Finally, in the case $imagie isn't a debug library, we try again with
- # -D to at least get *exported* symbols. If we can't use --demangle,
- # we use c++filt instead, if it exists on this system.
- my @nm_commands = (ShellEscape($nm, "-n", $flatten_flag, $demangle_flag,
- $image) . " 2>$dev_null $cppfilt_flag",
- ShellEscape($nm, "-D", "-n", $flatten_flag, $demangle_flag,
- $image) . " 2>$dev_null $cppfilt_flag",
- # 6nm is for Go binaries
- ShellEscape("6nm", "$image") . " 2>$dev_null | sort",
- );
-
- # If the executable is an MS Windows PDB-format executable, we'll
- # have set up obj_tool_map("nm_pdb"). In this case, we actually
- # want to use both unix nm and windows-specific nm_pdb, since
- # PDB-format executables can apparently include dwarf .o files.
- if (exists $obj_tool_map{"nm_pdb"}) {
- push(@nm_commands,
- ShellEscape($obj_tool_map{"nm_pdb"}, "--demangle", $image)
- . " 2>$dev_null");
- }
-
- foreach my $nm_command (@nm_commands) {
- my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp);
- return $symbol_table if (%{$symbol_table});
- }
- my $symbol_table = {};
- return $symbol_table;
-}
-
-
-# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings.
-# To make them more readable, we add underscores at interesting places.
-# This routine removes the underscores, producing the canonical representation
-# used by pprof to represent addresses, particularly in the tested routines.
-sub CanonicalHex {
- my $arg = shift;
- return join '', (split '_',$arg);
-}
-
-
-# Unit test for AddressAdd:
-sub AddressAddUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressAddUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressAdd ($row->[0], $row->[1]);
- if ($sum ne $row->[2]) {
- printf STDERR "ERROR: %s != %s + %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[2];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressAdd 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1]));
- my $expected = join '', (split '_',$row->[2]);
- if ($sum ne CanonicalHex($row->[2])) {
- printf STDERR "ERROR: %s != %s + %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[2];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressAdd 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Unit test for AddressSub:
-sub AddressSubUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressSubUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressSub ($row->[0], $row->[1]);
- if ($sum ne $row->[3]) {
- printf STDERR "ERROR: %s != %s - %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[3];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressSub 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1]));
- if ($sum ne CanonicalHex($row->[3])) {
- printf STDERR "ERROR: %s != %s - %s = %s\n", $sum,
- $row->[0], $row->[1], $row->[3];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressSub 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Unit test for AddressInc:
-sub AddressIncUnitTest {
- my $test_data_8 = shift;
- my $test_data_16 = shift;
- my $error_count = 0;
- my $fail_count = 0;
- my $pass_count = 0;
- # print STDERR "AddressIncUnitTest: ", 1+$#{$test_data_8}, " tests\n";
-
- # First a few 8-nibble addresses. Note that this implementation uses
- # plain old arithmetic, so a quick sanity check along with verifying what
- # happens to overflow (we want it to wrap):
- $address_length = 8;
- foreach my $row (@{$test_data_8}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressInc ($row->[0]);
- if ($sum ne $row->[4]) {
- printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum,
- $row->[0], $row->[4];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressInc 32-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count = $fail_count;
- $fail_count = 0;
- $pass_count = 0;
-
- # Now 16-nibble addresses.
- $address_length = 16;
- foreach my $row (@{$test_data_16}) {
- if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; }
- my $sum = AddressInc (CanonicalHex($row->[0]));
- if ($sum ne CanonicalHex($row->[4])) {
- printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum,
- $row->[0], $row->[4];
- ++$fail_count;
- } else {
- ++$pass_count;
- }
- }
- printf STDERR "AddressInc 64-bit tests: %d passes, %d failures\n",
- $pass_count, $fail_count;
- $error_count += $fail_count;
-
- return $error_count;
-}
-
-
-# Driver for unit tests.
-# Currently just the address add/subtract/increment routines for 64-bit.
-sub RunUnitTests {
- my $error_count = 0;
-
- # This is a list of tuples [a, b, a+b, a-b, a+1]
- my $unit_test_data_8 = [
- [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)],
- [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)],
- [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)],
- [qw(00000001 ffffffff 00000000 00000002 00000002)],
- [qw(00000001 fffffff0 fffffff1 00000011 00000002)],
- ];
- my $unit_test_data_16 = [
- # The implementation handles data in 7-nibble chunks, so those are the
- # interesting boundaries.
- [qw(aaaaaaaa 50505050
- 00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)],
- [qw(50505050 aaaaaaaa
- 00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)],
- [qw(ffffffff aaaaaaaa
- 00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)],
- [qw(00000001 ffffffff
- 00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)],
- [qw(00000001 fffffff0
- 00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)],
-
- [qw(00_a00000a_aaaaaaa 50505050
- 00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)],
- [qw(0f_fff0005_0505050 aaaaaaaa
- 0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)],
- [qw(00_000000f_fffffff 01_800000a_aaaaaaa
- 01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)],
- [qw(00_0000000_0000001 ff_fffffff_fffffff
- 00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)],
- [qw(00_0000000_0000001 ff_fffffff_ffffff0
- ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)],
- ];
-
- $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16);
- $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16);
- $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16);
- if ($error_count > 0) {
- print STDERR $error_count, " errors: FAILED\n";
- } else {
- print STDERR "PASS\n";
- }
- exit ($error_count);
-}
diff --git a/extra/jemalloc/config.guess b/extra/jemalloc/config.guess
deleted file mode 100755
index d622a44e551..00000000000
--- a/extra/jemalloc/config.guess
+++ /dev/null
@@ -1,1530 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012 Free Software Foundation, Inc.
-
-timestamp='2012-02-10'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner. Please send patches (context
-# diff format) to <config-patches@gnu.org> and include a ChangeLog
-# entry.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
-#
-# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
- --version | -v )
- echo "$version" ; exit ;;
- --help | --h* | -h )
- echo "$usage"; exit ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help" >&2
- exit 1 ;;
- * )
- break ;;
- esac
-done
-
-if test $# != 0; then
- echo "$me: too many arguments$help" >&2
- exit 1
-fi
-
-trap 'exit 1' 1 2 15
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
- PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- *:NetBSD:*:*)
- # NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
- # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
- # switched to ELF, *-*-netbsd* would select the old
- # object file format. This provides both forward
- # compatibility and a consistent mechanism for selecting the
- # object file format.
- #
- # Note: NetBSD doesn't particularly care about the vendor
- # portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
- armeb) machine=armeb-unknown ;;
- arm*) machine=arm-unknown ;;
- sh3el) machine=shl-unknown ;;
- sh3eb) machine=sh-unknown ;;
- sh5el) machine=sh5le-unknown ;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
- esac
- # The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
- case "${UNAME_MACHINE_ARCH}" in
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ELF__
- then
- # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
- # Return netbsd for either. FIX?
- os=netbsd
- else
- os=netbsdelf
- fi
- ;;
- *)
- os=netbsd
- ;;
- esac
- # The OS release
- # Debian GNU/NetBSD machines have a different userland, and
- # thus, need a distinct triplet. However, they do not need
- # kernel version information, so it can be replaced with a
- # suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
- Debian*)
- release='-gnu'
- ;;
- *)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
- ;;
- esac
- # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
- # contains redundant information, the shorter form:
- # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
- exit ;;
- *:OpenBSD:*:*)
- UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
- exit ;;
- *:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
- exit ;;
- *:SolidBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
- exit ;;
- macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- *:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- alpha:OSF1:*:*)
- case $UNAME_RELEASE in
- *4.0)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- ;;
- *5.*)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
- ;;
- esac
- # According to Compaq, /usr/sbin/psrinfo has been available on
- # OSF/1 and Tru64 systems produced since 1995. I hope that
- # covers most systems running today. This code pipes the CPU
- # types through head -n 1, so we only detect the type of CPU 0.
- ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
- case "$ALPHA_CPU_TYPE" in
- "EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
- "EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
- "LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
- "EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
- "EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
- "EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
- "EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
- "EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
- "EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
- "EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
- "EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
- "EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
- esac
- # A Pn.n version is a patched version.
- # A Vn.n version is a released version.
- # A Tn.n version is a released field test version.
- # A Xn.n version is an unreleased experimental baselevel.
- # 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
- exitcode=$?
- trap '' 0
- exit $exitcode ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit ;;
- Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit ;;
- *:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
- exit ;;
- *:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
- exit ;;
- *:OS/390:*:*)
- echo i370-ibm-openedition
- exit ;;
- *:z/VM:*:*)
- echo s390-ibm-zvmoe
- exit ;;
- *:OS400:*:*)
- echo powerpc-ibm-os400
- exit ;;
- arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
- exit ;;
- arm:riscos:*:*|arm:RISCOS:*:*)
- echo arm-unknown-riscos
- exit ;;
- SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit ;;
- Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
- # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "`(/bin/universe) 2>/dev/null`" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit ;;
- NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit ;;
- DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit ;;
- DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
- case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7; exit ;;
- esac ;;
- s390x:SunOS:*:*)
- echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux${UNAME_RELEASE}
- exit ;;
- i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- eval $set_cc_for_build
- SUN_ARCH="i386"
- # If there is a compiler, see if it is configured for 64-bit objects.
- # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
- # This test works for both compilers.
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- SUN_ARCH="x86_64"
- fi
- fi
- echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:6*:*)
- # According to config.sub, this is the proper way to canonicalize
- # SunOS6. Hard to guess exactly what SunOS6 will be like, but
- # it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:*:*)
- case "`/usr/bin/arch -k`" in
- Series*|S4*)
- UNAME_RELEASE=`uname -v`
- ;;
- esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit ;;
- sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
- exit ;;
- sun*:*:4.2BSD:*)
- UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
- case "`/bin/arch`" in
- sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
- ;;
- sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
- ;;
- esac
- exit ;;
- aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
- exit ;;
- # The situation for MiNT is a little confusing. The machine name
- # can be virtually everything (everything which is not
- # "atarist" or "atariste" at least should have a processor
- # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
- # to the lowercase version "mint" (or "freemint"). Finally
- # the system name "TOS" denotes a system which is actually not
- # MiNT. But MiNT is downward compatible to TOS, so this should
- # be no problem.
- atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
- hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
- *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
- m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
- exit ;;
- powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
- exit ;;
- RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit ;;
- RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
- exit ;;
- VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
- exit ;;
- 2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
- exit ;;
- mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-#ifdef __cplusplus
-#include <stdio.h> /* for printf() prototype */
- int main (int argc, char *argv[]) {
-#else
- int main (argc, argv) int argc; char *argv[]; {
-#endif
- #if defined (host_mips) && defined (MIPSEB)
- #if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
- #endif
- #endif
- exit (-1);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
- { echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos${UNAME_RELEASE}
- exit ;;
- Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit ;;
- Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit ;;
- Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit ;;
- Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit ;;
- m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit ;;
- m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit ;;
- m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit ;;
- AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
- then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
- then
- echo m88k-dg-dgux${UNAME_RELEASE}
- else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
- fi
- else
- echo i586-dg-dgux${UNAME_RELEASE}
- fi
- exit ;;
- M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit ;;
- M88*:*:R3*:*)
- # Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit ;;
- XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit ;;
- Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit ;;
- *:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit ;;
- ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
- i*86:AIX:*:*)
- echo i386-ibm-aix
- exit ;;
- ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit ;;
- *:AIX:2:3)
- if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <sys/systemcfg.h>
-
- main()
- {
- if (!__power_pc())
- exit(1);
- puts("powerpc-ibm-aix3.2.5");
- exit(0);
- }
-EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
- then
- echo "$SYSTEM_NAME"
- else
- echo rs6000-ibm-aix3.2.5
- fi
- elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
- else
- echo rs6000-ibm-aix3.2
- fi
- exit ;;
- *:AIX:*:[4567])
- IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
- IBM_ARCH=rs6000
- else
- IBM_ARCH=powerpc
- fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit ;;
- *:AIX:*:*)
- echo rs6000-ibm-aix
- exit ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
- echo romp-ibm-bsd4.4
- exit ;;
- ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit ;; # report: romp-ibm BSD 4.3
- *:BOSX:*:*)
- echo rs6000-bull-bosx
- exit ;;
- DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit ;;
- 9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit ;;
- hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit ;;
- 9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
- sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
- fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-
- #define _HPUX_SOURCE
- #include <stdlib.h>
- #include <unistd.h>
-
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
-
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
-EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
- test -z "$HP_ARCH" && HP_ARCH=hppa
- fi ;;
- esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
- then
- eval $set_cc_for_build
-
- # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
- # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
- # generating 64-bit code. GNU and HP use different nomenclature:
- #
- # $ CC_FOR_BUILD=cc ./config.guess
- # => hppa2.0w-hp-hpux11.23
- # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
- # => hppa64-hp-hpux11.23
-
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
- grep -q __LP64__
- then
- HP_ARCH="hppa2.0w"
- else
- HP_ARCH="hppa64"
- fi
- fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit ;;
- ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
- exit ;;
- 3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <unistd.h>
- int
- main ()
- {
- long cpu = sysconf (_SC_CPU_VERSION);
- /* The order matters, because CPU_IS_HP_MC68K erroneously returns
- true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
- results, however. */
- if (CPU_IS_PA_RISC (cpu))
- {
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
- default: puts ("hppa-hitachi-hiuxwe2"); break;
- }
- }
- else if (CPU_IS_HP_MC68K (cpu))
- puts ("m68k-hitachi-hiuxwe2");
- else puts ("unknown-hitachi-hiuxwe2");
- exit (0);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
- echo unknown-hitachi-hiuxwe2
- exit ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
- echo hppa1.1-hp-bsd
- exit ;;
- 9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit ;;
- *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
- echo hppa1.1-hp-osf
- exit ;;
- hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit ;;
- i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
- else
- echo ${UNAME_MACHINE}-unknown-osf1
- fi
- exit ;;
- parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit ;;
- C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit ;;
- C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit ;;
- C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit ;;
- C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit ;;
- CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
- | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
- -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
- -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- *:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- 5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit ;;
- sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:FreeBSD:*:*)
- UNAME_PROCESSOR=`/usr/bin/uname -p`
- case ${UNAME_PROCESSOR} in
- amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- esac
- exit ;;
- i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
- exit ;;
- *:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit ;;
- i*:MSYS*:*)
- echo ${UNAME_MACHINE}-pc-msys
- exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
- exit ;;
- i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
- exit ;;
- *:Interix*:*)
- case ${UNAME_MACHINE} in
- x86)
- echo i586-pc-interix${UNAME_RELEASE}
- exit ;;
- authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix${UNAME_RELEASE}
- exit ;;
- IA64)
- echo ia64-unknown-interix${UNAME_RELEASE}
- exit ;;
- esac ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit ;;
- 8664:Windows_NT:*)
- echo x86_64-pc-mks
- exit ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit ;;
- i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
- exit ;;
- amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
- exit ;;
- prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- *:GNU:*:*)
- # the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit ;;
- *:GNU/*:*:*)
- # other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
- exit ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
- exit ;;
- aarch64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- aarch64_be:Linux:*:*)
- UNAME_MACHINE=aarch64_be
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- EV5) UNAME_MACHINE=alphaev5 ;;
- EV56) UNAME_MACHINE=alphaev56 ;;
- PCA56) UNAME_MACHINE=alphapca56 ;;
- PCA57) UNAME_MACHINE=alphapca56 ;;
- EV6) UNAME_MACHINE=alphaev6 ;;
- EV67) UNAME_MACHINE=alphaev67 ;;
- EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
- objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
- exit ;;
- arm*:Linux:*:*)
- eval $set_cc_for_build
- if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_EABI__
- then
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- else
- if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_PCS_VFP
- then
- echo ${UNAME_MACHINE}-unknown-linux-gnueabi
- else
- echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
- fi
- fi
- exit ;;
- avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- cris:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-gnu
- exit ;;
- crisv32:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-gnu
- exit ;;
- frv:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- hexagon:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- i*86:Linux:*:*)
- LIBC=gnu
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
- exit ;;
- ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- mips:Linux:*:* | mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef ${UNAME_MACHINE}
- #undef ${UNAME_MACHINE}el
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=${UNAME_MACHINE}el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=${UNAME_MACHINE}
- #else
- CPU=
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
- ;;
- or32:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- padre:Linux:*:*)
- echo sparc-unknown-linux-gnu
- exit ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
- exit ;;
- parisc:Linux:*:* | hppa:Linux:*:*)
- # Look for CPU level
- case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-gnu ;;
- PA8*) echo hppa2.0-unknown-linux-gnu ;;
- *) echo hppa-unknown-linux-gnu ;;
- esac
- exit ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
- exit ;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
- exit ;;
- s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
- exit ;;
- sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- tile*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-gnu
- exit ;;
- x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- i*86:DYNIX/ptx:4*:*)
- # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
- # earlier versions are messed up and put the nodename in both
- # sysname and nodename.
- echo i386-sequent-sysv4
- exit ;;
- i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
- # I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit ;;
- i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
- # is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
- exit ;;
- i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
- exit ;;
- i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
- exit ;;
- i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
- exit ;;
- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
- if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
- else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
- fi
- exit ;;
- i*86:*:5:[678]*)
- # UnixWare 7.x, OpenUNIX and OpenServer 6.
- case `/bin/uname -X | grep "^Machine"` in
- *486*) UNAME_MACHINE=i486 ;;
- *Pentium) UNAME_MACHINE=i586 ;;
- *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
- esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit ;;
- i*86:*:3.2:*)
- if test -f /usr/options/cb.name; then
- UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
- elif /bin/uname -X 2>/dev/null >/dev/null ; then
- UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
- (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
- (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
- && UNAME_MACHINE=i586
- (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
- && UNAME_MACHINE=i686
- (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
- && UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
- else
- echo ${UNAME_MACHINE}-pc-sysv32
- fi
- exit ;;
- pc:*:*:*)
- # Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i586.
- # Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configury will decide that
- # this is a cross-build.
- echo i586-pc-msdosdjgpp
- exit ;;
- Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit ;;
- paragon:*:*:*)
- echo i860-intel-osf1
- exit ;;
- i860:*:4.*:*) # i860-SVR4
- if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
- else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
- fi
- exit ;;
- mini*:CTIX:SYS*5:*)
- # "miniframe"
- echo m68010-convergent-sysv
- exit ;;
- mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit ;;
- M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit ;;
- M68*:*:R3V[5678]*:*)
- test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
- 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
- OS_REL=''
- test -r /etc/.relid \
- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
- 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4; exit; } ;;
- NCR*:*:4.2:* | MPRAS*:*:4.2:*)
- OS_REL='.3'
- test -r /etc/.relid \
- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
- /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
- m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit ;;
- TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
- exit ;;
- RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
- RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
- *:SINIX-*:*:*)
- if uname -p 2>/dev/null >/dev/null ; then
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
- else
- echo ns32k-sni-sysv
- fi
- exit ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
- *:UNIX_System_V:4*:FTX*)
- # From Gerald Hewes <hewes@openmarket.com>.
- # How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
- *:*:*:FTX*)
- # From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
- i*86:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
- exit ;;
- *:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit ;;
- mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
- exit ;;
- news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit ;;
- R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
- else
- echo mips-unknown-sysv${UNAME_RELEASE}
- fi
- exit ;;
- BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit ;;
- BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit ;;
- BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit ;;
- BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
- echo i586-pc-haiku
- exit ;;
- SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux${UNAME_RELEASE}
- exit ;;
- Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit ;;
- *:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit ;;
- *:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- case $UNAME_PROCESSOR in
- i386)
- eval $set_cc_for_build
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- UNAME_PROCESSOR="x86_64"
- fi
- fi ;;
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit ;;
- *:procnto*:*:* | *:QNX:[0123456789]*:*)
- UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
- UNAME_PROCESSOR=i386
- UNAME_MACHINE=pc
- fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit ;;
- *:QNX:*:4*)
- echo i386-pc-qnx
- exit ;;
- NEO-?:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk${UNAME_RELEASE}
- exit ;;
- NSE-?:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
- exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
- exit ;;
- *:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit ;;
- BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit ;;
- DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit ;;
- *:Plan9:*:*)
- # "uname -m" is not consistent, so use $cputype instead. 386
- # is converted to i386 for consistency with other x86
- # operating systems.
- if test "$cputype" = "386"; then
- UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
- fi
- echo ${UNAME_MACHINE}-unknown-plan9
- exit ;;
- *:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit ;;
- *:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit ;;
- KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit ;;
- XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit ;;
- *:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit ;;
- *:ITS:*:*)
- echo pdp10-unknown-its
- exit ;;
- SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit ;;
- *:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
- *:*VMS:*:*)
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
- A*) echo alpha-dec-vms ; exit ;;
- I*) echo ia64-dec-vms ; exit ;;
- V*) echo vax-dec-vms ; exit ;;
- esac ;;
- *:XENIX:*:SysV)
- echo i386-pc-xenix
- exit ;;
- i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
- exit ;;
- i*86:rdos:*:*)
- echo ${UNAME_MACHINE}-pc-rdos
- exit ;;
- i*86:AROS:*:*)
- echo ${UNAME_MACHINE}-pc-aros
- exit ;;
- x86_64:VMkernel:*:*)
- echo ${UNAME_MACHINE}-unknown-esx
- exit ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
- I don't know.... */
- printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
- printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
- "4"
-#else
- ""
-#endif
- ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
- int version;
- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- if (version < 4)
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
- else
- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
- exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
- printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
- printf ("ns32k-encore-mach\n"); exit (0);
-#else
- printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
- printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
- printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
- printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-# include <sys/param.h>
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
- printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
- exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- c34*)
- echo c34-convex-bsd
- exit ;;
- c38*)
- echo c38-convex-bsd
- exit ;;
- c4*)
- echo c4-convex-bsd
- exit ;;
- esac
-fi
-
-cat >&2 <<EOF
-$0: unable to guess system type
-
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
-
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
-and
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
-
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
-
-hostinfo = `(hostinfo) 2>/dev/null`
-/bin/universe = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
-EOF
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/extra/jemalloc/config.stamp.in b/extra/jemalloc/config.stamp.in
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/extra/jemalloc/config.stamp.in
+++ /dev/null
diff --git a/extra/jemalloc/config.sub b/extra/jemalloc/config.sub
deleted file mode 100755
index c894da45500..00000000000
--- a/extra/jemalloc/config.sub
+++ /dev/null
@@ -1,1773 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012 Free Software Foundation, Inc.
-
-timestamp='2012-02-10'
-
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted GNU ChangeLog entry.
-#
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support. The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
-
-Canonicalize a configuration name.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
- --version | -v )
- echo "$version" ; exit ;;
- --help | --h* | -h )
- echo "$usage"; exit ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help"
- exit 1 ;;
-
- *local*)
- # First pass through any local machine types.
- echo $1
- exit ;;
-
- * )
- break ;;
- esac
-done
-
-case $# in
- 0) echo "$me: missing argument$help" >&2
- exit 1;;
- 1) ;;
- *) echo "$me: too many arguments$help" >&2
- exit 1;;
-esac
-
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
- linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
- knetbsd*-gnu* | netbsd*-gnu* | \
- kopensolaris*-gnu* | \
- storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- android-linux)
- os=-linux-android
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
-
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze)
- os=
- basic_machine=$1
- ;;
- -bluegene*)
- os=-cnk
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco6)
- os=-sco5v6
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*)
- os=-lynxos
- ;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
- ;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
- ;;
- -psos*)
- os=-psos
- ;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
-esac
-
-# Decode aliases for certain CPU-COMPANY combinations.
-case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | aarch64 | aarch64_be \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
- | be32 | be64 \
- | bfin \
- | c4x | clipper \
- | d10v | d30v | dlx | dsp16xx \
- | epiphany \
- | fido | fr30 | frv \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | hexagon \
- | i370 | i860 | i960 | ia64 \
- | ip2k | iq2000 \
- | le32 | le64 \
- | lm32 \
- | m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | mcore | mep | metag \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipstx39 | mipstx39el \
- | mn10200 | mn10300 \
- | moxie \
- | mt \
- | msp430 \
- | nds32 | nds32le | nds32be \
- | nios | nios2 \
- | ns16k | ns32k \
- | open8 \
- | or32 \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle \
- | pyramid \
- | rl78 | rx \
- | score \
- | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
- | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu \
- | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
- | ubicom32 \
- | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
- | we32k \
- | x86 | xc16x | xstormy16 | xtensa \
- | z8k | z80)
- basic_machine=$basic_machine-unknown
- ;;
- c54x)
- basic_machine=tic54x-unknown
- ;;
- c55x)
- basic_machine=tic55x-unknown
- ;;
- c6x)
- basic_machine=tic6x-unknown
- ;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
- ;;
- ms1)
- basic_machine=mt-unknown
- ;;
-
- strongarm | thumb | xscale)
- basic_machine=arm-unknown
- ;;
- xgate)
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- xscaleeb)
- basic_machine=armeb-unknown
- ;;
-
- xscaleel)
- basic_machine=armel-unknown
- ;;
-
- # We use `pc' rather than `unknown'
- # because (1) that's what they normally are, and
- # (2) the word "unknown" tends to confuse beginning users.
- i*86 | x86_64)
- basic_machine=$basic_machine-pc
- ;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | aarch64-* | aarch64_be-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* | avr32-* \
- | be32-* | be64-* \
- | bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* \
- | clipper-* | craynv-* | cydra-* \
- | d10v-* | d30v-* | dlx-* \
- | elxsi-* \
- | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | hexagon-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* | iq2000-* \
- | le32-* | le64-* \
- | lm32-* \
- | m32c-* | m32r-* | m32rle-* \
- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- | mips16-* \
- | mips64-* | mips64el-* \
- | mips64octeon-* | mips64octeonel-* \
- | mips64orion-* | mips64orionel-* \
- | mips64r5900-* | mips64r5900el-* \
- | mips64vr-* | mips64vrel-* \
- | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* \
- | mips64vr5000-* | mips64vr5000el-* \
- | mips64vr5900-* | mips64vr5900el-* \
- | mipsisa32-* | mipsisa32el-* \
- | mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa64-* | mipsisa64el-* \
- | mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64sb1-* | mipsisa64sb1el-* \
- | mipsisa64sr71k-* | mipsisa64sr71kel-* \
- | mipstx39-* | mipstx39el-* \
- | mmix-* \
- | mt-* \
- | msp430-* \
- | nds32-* | nds32le-* | nds32be-* \
- | nios-* | nios2-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
- | open8-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
- | pyramid-* \
- | rl78-* | romp-* | rs6000-* | rx-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
- | sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
- | tahoe-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
- | tile*-* \
- | tron-* \
- | ubicom32-* \
- | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
- | vax-* \
- | we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* \
- | xstormy16-* | xtensa*-* \
- | ymp-* \
- | z8k-* | z80-*)
- ;;
- # Recognize the basic CPU types without company name, with glob match.
- xtensa*)
- basic_machine=$basic_machine-unknown
- ;;
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
- ;;
- 3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- abacus)
- basic_machine=abacus-unknown
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amd64)
- basic_machine=x86_64-pc
- ;;
- amd64-*)
- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aros)
- basic_machine=i386-pc
- os=-aros
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- blackfin)
- basic_machine=bfin-unknown
- os=-linux
- ;;
- blackfin-*)
- basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- bluegene*)
- basic_machine=powerpc-ibm
- os=-cnk
- ;;
- c54x-*)
- basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c55x-*)
- basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c6x-*)
- basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c90)
- basic_machine=c90-cray
- os=-unicos
- ;;
- cegcc)
- basic_machine=arm-unknown
- os=-cegcc
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
- ;;
- cr16 | cr16-*)
- basic_machine=cr16-unknown
- os=-elf
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- crisv32 | crisv32-* | etraxfs*)
- basic_machine=crisv32-axis
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- crx)
- basic_machine=crx-unknown
- os=-elf
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
- ;;
- decsystem10* | dec10*)
- basic_machine=pdp10-dec
- os=-tops10
- ;;
- decsystem20* | dec20*)
- basic_machine=pdp10-dec
- os=-tops20
- ;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- dicos)
- basic_machine=i686-pc
- os=-dicos
- ;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
- ;;
- encore | umax | mmax)
- basic_machine=ns32k-encore
- ;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
- ;;
- fx2800)
- basic_machine=i860-alliant
- ;;
- genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
- ;;
- h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
- ;;
- hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
- ;;
- hp9k3[2-9][0-9])
- basic_machine=m68k-hp
- ;;
- hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
- ;;
- hp9k78[0-9] | hp78[0-9])
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
- ;;
- i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
- ;;
- i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
- ;;
- i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
- ;;
- i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
- ;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
- ;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
- ;;
- iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- -irix*)
- ;;
- *)
- os=-irix4
- ;;
- esac
- ;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- m68knommu)
- basic_machine=m68k-unknown
- os=-linux
- ;;
- m68knommu-*)
- basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- microblaze)
- basic_machine=microblaze-xilinx
- ;;
- mingw32)
- basic_machine=i386-pc
- os=-mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- os=-mingw32ce
- ;;
- miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
- ;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- ms1-*)
- basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
- ;;
- msys)
- basic_machine=i386-pc
- os=-msys
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- nacl)
- basic_machine=le32-unknown
- os=-nacl
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
- ;;
- news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
- ;;
- next | m*-next )
- basic_machine=m68k-next
- case $os in
- -nextstep* )
- ;;
- -ns2*)
- os=-nextstep2
- ;;
- *)
- os=-nextstep3
- ;;
- esac
- ;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
- np1)
- basic_machine=np1-gould
- ;;
- neo-tandem)
- basic_machine=neo-tandem
- ;;
- nse-tandem)
- basic_machine=nse-tandem
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
- ;;
- op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- openrisc | openrisc-*)
- basic_machine=or32-unknown
- ;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
- ;;
- pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- parisc)
- basic_machine=hppa-unknown
- os=-linux
- ;;
- parisc-*)
- basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- pbd)
- basic_machine=sparc-tti
- ;;
- pbb)
- basic_machine=m68k-tti
- ;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
- ;;
- pc98)
- basic_machine=i386-pc
- ;;
- pc98-*)
- basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium | p5 | k5 | k6 | nexgen | viac3)
- basic_machine=i586-pc
- ;;
- pentiumpro | p6 | 6x86 | athlon | athlon_*)
- basic_machine=i686-pc
- ;;
- pentiumii | pentium2 | pentiumiii | pentium3)
- basic_machine=i686-pc
- ;;
- pentium4)
- basic_machine=i786-pc
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium4-*)
- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pn)
- basic_machine=pn-gould
- ;;
- power) basic_machine=power-ibm
- ;;
- ppc | ppcbe) basic_machine=powerpc-unknown
- ;;
- ppc-* | ppcbe-*)
- basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppcle | powerpclittle | ppc-le | powerpc-little)
- basic_machine=powerpcle-unknown
- ;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little | ppc64-le | powerpc64-little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rdos)
- basic_machine=i386-pc
- os=-rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- rm[46]00)
- basic_machine=mips-siemens
- ;;
- rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- s390 | s390-*)
- basic_machine=s390-ibm
- ;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
- ;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
- ;;
- sb1)
- basic_machine=mipsisa64sb1-unknown
- ;;
- sb1el)
- basic_machine=mipsisa64sb1el-unknown
- ;;
- sde)
- basic_machine=mipsisa32-sde
- os=-elf
- ;;
- sei)
- basic_machine=mips-sei
- os=-seiux
- ;;
- sequent)
- basic_machine=i386-sequent
- ;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
- ;;
- sh5el)
- basic_machine=sh5le-unknown
- ;;
- sh64)
- basic_machine=sh64-unknown
- ;;
- sparclite-wrs | simso-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
- ;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
- ;;
- spur)
- basic_machine=spur-unknown
- ;;
- st2000)
- basic_machine=m68k-tandem
- ;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
- ;;
- strongarm-* | thumb-*)
- basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- sun2)
- basic_machine=m68000-sun
- ;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
- ;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
- ;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
- ;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
- ;;
- sun4)
- basic_machine=sparc-sun
- ;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
- ;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
- ;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
- ;;
- t90)
- basic_machine=t90-cray
- os=-unicos
- ;;
- tile*)
- basic_machine=$basic_machine-unknown
- os=-linux-gnu
- ;;
- tx39)
- basic_machine=mipstx39-unknown
- ;;
- tx39el)
- basic_machine=mipstx39el-unknown
- ;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
- ;;
- tower | tower-32)
- basic_machine=m68k-ncr
- ;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
- ;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
- ;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
- ;;
- vms)
- basic_machine=vax-dec
- os=-vms
- ;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
- ;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
- ;;
- w65*)
- basic_machine=w65-wdc
- os=-none
- ;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
- ;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
- ;;
- xps | xps100)
- basic_machine=xps100-honeywell
- ;;
- xscale-* | xscalee[bl]-*)
- basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
- ;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
- ;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
- ;;
- z80-*-coff)
- basic_machine=z80-unknown
- os=-sim
- ;;
- none)
- basic_machine=none-none
- os=-none
- ;;
-
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
- ;;
- op50n)
- basic_machine=hppa1.1-oki
- ;;
- op60c)
- basic_machine=hppa1.1-oki
- ;;
- romp)
- basic_machine=romp-ibm
- ;;
- mmix)
- basic_machine=mmix-knuth
- ;;
- rs6000)
- basic_machine=rs6000-ibm
- ;;
- vax)
- basic_machine=vax-dec
- ;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
- ;;
- pdp11)
- basic_machine=pdp11-dec
- ;;
- we32k)
- basic_machine=we32k-att
- ;;
- sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
- basic_machine=sh-unknown
- ;;
- sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
- basic_machine=sparc-sun
- ;;
- cydra)
- basic_machine=cydra-cydrome
- ;;
- orion)
- basic_machine=orion-highlevel
- ;;
- orion105)
- basic_machine=clipper-highlevel
- ;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
- ;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
- ;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
- ;;
- *)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
- ;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
- ;;
- *)
- ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if [ x"$os" != x"" ]
-then
-case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -auroraux)
- os=-auroraux
- ;;
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
- ;;
- -solaris)
- os=-solaris2
- ;;
- -svr4*)
- os=-sysv4
- ;;
- -unixware*)
- os=-sysv4.2uw
- ;;
- -gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
- ;;
- # First accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST END IN A *, to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
- | -sym* | -kopensolaris* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* | -aros* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -openbsd* | -solidbsd* \
- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* | -cegcc* \
- | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-android* \
- | -linux-newlib* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* \
- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
- | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
- # Remember, each alternative MUST END IN *, to match a version number.
- ;;
- -qnx*)
- case $basic_machine in
- x86-* | i*86-*)
- ;;
- *)
- os=-nto$os
- ;;
- esac
- ;;
- -nto-qnx*)
- ;;
- -nto*)
- os=`echo $os | sed -e 's|nto|nto-qnx|'`
- ;;
- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
- ;;
- -mac*)
- os=`echo $os | sed -e 's|mac|macos|'`
- ;;
- -linux-dietlibc)
- os=-linux-dietlibc
- ;;
- -linux*)
- os=`echo $os | sed -e 's|linux|linux-gnu|'`
- ;;
- -sunos5*)
- os=`echo $os | sed -e 's|sunos5|solaris2|'`
- ;;
- -sunos6*)
- os=`echo $os | sed -e 's|sunos6|solaris3|'`
- ;;
- -opened*)
- os=-openedition
- ;;
- -os400*)
- os=-os400
- ;;
- -wince*)
- os=-wince
- ;;
- -osfrose*)
- os=-osfrose
- ;;
- -osf*)
- os=-osf
- ;;
- -utek*)
- os=-bsd
- ;;
- -dynix*)
- os=-bsd
- ;;
- -acis*)
- os=-aos
- ;;
- -atheos*)
- os=-atheos
- ;;
- -syllable*)
- os=-syllable
- ;;
- -386bsd)
- os=-bsd
- ;;
- -ctix* | -uts*)
- os=-sysv
- ;;
- -nova*)
- os=-rtmk-nova
- ;;
- -ns2 )
- os=-nextstep2
- ;;
- -nsk*)
- os=-nsk
- ;;
- # Preserve the version number of sinix5.
- -sinix5.*)
- os=`echo $os | sed -e 's|sinix|sysv|'`
- ;;
- -sinix*)
- os=-sysv4
- ;;
- -tpf*)
- os=-tpf
- ;;
- -triton*)
- os=-sysv3
- ;;
- -oss*)
- os=-sysv3
- ;;
- -svr4)
- os=-sysv4
- ;;
- -svr3)
- os=-sysv3
- ;;
- -sysvr4)
- os=-sysv4
- ;;
- # This must come after -sysvr4.
- -sysv*)
- ;;
- -ose*)
- os=-ose
- ;;
- -es1800*)
- os=-ose
- ;;
- -xenix)
- os=-xenix
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
- ;;
- -aros*)
- os=-aros
- ;;
- -kaos*)
- os=-kaos
- ;;
- -zvmoe)
- os=-zvmoe
- ;;
- -dicos*)
- os=-dicos
- ;;
- -nacl*)
- ;;
- -none)
- ;;
- *)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
- exit 1
- ;;
-esac
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system. Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-case $basic_machine in
- score-*)
- os=-elf
- ;;
- spu-*)
- os=-elf
- ;;
- *-acorn)
- os=-riscix1.2
- ;;
- arm*-rebel)
- os=-linux
- ;;
- arm*-semi)
- os=-aout
- ;;
- c4x-* | tic4x-*)
- os=-coff
- ;;
- tic54x-*)
- os=-coff
- ;;
- tic55x-*)
- os=-coff
- ;;
- tic6x-*)
- os=-coff
- ;;
- # This must come before the *-dec entry.
- pdp10-*)
- os=-tops20
- ;;
- pdp11-*)
- os=-none
- ;;
- *-dec | vax-*)
- os=-ultrix4.2
- ;;
- m68*-apollo)
- os=-domain
- ;;
- i386-sun)
- os=-sunos4.0.2
- ;;
- m68000-sun)
- os=-sunos3
- ;;
- m68*-cisco)
- os=-aout
- ;;
- mep-*)
- os=-elf
- ;;
- mips*-cisco)
- os=-elf
- ;;
- mips*-*)
- os=-elf
- ;;
- or32-*)
- os=-coff
- ;;
- *-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
- ;;
- sparc-* | *-sun)
- os=-sunos4.1.1
- ;;
- *-be)
- os=-beos
- ;;
- *-haiku)
- os=-haiku
- ;;
- *-ibm)
- os=-aix
- ;;
- *-knuth)
- os=-mmixware
- ;;
- *-wec)
- os=-proelf
- ;;
- *-winbond)
- os=-proelf
- ;;
- *-oki)
- os=-proelf
- ;;
- *-hp)
- os=-hpux
- ;;
- *-hitachi)
- os=-hiux
- ;;
- i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
- ;;
- *-cbm)
- os=-amigaos
- ;;
- *-dg)
- os=-dgux
- ;;
- *-dolphin)
- os=-sysv3
- ;;
- m68k-ccur)
- os=-rtu
- ;;
- m88k-omron*)
- os=-luna
- ;;
- *-next )
- os=-nextstep
- ;;
- *-sequent)
- os=-ptx
- ;;
- *-crds)
- os=-unos
- ;;
- *-ns)
- os=-genix
- ;;
- i370-*)
- os=-mvs
- ;;
- *-next)
- os=-nextstep3
- ;;
- *-gould)
- os=-sysv
- ;;
- *-highlevel)
- os=-bsd
- ;;
- *-encore)
- os=-bsd
- ;;
- *-sgi)
- os=-irix
- ;;
- *-siemens)
- os=-sysv4
- ;;
- *-masscomp)
- os=-rtu
- ;;
- f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
- ;;
- *-rom68k)
- os=-coff
- ;;
- *-*bug)
- os=-coff
- ;;
- *-apple)
- os=-macos
- ;;
- *-atari*)
- os=-mint
- ;;
- *)
- os=-none
- ;;
-esac
-fi
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
- case $os in
- -riscix*)
- vendor=acorn
- ;;
- -sunos*)
- vendor=sun
- ;;
- -cnk*|-aix*)
- vendor=ibm
- ;;
- -beos*)
- vendor=be
- ;;
- -hpux*)
- vendor=hp
- ;;
- -mpeix*)
- vendor=hp
- ;;
- -hiux*)
- vendor=hitachi
- ;;
- -unos*)
- vendor=crds
- ;;
- -dgux*)
- vendor=dg
- ;;
- -luna*)
- vendor=omron
- ;;
- -genix*)
- vendor=ns
- ;;
- -mvs* | -opened*)
- vendor=ibm
- ;;
- -os400*)
- vendor=ibm
- ;;
- -ptx*)
- vendor=sequent
- ;;
- -tpf*)
- vendor=ibm
- ;;
- -vxsim* | -vxworks* | -windiss*)
- vendor=wrs
- ;;
- -aux*)
- vendor=apple
- ;;
- -hms*)
- vendor=hitachi
- ;;
- -mpw* | -macos*)
- vendor=apple
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- vendor=atari
- ;;
- -vos*)
- vendor=stratus
- ;;
- esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
- ;;
-esac
-
-echo $basic_machine$os
-exit
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/extra/jemalloc/configure b/extra/jemalloc/configure
deleted file mode 100755
index c112a47d45d..00000000000
--- a/extra/jemalloc/configure
+++ /dev/null
@@ -1,8339 +0,0 @@
-#! /bin/sh
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68.
-#
-#
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
-#
-#
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## -------------------- ##
-## M4sh Initialization. ##
-## -------------------- ##
-
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
- emulate sh
- NULLCMD=:
- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in #(
- *posix*) :
- set -o posix ;; #(
- *) :
- ;;
-esac
-fi
-
-
-as_nl='
-'
-export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- PATH_SEPARATOR=:
- (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
- (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
- PATH_SEPARATOR=';'
- }
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
-# Find who we are. Look in the path if we contain no directory separator.
-as_myself=
-case $0 in #((
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
- done
-IFS=$as_save_IFS
-
- ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
- as_myself=$0
-fi
-if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- exit 1
-fi
-
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
- emulate sh
- NULLCMD=:
- # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '\${1+\"\$@\"}'='\"\$@\"'
- setopt NO_GLOB_SUBST
-else
- case \`(set -o) 2>/dev/null\` in #(
- *posix*) :
- set -o posix ;; #(
- *) :
- ;;
-esac
-fi
-"
- as_required="as_fn_return () { (exit \$1); }
-as_fn_success () { as_fn_return 0; }
-as_fn_failure () { as_fn_return 1; }
-as_fn_ret_success () { return 0; }
-as_fn_ret_failure () { return 1; }
-
-exitcode=0
-as_fn_success || { exitcode=1; echo as_fn_success failed.; }
-as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
-as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
-as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
-
-else
- exitcode=1; echo positional parameters were not saved.
-fi
-test x\$exitcode = x0 || exit 1"
- as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
- as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
- eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
- test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
-test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
- as_have_required=yes
-else
- as_have_required=no
-fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
-
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-as_found=false
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- as_found=:
- case $as_dir in #(
- /*)
- for as_base in sh bash ksh sh5; do
- # Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
- if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
- CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
- break 2
-fi
-fi
- done;;
- esac
- as_found=false
-done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
-IFS=$as_save_IFS
-
-
- if test "x$CONFIG_SHELL" != x; then :
- # We cannot yet assume a decent shell, so we have to provide a
- # neutralization value for shells without unset; and this also
- # works around shells that cannot unset nonexistent variables.
- # Preserve -v and -x to the replacement shell.
- BASH_ENV=/dev/null
- ENV=/dev/null
- (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
- export CONFIG_SHELL
- case $- in # ((((
- *v*x* | *x*v* ) as_opts=-vx ;;
- *v* ) as_opts=-v ;;
- *x* ) as_opts=-x ;;
- * ) as_opts= ;;
- esac
- exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
-fi
-
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
- else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
-$0: including any error possibly output before this
-$0: message. Then install a modern shell, or manually run
-$0: the script under such a shell if you do have one."
- fi
- exit 1
-fi
-fi
-fi
-SHELL=${CONFIG_SHELL-/bin/sh}
-export SHELL
-# Unset more variables known to interfere with behavior of common tools.
-CLICOLOR_FORCE= GREP_OPTIONS=
-unset CLICOLOR_FORCE GREP_OPTIONS
-
-## --------------------- ##
-## M4sh Shell Functions. ##
-## --------------------- ##
-# as_fn_unset VAR
-# ---------------
-# Portably unset VAR.
-as_fn_unset ()
-{
- { eval $1=; unset $1;}
-}
-as_unset=as_fn_unset
-
-# as_fn_set_status STATUS
-# -----------------------
-# Set $? to STATUS, without forking.
-as_fn_set_status ()
-{
- return $1
-} # as_fn_set_status
-
-# as_fn_exit STATUS
-# -----------------
-# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
-as_fn_exit ()
-{
- set +e
- as_fn_set_status $1
- exit $1
-} # as_fn_exit
-
-# as_fn_mkdir_p
-# -------------
-# Create "$as_dir" as a directory, including parents if necessary.
-as_fn_mkdir_p ()
-{
-
- case $as_dir in #(
- -*) as_dir=./$as_dir;;
- esac
- test -d "$as_dir" || eval $as_mkdir_p || {
- as_dirs=
- while :; do
- case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
- *) as_qdir=$as_dir;;
- esac
- as_dirs="'$as_qdir' $as_dirs"
- as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- test -d "$as_dir" && break
- done
- test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
-
-
-} # as_fn_mkdir_p
-# as_fn_append VAR VALUE
-# ----------------------
-# Append the text in VALUE to the end of the definition contained in VAR. Take
-# advantage of any shell optimizations that allow amortized linear growth over
-# repeated appends, instead of the typical quadratic growth present in naive
-# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
- eval 'as_fn_append ()
- {
- eval $1+=\$2
- }'
-else
- as_fn_append ()
- {
- eval $1=\$$1\$2
- }
-fi # as_fn_append
-
-# as_fn_arith ARG...
-# ------------------
-# Perform arithmetic evaluation on the ARGs, and store the result in the
-# global $as_val. Take advantage of shells that can avoid forks. The arguments
-# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
- eval 'as_fn_arith ()
- {
- as_val=$(( $* ))
- }'
-else
- as_fn_arith ()
- {
- as_val=`expr "$@" || test $? -eq 1`
- }
-fi # as_fn_arith
-
-
-# as_fn_error STATUS ERROR [LINENO LOG_FD]
-# ----------------------------------------
-# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with STATUS, using 1 if that was 0.
-as_fn_error ()
-{
- as_status=$1; test $as_status -eq 0 && as_status=1
- if test "$4"; then
- as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
- fi
- $as_echo "$as_me: error: $2" >&2
- as_fn_exit $as_status
-} # as_fn_error
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
-
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-
- as_lineno_1=$LINENO as_lineno_1a=$LINENO
- as_lineno_2=$LINENO as_lineno_2a=$LINENO
- eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
- test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
- # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
- sed -n '
- p
- /[$]LINENO/=
- ' <$as_myself |
- sed '
- s/[$]LINENO.*/&-/
- t lineno
- b
- :lineno
- N
- :loop
- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
- t loop
- s/-\n.*//
- ' >$as_me.lineno &&
- chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensitive to this).
- . "./$as_me.lineno"
- # Exit status is that of the last command.
- exit
-}
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in #(((((
--n*)
- case `echo 'xy\c'` in
- *c*) ECHO_T=' ';; # ECHO_T is single tab character.
- xy) ECHO_C='\c';;
- *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
- ECHO_T=' ';;
- esac;;
-*)
- ECHO_N='-n';;
-esac
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
- rm -f conf$$.dir/conf$$.file
-else
- rm -f conf$$.dir
- mkdir conf$$.dir 2>/dev/null
-fi
-if (echo >conf$$.file) 2>/dev/null; then
- if ln -s conf$$.file conf$$ 2>/dev/null; then
- as_ln_s='ln -s'
- # ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -p'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
- elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
- else
- as_ln_s='cp -p'
- fi
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p='mkdir -p "$as_dir"'
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-if test -x / >/dev/null 2>&1; then
- as_test_x='test -x'
-else
- if ls -dL / >/dev/null 2>&1; then
- as_ls_L_option=L
- else
- as_ls_L_option=
- fi
- as_test_x='
- eval sh -c '\''
- if test -d "$1"; then
- test -d "$1/.";
- else
- case $1 in #(
- -*)set "./$1";;
- esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
- ???[sx]*):;;*)false;;esac;fi
- '\'' sh
- '
-fi
-as_executable_p=$as_test_x
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-test -n "$DJDIR" || exec 7<&0 </dev/null
-exec 6>&1
-
-# Name of the host.
-# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_clean_files=
-ac_config_libobj_dir=.
-LIBOBJS=
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-
-# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
-
-ac_unique_file="Makefile.in"
-# Factoring default headers for most tests.
-ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
-# include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif"
-
-ac_subst_vars='LTLIBOBJS
-LIBOBJS
-cfgoutputs_out
-cfgoutputs_in
-cfghdrs_out
-cfghdrs_in
-enable_zone_allocator
-enable_tls
-enable_lazy_lock
-jemalloc_version_gid
-jemalloc_version_nrev
-jemalloc_version_bugfix
-jemalloc_version_minor
-jemalloc_version_major
-jemalloc_version
-enable_xmalloc
-enable_valgrind
-enable_utrace
-enable_fill
-enable_dss
-enable_munmap
-enable_mremap
-enable_tcache
-enable_prof
-enable_stats
-enable_debug
-install_suffix
-enable_experimental
-AUTOCONF
-LD
-AR
-RANLIB
-INSTALL_DATA
-INSTALL_SCRIPT
-INSTALL_PROGRAM
-enable_autogen
-RPATH_EXTRA
-CC_MM
-MKLIB
-LDTARGET
-CTARGET
-PIC_CFLAGS
-SOREV
-EXTRA_LDFLAGS
-DSO_LDFLAGS
-libprefix
-exe
-a
-o
-importlib
-so
-LD_PRELOAD_VAR
-RPATH
-abi
-host_os
-host_vendor
-host_cpu
-host
-build_os
-build_vendor
-build_cpu
-build
-EGREP
-GREP
-CPP
-OBJEXT
-EXEEXT
-ac_ct_CC
-CPPFLAGS
-LDFLAGS
-CFLAGS
-CC
-XSLROOT
-XSLTPROC
-MANDIR
-DATADIR
-LIBDIR
-INCLUDEDIR
-BINDIR
-PREFIX
-abs_objroot
-objroot
-abs_srcroot
-srcroot
-rev
-target_alias
-host_alias
-build_alias
-LIBS
-ECHO_T
-ECHO_N
-ECHO_C
-DEFS
-mandir
-localedir
-libdir
-psdir
-pdfdir
-dvidir
-htmldir
-infodir
-docdir
-oldincludedir
-includedir
-localstatedir
-sharedstatedir
-sysconfdir
-datadir
-datarootdir
-libexecdir
-sbindir
-bindir
-program_transform_name
-prefix
-exec_prefix
-PACKAGE_URL
-PACKAGE_BUGREPORT
-PACKAGE_STRING
-PACKAGE_VERSION
-PACKAGE_TARNAME
-PACKAGE_NAME
-PATH_SEPARATOR
-SHELL'
-ac_subst_files=''
-ac_user_opts='
-enable_option_checking
-with_xslroot
-with_rpath
-enable_autogen
-enable_experimental
-with_mangling
-with_jemalloc_prefix
-with_export
-with_private_namespace
-with_install_suffix
-enable_cc_silence
-enable_debug
-enable_ivsalloc
-enable_stats
-enable_prof
-enable_prof_libunwind
-with_static_libunwind
-enable_prof_libgcc
-enable_prof_gcc
-enable_tcache
-enable_mremap
-enable_munmap
-enable_dss
-enable_fill
-enable_utrace
-enable_valgrind
-enable_xmalloc
-enable_lazy_lock
-enable_tls
-enable_zone_allocator
-'
- ac_precious_vars='build_alias
-host_alias
-target_alias
-CC
-CFLAGS
-LDFLAGS
-LIBS
-CPPFLAGS
-CPP'
-
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-ac_unrecognized_opts=
-ac_unrecognized_sep=
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-# (The list follows the same order as the GNU Coding Standards.)
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datarootdir='${prefix}/share'
-datadir='${datarootdir}'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE}'
-infodir='${datarootdir}/info'
-htmldir='${docdir}'
-dvidir='${docdir}'
-pdfdir='${docdir}'
-psdir='${docdir}'
-libdir='${exec_prefix}/lib'
-localedir='${datarootdir}/locale'
-mandir='${datarootdir}/man'
-
-ac_prev=
-ac_dashdash=
-for ac_option
-do
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval $ac_prev=\$ac_option
- ac_prev=
- continue
- fi
-
- case $ac_option in
- *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
- *=) ac_optarg= ;;
- *) ac_optarg=yes ;;
- esac
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case $ac_dashdash$ac_option in
- --)
- ac_dashdash=yes ;;
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir=$ac_optarg ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build_alias ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build_alias=$ac_optarg ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file=$ac_optarg ;;
-
- --config-cache | -C)
- cache_file=config.cache ;;
-
- -datadir | --datadir | --datadi | --datad)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=*)
- datadir=$ac_optarg ;;
-
- -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
- | --dataroo | --dataro | --datar)
- ac_prev=datarootdir ;;
- -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
- | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
- datarootdir=$ac_optarg ;;
-
- -disable-* | --disable-*)
- ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
- ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
- case $ac_user_opts in
- *"
-"enable_$ac_useropt"
-"*) ;;
- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
- ac_unrecognized_sep=', ';;
- esac
- eval enable_$ac_useropt=no ;;
-
- -docdir | --docdir | --docdi | --doc | --do)
- ac_prev=docdir ;;
- -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
- docdir=$ac_optarg ;;
-
- -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
- ac_prev=dvidir ;;
- -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
- dvidir=$ac_optarg ;;
-
- -enable-* | --enable-*)
- ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
- ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
- case $ac_user_opts in
- *"
-"enable_$ac_useropt"
-"*) ;;
- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
- ac_unrecognized_sep=', ';;
- esac
- eval enable_$ac_useropt=\$ac_optarg ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix=$ac_optarg ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he | -h)
- ac_init_help=long ;;
- -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
- ac_init_help=recursive ;;
- -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
- ac_init_help=short ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host_alias ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host_alias=$ac_optarg ;;
-
- -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
- ac_prev=htmldir ;;
- -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
- | --ht=*)
- htmldir=$ac_optarg ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir=$ac_optarg ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir=$ac_optarg ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir=$ac_optarg ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir=$ac_optarg ;;
-
- -localedir | --localedir | --localedi | --localed | --locale)
- ac_prev=localedir ;;
- -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
- localedir=$ac_optarg ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst | --locals)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
- localstatedir=$ac_optarg ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir=$ac_optarg ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c | -n)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir=$ac_optarg ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix=$ac_optarg ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix=$ac_optarg ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix=$ac_optarg ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name=$ac_optarg ;;
-
- -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
- ac_prev=pdfdir ;;
- -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
- pdfdir=$ac_optarg ;;
-
- -psdir | --psdir | --psdi | --psd | --ps)
- ac_prev=psdir ;;
- -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
- psdir=$ac_optarg ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir=$ac_optarg ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir=$ac_optarg ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site=$ac_optarg ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir=$ac_optarg ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir=$ac_optarg ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target_alias ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target_alias=$ac_optarg ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers | -V)
- ac_init_version=: ;;
-
- -with-* | --with-*)
- ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
- ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
- case $ac_user_opts in
- *"
-"with_$ac_useropt"
-"*) ;;
- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
- ac_unrecognized_sep=', ';;
- esac
- eval with_$ac_useropt=\$ac_optarg ;;
-
- -without-* | --without-*)
- ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
- ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
- case $ac_user_opts in
- *"
-"with_$ac_useropt"
-"*) ;;
- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
- ac_unrecognized_sep=', ';;
- esac
- eval with_$ac_useropt=no ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes=$ac_optarg ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries=$ac_optarg ;;
-
- -*) as_fn_error $? "unrecognized option: \`$ac_option'
-Try \`$0 --help' for more information"
- ;;
-
- *=*)
- ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
- # Reject names that are not valid shell variable names.
- case $ac_envvar in #(
- '' | [0-9]* | *[!_$as_cr_alnum]* )
- as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
- esac
- eval $ac_envvar=\$ac_optarg
- export $ac_envvar ;;
-
- *)
- # FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
- expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
- : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- as_fn_error $? "missing argument to $ac_option"
-fi
-
-if test -n "$ac_unrecognized_opts"; then
- case $enable_option_checking in
- no) ;;
- fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
- esac
-fi
-
-# Check all directory arguments for consistency.
-for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
- datadir sysconfdir sharedstatedir localstatedir includedir \
- oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir
-do
- eval ac_val=\$$ac_var
- # Remove trailing slashes.
- case $ac_val in
- */ )
- ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
- eval $ac_var=\$ac_val;;
- esac
- # Be sure to have absolute directory names.
- case $ac_val in
- [\\/$]* | ?:[\\/]* ) continue;;
- NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
- esac
- as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
- if test "x$build_alias" = x; then
- cross_compiling=maybe
- $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used" >&2
- elif test "x$build_alias" != "x$host_alias"; then
- cross_compiling=yes
- fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-ac_pwd=`pwd` && test -n "$ac_pwd" &&
-ac_ls_di=`ls -di .` &&
-ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
- as_fn_error $? "working directory cannot be determined"
-test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
- as_fn_error $? "pwd does not report name of working directory"
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then the parent directory.
- ac_confdir=`$as_dirname -- "$as_myself" ||
-$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_myself" : 'X\(//\)[^/]' \| \
- X"$as_myself" : 'X\(//\)$' \| \
- X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- srcdir=$ac_confdir
- if test ! -r "$srcdir/$ac_unique_file"; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r "$srcdir/$ac_unique_file"; then
- test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
- as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
-fi
-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
-ac_abs_confdir=`(
- cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
- pwd)`
-# When building in place, set srcdir=.
-if test "$ac_abs_confdir" = "$ac_pwd"; then
- srcdir=.
-fi
-# Remove unnecessary trailing slashes from srcdir.
-# Double slashes in file names in object file debugging info
-# mess up M-x gdb in Emacs.
-case $srcdir in
-*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
-esac
-for ac_var in $ac_precious_vars; do
- eval ac_env_${ac_var}_set=\${${ac_var}+set}
- eval ac_env_${ac_var}_value=\$${ac_var}
- eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
- eval ac_cv_env_${ac_var}_value=\$${ac_var}
-done
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat <<_ACEOF
-\`configure' configures this package to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE. See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
- -h, --help display this help and exit
- --help=short display options specific to this package
- --help=recursive display the short help of all the included packages
- -V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking ...' messages
- --cache-file=FILE cache test results in FILE [disabled]
- -C, --config-cache alias for \`--cache-file=config.cache'
- -n, --no-create do not create output files
- --srcdir=DIR find the sources in DIR [configure dir or \`..']
-
-Installation directories:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
- --bindir=DIR user executables [EPREFIX/bin]
- --sbindir=DIR system admin executables [EPREFIX/sbin]
- --libexecdir=DIR program executables [EPREFIX/libexec]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --libdir=DIR object code libraries [EPREFIX/lib]
- --includedir=DIR C header files [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc [/usr/include]
- --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
- --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
- --infodir=DIR info documentation [DATAROOTDIR/info]
- --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
- --mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
- --htmldir=DIR html documentation [DOCDIR]
- --dvidir=DIR dvi documentation [DOCDIR]
- --pdfdir=DIR pdf documentation [DOCDIR]
- --psdir=DIR ps documentation [DOCDIR]
-_ACEOF
-
- cat <<\_ACEOF
-
-System types:
- --build=BUILD configure for building on BUILD [guessed]
- --host=HOST cross-compile to build programs to run on HOST [BUILD]
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
-
- cat <<\_ACEOF
-
-Optional Features:
- --disable-option-checking ignore unrecognized --enable/--with options
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --enable-autogen Automatically regenerate configure output
- --disable-experimental Disable support for the experimental API
- --enable-cc-silence Silence irrelevant compiler warnings
- --enable-debug Build debugging code (implies --enable-ivsalloc)
- --enable-ivsalloc Validate pointers passed through the public API
- --disable-stats Disable statistics calculation/reporting
- --enable-prof Enable allocation profiling
- --enable-prof-libunwind Use libunwind for backtracing
- --disable-prof-libgcc Do not use libgcc for backtracing
- --disable-prof-gcc Do not use gcc intrinsics for backtracing
- --disable-tcache Disable per thread caches
- --enable-mremap Enable mremap(2) for huge realloc()
- --disable-munmap Disable VM deallocation via munmap(2)
- --enable-dss Enable allocation from DSS
- --disable-fill Disable support for junk/zero filling, quarantine,
- and redzones
- --enable-utrace Enable utrace(2)-based tracing
- --disable-valgrind Disable support for Valgrind
- --enable-xmalloc Support xmalloc option
- --enable-lazy-lock Enable lazy locking (only lock when multi-threaded)
- --disable-tls Disable thread-local storage (__thread keyword)
- --disable-zone-allocator
- Disable zone allocator for Darwin
-
-Optional Packages:
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --with-xslroot=<path> XSL stylesheet root path
- --with-rpath=<rpath> Colon-separated rpath (ELF systems only)
- --with-mangling=<map> Mangle symbols in <map>
- --with-jemalloc-prefix=<prefix>
- Prefix to prepend to all public APIs
- --without-export disable exporting jemalloc public APIs
- --with-private-namespace=<prefix>
- Prefix to prepend to all library-private APIs
- --with-install-suffix=<suffix>
- Suffix to append to all installed files
- --with-static-libunwind=<libunwind.a>
- Path to static libunwind library; use rather than
- dynamically linking
-
-Some influential environment variables:
- CC C compiler command
- CFLAGS C compiler flags
- LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
- nonstandard directory <lib dir>
- LIBS libraries to pass to the linker, e.g. -l<library>
- CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
- you have headers in a nonstandard directory <include dir>
- CPP C preprocessor
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-Report bugs to the package provider.
-_ACEOF
-ac_status=$?
-fi
-
-if test "$ac_init_help" = "recursive"; then
- # If there are subdirs, report their specific --help.
- for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
- test -d "$ac_dir" ||
- { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
- continue
- ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
- # A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
- case $ac_top_builddir_sub in
- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
- esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
- .) # We are building in place.
- ac_srcdir=.
- ac_top_srcdir=$ac_top_builddir_sub
- ac_abs_top_srcdir=$ac_pwd ;;
- [\\/]* | ?:[\\/]* ) # Absolute name.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir
- ac_abs_top_srcdir=$srcdir ;;
- *) # Relative name.
- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_build_prefix$srcdir
- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
- cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
- if test -f "$ac_srcdir/configure.gnu"; then
- echo &&
- $SHELL "$ac_srcdir/configure.gnu" --help=recursive
- elif test -f "$ac_srcdir/configure"; then
- echo &&
- $SHELL "$ac_srcdir/configure" --help=recursive
- else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
- fi || ac_status=$?
- cd "$ac_pwd" || { ac_status=$?; break; }
- done
-fi
-
-test -n "$ac_init_help" && exit $ac_status
-if $ac_init_version; then
- cat <<\_ACEOF
-configure
-generated by GNU Autoconf 2.68
-
-Copyright (C) 2010 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
- exit
-fi
-
-## ------------------------ ##
-## Autoconf initialization. ##
-## ------------------------ ##
-
-# ac_fn_c_try_compile LINENO
-# --------------------------
-# Try to compile conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_compile ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
- if { { ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compile") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_compile
-
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_try_run LINENO
-# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
-ac_fn_c_try_run ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
- ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=$ac_status
-fi
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_run
-
-# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
-# --------------------------------------------
-# Tries to find the compile-time value of EXPR in a program that includes
-# INCLUDES, setting VAR accordingly. Returns whether the value could be
-# computed
-ac_fn_c_compute_int ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if test "$cross_compiling" = yes; then
- # Depending upon the size, compute the lo and hi bounds.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) >= 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_lo=0 ac_mid=0
- while :; do
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_hi=$ac_mid; break
-else
- as_fn_arith $ac_mid + 1 && ac_lo=$as_val
- if test $ac_lo -le $ac_mid; then
- ac_lo= ac_hi=
- break
- fi
- as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) < 0)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_hi=-1 ac_mid=-1
- while :; do
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) >= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_lo=$ac_mid; break
-else
- as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
- if test $ac_mid -le $ac_hi; then
- ac_lo= ac_hi=
- break
- fi
- as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- ac_lo= ac_hi=
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
- as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_hi=$ac_mid
-else
- as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in #((
-?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
-'') ac_retval=1 ;;
-esac
- else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
- FILE *f = fopen ("conftest.val", "w");
- if (! f)
- return 1;
- if (($2) < 0)
- {
- long int i = longval ();
- if (i != ($2))
- return 1;
- fprintf (f, "%ld", i);
- }
- else
- {
- unsigned long int i = ulongval ();
- if (i != ($2))
- return 1;
- fprintf (f, "%lu", i);
- }
- /* Do not output a trailing newline, as this causes \r\n confusion
- on some platforms. */
- return ferror (f) || fclose (f) != 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
- ac_retval=1
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-rm -f conftest.val
-
- fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_compute_int
-
-# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists and can be compiled using the include files in
-# INCLUDES, setting the cache variable VAR accordingly.
-ac_fn_c_check_header_compile ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_compile
-
-# ac_fn_c_try_link LINENO
-# -----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_link ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- $as_test_x conftest$ac_exeext
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
- # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
- # interfere with the next link command; also delete a directory that is
- # left behind by Apple's compiler. We do this before executing the actions.
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_link
-
-# ac_fn_c_check_func LINENO FUNC VAR
-# ----------------------------------
-# Tests whether FUNC exists, setting the cache variable VAR accordingly
-ac_fn_c_check_func ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $2 innocuous_$2
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $2
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $2 ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$2 || defined __stub___$2
-choke me
-#endif
-
-int
-main ()
-{
-return $2 ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_func
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
-# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
-# -------------------------------------------
-# Tests whether TYPE exists after having included INCLUDES, setting cache
-# variable VAR accordingly.
-ac_fn_c_check_type ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=no"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-if (sizeof ($2))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-if (sizeof (($2)))
- return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
- eval "$3=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_type
-cat >config.log <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by $as_me, which was
-generated by GNU Autoconf 2.68. Invocation command line was
-
- $ $0 $@
-
-_ACEOF
-exec 5>>config.log
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
-
-/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
-/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
-/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
- done
-IFS=$as_save_IFS
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
- for ac_arg
- do
- case $ac_arg in
- -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- continue ;;
- *\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
- esac
- case $ac_pass in
- 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
- 2)
- as_fn_append ac_configure_args1 " '$ac_arg'"
- if test $ac_must_keep_next = true; then
- ac_must_keep_next=false # Got value, back to normal.
- else
- case $ac_arg in
- *=* | --config-cache | -C | -disable-* | --disable-* \
- | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
- | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
- | -with-* | --with-* | -without-* | --without-* | --x)
- case "$ac_configure_args0 " in
- "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
- esac
- ;;
- -* ) ac_must_keep_next=true ;;
- esac
- fi
- as_fn_append ac_configure_args " '$ac_arg'"
- ;;
- esac
- done
-done
-{ ac_configure_args0=; unset ac_configure_args0;}
-{ ac_configure_args1=; unset ac_configure_args1;}
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log. We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Use '\'' to represent an apostrophe within the trap.
-# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
-trap 'exit_status=$?
- # Save into config.log some information that might help in debugging.
- {
- echo
-
- $as_echo "## ---------------- ##
-## Cache variables. ##
-## ---------------- ##"
- echo
- # The following way of writing the cache mishandles newlines in values,
-(
- for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
- eval ac_val=\$$ac_var
- case $ac_val in #(
- *${as_nl}*)
- case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
- esac
- case $ac_var in #(
- _ | IFS | as_nl) ;; #(
- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
- *) { eval $ac_var=; unset $ac_var;} ;;
- esac ;;
- esac
- done
- (set) 2>&1 |
- case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
- *${as_nl}ac_space=\ *)
- sed -n \
- "s/'\''/'\''\\\\'\'''\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
- ;; #(
- *)
- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
- ;;
- esac |
- sort
-)
- echo
-
- $as_echo "## ----------------- ##
-## Output variables. ##
-## ----------------- ##"
- echo
- for ac_var in $ac_subst_vars
- do
- eval ac_val=\$$ac_var
- case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
- esac
- $as_echo "$ac_var='\''$ac_val'\''"
- done | sort
- echo
-
- if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
-## File substitutions. ##
-## ------------------- ##"
- echo
- for ac_var in $ac_subst_files
- do
- eval ac_val=\$$ac_var
- case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
- esac
- $as_echo "$ac_var='\''$ac_val'\''"
- done | sort
- echo
- fi
-
- if test -s confdefs.h; then
- $as_echo "## ----------- ##
-## confdefs.h. ##
-## ----------- ##"
- echo
- cat confdefs.h
- echo
- fi
- test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
- } >&5
- rm -f core *.core core.conftest.* &&
- rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
- exit $exit_status
-' 0
-for ac_signal in 1 2 13 15; do
- trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -f -r conftest* confdefs.h
-
-$as_echo "/* confdefs.h */" > confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
-if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
-elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
-else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
-fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
-do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
- sed 's/^/| /' "$ac_site_file" >&5
- . "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5; }
- fi
-done
-
-if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special files
- # actually), so we avoid doing that. DJGPP emulates it as a regular file.
- if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
- case $cache_file in
- [\\/]* | ?:[\\/]* ) . "$cache_file";;
- *) . "./$cache_file";;
- esac
- fi
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
- >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in $ac_precious_vars; do
- eval ac_old_set=\$ac_cv_env_${ac_var}_set
- eval ac_new_set=\$ac_env_${ac_var}_set
- eval ac_old_val=\$ac_cv_env_${ac_var}_value
- eval ac_new_val=\$ac_env_${ac_var}_value
- case $ac_old_set,$ac_new_set in
- set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,);;
- *)
- if test "x$ac_old_val" != "x$ac_new_val"; then
- # differences in whitespace do not lead to failure.
- ac_old_val_w=`echo x $ac_old_val`
- ac_new_val_w=`echo x $ac_new_val`
- if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
- ac_cache_corrupted=:
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
- eval $ac_var=\$ac_old_val
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
- fi;;
- esac
- # Pass precious variables to config.status.
- if test "$ac_new_set" = set; then
- case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
- *) ac_arg=$ac_var=$ac_new_val ;;
- esac
- case " $ac_configure_args " in
- *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
- *) as_fn_append ac_configure_args " '$ac_arg'" ;;
- esac
- fi
-done
-if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
-fi
-## -------------------- ##
-## Main body of script. ##
-## -------------------- ##
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-
-
-
-
-
-
-rev=1
-
-
-srcroot=$srcdir
-if test "x${srcroot}" = "x." ; then
- srcroot=""
-else
- srcroot="${srcroot}/"
-fi
-
-abs_srcroot="`cd \"${srcdir}\"; pwd`/"
-
-
-objroot=""
-
-abs_objroot="`pwd`/"
-
-
-if test "x$prefix" = "xNONE" ; then
- prefix="/usr/local"
-fi
-if test "x$exec_prefix" = "xNONE" ; then
- exec_prefix=$prefix
-fi
-PREFIX=$prefix
-
-BINDIR=`eval echo $bindir`
-BINDIR=`eval echo $BINDIR`
-
-INCLUDEDIR=`eval echo $includedir`
-INCLUDEDIR=`eval echo $INCLUDEDIR`
-
-LIBDIR=`eval echo $libdir`
-LIBDIR=`eval echo $LIBDIR`
-
-DATADIR=`eval echo $datadir`
-DATADIR=`eval echo $DATADIR`
-
-MANDIR=`eval echo $mandir`
-MANDIR=`eval echo $MANDIR`
-
-
-# Extract the first word of "xsltproc", so it can be a program name with args.
-set dummy xsltproc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_XSLTPROC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $XSLTPROC in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_XSLTPROC="$XSLTPROC" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_XSLTPROC="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_XSLTPROC" && ac_cv_path_XSLTPROC="false"
- ;;
-esac
-fi
-XSLTPROC=$ac_cv_path_XSLTPROC
-if test -n "$XSLTPROC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC" >&5
-$as_echo "$XSLTPROC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-if test -d "/usr/share/xml/docbook/stylesheet/docbook-xsl" ; then
- DEFAULT_XSLROOT="/usr/share/xml/docbook/stylesheet/docbook-xsl"
-elif test -d "/usr/share/sgml/docbook/xsl-stylesheets" ; then
- DEFAULT_XSLROOT="/usr/share/sgml/docbook/xsl-stylesheets"
-else
- DEFAULT_XSLROOT=""
-fi
-
-# Check whether --with-xslroot was given.
-if test "${with_xslroot+set}" = set; then :
- withval=$with_xslroot;
-if test "x$with_xslroot" = "xno" ; then
- XSLROOT="${DEFAULT_XSLROOT}"
-else
- XSLROOT="${with_xslroot}"
-fi
-
-else
- XSLROOT="${DEFAULT_XSLROOT}"
-
-fi
-
-
-
-CFLAGS=$CFLAGS
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-else
- CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- fi
-fi
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# != 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
- fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- for ac_prog in cl.exe
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$CC" && break
- done
-fi
-if test -z "$CC"; then
- ac_ct_CC=$CC
- for ac_prog in cl.exe
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$ac_ct_CC" && break
-done
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-fi
-
-fi
-
-
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
-
-# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
-set X $ac_compile
-ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
- { { ac_try="$ac_compiler $ac_option >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compiler $ac_option >&5") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- sed '10a\
-... rest of stderr output deleted ...
- 10q' conftest.err >conftest.er1
- cat conftest.er1 >&5
- fi
- rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }
-done
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-
-# The possible output files:
-ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
-
-ac_rmfiles=
-for ac_file in $ac_files
-do
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
- * ) ac_rmfiles="$ac_rmfiles $ac_file";;
- esac
-done
-rm -f $ac_rmfiles
-
-if { { ac_try="$ac_link_default"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link_default") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
-# in a Makefile. We should not override ac_cv_exeext if it was cached,
-# so that the user can short-circuit this test for compilers unknown to
-# Autoconf.
-for ac_file in $ac_files ''
-do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
- ;;
- [ab].out )
- # We found the default executable, but exeext='' is most
- # certainly right.
- break;;
- *.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
- then :; else
- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- fi
- # We set ac_cv_exeext here because the later test for it is not
- # safe: cross compilers may not add the suffix if given an `-o'
- # argument, so we may need to know it at that point already.
- # Even if this section looks crufty: it has the advantage of
- # actually working.
- break;;
- * )
- break;;
- esac
-done
-test "$ac_cv_exeext" = no && ac_cv_exeext=
-
-else
- ac_file=''
-fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
-ac_exeext=$ac_cv_exeext
-
-rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
-if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- break;;
- * ) break;;
- esac
-done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdio.h>
-int
-main ()
-{
-FILE *f = fopen ("conftest.out", "w");
- return ferror (f) || fclose (f) != 0;
-
- ;
- return 0;
-}
-_ACEOF
-ac_clean_files="$ac_clean_files conftest.out"
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
-if test "$cross_compiling" != yes; then
- { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }
- if { ac_try='./conftest$ac_cv_exeext'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5; }
- fi
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
-
-rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
-ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { { ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compile") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- for ac_file in conftest.o conftest.obj conftest.*; do
- test -f "$ac_file" || continue;
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
- *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
- break;;
- esac
-done
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_compiler_gnu=yes
-else
- ac_compiler_gnu=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
-if test $ac_compiler_gnu = yes; then
- GCC=yes
-else
- GCC=
-fi
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_save_c_werror_flag=$ac_c_werror_flag
- ac_c_werror_flag=yes
- ac_cv_prog_cc_g=no
- CFLAGS="-g"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_g=yes
-else
- CFLAGS=""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
- ac_c_werror_flag=$ac_save_c_werror_flag
- CFLAGS="-g"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_g=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_c_werror_flag=$ac_save_c_werror_flag
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
-_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
- CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_c89=$ac_arg
-fi
-rm -f core conftest.err conftest.$ac_objext
- test "x$ac_cv_prog_cc_c89" != "xno" && break
-done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
-
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-if test "x$GCC" != "xyes" ; then
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler is MSVC" >&5
-$as_echo_n "checking whether compiler is MSVC... " >&6; }
-if ${je_cv_msvc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
-#ifndef _MSC_VER
- int fail-1;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- je_cv_msvc=yes
-else
- je_cv_msvc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_msvc" >&5
-$as_echo "$je_cv_msvc" >&6; }
-fi
-
-if test "x$CFLAGS" = "x" ; then
- no_CFLAGS="yes"
- if test "x$GCC" = "xyes" ; then
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -std=gnu99" >&5
-$as_echo_n "checking whether compiler supports -std=gnu99... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-std=gnu99"
-else
- CFLAGS="${CFLAGS} -std=gnu99"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wall" >&5
-$as_echo_n "checking whether compiler supports -Wall... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-Wall"
-else
- CFLAGS="${CFLAGS} -Wall"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -pipe" >&5
-$as_echo_n "checking whether compiler supports -pipe... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-pipe"
-else
- CFLAGS="${CFLAGS} -pipe"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -g3" >&5
-$as_echo_n "checking whether compiler supports -g3... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-g3"
-else
- CFLAGS="${CFLAGS} -g3"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- elif test "x$je_cv_msvc" = "xyes" ; then
- CC="$CC -nologo"
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Zi" >&5
-$as_echo_n "checking whether compiler supports -Zi... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-Zi"
-else
- CFLAGS="${CFLAGS} -Zi"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -MT" >&5
-$as_echo_n "checking whether compiler supports -MT... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-MT"
-else
- CFLAGS="${CFLAGS} -MT"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -W3" >&5
-$as_echo_n "checking whether compiler supports -W3... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-W3"
-else
- CFLAGS="${CFLAGS} -W3"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- CPPFLAGS="$CPPFLAGS -I${srcroot}/include/msvc_compat"
- fi
-fi
-if test "x$EXTRA_CFLAGS" != "x" ; then
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports $EXTRA_CFLAGS" >&5
-$as_echo_n "checking whether compiler supports $EXTRA_CFLAGS... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="$EXTRA_CFLAGS"
-else
- CFLAGS="${CFLAGS} $EXTRA_CFLAGS"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
- if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (void *)
-See \`config.log' for more details" "$LINENO" 5; }
- else
- ac_cv_sizeof_void_p=0
- fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
-
-
-if test "x${ac_cv_sizeof_void_p}" = "x8" ; then
- LG_SIZEOF_PTR=3
-elif test "x${ac_cv_sizeof_void_p}" = "x4" ; then
- LG_SIZEOF_PTR=2
-else
- as_fn_error $? "Unsupported pointer size: ${ac_cv_sizeof_void_p}" "$LINENO" 5
-fi
-cat >>confdefs.h <<_ACEOF
-#define LG_SIZEOF_PTR $LG_SIZEOF_PTR
-_ACEOF
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
-$as_echo_n "checking size of int... " >&6; }
-if ${ac_cv_sizeof_int+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then :
-
-else
- if test "$ac_cv_type_int" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (int)
-See \`config.log' for more details" "$LINENO" 5; }
- else
- ac_cv_sizeof_int=0
- fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
-$as_echo "$ac_cv_sizeof_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
-
-
-if test "x${ac_cv_sizeof_int}" = "x8" ; then
- LG_SIZEOF_INT=3
-elif test "x${ac_cv_sizeof_int}" = "x4" ; then
- LG_SIZEOF_INT=2
-else
- as_fn_error $? "Unsupported int size: ${ac_cv_sizeof_int}" "$LINENO" 5
-fi
-cat >>confdefs.h <<_ACEOF
-#define LG_SIZEOF_INT $LG_SIZEOF_INT
-_ACEOF
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
-$as_echo_n "checking size of long... " >&6; }
-if ${ac_cv_sizeof_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then :
-
-else
- if test "$ac_cv_type_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (long)
-See \`config.log' for more details" "$LINENO" 5; }
- else
- ac_cv_sizeof_long=0
- fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
-$as_echo "$ac_cv_sizeof_long" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
-_ACEOF
-
-
-if test "x${ac_cv_sizeof_long}" = "x8" ; then
- LG_SIZEOF_LONG=3
-elif test "x${ac_cv_sizeof_long}" = "x4" ; then
- LG_SIZEOF_LONG=2
-else
- as_fn_error $? "Unsupported long size: ${ac_cv_sizeof_long}" "$LINENO" 5
-fi
-cat >>confdefs.h <<_ACEOF
-#define LG_SIZEOF_LONG $LG_SIZEOF_LONG
-_ACEOF
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of intmax_t" >&5
-$as_echo_n "checking size of intmax_t... " >&6; }
-if ${ac_cv_sizeof_intmax_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (intmax_t))" "ac_cv_sizeof_intmax_t" "$ac_includes_default"; then :
-
-else
- if test "$ac_cv_type_intmax_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (intmax_t)
-See \`config.log' for more details" "$LINENO" 5; }
- else
- ac_cv_sizeof_intmax_t=0
- fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_intmax_t" >&5
-$as_echo "$ac_cv_sizeof_intmax_t" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INTMAX_T $ac_cv_sizeof_intmax_t
-_ACEOF
-
-
-if test "x${ac_cv_sizeof_intmax_t}" = "x16" ; then
- LG_SIZEOF_INTMAX_T=4
-elif test "x${ac_cv_sizeof_intmax_t}" = "x8" ; then
- LG_SIZEOF_INTMAX_T=3
-elif test "x${ac_cv_sizeof_intmax_t}" = "x4" ; then
- LG_SIZEOF_INTMAX_T=2
-else
- as_fn_error $? "Unsupported intmax_t size: ${ac_cv_sizeof_intmax_t}" "$LINENO" 5
-fi
-cat >>confdefs.h <<_ACEOF
-#define LG_SIZEOF_INTMAX_T $LG_SIZEOF_INTMAX_T
-_ACEOF
-
-
-ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
-fi
-
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-
-
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
- as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
-esac
-build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "x$host_alias" = x; then
- ac_cv_host=$ac_cv_build
-else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
-
-CPU_SPINWAIT=""
-case "${host_cpu}" in
- i[345]86)
- ;;
- i686)
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __asm__ is compilable" >&5
-$as_echo_n "checking whether __asm__ is compilable... " >&6; }
-if ${je_cv_asm+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-__asm__ volatile("pause"); return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_asm=yes
-else
- je_cv_asm=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_asm" >&5
-$as_echo "$je_cv_asm" >&6; }
-
- if test "x${je_cv_asm}" = "xyes" ; then
- CPU_SPINWAIT='__asm__ volatile("pause")'
- fi
- ;;
- x86_64)
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __asm__ syntax is compilable" >&5
-$as_echo_n "checking whether __asm__ syntax is compilable... " >&6; }
-if ${je_cv_asm+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-__asm__ volatile("pause"); return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_asm=yes
-else
- je_cv_asm=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_asm" >&5
-$as_echo "$je_cv_asm" >&6; }
-
- if test "x${je_cv_asm}" = "xyes" ; then
- CPU_SPINWAIT='__asm__ volatile("pause")'
- fi
- ;;
- *)
- ;;
-esac
-cat >>confdefs.h <<_ACEOF
-#define CPU_SPINWAIT $CPU_SPINWAIT
-_ACEOF
-
-
-LD_PRELOAD_VAR="LD_PRELOAD"
-so="so"
-importlib="${so}"
-o="$ac_objext"
-a="a"
-exe="$ac_exeext"
-libprefix="lib"
-DSO_LDFLAGS='-shared -Wl,-soname,$(@F)'
-RPATH='-Wl,-rpath,$(1)'
-SOREV="${so}.${rev}"
-PIC_CFLAGS='-fPIC -DPIC'
-CTARGET='-o $@'
-LDTARGET='-o $@'
-EXTRA_LDFLAGS=
-MKLIB='ar crus $@'
-CC_MM=1
-
-default_munmap="1"
-JEMALLOC_USABLE_SIZE_CONST="const"
-case "${host}" in
- *-*-darwin*)
- CFLAGS="$CFLAGS"
- abi="macho"
- $as_echo "#define JEMALLOC_PURGE_MADVISE_FREE " >>confdefs.h
-
- RPATH=""
- LD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
- so="dylib"
- importlib="${so}"
- force_tls="0"
- DSO_LDFLAGS='-shared -Wl,-dylib_install_name,$(@F)'
- SOREV="${rev}.${so}"
- ;;
- *-*-freebsd*)
- CFLAGS="$CFLAGS"
- abi="elf"
- $as_echo "#define JEMALLOC_PURGE_MADVISE_FREE " >>confdefs.h
-
- force_lazy_lock="1"
- ;;
- *-*-linux*)
- CFLAGS="$CFLAGS"
- CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
- abi="elf"
- $as_echo "#define JEMALLOC_HAS_ALLOCA_H 1" >>confdefs.h
-
- $as_echo "#define JEMALLOC_PURGE_MADVISE_DONTNEED " >>confdefs.h
-
- $as_echo "#define JEMALLOC_THREADED_INIT " >>confdefs.h
-
- JEMALLOC_USABLE_SIZE_CONST=""
- default_munmap="0"
- ;;
- *-*-netbsd*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking ABI" >&5
-$as_echo_n "checking ABI... " >&6; }
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __ELF__
-/* ELF */
-#else
-#error aout
-#endif
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- CFLAGS="$CFLAGS"; abi="elf"
-else
- abi="aout"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $abi" >&5
-$as_echo "$abi" >&6; }
- $as_echo "#define JEMALLOC_PURGE_MADVISE_FREE " >>confdefs.h
-
- ;;
- *-*-solaris2*)
- CFLAGS="$CFLAGS"
- abi="elf"
- RPATH='-Wl,-R,$(1)'
- CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
- LIBS="$LIBS -lposix4 -lsocket -lnsl"
- ;;
- *-ibm-aix*)
- if "$LG_SIZEOF_PTR" = "8"; then
- LD_PRELOAD_VAR="LDR_PRELOAD64"
- else
- LD_PRELOAD_VAR="LDR_PRELOAD"
- fi
- abi="xcoff"
- ;;
- *-*-mingw*)
- abi="pecoff"
- force_tls="0"
- RPATH=""
- so="dll"
- if test "x$je_cv_msvc" = "xyes" ; then
- importlib="lib"
- DSO_LDFLAGS="-LD"
- EXTRA_LDFLAGS="-link -DEBUG"
- CTARGET='-Fo$@'
- LDTARGET='-Fe$@'
- MKLIB='lib -nologo -out:$@'
- CC_MM=
- else
- importlib="${so}"
- DSO_LDFLAGS="-shared"
- fi
- a="lib"
- libprefix=""
- SOREV="${so}"
- PIC_CFLAGS=""
- ;;
- *)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Unsupported operating system: ${host}" >&5
-$as_echo "Unsupported operating system: ${host}" >&6; }
- abi="elf"
- ;;
-esac
-cat >>confdefs.h <<_ACEOF
-#define JEMALLOC_USABLE_SIZE_CONST $JEMALLOC_USABLE_SIZE_CONST
-_ACEOF
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-if test "x$abi" != "xpecoff"; then
- LIBS="$LIBS -lm"
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__ syntax is compilable" >&5
-$as_echo_n "checking whether __attribute__ syntax is compilable... " >&6; }
-if ${je_cv_attribute+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-static __attribute__((unused)) void foo(void){}
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_attribute=yes
-else
- je_cv_attribute=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_attribute" >&5
-$as_echo "$je_cv_attribute" >&6; }
-
-if test "x${je_cv_attribute}" = "xyes" ; then
- $as_echo "#define JEMALLOC_HAVE_ATTR " >>confdefs.h
-
- if test "x${GCC}" = "xyes" -a "x${abi}" = "xelf"; then
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fvisibility=hidden" >&5
-$as_echo_n "checking whether compiler supports -fvisibility=hidden... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-fvisibility=hidden"
-else
- CFLAGS="${CFLAGS} -fvisibility=hidden"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- fi
-fi
-SAVED_CFLAGS="${CFLAGS}"
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror" >&5
-$as_echo_n "checking whether compiler supports -Werror... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-Werror"
-else
- CFLAGS="${CFLAGS} -Werror"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether tls_model attribute is compilable" >&5
-$as_echo_n "checking whether tls_model attribute is compilable... " >&6; }
-if ${je_cv_tls_model+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-static __thread int
- __attribute__((tls_model("initial-exec"))) foo;
- foo = 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_tls_model=yes
-else
- je_cv_tls_model=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_tls_model" >&5
-$as_echo "$je_cv_tls_model" >&6; }
-
-CFLAGS="${SAVED_CFLAGS}"
-if test "x${je_cv_tls_model}" = "xyes" ; then
- $as_echo "#define JEMALLOC_TLS_MODEL __attribute__((tls_model(\"initial-exec\")))" >>confdefs.h
-
-else
- $as_echo "#define JEMALLOC_TLS_MODEL " >>confdefs.h
-
-fi
-
-
-# Check whether --with-rpath was given.
-if test "${with_rpath+set}" = set; then :
- withval=$with_rpath; if test "x$with_rpath" = "xno" ; then
- RPATH_EXTRA=
-else
- RPATH_EXTRA="`echo $with_rpath | tr \":\" \" \"`"
-fi
-else
- RPATH_EXTRA=
-
-fi
-
-
-
-# Check whether --enable-autogen was given.
-if test "${enable_autogen+set}" = set; then :
- enableval=$enable_autogen; if test "x$enable_autogen" = "xno" ; then
- enable_autogen="0"
-else
- enable_autogen="1"
-fi
-
-else
- enable_autogen="0"
-
-fi
-
-
-
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
-if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- rm -rf conftest.one conftest.two conftest.dir
- echo one > conftest.one
- echo two > conftest.two
- mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
- test -s conftest.one && test -s conftest.two &&
- test -s conftest.dir/conftest.one &&
- test -s conftest.dir/conftest.two
- then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- fi
- done
- done
- ;;
-esac
-
- done
-IFS=$as_save_IFS
-
-rm -rf conftest.one conftest.two conftest.dir
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL=$ac_cv_path_install
- else
- # As a last resort, use the slow shell script. Don't cache a
- # value for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the value is a relative name.
- INSTALL=$ac_install_sh
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
- ac_ct_RANLIB=$RANLIB
- # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_RANLIB"; then
- ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_RANLIB" = x; then
- RANLIB=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- RANLIB=$ac_ct_RANLIB
- fi
-else
- RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-# Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $AR in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_AR="$AR" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_AR" && ac_cv_path_AR="false"
- ;;
-esac
-fi
-AR=$ac_cv_path_AR
-if test -n "$AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-# Extract the first word of "ld", so it can be a program name with args.
-set dummy ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $LD in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_LD="$LD" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_LD="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_LD" && ac_cv_path_LD="false"
- ;;
-esac
-fi
-LD=$ac_cv_path_LD
-if test -n "$LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-# Extract the first word of "autoconf", so it can be a program name with args.
-set dummy autoconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_AUTOCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $AUTOCONF in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_AUTOCONF="$AUTOCONF" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_AUTOCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- test -z "$ac_cv_path_AUTOCONF" && ac_cv_path_AUTOCONF="false"
- ;;
-esac
-fi
-AUTOCONF=$ac_cv_path_AUTOCONF
-if test -n "$AUTOCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AUTOCONF" >&5
-$as_echo "$AUTOCONF" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-
-public_syms="malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free malloc_usable_size malloc_stats_print mallctl mallctlnametomib mallctlbymib"
-
-ac_fn_c_check_func "$LINENO" "memalign" "ac_cv_func_memalign"
-if test "x$ac_cv_func_memalign" = xyes; then :
- $as_echo "#define JEMALLOC_OVERRIDE_MEMALIGN " >>confdefs.h
-
- public_syms="${public_syms} memalign"
-fi
-
-ac_fn_c_check_func "$LINENO" "valloc" "ac_cv_func_valloc"
-if test "x$ac_cv_func_valloc" = xyes; then :
- $as_echo "#define JEMALLOC_OVERRIDE_VALLOC " >>confdefs.h
-
- public_syms="${public_syms} valloc"
-fi
-
-
-# Check whether --enable-experimental was given.
-if test "${enable_experimental+set}" = set; then :
- enableval=$enable_experimental; if test "x$enable_experimental" = "xno" ; then
- enable_experimental="0"
-else
- enable_experimental="1"
-fi
-
-else
- enable_experimental="1"
-
-fi
-
-if test "x$enable_experimental" = "x1" ; then
- $as_echo "#define JEMALLOC_EXPERIMENTAL " >>confdefs.h
-
- public_syms="${public_syms} allocm dallocm nallocm rallocm sallocm"
-fi
-
-
-
-# Check whether --with-mangling was given.
-if test "${with_mangling+set}" = set; then :
- withval=$with_mangling; mangling_map="$with_mangling"
-else
- mangling_map=""
-fi
-
-for nm in `echo ${mangling_map} |tr ',' ' '` ; do
- k="`echo ${nm} |tr ':' ' ' |awk '{print $1}'`"
- n="je_${k}"
- m=`echo ${nm} |tr ':' ' ' |awk '{print $2}'`
- cat >>confdefs.h <<_ACEOF
-#define ${n} ${m}
-_ACEOF
-
- public_syms=`for sym in ${public_syms}; do echo "${sym}"; done |grep -v "^${k}\$" |tr '\n' ' '`
-done
-
-
-# Check whether --with-jemalloc_prefix was given.
-if test "${with_jemalloc_prefix+set}" = set; then :
- withval=$with_jemalloc_prefix; JEMALLOC_PREFIX="$with_jemalloc_prefix"
-else
- if test "x$abi" != "xmacho" -a "x$abi" != "xpecoff"; then
- JEMALLOC_PREFIX=""
-else
- JEMALLOC_PREFIX="je_"
-fi
-
-fi
-
-if test "x$JEMALLOC_PREFIX" != "x" ; then
- JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr "a-z" "A-Z"`
- cat >>confdefs.h <<_ACEOF
-#define JEMALLOC_PREFIX "$JEMALLOC_PREFIX"
-_ACEOF
-
- cat >>confdefs.h <<_ACEOF
-#define JEMALLOC_CPREFIX "$JEMALLOC_CPREFIX"
-_ACEOF
-
-fi
-for stem in ${public_syms}; do
- n="je_${stem}"
- m="${JEMALLOC_PREFIX}${stem}"
- cat >>confdefs.h <<_ACEOF
-#define ${n} ${m}
-_ACEOF
-
-done
-
-
-# Check whether --with-export was given.
-if test "${with_export+set}" = set; then :
- withval=$with_export; if test "x$with_export" = "xno"; then
- $as_echo "#define JEMALLOC_EXPORT /**/" >>confdefs.h
-
-fi
-
-fi
-
-
-
-# Check whether --with-private_namespace was given.
-if test "${with_private_namespace+set}" = set; then :
- withval=$with_private_namespace; JEMALLOC_PRIVATE_NAMESPACE="$with_private_namespace"
-else
- JEMALLOC_PRIVATE_NAMESPACE=""
-
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define JEMALLOC_PRIVATE_NAMESPACE "$JEMALLOC_PRIVATE_NAMESPACE"
-_ACEOF
-
-if test "x$JEMALLOC_PRIVATE_NAMESPACE" != "x" ; then
- cat >>confdefs.h <<_ACEOF
-#define JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix) ${JEMALLOC_PRIVATE_NAMESPACE}##string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix
-_ACEOF
-
-else
- cat >>confdefs.h <<_ACEOF
-#define JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix) string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix
-_ACEOF
-
-fi
-
-
-# Check whether --with-install_suffix was given.
-if test "${with_install_suffix+set}" = set; then :
- withval=$with_install_suffix; INSTALL_SUFFIX="$with_install_suffix"
-else
- INSTALL_SUFFIX=
-
-fi
-
-install_suffix="$INSTALL_SUFFIX"
-
-
-cfgoutputs_in="${srcroot}Makefile.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/html.xsl.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/manpages.xsl.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/jemalloc.xml.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}include/jemalloc/jemalloc.h.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}include/jemalloc/internal/jemalloc_internal.h.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}test/jemalloc_test.h.in"
-
-cfgoutputs_out="Makefile"
-cfgoutputs_out="${cfgoutputs_out} doc/html.xsl"
-cfgoutputs_out="${cfgoutputs_out} doc/manpages.xsl"
-cfgoutputs_out="${cfgoutputs_out} doc/jemalloc${install_suffix}.xml"
-cfgoutputs_out="${cfgoutputs_out} include/jemalloc/jemalloc${install_suffix}.h"
-cfgoutputs_out="${cfgoutputs_out} include/jemalloc/internal/jemalloc_internal.h"
-cfgoutputs_out="${cfgoutputs_out} test/jemalloc_test.h"
-
-cfgoutputs_tup="Makefile"
-cfgoutputs_tup="${cfgoutputs_tup} doc/html.xsl:doc/html.xsl.in"
-cfgoutputs_tup="${cfgoutputs_tup} doc/manpages.xsl:doc/manpages.xsl.in"
-cfgoutputs_tup="${cfgoutputs_tup} doc/jemalloc${install_suffix}.xml:doc/jemalloc.xml.in"
-cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/jemalloc${install_suffix}.h:include/jemalloc/jemalloc.h.in"
-cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/internal/jemalloc_internal.h"
-cfgoutputs_tup="${cfgoutputs_tup} test/jemalloc_test.h:test/jemalloc_test.h.in"
-
-cfghdrs_in="${srcroot}include/jemalloc/jemalloc_defs.h.in"
-cfghdrs_in="${cfghdrs_in} ${srcroot}include/jemalloc/internal/size_classes.sh"
-
-cfghdrs_out="include/jemalloc/jemalloc_defs${install_suffix}.h"
-cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/size_classes.h"
-
-cfghdrs_tup="include/jemalloc/jemalloc_defs${install_suffix}.h:include/jemalloc/jemalloc_defs.h.in"
-
-# Check whether --enable-cc-silence was given.
-if test "${enable_cc_silence+set}" = set; then :
- enableval=$enable_cc_silence; if test "x$enable_cc_silence" = "xno" ; then
- enable_cc_silence="0"
-else
- enable_cc_silence="1"
-fi
-
-else
- enable_cc_silence="0"
-
-fi
-
-if test "x$enable_cc_silence" = "x1" ; then
- $as_echo "#define JEMALLOC_CC_SILENCE " >>confdefs.h
-
-fi
-
-# Check whether --enable-debug was given.
-if test "${enable_debug+set}" = set; then :
- enableval=$enable_debug; if test "x$enable_debug" = "xno" ; then
- enable_debug="0"
-else
- enable_debug="1"
-fi
-
-else
- enable_debug="0"
-
-fi
-
-if test "x$enable_debug" = "x1" ; then
- $as_echo "#define JEMALLOC_DEBUG " >>confdefs.h
-
- enable_ivsalloc="1"
-fi
-
-
-# Check whether --enable-ivsalloc was given.
-if test "${enable_ivsalloc+set}" = set; then :
- enableval=$enable_ivsalloc; if test "x$enable_ivsalloc" = "xno" ; then
- enable_ivsalloc="0"
-else
- enable_ivsalloc="1"
-fi
-
-else
- enable_ivsalloc="0"
-
-fi
-
-if test "x$enable_ivsalloc" = "x1" ; then
- $as_echo "#define JEMALLOC_IVSALLOC " >>confdefs.h
-
-fi
-
-if test "x$enable_debug" = "x0" -a "x$no_CFLAGS" = "xyes" ; then
- optimize="no"
- echo "$EXTRA_CFLAGS" | grep "\-O" >/dev/null || optimize="yes"
- if test "x${optimize}" = "xyes" ; then
- if test "x$GCC" = "xyes" ; then
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O3" >&5
-$as_echo_n "checking whether compiler supports -O3... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-O3"
-else
- CFLAGS="${CFLAGS} -O3"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -funroll-loops" >&5
-$as_echo_n "checking whether compiler supports -funroll-loops... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-funroll-loops"
-else
- CFLAGS="${CFLAGS} -funroll-loops"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- elif test "x$je_cv_msvc" = "xyes" ; then
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O2" >&5
-$as_echo_n "checking whether compiler supports -O2... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-O2"
-else
- CFLAGS="${CFLAGS} -O2"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- else
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O" >&5
-$as_echo_n "checking whether compiler supports -O... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="-O"
-else
- CFLAGS="${CFLAGS} -O"
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- CFLAGS="${TCFLAGS}"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- fi
- fi
-fi
-
-# Check whether --enable-stats was given.
-if test "${enable_stats+set}" = set; then :
- enableval=$enable_stats; if test "x$enable_stats" = "xno" ; then
- enable_stats="0"
-else
- enable_stats="1"
-fi
-
-else
- enable_stats="1"
-
-fi
-
-if test "x$enable_stats" = "x1" ; then
- $as_echo "#define JEMALLOC_STATS " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-prof was given.
-if test "${enable_prof+set}" = set; then :
- enableval=$enable_prof; if test "x$enable_prof" = "xno" ; then
- enable_prof="0"
-else
- enable_prof="1"
-fi
-
-else
- enable_prof="0"
-
-fi
-
-if test "x$enable_prof" = "x1" ; then
- backtrace_method=""
-else
- backtrace_method="N/A"
-fi
-
-# Check whether --enable-prof-libunwind was given.
-if test "${enable_prof_libunwind+set}" = set; then :
- enableval=$enable_prof_libunwind; if test "x$enable_prof_libunwind" = "xno" ; then
- enable_prof_libunwind="0"
-else
- enable_prof_libunwind="1"
-fi
-
-else
- enable_prof_libunwind="0"
-
-fi
-
-
-# Check whether --with-static_libunwind was given.
-if test "${with_static_libunwind+set}" = set; then :
- withval=$with_static_libunwind; if test "x$with_static_libunwind" = "xno" ; then
- LUNWIND="-lunwind"
-else
- if test ! -f "$with_static_libunwind" ; then
- as_fn_error $? "Static libunwind not found: $with_static_libunwind" "$LINENO" 5
- fi
- LUNWIND="$with_static_libunwind"
-fi
-else
- LUNWIND="-lunwind"
-
-fi
-
-if test "x$backtrace_method" = "x" -a "x$enable_prof_libunwind" = "x1" ; then
- for ac_header in libunwind.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "libunwind.h" "ac_cv_header_libunwind_h" "$ac_includes_default"
-if test "x$ac_cv_header_libunwind_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBUNWIND_H 1
-_ACEOF
-
-else
- enable_prof_libunwind="0"
-fi
-
-done
-
- if test "x$LUNWIND" = "x-lunwind" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for backtrace in -lunwind" >&5
-$as_echo_n "checking for backtrace in -lunwind... " >&6; }
-if ${ac_cv_lib_unwind_backtrace+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lunwind $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char backtrace ();
-int
-main ()
-{
-return backtrace ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_unwind_backtrace=yes
-else
- ac_cv_lib_unwind_backtrace=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unwind_backtrace" >&5
-$as_echo "$ac_cv_lib_unwind_backtrace" >&6; }
-if test "x$ac_cv_lib_unwind_backtrace" = xyes; then :
- LIBS="$LIBS $LUNWIND"
-else
- enable_prof_libunwind="0"
-fi
-
- else
- LIBS="$LIBS $LUNWIND"
- fi
- if test "x${enable_prof_libunwind}" = "x1" ; then
- backtrace_method="libunwind"
- $as_echo "#define JEMALLOC_PROF_LIBUNWIND " >>confdefs.h
-
- fi
-fi
-
-# Check whether --enable-prof-libgcc was given.
-if test "${enable_prof_libgcc+set}" = set; then :
- enableval=$enable_prof_libgcc; if test "x$enable_prof_libgcc" = "xno" ; then
- enable_prof_libgcc="0"
-else
- enable_prof_libgcc="1"
-fi
-
-else
- enable_prof_libgcc="1"
-
-fi
-
-if test "x$backtrace_method" = "x" -a "x$enable_prof_libgcc" = "x1" \
- -a "x$GCC" = "xyes" ; then
- for ac_header in unwind.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "unwind.h" "ac_cv_header_unwind_h" "$ac_includes_default"
-if test "x$ac_cv_header_unwind_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_UNWIND_H 1
-_ACEOF
-
-else
- enable_prof_libgcc="0"
-fi
-
-done
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _Unwind_Backtrace in -lgcc" >&5
-$as_echo_n "checking for _Unwind_Backtrace in -lgcc... " >&6; }
-if ${ac_cv_lib_gcc__Unwind_Backtrace+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lgcc $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char _Unwind_Backtrace ();
-int
-main ()
-{
-return _Unwind_Backtrace ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_gcc__Unwind_Backtrace=yes
-else
- ac_cv_lib_gcc__Unwind_Backtrace=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcc__Unwind_Backtrace" >&5
-$as_echo "$ac_cv_lib_gcc__Unwind_Backtrace" >&6; }
-if test "x$ac_cv_lib_gcc__Unwind_Backtrace" = xyes; then :
- LIBS="$LIBS -lgcc"
-else
- enable_prof_libgcc="0"
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking libgcc-based backtracing reliability on ${host_cpu}" >&5
-$as_echo_n "checking libgcc-based backtracing reliability on ${host_cpu}... " >&6; }
- case "${host_cpu}" in
- i[3456]86)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unreliable" >&5
-$as_echo "unreliable" >&6; }
- enable_prof_libgcc="0";
- ;;
- x86_64)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: reliable" >&5
-$as_echo "reliable" >&6; }
- ;;
- *)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unreliable" >&5
-$as_echo "unreliable" >&6; }
- enable_prof_libgcc="0";
- ;;
- esac
- if test "x${enable_prof_libgcc}" = "x1" ; then
- backtrace_method="libgcc"
- $as_echo "#define JEMALLOC_PROF_LIBGCC " >>confdefs.h
-
- fi
-else
- enable_prof_libgcc="0"
-fi
-
-# Check whether --enable-prof-gcc was given.
-if test "${enable_prof_gcc+set}" = set; then :
- enableval=$enable_prof_gcc; if test "x$enable_prof_gcc" = "xno" ; then
- enable_prof_gcc="0"
-else
- enable_prof_gcc="1"
-fi
-
-else
- enable_prof_gcc="1"
-
-fi
-
-if test "x$backtrace_method" = "x" -a "x$enable_prof_gcc" = "x1" \
- -a "x$GCC" = "xyes" ; then
- backtrace_method="gcc intrinsics"
- $as_echo "#define JEMALLOC_PROF_GCC " >>confdefs.h
-
-else
- enable_prof_gcc="0"
-fi
-
-if test "x$backtrace_method" = "x" ; then
- backtrace_method="none (disabling profiling)"
- enable_prof="0"
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking configured backtracing method" >&5
-$as_echo_n "checking configured backtracing method... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $backtrace_method" >&5
-$as_echo "$backtrace_method" >&6; }
-if test "x$enable_prof" = "x1" ; then
- if test "x${force_tls}" = "x0" ; then
- as_fn_error $? "Heap profiling requires TLS" "$LINENO" 5;
- fi
- force_tls="1"
- $as_echo "#define JEMALLOC_PROF " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-tcache was given.
-if test "${enable_tcache+set}" = set; then :
- enableval=$enable_tcache; if test "x$enable_tcache" = "xno" ; then
- enable_tcache="0"
-else
- enable_tcache="1"
-fi
-
-else
- enable_tcache="1"
-
-fi
-
-if test "x$enable_tcache" = "x1" ; then
- $as_echo "#define JEMALLOC_TCACHE " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-mremap was given.
-if test "${enable_mremap+set}" = set; then :
- enableval=$enable_mremap; if test "x$enable_mremap" = "xno" ; then
- enable_mremap="0"
-else
- enable_mremap="1"
-fi
-
-else
- enable_mremap="0"
-
-fi
-
-if test "x$enable_mremap" = "x1" ; then
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mremap(...MREMAP_FIXED...) is compilable" >&5
-$as_echo_n "checking whether mremap(...MREMAP_FIXED...) is compilable... " >&6; }
-if ${je_cv_mremap_fixed+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#define _GNU_SOURCE
-#include <sys/mman.h>
-
-int
-main ()
-{
-
-void *p = mremap((void *)0, 0, 0, MREMAP_MAYMOVE|MREMAP_FIXED, (void *)0);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_mremap_fixed=yes
-else
- je_cv_mremap_fixed=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_mremap_fixed" >&5
-$as_echo "$je_cv_mremap_fixed" >&6; }
-
- if test "x${je_cv_mremap_fixed}" = "xno" ; then
- enable_mremap="0"
- fi
-fi
-if test "x$enable_mremap" = "x1" ; then
- $as_echo "#define JEMALLOC_MREMAP " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-munmap was given.
-if test "${enable_munmap+set}" = set; then :
- enableval=$enable_munmap; if test "x$enable_munmap" = "xno" ; then
- enable_munmap="0"
-else
- enable_munmap="1"
-fi
-
-else
- enable_munmap="${default_munmap}"
-
-fi
-
-if test "x$enable_munmap" = "x1" ; then
- $as_echo "#define JEMALLOC_MUNMAP " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-dss was given.
-if test "${enable_dss+set}" = set; then :
- enableval=$enable_dss; if test "x$enable_dss" = "xno" ; then
- enable_dss="0"
-else
- enable_dss="1"
-fi
-
-else
- enable_dss="0"
-
-fi
-
-ac_fn_c_check_func "$LINENO" "sbrk" "ac_cv_func_sbrk"
-if test "x$ac_cv_func_sbrk" = xyes; then :
- have_sbrk="1"
-else
- have_sbrk="0"
-fi
-
-if test "x$have_sbrk" = "x1" ; then
- $as_echo "#define JEMALLOC_HAVE_SBRK " >>confdefs.h
-
-else
- enable_dss="0"
-fi
-
-if test "x$enable_dss" = "x1" ; then
- $as_echo "#define JEMALLOC_DSS " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-fill was given.
-if test "${enable_fill+set}" = set; then :
- enableval=$enable_fill; if test "x$enable_fill" = "xno" ; then
- enable_fill="0"
-else
- enable_fill="1"
-fi
-
-else
- enable_fill="1"
-
-fi
-
-if test "x$enable_fill" = "x1" ; then
- $as_echo "#define JEMALLOC_FILL " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-utrace was given.
-if test "${enable_utrace+set}" = set; then :
- enableval=$enable_utrace; if test "x$enable_utrace" = "xno" ; then
- enable_utrace="0"
-else
- enable_utrace="1"
-fi
-
-else
- enable_utrace="0"
-
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether utrace(2) is compilable" >&5
-$as_echo_n "checking whether utrace(2) is compilable... " >&6; }
-if ${je_cv_utrace+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/ktrace.h>
-
-int
-main ()
-{
-
- utrace((void *)0, 0);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_utrace=yes
-else
- je_cv_utrace=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_utrace" >&5
-$as_echo "$je_cv_utrace" >&6; }
-
-if test "x${je_cv_utrace}" = "xno" ; then
- enable_utrace="0"
-fi
-if test "x$enable_utrace" = "x1" ; then
- $as_echo "#define JEMALLOC_UTRACE " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-valgrind was given.
-if test "${enable_valgrind+set}" = set; then :
- enableval=$enable_valgrind; if test "x$enable_valgrind" = "xno" ; then
- enable_valgrind="0"
-else
- enable_valgrind="1"
-fi
-
-else
- enable_valgrind="1"
-
-fi
-
-if test "x$enable_valgrind" = "x1" ; then
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether valgrind is compilable" >&5
-$as_echo_n "checking whether valgrind is compilable... " >&6; }
-if ${je_cv_valgrind+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <valgrind/valgrind.h>
-#include <valgrind/memcheck.h>
-
-#if !defined(VALGRIND_RESIZEINPLACE_BLOCK)
-# error "Incompatible Valgrind version"
-#endif
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_valgrind=yes
-else
- je_cv_valgrind=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_valgrind" >&5
-$as_echo "$je_cv_valgrind" >&6; }
-
- if test "x${je_cv_valgrind}" = "xno" ; then
- enable_valgrind="0"
- fi
- if test "x$enable_valgrind" = "x1" ; then
- $as_echo "#define JEMALLOC_VALGRIND " >>confdefs.h
-
- fi
-fi
-
-
-# Check whether --enable-xmalloc was given.
-if test "${enable_xmalloc+set}" = set; then :
- enableval=$enable_xmalloc; if test "x$enable_xmalloc" = "xno" ; then
- enable_xmalloc="0"
-else
- enable_xmalloc="1"
-fi
-
-else
- enable_xmalloc="0"
-
-fi
-
-if test "x$enable_xmalloc" = "x1" ; then
- $as_echo "#define JEMALLOC_XMALLOC " >>confdefs.h
-
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking STATIC_PAGE_SHIFT" >&5
-$as_echo_n "checking STATIC_PAGE_SHIFT... " >&6; }
-if ${je_cv_static_page_shift+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run test program while cross compiling
-See \`config.log' for more details" "$LINENO" 5; }
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <strings.h>
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <unistd.h>
-#endif
-#include <stdio.h>
-
-int
-main ()
-{
-
- int result;
- FILE *f;
-
-#ifdef _WIN32
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- result = si.dwPageSize;
-#else
- result = sysconf(_SC_PAGESIZE);
-#endif
- if (result == -1) {
- return 1;
- }
- result = ffsl(result) - 1;
-
- f = fopen("conftest.out", "w");
- if (f == NULL) {
- return 1;
- }
- fprintf(f, "%d\n", result);
- fclose(f);
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- je_cv_static_page_shift=`cat conftest.out`
-else
- je_cv_static_page_shift=undefined
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_static_page_shift" >&5
-$as_echo "$je_cv_static_page_shift" >&6; }
-
-if test "x$je_cv_static_page_shift" != "xundefined"; then
- cat >>confdefs.h <<_ACEOF
-#define STATIC_PAGE_SHIFT $je_cv_static_page_shift
-_ACEOF
-
-else
- as_fn_error $? "cannot determine value for STATIC_PAGE_SHIFT" "$LINENO" 5
-fi
-
-
-if test -d "${srcroot}.git" ; then
- git describe --long --abbrev=40 > ${srcroot}VERSION
-fi
-jemalloc_version=`cat ${srcroot}VERSION`
-jemalloc_version_major=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print $1}'`
-jemalloc_version_minor=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print $2}'`
-jemalloc_version_bugfix=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print $3}'`
-jemalloc_version_nrev=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print $4}'`
-jemalloc_version_gid=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print $5}'`
-
-
-
-
-
-
-
-
-if test "x$abi" != "xpecoff" ; then
- for ac_header in pthread.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PTHREAD_H 1
-_ACEOF
-
-else
- as_fn_error $? "pthread.h is missing" "$LINENO" 5
-fi
-
-done
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
-$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpthread $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pthread_create ();
-int
-main ()
-{
-return pthread_create ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_pthread_pthread_create=yes
-else
- ac_cv_lib_pthread_pthread_create=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
-$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
- LIBS="$LIBS -lpthread"
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
-$as_echo_n "checking for library containing pthread_create... " >&6; }
-if ${ac_cv_search_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pthread_create ();
-int
-main ()
-{
-return pthread_create ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' ; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_pthread_create=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_pthread_create+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_pthread_create+:} false; then :
-
-else
- ac_cv_search_pthread_create=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5
-$as_echo "$ac_cv_search_pthread_create" >&6; }
-ac_res=$ac_cv_search_pthread_create
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-else
- as_fn_error $? "libpthread is missing" "$LINENO" 5
-fi
-
-fi
-
-fi
-
-CPPFLAGS="$CPPFLAGS -D_REENTRANT"
-
-ac_fn_c_check_func "$LINENO" "_malloc_thread_cleanup" "ac_cv_func__malloc_thread_cleanup"
-if test "x$ac_cv_func__malloc_thread_cleanup" = xyes; then :
- have__malloc_thread_cleanup="1"
-else
- have__malloc_thread_cleanup="0"
-
-fi
-
-if test "x$have__malloc_thread_cleanup" = "x1" ; then
- $as_echo "#define JEMALLOC_MALLOC_THREAD_CLEANUP " >>confdefs.h
-
- force_tls="1"
-fi
-
-ac_fn_c_check_func "$LINENO" "_pthread_mutex_init_calloc_cb" "ac_cv_func__pthread_mutex_init_calloc_cb"
-if test "x$ac_cv_func__pthread_mutex_init_calloc_cb" = xyes; then :
- have__pthread_mutex_init_calloc_cb="1"
-else
- have__pthread_mutex_init_calloc_cb="0"
-
-fi
-
-if test "x$have__pthread_mutex_init_calloc_cb" = "x1" ; then
- $as_echo "#define JEMALLOC_MUTEX_INIT_CB 1" >>confdefs.h
-
-fi
-
-# Check whether --enable-lazy_lock was given.
-if test "${enable_lazy_lock+set}" = set; then :
- enableval=$enable_lazy_lock; if test "x$enable_lazy_lock" = "xno" ; then
- enable_lazy_lock="0"
-else
- enable_lazy_lock="1"
-fi
-
-else
- enable_lazy_lock="0"
-
-fi
-
-if test "x$enable_lazy_lock" = "x0" -a "x${force_lazy_lock}" = "x1" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Forcing lazy-lock to avoid allocator/threading bootstrap issues" >&5
-$as_echo "Forcing lazy-lock to avoid allocator/threading bootstrap issues" >&6; }
- enable_lazy_lock="1"
-fi
-if test "x$enable_lazy_lock" = "x1" ; then
- if test "x$abi" != "xpecoff" ; then
- for ac_header in dlfcn.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
-if test "x$ac_cv_header_dlfcn_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DLFCN_H 1
-_ACEOF
-
-else
- as_fn_error $? "dlfcn.h is missing" "$LINENO" 5
-fi
-
-done
-
- ac_fn_c_check_func "$LINENO" "dlsym" "ac_cv_func_dlsym"
-if test "x$ac_cv_func_dlsym" = xyes; then :
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5
-$as_echo_n "checking for dlsym in -ldl... " >&6; }
-if ${ac_cv_lib_dl_dlsym+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlsym ();
-int
-main ()
-{
-return dlsym ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_dl_dlsym=yes
-else
- ac_cv_lib_dl_dlsym=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym" >&5
-$as_echo "$ac_cv_lib_dl_dlsym" >&6; }
-if test "x$ac_cv_lib_dl_dlsym" = xyes; then :
- LIBS="$LIBS -ldl"
-else
- as_fn_error $? "libdl is missing" "$LINENO" 5
-fi
-
-
-fi
-
- fi
- $as_echo "#define JEMALLOC_LAZY_LOCK " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-tls was given.
-if test "${enable_tls+set}" = set; then :
- enableval=$enable_tls; if test "x$enable_tls" = "xno" ; then
- enable_tls="0"
-else
- enable_tls="1"
-fi
-
-else
- enable_tls="1"
-
-fi
-
-if test "x${enable_tls}" = "x0" -a "x${force_tls}" = "x1" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Forcing TLS to avoid allocator/threading bootstrap issues" >&5
-$as_echo "Forcing TLS to avoid allocator/threading bootstrap issues" >&6; }
- enable_tls="1"
-fi
-if test "x${enable_tls}" = "x1" -a "x${force_tls}" = "x0" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Forcing no TLS to avoid allocator/threading bootstrap issues" >&5
-$as_echo "Forcing no TLS to avoid allocator/threading bootstrap issues" >&6; }
- enable_tls="0"
-fi
-if test "x${enable_tls}" = "x1" ; then
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS" >&5
-$as_echo_n "checking for TLS... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
- __thread int x;
-
-int
-main ()
-{
-
- x = 42;
-
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- enable_tls="0"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-if test "x${enable_tls}" = "x1" ; then
- cat >>confdefs.h <<_ACEOF
-#define JEMALLOC_TLS
-_ACEOF
-
-elif test "x${force_tls}" = "x1" ; then
- as_fn_error $? "Failed to configure TLS, which is mandatory for correct function" "$LINENO" 5
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program using ffsl is compilable" >&5
-$as_echo_n "checking whether a program using ffsl is compilable... " >&6; }
-if ${je_cv_function_ffsl+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <stdio.h>
-#include <strings.h>
-#include <string.h>
-
-int
-main ()
-{
-
- {
- int rv = ffsl(0x08);
- printf("%d\n", rv);
- }
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_function_ffsl=yes
-else
- je_cv_function_ffsl=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_function_ffsl" >&5
-$as_echo "$je_cv_function_ffsl" >&6; }
-
-if test "x${je_cv_function_ffsl}" != "xyes" ; then
- as_fn_error $? "Cannot build without ffsl(3)" "$LINENO" 5
-fi
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether atomic(9) is compilable" >&5
-$as_echo_n "checking whether atomic(9) is compilable... " >&6; }
-if ${je_cv_atomic9+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <sys/types.h>
-#include <machine/atomic.h>
-#include <inttypes.h>
-
-int
-main ()
-{
-
- {
- uint32_t x32 = 0;
- volatile uint32_t *x32p = &x32;
- atomic_fetchadd_32(x32p, 1);
- }
- {
- unsigned long xlong = 0;
- volatile unsigned long *xlongp = &xlong;
- atomic_fetchadd_long(xlongp, 1);
- }
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_atomic9=yes
-else
- je_cv_atomic9=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_atomic9" >&5
-$as_echo "$je_cv_atomic9" >&6; }
-
-if test "x${je_cv_atomic9}" = "xyes" ; then
- $as_echo "#define JEMALLOC_ATOMIC9 1" >>confdefs.h
-
-fi
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Darwin OSAtomic*() is compilable" >&5
-$as_echo_n "checking whether Darwin OSAtomic*() is compilable... " >&6; }
-if ${je_cv_osatomic+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <libkern/OSAtomic.h>
-#include <inttypes.h>
-
-int
-main ()
-{
-
- {
- int32_t x32 = 0;
- volatile int32_t *x32p = &x32;
- OSAtomicAdd32(1, x32p);
- }
- {
- int64_t x64 = 0;
- volatile int64_t *x64p = &x64;
- OSAtomicAdd64(1, x64p);
- }
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_osatomic=yes
-else
- je_cv_osatomic=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_osatomic" >&5
-$as_echo "$je_cv_osatomic" >&6; }
-
-if test "x${je_cv_osatomic}" = "xyes" ; then
- $as_echo "#define JEMALLOC_OSATOMIC " >>confdefs.h
-
-fi
-
-
-
-
-if test "x${je_cv_atomic9}" != "xyes" -a "x${je_cv_osatomic}" != "xyes" ; then
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to force 32-bit __sync_{add,sub}_and_fetch()" >&5
-$as_echo_n "checking whether to force 32-bit __sync_{add,sub}_and_fetch()... " >&6; }
-if ${je_cv_sync_compare_and_swap_4+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
- #include <stdint.h>
-
-int
-main ()
-{
-
- #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
- {
- uint32_t x32 = 0;
- __sync_add_and_fetch(&x32, 42);
- __sync_sub_and_fetch(&x32, 1);
- }
- #else
- #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 is defined, no need to force
- #endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_sync_compare_and_swap_4=yes
-else
- je_cv_sync_compare_and_swap_4=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_sync_compare_and_swap_4" >&5
-$as_echo "$je_cv_sync_compare_and_swap_4" >&6; }
-
- if test "x${je_cv_sync_compare_and_swap_4}" = "xyes" ; then
- $as_echo "#define JE_FORCE_SYNC_COMPARE_AND_SWAP_4 " >>confdefs.h
-
- fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to force 64-bit __sync_{add,sub}_and_fetch()" >&5
-$as_echo_n "checking whether to force 64-bit __sync_{add,sub}_and_fetch()... " >&6; }
-if ${je_cv_sync_compare_and_swap_8+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
- #include <stdint.h>
-
-int
-main ()
-{
-
- #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
- {
- uint64_t x64 = 0;
- __sync_add_and_fetch(&x64, 42);
- __sync_sub_and_fetch(&x64, 1);
- }
- #else
- #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 is defined, no need to force
- #endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_sync_compare_and_swap_8=yes
-else
- je_cv_sync_compare_and_swap_8=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_sync_compare_and_swap_8" >&5
-$as_echo "$je_cv_sync_compare_and_swap_8" >&6; }
-
- if test "x${je_cv_sync_compare_and_swap_8}" = "xyes" ; then
- $as_echo "#define JE_FORCE_SYNC_COMPARE_AND_SWAP_8 " >>confdefs.h
-
- fi
-
-fi
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Darwin OSSpin*() is compilable" >&5
-$as_echo_n "checking whether Darwin OSSpin*() is compilable... " >&6; }
-if ${je_cv_osspin+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <libkern/OSAtomic.h>
-#include <inttypes.h>
-
-int
-main ()
-{
-
- OSSpinLock lock = 0;
- OSSpinLockLock(&lock);
- OSSpinLockUnlock(&lock);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- je_cv_osspin=yes
-else
- je_cv_osspin=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_osspin" >&5
-$as_echo "$je_cv_osspin" >&6; }
-
-if test "x${je_cv_osspin}" = "xyes" ; then
- $as_echo "#define JEMALLOC_OSSPIN " >>confdefs.h
-
-fi
-
-
-# Check whether --enable-zone-allocator was given.
-if test "${enable_zone_allocator+set}" = set; then :
- enableval=$enable_zone_allocator; if test "x$enable_zone_allocator" = "xno" ; then
- enable_zone_allocator="0"
-else
- enable_zone_allocator="1"
-fi
-
-else
- if test "x${abi}" = "xmacho"; then
- enable_zone_allocator="1"
-fi
-
-
-fi
-
-
-
-if test "x${enable_zone_allocator}" = "x1" ; then
- if test "x${abi}" != "xmacho"; then
- as_fn_error $? "--enable-zone-allocator is only supported on Darwin" "$LINENO" 5
- fi
- $as_echo "#define JEMALLOC_IVSALLOC " >>confdefs.h
-
- $as_echo "#define JEMALLOC_ZONE " >>confdefs.h
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking malloc zone version" >&5
-$as_echo_n "checking malloc zone version... " >&6; }
-
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <malloc/malloc.h>
-int
-main ()
-{
-static foo[sizeof(malloc_zone_t) == sizeof(void *) * 14 ? 1 : -1]
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- JEMALLOC_ZONE_VERSION=3
-else
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <malloc/malloc.h>
-int
-main ()
-{
-static foo[sizeof(malloc_zone_t) == sizeof(void *) * 15 ? 1 : -1]
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- JEMALLOC_ZONE_VERSION=5
-else
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <malloc/malloc.h>
-int
-main ()
-{
-static foo[sizeof(malloc_zone_t) == sizeof(void *) * 16 ? 1 : -1]
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <malloc/malloc.h>
-int
-main ()
-{
-static foo[sizeof(malloc_introspection_t) == sizeof(void *) * 9 ? 1 : -1]
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- JEMALLOC_ZONE_VERSION=6
-else
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <malloc/malloc.h>
-int
-main ()
-{
-static foo[sizeof(malloc_introspection_t) == sizeof(void *) * 13 ? 1 : -1]
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- JEMALLOC_ZONE_VERSION=7
-else
- JEMALLOC_ZONE_VERSION=
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <malloc/malloc.h>
-int
-main ()
-{
-static foo[sizeof(malloc_zone_t) == sizeof(void *) * 17 ? 1 : -1]
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- JEMALLOC_ZONE_VERSION=8
-else
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <malloc/malloc.h>
-int
-main ()
-{
-static foo[sizeof(malloc_zone_t) > sizeof(void *) * 17 ? 1 : -1]
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- JEMALLOC_ZONE_VERSION=9
-else
- JEMALLOC_ZONE_VERSION=
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- if test "x${JEMALLOC_ZONE_VERSION}" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; }
- as_fn_error $? "Unsupported malloc zone version" "$LINENO" 5
- fi
- if test "${JEMALLOC_ZONE_VERSION}" = 9; then
- JEMALLOC_ZONE_VERSION=8
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: > 8" >&5
-$as_echo "> 8" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JEMALLOC_ZONE_VERSION" >&5
-$as_echo "$JEMALLOC_ZONE_VERSION" >&6; }
- fi
- cat >>confdefs.h <<_ACEOF
-#define JEMALLOC_ZONE_VERSION $JEMALLOC_ZONE_VERSION
-_ACEOF
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
-$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
-if ${ac_cv_header_stdbool_h+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#include <stdbool.h>
-#ifndef bool
- "error: bool is not defined"
-#endif
-#ifndef false
- "error: false is not defined"
-#endif
-#if false
- "error: false is not 0"
-#endif
-#ifndef true
- "error: true is not defined"
-#endif
-#if true != 1
- "error: true is not 1"
-#endif
-#ifndef __bool_true_false_are_defined
- "error: __bool_true_false_are_defined is not defined"
-#endif
-
- struct s { _Bool s: 1; _Bool t; } s;
-
- char a[true == 1 ? 1 : -1];
- char b[false == 0 ? 1 : -1];
- char c[__bool_true_false_are_defined == 1 ? 1 : -1];
- char d[(bool) 0.5 == true ? 1 : -1];
- /* See body of main program for 'e'. */
- char f[(_Bool) 0.0 == false ? 1 : -1];
- char g[true];
- char h[sizeof (_Bool)];
- char i[sizeof s.t];
- enum { j = false, k = true, l = false * true, m = true * 256 };
- /* The following fails for
- HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
- _Bool n[m];
- char o[sizeof n == m * sizeof n[0] ? 1 : -1];
- char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
- /* Catch a bug in an HP-UX C compiler. See
- http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
- http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
- */
- _Bool q = true;
- _Bool *pq = &q;
-
-int
-main ()
-{
-
- bool e = &s;
- *pq |= q;
- *pq |= ! q;
- /* Refer to every declared value, to avoid compiler optimizations. */
- return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
- + !m + !n + !o + !p + !q + !pq);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdbool_h=yes
-else
- ac_cv_header_stdbool_h=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
-$as_echo "$ac_cv_header_stdbool_h" >&6; }
-ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
-if test "x$ac_cv_type__Bool" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE__BOOL 1
-_ACEOF
-
-
-fi
-
-if test $ac_cv_header_stdbool_h = yes; then
-
-$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
-
-fi
-
-
-ac_config_commands="$ac_config_commands include/jemalloc/internal/size_classes.h"
-
-
-
-
-ac_config_headers="$ac_config_headers $cfghdrs_tup"
-
-
-ac_config_files="$ac_config_files $cfgoutputs_tup config.stamp bin/jemalloc.sh"
-
-
-
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems. If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, we kill variables containing newlines.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(
- for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
- eval ac_val=\$$ac_var
- case $ac_val in #(
- *${as_nl}*)
- case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
- esac
- case $ac_var in #(
- _ | IFS | as_nl) ;; #(
- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
- *) { eval $ac_var=; unset $ac_var;} ;;
- esac ;;
- esac
- done
-
- (set) 2>&1 |
- case $as_nl`(ac_space=' '; set) 2>&1` in #(
- *${as_nl}ac_space=\ *)
- # `set' does not quote correctly, so add quotes: double-quote
- # substitution turns \\\\ into \\, and sed turns \\ into \.
- sed -n \
- "s/'/'\\\\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
- ;; #(
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
- ;;
- esac |
- sort
-) |
- sed '
- /^ac_cv_env_/b end
- t clear
- :clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
- t end
- s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
- :end' >>confcache
-if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
- if test -w "$cache_file"; then
- if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
- if test ! -f "$cache_file" || test -h "$cache_file"; then
- cat confcache >"$cache_file"
- else
- case $cache_file in #(
- */* | ?:*)
- mv -f confcache "$cache_file"$$ &&
- mv -f "$cache_file"$$ "$cache_file" ;; #(
- *)
- mv -f confcache "$cache_file" ;;
- esac
- fi
- fi
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
- fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-DEFS=-DHAVE_CONFIG_H
-
-ac_libobjs=
-ac_ltlibobjs=
-U=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
- # 1. Remove the extension, and $U if already installed.
- ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
- # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
- # will be set to the directory where LIBOBJS objects are built.
- as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
- as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: "${CONFIG_STATUS=./config.status}"
-ac_write_fail=0
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
-as_write_fail=0
-cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-
-SHELL=\${CONFIG_SHELL-$SHELL}
-export SHELL
-_ASEOF
-cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
-## -------------------- ##
-## M4sh Initialization. ##
-## -------------------- ##
-
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
- emulate sh
- NULLCMD=:
- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in #(
- *posix*) :
- set -o posix ;; #(
- *) :
- ;;
-esac
-fi
-
-
-as_nl='
-'
-export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- PATH_SEPARATOR=:
- (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
- (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
- PATH_SEPARATOR=';'
- }
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
-# Find who we are. Look in the path if we contain no directory separator.
-as_myself=
-case $0 in #((
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
- done
-IFS=$as_save_IFS
-
- ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
- as_myself=$0
-fi
-if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- exit 1
-fi
-
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-
-# as_fn_error STATUS ERROR [LINENO LOG_FD]
-# ----------------------------------------
-# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with STATUS, using 1 if that was 0.
-as_fn_error ()
-{
- as_status=$1; test $as_status -eq 0 && as_status=1
- if test "$4"; then
- as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
- fi
- $as_echo "$as_me: error: $2" >&2
- as_fn_exit $as_status
-} # as_fn_error
-
-
-# as_fn_set_status STATUS
-# -----------------------
-# Set $? to STATUS, without forking.
-as_fn_set_status ()
-{
- return $1
-} # as_fn_set_status
-
-# as_fn_exit STATUS
-# -----------------
-# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
-as_fn_exit ()
-{
- set +e
- as_fn_set_status $1
- exit $1
-} # as_fn_exit
-
-# as_fn_unset VAR
-# ---------------
-# Portably unset VAR.
-as_fn_unset ()
-{
- { eval $1=; unset $1;}
-}
-as_unset=as_fn_unset
-# as_fn_append VAR VALUE
-# ----------------------
-# Append the text in VALUE to the end of the definition contained in VAR. Take
-# advantage of any shell optimizations that allow amortized linear growth over
-# repeated appends, instead of the typical quadratic growth present in naive
-# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
- eval 'as_fn_append ()
- {
- eval $1+=\$2
- }'
-else
- as_fn_append ()
- {
- eval $1=\$$1\$2
- }
-fi # as_fn_append
-
-# as_fn_arith ARG...
-# ------------------
-# Perform arithmetic evaluation on the ARGs, and store the result in the
-# global $as_val. Take advantage of shells that can avoid forks. The arguments
-# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
- eval 'as_fn_arith ()
- {
- as_val=$(( $* ))
- }'
-else
- as_fn_arith ()
- {
- as_val=`expr "$@" || test $? -eq 1`
- }
-fi # as_fn_arith
-
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
-
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in #(((((
--n*)
- case `echo 'xy\c'` in
- *c*) ECHO_T=' ';; # ECHO_T is single tab character.
- xy) ECHO_C='\c';;
- *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
- ECHO_T=' ';;
- esac;;
-*)
- ECHO_N='-n';;
-esac
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
- rm -f conf$$.dir/conf$$.file
-else
- rm -f conf$$.dir
- mkdir conf$$.dir 2>/dev/null
-fi
-if (echo >conf$$.file) 2>/dev/null; then
- if ln -s conf$$.file conf$$ 2>/dev/null; then
- as_ln_s='ln -s'
- # ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -p'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
- elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
- else
- as_ln_s='cp -p'
- fi
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-
-# as_fn_mkdir_p
-# -------------
-# Create "$as_dir" as a directory, including parents if necessary.
-as_fn_mkdir_p ()
-{
-
- case $as_dir in #(
- -*) as_dir=./$as_dir;;
- esac
- test -d "$as_dir" || eval $as_mkdir_p || {
- as_dirs=
- while :; do
- case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
- *) as_qdir=$as_dir;;
- esac
- as_dirs="'$as_qdir' $as_dirs"
- as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- test -d "$as_dir" && break
- done
- test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
-
-
-} # as_fn_mkdir_p
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p='mkdir -p "$as_dir"'
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-if test -x / >/dev/null 2>&1; then
- as_test_x='test -x'
-else
- if ls -dL / >/dev/null 2>&1; then
- as_ls_L_option=L
- else
- as_ls_L_option=
- fi
- as_test_x='
- eval sh -c '\''
- if test -d "$1"; then
- test -d "$1/.";
- else
- case $1 in #(
- -*)set "./$1";;
- esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
- ???[sx]*):;;*)false;;esac;fi
- '\'' sh
- '
-fi
-as_executable_p=$as_test_x
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-exec 6>&1
-## ----------------------------------- ##
-## Main body of $CONFIG_STATUS script. ##
-## ----------------------------------- ##
-_ASEOF
-test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# Save the log message, to keep $0 and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.
-ac_log="
-This file was extended by $as_me, which was
-generated by GNU Autoconf 2.68. Invocation command line was
-
- CONFIG_FILES = $CONFIG_FILES
- CONFIG_HEADERS = $CONFIG_HEADERS
- CONFIG_LINKS = $CONFIG_LINKS
- CONFIG_COMMANDS = $CONFIG_COMMANDS
- $ $0 $@
-
-on `(hostname || uname -n) 2>/dev/null | sed 1q`
-"
-
-_ACEOF
-
-case $ac_config_files in *"
-"*) set x $ac_config_files; shift; ac_config_files=$*;;
-esac
-
-case $ac_config_headers in *"
-"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
-esac
-
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-# Files that config.status was made for.
-config_files="$ac_config_files"
-config_headers="$ac_config_headers"
-config_commands="$ac_config_commands"
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-ac_cs_usage="\
-\`$as_me' instantiates files and other configuration actions
-from templates according to the current configuration. Unless the files
-and actions are specified as TAGs, all are instantiated by default.
-
-Usage: $0 [OPTION]... [TAG]...
-
- -h, --help print this help, then exit
- -V, --version print version number and configuration settings, then exit
- --config print configuration, then exit
- -q, --quiet, --silent
- do not print progress messages
- -d, --debug don't remove temporary files
- --recheck update $as_me by reconfiguring in the same conditions
- --file=FILE[:TEMPLATE]
- instantiate the configuration file FILE
- --header=FILE[:TEMPLATE]
- instantiate the configuration header FILE
-
-Configuration files:
-$config_files
-
-Configuration headers:
-$config_headers
-
-Configuration commands:
-$config_commands
-
-Report bugs to the package provider."
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
-ac_cs_version="\\
-config.status
-configured by $0, generated by GNU Autoconf 2.68,
- with options \\"\$ac_cs_config\\"
-
-Copyright (C) 2010 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-
-ac_pwd='$ac_pwd'
-srcdir='$srcdir'
-INSTALL='$INSTALL'
-test -n "\$AWK" || AWK=awk
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# The default lists apply if the user does not specify any file.
-ac_need_defaults=:
-while test $# != 0
-do
- case $1 in
- --*=?*)
- ac_option=`expr "X$1" : 'X\([^=]*\)='`
- ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
- ac_shift=:
- ;;
- --*=)
- ac_option=`expr "X$1" : 'X\([^=]*\)='`
- ac_optarg=
- ac_shift=:
- ;;
- *)
- ac_option=$1
- ac_optarg=$2
- ac_shift=shift
- ;;
- esac
-
- case $ac_option in
- # Handling of the options.
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- ac_cs_recheck=: ;;
- --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
- --config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
- --debug | --debu | --deb | --de | --d | -d )
- debug=: ;;
- --file | --fil | --fi | --f )
- $ac_shift
- case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
- '') as_fn_error $? "missing file argument" ;;
- esac
- as_fn_append CONFIG_FILES " '$ac_optarg'"
- ac_need_defaults=false;;
- --header | --heade | --head | --hea )
- $ac_shift
- case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
- esac
- as_fn_append CONFIG_HEADERS " '$ac_optarg'"
- ac_need_defaults=false;;
- --he | --h)
- # Conflict between --help and --header
- as_fn_error $? "ambiguous option: \`$1'
-Try \`$0 --help' for more information.";;
- --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil | --si | --s)
- ac_cs_silent=: ;;
-
- # This is an error.
- -*) as_fn_error $? "unrecognized option: \`$1'
-Try \`$0 --help' for more information." ;;
-
- *) as_fn_append ac_config_targets " $1"
- ac_need_defaults=false ;;
-
- esac
- shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
- exec 6>/dev/null
- ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-if \$ac_cs_recheck; then
- set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
- shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
- CONFIG_SHELL='$SHELL'
- export CONFIG_SHELL
- exec "\$@"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-exec 5>>config.log
-{
- echo
- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
- $as_echo "$ac_log"
-} >&5
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-
-# Handling of arguments.
-for ac_config_target in $ac_config_targets
-do
- case $ac_config_target in
- "include/jemalloc/internal/size_classes.h") CONFIG_COMMANDS="$CONFIG_COMMANDS include/jemalloc/internal/size_classes.h" ;;
- "$cfghdrs_tup") CONFIG_HEADERS="$CONFIG_HEADERS $cfghdrs_tup" ;;
- "$cfgoutputs_tup") CONFIG_FILES="$CONFIG_FILES $cfgoutputs_tup" ;;
- "config.stamp") CONFIG_FILES="$CONFIG_FILES config.stamp" ;;
- "bin/jemalloc.sh") CONFIG_FILES="$CONFIG_FILES bin/jemalloc.sh" ;;
-
- *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
- esac
-done
-
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used. Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
- test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
-fi
-
-# Have a temporary directory for convenience. Make it in the build tree
-# simply because there is no reason against having it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Hook for its removal unless debugging.
-# Note that there is a small window in which the directory will not be cleaned:
-# after its creation but before its name has been assigned to `$tmp'.
-$debug ||
-{
- tmp= ac_tmp=
- trap 'exit_status=$?
- : "${ac_tmp:=$tmp}"
- { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
-' 0
- trap 'as_fn_exit 1' 1 2 13 15
-}
-# Create a (secure) tmp directory for tmp files.
-
-{
- tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
- test -d "$tmp"
-} ||
-{
- tmp=./conf$$-$RANDOM
- (umask 077 && mkdir "$tmp")
-} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
-ac_tmp=$tmp
-
-# Set up the scripts for CONFIG_FILES section.
-# No need to generate them if there are no CONFIG_FILES.
-# This happens for instance with `./config.status config.h'.
-if test -n "$CONFIG_FILES"; then
-
-
-ac_cr=`echo X | tr X '\015'`
-# On cygwin, bash can eat \r inside `` if the user requested igncr.
-# But we know of no other shell where ac_cr would be empty at this
-# point, so we can use a bashism as a fallback.
-if test "x$ac_cr" = x; then
- eval ac_cr=\$\'\\r\'
-fi
-ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
-if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
- ac_cs_awk_cr='\\r'
-else
- ac_cs_awk_cr=$ac_cr
-fi
-
-echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
-_ACEOF
-
-
-{
- echo "cat >conf$$subs.awk <<_ACEOF" &&
- echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
- echo "_ACEOF"
-} >conf$$subs.sh ||
- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
-ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
- . ./conf$$subs.sh ||
- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
-
- ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
- if test $ac_delim_n = $ac_delim_num; then
- break
- elif $ac_last_try; then
- as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
- else
- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
- fi
-done
-rm -f conf$$subs.sh
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
-_ACEOF
-sed -n '
-h
-s/^/S["/; s/!.*/"]=/
-p
-g
-s/^[^!]*!//
-:repl
-t repl
-s/'"$ac_delim"'$//
-t delim
-:nl
-h
-s/\(.\{148\}\)..*/\1/
-t more1
-s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
-p
-n
-b repl
-:more1
-s/["\\]/\\&/g; s/^/"/; s/$/"\\/
-p
-g
-s/.\{148\}//
-t nl
-:delim
-h
-s/\(.\{148\}\)..*/\1/
-t more2
-s/["\\]/\\&/g; s/^/"/; s/$/"/
-p
-b
-:more2
-s/["\\]/\\&/g; s/^/"/; s/$/"\\/
-p
-g
-s/.\{148\}//
-t delim
-' <conf$$subs.awk | sed '
-/^[^""]/{
- N
- s/\n//
-}
-' >>$CONFIG_STATUS || ac_write_fail=1
-rm -f conf$$subs.awk
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-_ACAWK
-cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
- for (key in S) S_is_set[key] = 1
- FS = ""
-
-}
-{
- line = $ 0
- nfields = split(line, field, "@")
- substed = 0
- len = length(field[1])
- for (i = 2; i < nfields; i++) {
- key = field[i]
- keylen = length(key)
- if (S_is_set[key]) {
- value = S[key]
- line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
- len += length(value) + length(field[++i])
- substed = 1
- } else
- len += 1 + keylen
- }
-
- print line
-}
-
-_ACAWK
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
- sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
-else
- cat
-fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
- || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
-_ACEOF
-
-# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
-# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
-h
-s///
-s/^/:/
-s/[ ]*$/:/
-s/:\$(srcdir):/:/g
-s/:\${srcdir}:/:/g
-s/:@srcdir@:/:/g
-s/^:*//
-s/:*$//
-x
-s/\(=[ ]*\).*/\1/
-G
-s/\n//
-s/^[^=]*=[ ]*$//
-}'
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-fi # test -n "$CONFIG_FILES"
-
-# Set up the scripts for CONFIG_HEADERS section.
-# No need to generate them if there are no CONFIG_HEADERS.
-# This happens for instance with `./config.status Makefile'.
-if test -n "$CONFIG_HEADERS"; then
-cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
-BEGIN {
-_ACEOF
-
-# Transform confdefs.h into an awk script `defines.awk', embedded as
-# here-document in config.status, that substitutes the proper values into
-# config.h.in to produce config.h.
-
-# Create a delimiter string that does not exist in confdefs.h, to ease
-# handling of long lines.
-ac_delim='%!_!# '
-for ac_last_try in false false :; do
- ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
- if test -z "$ac_tt"; then
- break
- elif $ac_last_try; then
- as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
- else
- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
- fi
-done
-
-# For the awk script, D is an array of macro values keyed by name,
-# likewise P contains macro parameters if any. Preserve backslash
-# newline sequences.
-
-ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
-sed -n '
-s/.\{148\}/&'"$ac_delim"'/g
-t rset
-:rset
-s/^[ ]*#[ ]*define[ ][ ]*/ /
-t def
-d
-:def
-s/\\$//
-t bsnl
-s/["\\]/\\&/g
-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
-D["\1"]=" \3"/p
-s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
-d
-:bsnl
-s/["\\]/\\&/g
-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
-D["\1"]=" \3\\\\\\n"\\/p
-t cont
-s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
-t cont
-d
-:cont
-n
-s/.\{148\}/&'"$ac_delim"'/g
-t clear
-:clear
-s/\\$//
-t bsnlc
-s/["\\]/\\&/g; s/^/"/; s/$/"/p
-d
-:bsnlc
-s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
-b cont
-' <confdefs.h | sed '
-s/'"$ac_delim"'/"\\\
-"/g' >>$CONFIG_STATUS || ac_write_fail=1
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
- for (key in D) D_is_set[key] = 1
- FS = ""
-}
-/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
- line = \$ 0
- split(line, arg, " ")
- if (arg[1] == "#") {
- defundef = arg[2]
- mac1 = arg[3]
- } else {
- defundef = substr(arg[1], 2)
- mac1 = arg[2]
- }
- split(mac1, mac2, "(") #)
- macro = mac2[1]
- prefix = substr(line, 1, index(line, defundef) - 1)
- if (D_is_set[macro]) {
- # Preserve the white space surrounding the "#".
- print prefix "define", macro P[macro] D[macro]
- next
- } else {
- # Replace #undef with comments. This is necessary, for example,
- # in the case of _POSIX_SOURCE, which is predefined and required
- # on some systems where configure will not decide to define it.
- if (defundef == "undef") {
- print "/*", prefix defundef, macro, "*/"
- next
- }
- }
-}
-{ print }
-_ACAWK
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
- as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
-fi # test -n "$CONFIG_HEADERS"
-
-
-eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
-shift
-for ac_tag
-do
- case $ac_tag in
- :[FHLC]) ac_mode=$ac_tag; continue;;
- esac
- case $ac_mode$ac_tag in
- :[FHL]*:*);;
- :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
- :[FH]-) ac_tag=-:-;;
- :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
- esac
- ac_save_IFS=$IFS
- IFS=:
- set x $ac_tag
- IFS=$ac_save_IFS
- shift
- ac_file=$1
- shift
-
- case $ac_mode in
- :L) ac_source=$1;;
- :[FH])
- ac_file_inputs=
- for ac_f
- do
- case $ac_f in
- -) ac_f="$ac_tmp/stdin";;
- *) # Look for the file first in the build tree, then in the source tree
- # (if the path is not absolute). The absolute path cannot be DOS-style,
- # because $ac_f cannot contain `:'.
- test -f "$ac_f" ||
- case $ac_f in
- [\\/$]*) false;;
- *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
- esac ||
- as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
- esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
- as_fn_append ac_file_inputs " '$ac_f'"
- done
-
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
- `' by configure.'
- if test x"$ac_file" != x-; then
- configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
- fi
- # Neutralize special characters interpreted by sed in replacement strings.
- case $configure_input in #(
- *\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
- sed 's/[\\\\&|]/\\\\&/g'`;; #(
- *) ac_sed_conf_input=$configure_input;;
- esac
-
- case $ac_tag in
- *:-:* | *:-) cat >"$ac_tmp/stdin" \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
- esac
- ;;
- esac
-
- ac_dir=`$as_dirname -- "$ac_file" ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_file" : 'X\(//\)[^/]' \| \
- X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- as_dir="$ac_dir"; as_fn_mkdir_p
- ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
- # A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
- case $ac_top_builddir_sub in
- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
- esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
- .) # We are building in place.
- ac_srcdir=.
- ac_top_srcdir=$ac_top_builddir_sub
- ac_abs_top_srcdir=$ac_pwd ;;
- [\\/]* | ?:[\\/]* ) # Absolute name.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir
- ac_abs_top_srcdir=$srcdir ;;
- *) # Relative name.
- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_build_prefix$srcdir
- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
-
- case $ac_mode in
- :F)
- #
- # CONFIG_FILE
- #
-
- case $INSTALL in
- [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
- *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
- esac
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# If the template does not know about datarootdir, expand it.
-# FIXME: This hack should be removed a few years after 2.60.
-ac_datarootdir_hack=; ac_datarootdir_seen=
-ac_sed_dataroot='
-/datarootdir/ {
- p
- q
-}
-/@datadir@/p
-/@docdir@/p
-/@infodir@/p
-/@localedir@/p
-/@mandir@/p'
-case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
-*datarootdir*) ac_datarootdir_seen=yes;;
-*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
- ac_datarootdir_hack='
- s&@datadir@&$datadir&g
- s&@docdir@&$docdir&g
- s&@infodir@&$infodir&g
- s&@localedir@&$localedir&g
- s&@mandir@&$mandir&g
- s&\\\${datarootdir}&$datarootdir&g' ;;
-esac
-_ACEOF
-
-# Neutralize VPATH when `$srcdir' = `.'.
-# Shell code in configure.ac might set extrasub.
-# FIXME: do we really want to maintain this feature?
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_sed_extra="$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s|@configure_input@|$ac_sed_conf_input|;t t
-s&@top_builddir@&$ac_top_builddir_sub&;t t
-s&@top_build_prefix@&$ac_top_build_prefix&;t t
-s&@srcdir@&$ac_srcdir&;t t
-s&@abs_srcdir@&$ac_abs_srcdir&;t t
-s&@top_srcdir@&$ac_top_srcdir&;t t
-s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
-s&@builddir@&$ac_builddir&;t t
-s&@abs_builddir@&$ac_abs_builddir&;t t
-s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
-s&@INSTALL@&$ac_INSTALL&;t t
-$ac_datarootdir_hack
-"
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
- >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
-
-test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
- { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
- { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
- "$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined" >&2;}
-
- rm -f "$ac_tmp/stdin"
- case $ac_file in
- -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
- *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
- esac \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5
- ;;
- :H)
- #
- # CONFIG_HEADER
- #
- if test x"$ac_file" != x-; then
- {
- $as_echo "/* $configure_input */" \
- && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
- } >"$ac_tmp/config.h" \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5
- if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
-$as_echo "$as_me: $ac_file is unchanged" >&6;}
- else
- rm -f "$ac_file"
- mv "$ac_tmp/config.h" "$ac_file" \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5
- fi
- else
- $as_echo "/* $configure_input */" \
- && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
- || as_fn_error $? "could not create -" "$LINENO" 5
- fi
- ;;
-
- :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
-$as_echo "$as_me: executing $ac_file commands" >&6;}
- ;;
- esac
-
-
- case $ac_file$ac_mode in
- "include/jemalloc/internal/size_classes.h":C)
- mkdir -p "include/jemalloc/internal"
- "${srcdir}/include/jemalloc/internal/size_classes.sh" > "${objroot}include/jemalloc/internal/size_classes.h"
- ;;
-
- esac
-done # for ac_tag
-
-
-as_fn_exit 0
-_ACEOF
-ac_clean_files=$ac_clean_files_save
-
-test $ac_write_fail = 0 ||
- as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded. So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status. When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
- ac_cs_success=:
- ac_config_status_args=
- test "$silent" = yes &&
- ac_config_status_args="$ac_config_status_args --quiet"
- exec 5>/dev/null
- $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
- exec 5>>config.log
- # Use ||, not &&, to avoid exiting from the if with $? = 1, which
- # would make configure fail if this is the last instruction.
- $ac_cs_success || as_fn_exit 1
-fi
-if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ===============================================================================" >&5
-$as_echo "===============================================================================" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: jemalloc version : ${jemalloc_version}" >&5
-$as_echo "jemalloc version : ${jemalloc_version}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: library revision : ${rev}" >&5
-$as_echo "library revision : ${rev}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CC : ${CC}" >&5
-$as_echo "CC : ${CC}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CPPFLAGS : ${CPPFLAGS}" >&5
-$as_echo "CPPFLAGS : ${CPPFLAGS}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS : ${CFLAGS}" >&5
-$as_echo "CFLAGS : ${CFLAGS}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: LDFLAGS : ${LDFLAGS}" >&5
-$as_echo "LDFLAGS : ${LDFLAGS}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS : ${LIBS}" >&5
-$as_echo "LIBS : ${LIBS}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: RPATH_EXTRA : ${RPATH_EXTRA}" >&5
-$as_echo "RPATH_EXTRA : ${RPATH_EXTRA}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: XSLTPROC : ${XSLTPROC}" >&5
-$as_echo "XSLTPROC : ${XSLTPROC}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: XSLROOT : ${XSLROOT}" >&5
-$as_echo "XSLROOT : ${XSLROOT}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: PREFIX : ${PREFIX}" >&5
-$as_echo "PREFIX : ${PREFIX}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: BINDIR : ${BINDIR}" >&5
-$as_echo "BINDIR : ${BINDIR}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: INCLUDEDIR : ${INCLUDEDIR}" >&5
-$as_echo "INCLUDEDIR : ${INCLUDEDIR}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBDIR : ${LIBDIR}" >&5
-$as_echo "LIBDIR : ${LIBDIR}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: DATADIR : ${DATADIR}" >&5
-$as_echo "DATADIR : ${DATADIR}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: MANDIR : ${MANDIR}" >&5
-$as_echo "MANDIR : ${MANDIR}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: srcroot : ${srcroot}" >&5
-$as_echo "srcroot : ${srcroot}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: abs_srcroot : ${abs_srcroot}" >&5
-$as_echo "abs_srcroot : ${abs_srcroot}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: objroot : ${objroot}" >&5
-$as_echo "objroot : ${objroot}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: abs_objroot : ${abs_objroot}" >&5
-$as_echo "abs_objroot : ${abs_objroot}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}" >&5
-$as_echo "JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: JEMALLOC_PRIVATE_NAMESPACE" >&5
-$as_echo "JEMALLOC_PRIVATE_NAMESPACE" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: : ${JEMALLOC_PRIVATE_NAMESPACE}" >&5
-$as_echo " : ${JEMALLOC_PRIVATE_NAMESPACE}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: install_suffix : ${install_suffix}" >&5
-$as_echo "install_suffix : ${install_suffix}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: autogen : ${enable_autogen}" >&5
-$as_echo "autogen : ${enable_autogen}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: experimental : ${enable_experimental}" >&5
-$as_echo "experimental : ${enable_experimental}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cc-silence : ${enable_cc_silence}" >&5
-$as_echo "cc-silence : ${enable_cc_silence}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: debug : ${enable_debug}" >&5
-$as_echo "debug : ${enable_debug}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: stats : ${enable_stats}" >&5
-$as_echo "stats : ${enable_stats}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: prof : ${enable_prof}" >&5
-$as_echo "prof : ${enable_prof}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: prof-libunwind : ${enable_prof_libunwind}" >&5
-$as_echo "prof-libunwind : ${enable_prof_libunwind}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: prof-libgcc : ${enable_prof_libgcc}" >&5
-$as_echo "prof-libgcc : ${enable_prof_libgcc}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: prof-gcc : ${enable_prof_gcc}" >&5
-$as_echo "prof-gcc : ${enable_prof_gcc}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: tcache : ${enable_tcache}" >&5
-$as_echo "tcache : ${enable_tcache}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: fill : ${enable_fill}" >&5
-$as_echo "fill : ${enable_fill}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: utrace : ${enable_utrace}" >&5
-$as_echo "utrace : ${enable_utrace}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: valgrind : ${enable_valgrind}" >&5
-$as_echo "valgrind : ${enable_valgrind}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: xmalloc : ${enable_xmalloc}" >&5
-$as_echo "xmalloc : ${enable_xmalloc}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: mremap : ${enable_mremap}" >&5
-$as_echo "mremap : ${enable_mremap}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: munmap : ${enable_munmap}" >&5
-$as_echo "munmap : ${enable_munmap}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: dss : ${enable_dss}" >&5
-$as_echo "dss : ${enable_dss}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: lazy_lock : ${enable_lazy_lock}" >&5
-$as_echo "lazy_lock : ${enable_lazy_lock}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: tls : ${enable_tls}" >&5
-$as_echo "tls : ${enable_tls}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ===============================================================================" >&5
-$as_echo "===============================================================================" >&6; }
diff --git a/extra/jemalloc/configure.ac b/extra/jemalloc/configure.ac
deleted file mode 100644
index c270662b6d4..00000000000
--- a/extra/jemalloc/configure.ac
+++ /dev/null
@@ -1,1333 +0,0 @@
-dnl Process this file with autoconf to produce a configure script.
-AC_INIT([Makefile.in])
-
-dnl ============================================================================
-dnl Custom macro definitions.
-
-dnl JE_CFLAGS_APPEND(cflag)
-AC_DEFUN([JE_CFLAGS_APPEND],
-[
-AC_MSG_CHECKING([whether compiler supports $1])
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
- CFLAGS="$1"
-else
- CFLAGS="${CFLAGS} $1"
-fi
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
-[[
-]], [[
- return 0;
-]])],
- AC_MSG_RESULT([yes]),
- AC_MSG_RESULT([no])
- [CFLAGS="${TCFLAGS}"]
-)
-])
-
-dnl JE_COMPILABLE(label, hcode, mcode, rvar)
-dnl
-dnl Use AC_LINK_IFELSE() rather than AC_COMPILE_IFELSE() so that linker errors
-dnl cause failure.
-AC_DEFUN([JE_COMPILABLE],
-[
-AC_CACHE_CHECK([whether $1 is compilable],
- [$4],
- [AC_LINK_IFELSE([AC_LANG_PROGRAM([$2],
- [$3])],
- [$4=yes],
- [$4=no])])
-])
-
-dnl ============================================================================
-
-dnl Library revision.
-rev=1
-AC_SUBST([rev])
-
-srcroot=$srcdir
-if test "x${srcroot}" = "x." ; then
- srcroot=""
-else
- srcroot="${srcroot}/"
-fi
-AC_SUBST([srcroot])
-abs_srcroot="`cd \"${srcdir}\"; pwd`/"
-AC_SUBST([abs_srcroot])
-
-objroot=""
-AC_SUBST([objroot])
-abs_objroot="`pwd`/"
-AC_SUBST([abs_objroot])
-
-dnl Munge install path variables.
-if test "x$prefix" = "xNONE" ; then
- prefix="/usr/local"
-fi
-if test "x$exec_prefix" = "xNONE" ; then
- exec_prefix=$prefix
-fi
-PREFIX=$prefix
-AC_SUBST([PREFIX])
-BINDIR=`eval echo $bindir`
-BINDIR=`eval echo $BINDIR`
-AC_SUBST([BINDIR])
-INCLUDEDIR=`eval echo $includedir`
-INCLUDEDIR=`eval echo $INCLUDEDIR`
-AC_SUBST([INCLUDEDIR])
-LIBDIR=`eval echo $libdir`
-LIBDIR=`eval echo $LIBDIR`
-AC_SUBST([LIBDIR])
-DATADIR=`eval echo $datadir`
-DATADIR=`eval echo $DATADIR`
-AC_SUBST([DATADIR])
-MANDIR=`eval echo $mandir`
-MANDIR=`eval echo $MANDIR`
-AC_SUBST([MANDIR])
-
-dnl Support for building documentation.
-AC_PATH_PROG([XSLTPROC], [xsltproc], [false], [$PATH])
-if test -d "/usr/share/xml/docbook/stylesheet/docbook-xsl" ; then
- DEFAULT_XSLROOT="/usr/share/xml/docbook/stylesheet/docbook-xsl"
-elif test -d "/usr/share/sgml/docbook/xsl-stylesheets" ; then
- DEFAULT_XSLROOT="/usr/share/sgml/docbook/xsl-stylesheets"
-else
- dnl Documentation building will fail if this default gets used.
- DEFAULT_XSLROOT=""
-fi
-AC_ARG_WITH([xslroot],
- [AS_HELP_STRING([--with-xslroot=<path>], [XSL stylesheet root path])], [
-if test "x$with_xslroot" = "xno" ; then
- XSLROOT="${DEFAULT_XSLROOT}"
-else
- XSLROOT="${with_xslroot}"
-fi
-],
- XSLROOT="${DEFAULT_XSLROOT}"
-)
-AC_SUBST([XSLROOT])
-
-dnl If CFLAGS isn't defined, set CFLAGS to something reasonable. Otherwise,
-dnl just prevent autoconf from molesting CFLAGS.
-CFLAGS=$CFLAGS
-AC_PROG_CC
-if test "x$GCC" != "xyes" ; then
- AC_CACHE_CHECK([whether compiler is MSVC],
- [je_cv_msvc],
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
- [
-#ifndef _MSC_VER
- int fail[-1];
-#endif
-])],
- [je_cv_msvc=yes],
- [je_cv_msvc=no])])
-fi
-
-if test "x$CFLAGS" = "x" ; then
- no_CFLAGS="yes"
- if test "x$GCC" = "xyes" ; then
- JE_CFLAGS_APPEND([-std=gnu99])
- JE_CFLAGS_APPEND([-Wall])
- JE_CFLAGS_APPEND([-pipe])
- JE_CFLAGS_APPEND([-g3])
- elif test "x$je_cv_msvc" = "xyes" ; then
- CC="$CC -nologo"
- JE_CFLAGS_APPEND([-Zi])
- JE_CFLAGS_APPEND([-MT])
- JE_CFLAGS_APPEND([-W3])
- CPPFLAGS="$CPPFLAGS -I${srcroot}/include/msvc_compat"
- fi
-fi
-dnl Append EXTRA_CFLAGS to CFLAGS, if defined.
-if test "x$EXTRA_CFLAGS" != "x" ; then
- JE_CFLAGS_APPEND([$EXTRA_CFLAGS])
-fi
-AC_PROG_CPP
-
-AC_CHECK_SIZEOF([void *])
-if test "x${ac_cv_sizeof_void_p}" = "x8" ; then
- LG_SIZEOF_PTR=3
-elif test "x${ac_cv_sizeof_void_p}" = "x4" ; then
- LG_SIZEOF_PTR=2
-else
- AC_MSG_ERROR([Unsupported pointer size: ${ac_cv_sizeof_void_p}])
-fi
-AC_DEFINE_UNQUOTED([LG_SIZEOF_PTR], [$LG_SIZEOF_PTR])
-
-AC_CHECK_SIZEOF([int])
-if test "x${ac_cv_sizeof_int}" = "x8" ; then
- LG_SIZEOF_INT=3
-elif test "x${ac_cv_sizeof_int}" = "x4" ; then
- LG_SIZEOF_INT=2
-else
- AC_MSG_ERROR([Unsupported int size: ${ac_cv_sizeof_int}])
-fi
-AC_DEFINE_UNQUOTED([LG_SIZEOF_INT], [$LG_SIZEOF_INT])
-
-AC_CHECK_SIZEOF([long])
-if test "x${ac_cv_sizeof_long}" = "x8" ; then
- LG_SIZEOF_LONG=3
-elif test "x${ac_cv_sizeof_long}" = "x4" ; then
- LG_SIZEOF_LONG=2
-else
- AC_MSG_ERROR([Unsupported long size: ${ac_cv_sizeof_long}])
-fi
-AC_DEFINE_UNQUOTED([LG_SIZEOF_LONG], [$LG_SIZEOF_LONG])
-
-AC_CHECK_SIZEOF([intmax_t])
-if test "x${ac_cv_sizeof_intmax_t}" = "x16" ; then
- LG_SIZEOF_INTMAX_T=4
-elif test "x${ac_cv_sizeof_intmax_t}" = "x8" ; then
- LG_SIZEOF_INTMAX_T=3
-elif test "x${ac_cv_sizeof_intmax_t}" = "x4" ; then
- LG_SIZEOF_INTMAX_T=2
-else
- AC_MSG_ERROR([Unsupported intmax_t size: ${ac_cv_sizeof_intmax_t}])
-fi
-AC_DEFINE_UNQUOTED([LG_SIZEOF_INTMAX_T], [$LG_SIZEOF_INTMAX_T])
-
-AC_CANONICAL_HOST
-dnl CPU-specific settings.
-CPU_SPINWAIT=""
-case "${host_cpu}" in
- i[[345]]86)
- ;;
- i686)
- JE_COMPILABLE([__asm__], [], [[__asm__ volatile("pause"); return 0;]],
- [je_cv_asm])
- if test "x${je_cv_asm}" = "xyes" ; then
- CPU_SPINWAIT='__asm__ volatile("pause")'
- fi
- ;;
- x86_64)
- JE_COMPILABLE([__asm__ syntax], [],
- [[__asm__ volatile("pause"); return 0;]], [je_cv_asm])
- if test "x${je_cv_asm}" = "xyes" ; then
- CPU_SPINWAIT='__asm__ volatile("pause")'
- fi
- ;;
- *)
- ;;
-esac
-AC_DEFINE_UNQUOTED([CPU_SPINWAIT], [$CPU_SPINWAIT])
-
-LD_PRELOAD_VAR="LD_PRELOAD"
-so="so"
-importlib="${so}"
-o="$ac_objext"
-a="a"
-exe="$ac_exeext"
-libprefix="lib"
-DSO_LDFLAGS='-shared -Wl,-soname,$(@F)'
-RPATH='-Wl,-rpath,$(1)'
-SOREV="${so}.${rev}"
-PIC_CFLAGS='-fPIC -DPIC'
-CTARGET='-o $@'
-LDTARGET='-o $@'
-EXTRA_LDFLAGS=
-MKLIB='ar crus $@'
-CC_MM=1
-
-dnl Platform-specific settings. abi and RPATH can probably be determined
-dnl programmatically, but doing so is error-prone, which makes it generally
-dnl not worth the trouble.
-dnl
-dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the
-dnl definitions need to be seen before any headers are included, which is a pain
-dnl to make happen otherwise.
-default_munmap="1"
-JEMALLOC_USABLE_SIZE_CONST="const"
-case "${host}" in
- *-*-darwin*)
- CFLAGS="$CFLAGS"
- abi="macho"
- AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
- RPATH=""
- LD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
- so="dylib"
- importlib="${so}"
- force_tls="0"
- DSO_LDFLAGS='-shared -Wl,-dylib_install_name,$(@F)'
- SOREV="${rev}.${so}"
- ;;
- *-*-freebsd*)
- CFLAGS="$CFLAGS"
- abi="elf"
- AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
- force_lazy_lock="1"
- ;;
- *-*-linux*)
- CFLAGS="$CFLAGS"
- CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
- abi="elf"
- AC_DEFINE([JEMALLOC_HAS_ALLOCA_H])
- AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ])
- AC_DEFINE([JEMALLOC_THREADED_INIT], [ ])
- JEMALLOC_USABLE_SIZE_CONST=""
- default_munmap="0"
- ;;
- *-*-netbsd*)
- AC_MSG_CHECKING([ABI])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
-[[#ifdef __ELF__
-/* ELF */
-#else
-#error aout
-#endif
-]])],
- [CFLAGS="$CFLAGS"; abi="elf"],
- [abi="aout"])
- AC_MSG_RESULT([$abi])
- AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ])
- ;;
- *-*-solaris2*)
- CFLAGS="$CFLAGS"
- abi="elf"
- RPATH='-Wl,-R,$(1)'
- dnl Solaris needs this for sigwait().
- CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
- LIBS="$LIBS -lposix4 -lsocket -lnsl"
- ;;
- *-ibm-aix*)
- if "$LG_SIZEOF_PTR" = "8"; then
- dnl 64bit AIX
- LD_PRELOAD_VAR="LDR_PRELOAD64"
- else
- dnl 32bit AIX
- LD_PRELOAD_VAR="LDR_PRELOAD"
- fi
- abi="xcoff"
- ;;
- *-*-mingw*)
- abi="pecoff"
- force_tls="0"
- RPATH=""
- so="dll"
- if test "x$je_cv_msvc" = "xyes" ; then
- importlib="lib"
- DSO_LDFLAGS="-LD"
- EXTRA_LDFLAGS="-link -DEBUG"
- CTARGET='-Fo$@'
- LDTARGET='-Fe$@'
- MKLIB='lib -nologo -out:$@'
- CC_MM=
- else
- importlib="${so}"
- DSO_LDFLAGS="-shared"
- fi
- a="lib"
- libprefix=""
- SOREV="${so}"
- PIC_CFLAGS=""
- ;;
- *)
- AC_MSG_RESULT([Unsupported operating system: ${host}])
- abi="elf"
- ;;
-esac
-AC_DEFINE_UNQUOTED([JEMALLOC_USABLE_SIZE_CONST], [$JEMALLOC_USABLE_SIZE_CONST])
-AC_SUBST([abi])
-AC_SUBST([RPATH])
-AC_SUBST([LD_PRELOAD_VAR])
-AC_SUBST([so])
-AC_SUBST([importlib])
-AC_SUBST([o])
-AC_SUBST([a])
-AC_SUBST([exe])
-AC_SUBST([libprefix])
-AC_SUBST([DSO_LDFLAGS])
-AC_SUBST([EXTRA_LDFLAGS])
-AC_SUBST([SOREV])
-AC_SUBST([PIC_CFLAGS])
-AC_SUBST([CTARGET])
-AC_SUBST([LDTARGET])
-AC_SUBST([MKLIB])
-AC_SUBST([CC_MM])
-
-if test "x$abi" != "xpecoff"; then
- dnl Heap profiling uses the log(3) function.
- LIBS="$LIBS -lm"
-fi
-
-JE_COMPILABLE([__attribute__ syntax],
- [static __attribute__((unused)) void foo(void){}],
- [],
- [je_cv_attribute])
-if test "x${je_cv_attribute}" = "xyes" ; then
- AC_DEFINE([JEMALLOC_HAVE_ATTR], [ ])
- if test "x${GCC}" = "xyes" -a "x${abi}" = "xelf"; then
- JE_CFLAGS_APPEND([-fvisibility=hidden])
- fi
-fi
-dnl Check for tls_model attribute support (clang 3.0 still lacks support).
-SAVED_CFLAGS="${CFLAGS}"
-JE_CFLAGS_APPEND([-Werror])
-JE_COMPILABLE([tls_model attribute], [],
- [static __thread int
- __attribute__((tls_model("initial-exec"))) foo;
- foo = 0;],
- [je_cv_tls_model])
-CFLAGS="${SAVED_CFLAGS}"
-if test "x${je_cv_tls_model}" = "xyes" ; then
- AC_DEFINE([JEMALLOC_TLS_MODEL],
- [__attribute__((tls_model("initial-exec")))])
-else
- AC_DEFINE([JEMALLOC_TLS_MODEL], [ ])
-fi
-
-dnl Support optional additions to rpath.
-AC_ARG_WITH([rpath],
- [AS_HELP_STRING([--with-rpath=<rpath>], [Colon-separated rpath (ELF systems only)])],
-if test "x$with_rpath" = "xno" ; then
- RPATH_EXTRA=
-else
- RPATH_EXTRA="`echo $with_rpath | tr \":\" \" \"`"
-fi,
- RPATH_EXTRA=
-)
-AC_SUBST([RPATH_EXTRA])
-
-dnl Disable rules that do automatic regeneration of configure output by default.
-AC_ARG_ENABLE([autogen],
- [AS_HELP_STRING([--enable-autogen], [Automatically regenerate configure output])],
-if test "x$enable_autogen" = "xno" ; then
- enable_autogen="0"
-else
- enable_autogen="1"
-fi
-,
-enable_autogen="0"
-)
-AC_SUBST([enable_autogen])
-
-AC_PROG_INSTALL
-AC_PROG_RANLIB
-AC_PATH_PROG([AR], [ar], [false], [$PATH])
-AC_PATH_PROG([LD], [ld], [false], [$PATH])
-AC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH])
-
-public_syms="malloc_conf malloc_message malloc calloc posix_memalign aligned_alloc realloc free malloc_usable_size malloc_stats_print mallctl mallctlnametomib mallctlbymib"
-
-dnl Check for allocator-related functions that should be wrapped.
-AC_CHECK_FUNC([memalign],
- [AC_DEFINE([JEMALLOC_OVERRIDE_MEMALIGN], [ ])
- public_syms="${public_syms} memalign"])
-AC_CHECK_FUNC([valloc],
- [AC_DEFINE([JEMALLOC_OVERRIDE_VALLOC], [ ])
- public_syms="${public_syms} valloc"])
-
-dnl Support the experimental API by default.
-AC_ARG_ENABLE([experimental],
- [AS_HELP_STRING([--disable-experimental],
- [Disable support for the experimental API])],
-[if test "x$enable_experimental" = "xno" ; then
- enable_experimental="0"
-else
- enable_experimental="1"
-fi
-],
-[enable_experimental="1"]
-)
-if test "x$enable_experimental" = "x1" ; then
- AC_DEFINE([JEMALLOC_EXPERIMENTAL], [ ])
- public_syms="${public_syms} allocm dallocm nallocm rallocm sallocm"
-fi
-AC_SUBST([enable_experimental])
-
-dnl Perform no name mangling by default.
-AC_ARG_WITH([mangling],
- [AS_HELP_STRING([--with-mangling=<map>], [Mangle symbols in <map>])],
- [mangling_map="$with_mangling"], [mangling_map=""])
-for nm in `echo ${mangling_map} |tr ',' ' '` ; do
- k="`echo ${nm} |tr ':' ' ' |awk '{print $1}'`"
- n="je_${k}"
- m=`echo ${nm} |tr ':' ' ' |awk '{print $2}'`
- AC_DEFINE_UNQUOTED([${n}], [${m}])
- dnl Remove key from public_syms so that it isn't redefined later.
- public_syms=`for sym in ${public_syms}; do echo "${sym}"; done |grep -v "^${k}\$" |tr '\n' ' '`
-done
-
-dnl Do not prefix public APIs by default.
-AC_ARG_WITH([jemalloc_prefix],
- [AS_HELP_STRING([--with-jemalloc-prefix=<prefix>], [Prefix to prepend to all public APIs])],
- [JEMALLOC_PREFIX="$with_jemalloc_prefix"],
- [if test "x$abi" != "xmacho" -a "x$abi" != "xpecoff"; then
- JEMALLOC_PREFIX=""
-else
- JEMALLOC_PREFIX="je_"
-fi]
-)
-if test "x$JEMALLOC_PREFIX" != "x" ; then
- JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr "a-z" "A-Z"`
- AC_DEFINE_UNQUOTED([JEMALLOC_PREFIX], ["$JEMALLOC_PREFIX"])
- AC_DEFINE_UNQUOTED([JEMALLOC_CPREFIX], ["$JEMALLOC_CPREFIX"])
-fi
-dnl Generate macros to rename public symbols. All public symbols are prefixed
-dnl with je_ in the source code, so these macro definitions are needed even if
-dnl --with-jemalloc-prefix wasn't specified.
-for stem in ${public_syms}; do
- n="je_${stem}"
- m="${JEMALLOC_PREFIX}${stem}"
- AC_DEFINE_UNQUOTED([${n}], [${m}])
-done
-
-AC_ARG_WITH([export],
- [AS_HELP_STRING([--without-export], [disable exporting jemalloc public APIs])],
- [if test "x$with_export" = "xno"; then
- AC_DEFINE([JEMALLOC_EXPORT],[])
-fi]
-)
-
-dnl Do not mangle library-private APIs by default.
-AC_ARG_WITH([private_namespace],
- [AS_HELP_STRING([--with-private-namespace=<prefix>], [Prefix to prepend to all library-private APIs])],
- [JEMALLOC_PRIVATE_NAMESPACE="$with_private_namespace"],
- [JEMALLOC_PRIVATE_NAMESPACE=""]
-)
-AC_DEFINE_UNQUOTED([JEMALLOC_PRIVATE_NAMESPACE], ["$JEMALLOC_PRIVATE_NAMESPACE"])
-if test "x$JEMALLOC_PRIVATE_NAMESPACE" != "x" ; then
- AC_DEFINE_UNQUOTED([JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix)], [${JEMALLOC_PRIVATE_NAMESPACE}##string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix])
-else
- AC_DEFINE_UNQUOTED([JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix)], [string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix])
-fi
-
-dnl Do not add suffix to installed files by default.
-AC_ARG_WITH([install_suffix],
- [AS_HELP_STRING([--with-install-suffix=<suffix>], [Suffix to append to all installed files])],
- [INSTALL_SUFFIX="$with_install_suffix"],
- [INSTALL_SUFFIX=]
-)
-install_suffix="$INSTALL_SUFFIX"
-AC_SUBST([install_suffix])
-
-cfgoutputs_in="${srcroot}Makefile.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/html.xsl.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/manpages.xsl.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}doc/jemalloc.xml.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}include/jemalloc/jemalloc.h.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}include/jemalloc/internal/jemalloc_internal.h.in"
-cfgoutputs_in="${cfgoutputs_in} ${srcroot}test/jemalloc_test.h.in"
-
-cfgoutputs_out="Makefile"
-cfgoutputs_out="${cfgoutputs_out} doc/html.xsl"
-cfgoutputs_out="${cfgoutputs_out} doc/manpages.xsl"
-cfgoutputs_out="${cfgoutputs_out} doc/jemalloc${install_suffix}.xml"
-cfgoutputs_out="${cfgoutputs_out} include/jemalloc/jemalloc${install_suffix}.h"
-cfgoutputs_out="${cfgoutputs_out} include/jemalloc/internal/jemalloc_internal.h"
-cfgoutputs_out="${cfgoutputs_out} test/jemalloc_test.h"
-
-cfgoutputs_tup="Makefile"
-cfgoutputs_tup="${cfgoutputs_tup} doc/html.xsl:doc/html.xsl.in"
-cfgoutputs_tup="${cfgoutputs_tup} doc/manpages.xsl:doc/manpages.xsl.in"
-cfgoutputs_tup="${cfgoutputs_tup} doc/jemalloc${install_suffix}.xml:doc/jemalloc.xml.in"
-cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/jemalloc${install_suffix}.h:include/jemalloc/jemalloc.h.in"
-cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/internal/jemalloc_internal.h"
-cfgoutputs_tup="${cfgoutputs_tup} test/jemalloc_test.h:test/jemalloc_test.h.in"
-
-cfghdrs_in="${srcroot}include/jemalloc/jemalloc_defs.h.in"
-cfghdrs_in="${cfghdrs_in} ${srcroot}include/jemalloc/internal/size_classes.sh"
-
-cfghdrs_out="include/jemalloc/jemalloc_defs${install_suffix}.h"
-cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/size_classes.h"
-
-cfghdrs_tup="include/jemalloc/jemalloc_defs${install_suffix}.h:include/jemalloc/jemalloc_defs.h.in"
-
-dnl Do not silence irrelevant compiler warnings by default, since enabling this
-dnl option incurs a performance penalty.
-AC_ARG_ENABLE([cc-silence],
- [AS_HELP_STRING([--enable-cc-silence],
- [Silence irrelevant compiler warnings])],
-[if test "x$enable_cc_silence" = "xno" ; then
- enable_cc_silence="0"
-else
- enable_cc_silence="1"
-fi
-],
-[enable_cc_silence="0"]
-)
-if test "x$enable_cc_silence" = "x1" ; then
- AC_DEFINE([JEMALLOC_CC_SILENCE], [ ])
-fi
-
-dnl Do not compile with debugging by default.
-AC_ARG_ENABLE([debug],
- [AS_HELP_STRING([--enable-debug], [Build debugging code (implies --enable-ivsalloc)])],
-[if test "x$enable_debug" = "xno" ; then
- enable_debug="0"
-else
- enable_debug="1"
-fi
-],
-[enable_debug="0"]
-)
-if test "x$enable_debug" = "x1" ; then
- AC_DEFINE([JEMALLOC_DEBUG], [ ])
- enable_ivsalloc="1"
-fi
-AC_SUBST([enable_debug])
-
-dnl Do not validate pointers by default.
-AC_ARG_ENABLE([ivsalloc],
- [AS_HELP_STRING([--enable-ivsalloc], [Validate pointers passed through the public API])],
-[if test "x$enable_ivsalloc" = "xno" ; then
- enable_ivsalloc="0"
-else
- enable_ivsalloc="1"
-fi
-],
-[enable_ivsalloc="0"]
-)
-if test "x$enable_ivsalloc" = "x1" ; then
- AC_DEFINE([JEMALLOC_IVSALLOC], [ ])
-fi
-
-dnl Only optimize if not debugging.
-if test "x$enable_debug" = "x0" -a "x$no_CFLAGS" = "xyes" ; then
- dnl Make sure that an optimization flag was not specified in EXTRA_CFLAGS.
- optimize="no"
- echo "$EXTRA_CFLAGS" | grep "\-O" >/dev/null || optimize="yes"
- if test "x${optimize}" = "xyes" ; then
- if test "x$GCC" = "xyes" ; then
- JE_CFLAGS_APPEND([-O3])
- JE_CFLAGS_APPEND([-funroll-loops])
- elif test "x$je_cv_msvc" = "xyes" ; then
- JE_CFLAGS_APPEND([-O2])
- else
- JE_CFLAGS_APPEND([-O])
- fi
- fi
-fi
-
-dnl Enable statistics calculation by default.
-AC_ARG_ENABLE([stats],
- [AS_HELP_STRING([--disable-stats],
- [Disable statistics calculation/reporting])],
-[if test "x$enable_stats" = "xno" ; then
- enable_stats="0"
-else
- enable_stats="1"
-fi
-],
-[enable_stats="1"]
-)
-if test "x$enable_stats" = "x1" ; then
- AC_DEFINE([JEMALLOC_STATS], [ ])
-fi
-AC_SUBST([enable_stats])
-
-dnl Do not enable profiling by default.
-AC_ARG_ENABLE([prof],
- [AS_HELP_STRING([--enable-prof], [Enable allocation profiling])],
-[if test "x$enable_prof" = "xno" ; then
- enable_prof="0"
-else
- enable_prof="1"
-fi
-],
-[enable_prof="0"]
-)
-if test "x$enable_prof" = "x1" ; then
- backtrace_method=""
-else
- backtrace_method="N/A"
-fi
-
-AC_ARG_ENABLE([prof-libunwind],
- [AS_HELP_STRING([--enable-prof-libunwind], [Use libunwind for backtracing])],
-[if test "x$enable_prof_libunwind" = "xno" ; then
- enable_prof_libunwind="0"
-else
- enable_prof_libunwind="1"
-fi
-],
-[enable_prof_libunwind="0"]
-)
-AC_ARG_WITH([static_libunwind],
- [AS_HELP_STRING([--with-static-libunwind=<libunwind.a>],
- [Path to static libunwind library; use rather than dynamically linking])],
-if test "x$with_static_libunwind" = "xno" ; then
- LUNWIND="-lunwind"
-else
- if test ! -f "$with_static_libunwind" ; then
- AC_MSG_ERROR([Static libunwind not found: $with_static_libunwind])
- fi
- LUNWIND="$with_static_libunwind"
-fi,
- LUNWIND="-lunwind"
-)
-if test "x$backtrace_method" = "x" -a "x$enable_prof_libunwind" = "x1" ; then
- AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind="0"])
- if test "x$LUNWIND" = "x-lunwind" ; then
- AC_CHECK_LIB([unwind], [backtrace], [LIBS="$LIBS $LUNWIND"],
- [enable_prof_libunwind="0"])
- else
- LIBS="$LIBS $LUNWIND"
- fi
- if test "x${enable_prof_libunwind}" = "x1" ; then
- backtrace_method="libunwind"
- AC_DEFINE([JEMALLOC_PROF_LIBUNWIND], [ ])
- fi
-fi
-
-AC_ARG_ENABLE([prof-libgcc],
- [AS_HELP_STRING([--disable-prof-libgcc],
- [Do not use libgcc for backtracing])],
-[if test "x$enable_prof_libgcc" = "xno" ; then
- enable_prof_libgcc="0"
-else
- enable_prof_libgcc="1"
-fi
-],
-[enable_prof_libgcc="1"]
-)
-if test "x$backtrace_method" = "x" -a "x$enable_prof_libgcc" = "x1" \
- -a "x$GCC" = "xyes" ; then
- AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc="0"])
- AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS="$LIBS -lgcc"], [enable_prof_libgcc="0"])
- dnl The following is conservative, in that it only has entries for CPUs on
- dnl which jemalloc has been tested.
- AC_MSG_CHECKING([libgcc-based backtracing reliability on ${host_cpu}])
- case "${host_cpu}" in
- i[[3456]]86)
- AC_MSG_RESULT([unreliable])
- enable_prof_libgcc="0";
- ;;
- x86_64)
- AC_MSG_RESULT([reliable])
- ;;
- *)
- AC_MSG_RESULT([unreliable])
- enable_prof_libgcc="0";
- ;;
- esac
- if test "x${enable_prof_libgcc}" = "x1" ; then
- backtrace_method="libgcc"
- AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ])
- fi
-else
- enable_prof_libgcc="0"
-fi
-
-AC_ARG_ENABLE([prof-gcc],
- [AS_HELP_STRING([--disable-prof-gcc],
- [Do not use gcc intrinsics for backtracing])],
-[if test "x$enable_prof_gcc" = "xno" ; then
- enable_prof_gcc="0"
-else
- enable_prof_gcc="1"
-fi
-],
-[enable_prof_gcc="1"]
-)
-if test "x$backtrace_method" = "x" -a "x$enable_prof_gcc" = "x1" \
- -a "x$GCC" = "xyes" ; then
- backtrace_method="gcc intrinsics"
- AC_DEFINE([JEMALLOC_PROF_GCC], [ ])
-else
- enable_prof_gcc="0"
-fi
-
-if test "x$backtrace_method" = "x" ; then
- backtrace_method="none (disabling profiling)"
- enable_prof="0"
-fi
-AC_MSG_CHECKING([configured backtracing method])
-AC_MSG_RESULT([$backtrace_method])
-if test "x$enable_prof" = "x1" ; then
- if test "x${force_tls}" = "x0" ; then
- AC_MSG_ERROR([Heap profiling requires TLS]);
- fi
- force_tls="1"
- AC_DEFINE([JEMALLOC_PROF], [ ])
-fi
-AC_SUBST([enable_prof])
-
-dnl Enable thread-specific caching by default.
-AC_ARG_ENABLE([tcache],
- [AS_HELP_STRING([--disable-tcache], [Disable per thread caches])],
-[if test "x$enable_tcache" = "xno" ; then
- enable_tcache="0"
-else
- enable_tcache="1"
-fi
-],
-[enable_tcache="1"]
-)
-if test "x$enable_tcache" = "x1" ; then
- AC_DEFINE([JEMALLOC_TCACHE], [ ])
-fi
-AC_SUBST([enable_tcache])
-
-dnl Disable mremap() for huge realloc() by default.
-AC_ARG_ENABLE([mremap],
- [AS_HELP_STRING([--enable-mremap], [Enable mremap(2) for huge realloc()])],
-[if test "x$enable_mremap" = "xno" ; then
- enable_mremap="0"
-else
- enable_mremap="1"
-fi
-],
-[enable_mremap="0"]
-)
-if test "x$enable_mremap" = "x1" ; then
- JE_COMPILABLE([mremap(...MREMAP_FIXED...)], [
-#define _GNU_SOURCE
-#include <sys/mman.h>
-], [
-void *p = mremap((void *)0, 0, 0, MREMAP_MAYMOVE|MREMAP_FIXED, (void *)0);
-], [je_cv_mremap_fixed])
- if test "x${je_cv_mremap_fixed}" = "xno" ; then
- enable_mremap="0"
- fi
-fi
-if test "x$enable_mremap" = "x1" ; then
- AC_DEFINE([JEMALLOC_MREMAP], [ ])
-fi
-AC_SUBST([enable_mremap])
-
-dnl Enable VM deallocation via munmap() by default.
-AC_ARG_ENABLE([munmap],
- [AS_HELP_STRING([--disable-munmap], [Disable VM deallocation via munmap(2)])],
-[if test "x$enable_munmap" = "xno" ; then
- enable_munmap="0"
-else
- enable_munmap="1"
-fi
-],
-[enable_munmap="${default_munmap}"]
-)
-if test "x$enable_munmap" = "x1" ; then
- AC_DEFINE([JEMALLOC_MUNMAP], [ ])
-fi
-AC_SUBST([enable_munmap])
-
-dnl Do not enable allocation from DSS by default.
-AC_ARG_ENABLE([dss],
- [AS_HELP_STRING([--enable-dss], [Enable allocation from DSS])],
-[if test "x$enable_dss" = "xno" ; then
- enable_dss="0"
-else
- enable_dss="1"
-fi
-],
-[enable_dss="0"]
-)
-dnl Check whether the BSD/SUSv1 sbrk() exists. If not, disable DSS support.
-AC_CHECK_FUNC([sbrk], [have_sbrk="1"], [have_sbrk="0"])
-if test "x$have_sbrk" = "x1" ; then
- AC_DEFINE([JEMALLOC_HAVE_SBRK], [ ])
-else
- enable_dss="0"
-fi
-
-if test "x$enable_dss" = "x1" ; then
- AC_DEFINE([JEMALLOC_DSS], [ ])
-fi
-AC_SUBST([enable_dss])
-
-dnl Support the junk/zero filling option by default.
-AC_ARG_ENABLE([fill],
- [AS_HELP_STRING([--disable-fill],
- [Disable support for junk/zero filling, quarantine, and redzones])],
-[if test "x$enable_fill" = "xno" ; then
- enable_fill="0"
-else
- enable_fill="1"
-fi
-],
-[enable_fill="1"]
-)
-if test "x$enable_fill" = "x1" ; then
- AC_DEFINE([JEMALLOC_FILL], [ ])
-fi
-AC_SUBST([enable_fill])
-
-dnl Disable utrace(2)-based tracing by default.
-AC_ARG_ENABLE([utrace],
- [AS_HELP_STRING([--enable-utrace], [Enable utrace(2)-based tracing])],
-[if test "x$enable_utrace" = "xno" ; then
- enable_utrace="0"
-else
- enable_utrace="1"
-fi
-],
-[enable_utrace="0"]
-)
-JE_COMPILABLE([utrace(2)], [
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/ktrace.h>
-], [
- utrace((void *)0, 0);
-], [je_cv_utrace])
-if test "x${je_cv_utrace}" = "xno" ; then
- enable_utrace="0"
-fi
-if test "x$enable_utrace" = "x1" ; then
- AC_DEFINE([JEMALLOC_UTRACE], [ ])
-fi
-AC_SUBST([enable_utrace])
-
-dnl Support Valgrind by default.
-AC_ARG_ENABLE([valgrind],
- [AS_HELP_STRING([--disable-valgrind], [Disable support for Valgrind])],
-[if test "x$enable_valgrind" = "xno" ; then
- enable_valgrind="0"
-else
- enable_valgrind="1"
-fi
-],
-[enable_valgrind="1"]
-)
-if test "x$enable_valgrind" = "x1" ; then
- JE_COMPILABLE([valgrind], [
-#include <valgrind/valgrind.h>
-#include <valgrind/memcheck.h>
-
-#if !defined(VALGRIND_RESIZEINPLACE_BLOCK)
-# error "Incompatible Valgrind version"
-#endif
-], [], [je_cv_valgrind])
- if test "x${je_cv_valgrind}" = "xno" ; then
- enable_valgrind="0"
- fi
- if test "x$enable_valgrind" = "x1" ; then
- AC_DEFINE([JEMALLOC_VALGRIND], [ ])
- fi
-fi
-AC_SUBST([enable_valgrind])
-
-dnl Do not support the xmalloc option by default.
-AC_ARG_ENABLE([xmalloc],
- [AS_HELP_STRING([--enable-xmalloc], [Support xmalloc option])],
-[if test "x$enable_xmalloc" = "xno" ; then
- enable_xmalloc="0"
-else
- enable_xmalloc="1"
-fi
-],
-[enable_xmalloc="0"]
-)
-if test "x$enable_xmalloc" = "x1" ; then
- AC_DEFINE([JEMALLOC_XMALLOC], [ ])
-fi
-AC_SUBST([enable_xmalloc])
-
-AC_CACHE_CHECK([STATIC_PAGE_SHIFT],
- [je_cv_static_page_shift],
- AC_RUN_IFELSE([AC_LANG_PROGRAM(
-[[
-#include <strings.h>
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <unistd.h>
-#endif
-#include <stdio.h>
-]],
-[[
- int result;
- FILE *f;
-
-#ifdef _WIN32
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- result = si.dwPageSize;
-#else
- result = sysconf(_SC_PAGESIZE);
-#endif
- if (result == -1) {
- return 1;
- }
- result = ffsl(result) - 1;
-
- f = fopen("conftest.out", "w");
- if (f == NULL) {
- return 1;
- }
- fprintf(f, "%d\n", result);
- fclose(f);
-
- return 0;
-]])],
- [je_cv_static_page_shift=`cat conftest.out`],
- [je_cv_static_page_shift=undefined]))
-
-if test "x$je_cv_static_page_shift" != "xundefined"; then
- AC_DEFINE_UNQUOTED([STATIC_PAGE_SHIFT], [$je_cv_static_page_shift])
-else
- AC_MSG_ERROR([cannot determine value for STATIC_PAGE_SHIFT])
-fi
-
-dnl ============================================================================
-dnl jemalloc configuration.
-dnl
-
-dnl Set VERSION if source directory has an embedded git repository.
-if test -d "${srcroot}.git" ; then
- git describe --long --abbrev=40 > ${srcroot}VERSION
-fi
-jemalloc_version=`cat ${srcroot}VERSION`
-jemalloc_version_major=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]1}'`
-jemalloc_version_minor=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]2}'`
-jemalloc_version_bugfix=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]3}'`
-jemalloc_version_nrev=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]4}'`
-jemalloc_version_gid=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]5}'`
-AC_SUBST([jemalloc_version])
-AC_SUBST([jemalloc_version_major])
-AC_SUBST([jemalloc_version_minor])
-AC_SUBST([jemalloc_version_bugfix])
-AC_SUBST([jemalloc_version_nrev])
-AC_SUBST([jemalloc_version_gid])
-
-dnl ============================================================================
-dnl Configure pthreads.
-
-if test "x$abi" != "xpecoff" ; then
- AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])])
- dnl Some systems may embed pthreads functionality in libc; check for libpthread
- dnl first, but try libc too before failing.
- AC_CHECK_LIB([pthread], [pthread_create], [LIBS="$LIBS -lpthread"],
- [AC_SEARCH_LIBS([pthread_create], , ,
- AC_MSG_ERROR([libpthread is missing]))])
-fi
-
-CPPFLAGS="$CPPFLAGS -D_REENTRANT"
-
-dnl Check whether the BSD-specific _malloc_thread_cleanup() exists. If so, use
-dnl it rather than pthreads TSD cleanup functions to support cleanup during
-dnl thread exit, in order to avoid pthreads library recursion during
-dnl bootstrapping.
-AC_CHECK_FUNC([_malloc_thread_cleanup],
- [have__malloc_thread_cleanup="1"],
- [have__malloc_thread_cleanup="0"]
- )
-if test "x$have__malloc_thread_cleanup" = "x1" ; then
- AC_DEFINE([JEMALLOC_MALLOC_THREAD_CLEANUP], [ ])
- force_tls="1"
-fi
-
-dnl Check whether the BSD-specific _pthread_mutex_init_calloc_cb() exists. If
-dnl so, mutex initialization causes allocation, and we need to implement this
-dnl callback function in order to prevent recursive allocation.
-AC_CHECK_FUNC([_pthread_mutex_init_calloc_cb],
- [have__pthread_mutex_init_calloc_cb="1"],
- [have__pthread_mutex_init_calloc_cb="0"]
- )
-if test "x$have__pthread_mutex_init_calloc_cb" = "x1" ; then
- AC_DEFINE([JEMALLOC_MUTEX_INIT_CB])
-fi
-
-dnl Disable lazy locking by default.
-AC_ARG_ENABLE([lazy_lock],
- [AS_HELP_STRING([--enable-lazy-lock],
- [Enable lazy locking (only lock when multi-threaded)])],
-[if test "x$enable_lazy_lock" = "xno" ; then
- enable_lazy_lock="0"
-else
- enable_lazy_lock="1"
-fi
-],
-[enable_lazy_lock="0"]
-)
-if test "x$enable_lazy_lock" = "x0" -a "x${force_lazy_lock}" = "x1" ; then
- AC_MSG_RESULT([Forcing lazy-lock to avoid allocator/threading bootstrap issues])
- enable_lazy_lock="1"
-fi
-if test "x$enable_lazy_lock" = "x1" ; then
- if test "x$abi" != "xpecoff" ; then
- AC_CHECK_HEADERS([dlfcn.h], , [AC_MSG_ERROR([dlfcn.h is missing])])
- AC_CHECK_FUNC([dlsym], [],
- [AC_CHECK_LIB([dl], [dlsym], [LIBS="$LIBS -ldl"],
- [AC_MSG_ERROR([libdl is missing])])
- ])
- fi
- AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ])
-fi
-AC_SUBST([enable_lazy_lock])
-
-AC_ARG_ENABLE([tls],
- [AS_HELP_STRING([--disable-tls], [Disable thread-local storage (__thread keyword)])],
-if test "x$enable_tls" = "xno" ; then
- enable_tls="0"
-else
- enable_tls="1"
-fi
-,
-enable_tls="1"
-)
-if test "x${enable_tls}" = "x0" -a "x${force_tls}" = "x1" ; then
- AC_MSG_RESULT([Forcing TLS to avoid allocator/threading bootstrap issues])
- enable_tls="1"
-fi
-if test "x${enable_tls}" = "x1" -a "x${force_tls}" = "x0" ; then
- AC_MSG_RESULT([Forcing no TLS to avoid allocator/threading bootstrap issues])
- enable_tls="0"
-fi
-if test "x${enable_tls}" = "x1" ; then
-AC_MSG_CHECKING([for TLS])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
-[[
- __thread int x;
-]], [[
- x = 42;
-
- return 0;
-]])],
- AC_MSG_RESULT([yes]),
- AC_MSG_RESULT([no])
- enable_tls="0")
-fi
-AC_SUBST([enable_tls])
-if test "x${enable_tls}" = "x1" ; then
- AC_DEFINE_UNQUOTED([JEMALLOC_TLS], [ ])
-elif test "x${force_tls}" = "x1" ; then
- AC_MSG_ERROR([Failed to configure TLS, which is mandatory for correct function])
-fi
-
-dnl ============================================================================
-dnl Check for ffsl(3), and fail if not found. This function exists on all
-dnl platforms that jemalloc currently has a chance of functioning on without
-dnl modification.
-JE_COMPILABLE([a program using ffsl], [
-#include <stdio.h>
-#include <strings.h>
-#include <string.h>
-], [
- {
- int rv = ffsl(0x08);
- printf("%d\n", rv);
- }
-], [je_cv_function_ffsl])
-if test "x${je_cv_function_ffsl}" != "xyes" ; then
- AC_MSG_ERROR([Cannot build without ffsl(3)])
-fi
-
-dnl ============================================================================
-dnl Check for atomic(9) operations as provided on FreeBSD.
-
-JE_COMPILABLE([atomic(9)], [
-#include <sys/types.h>
-#include <machine/atomic.h>
-#include <inttypes.h>
-], [
- {
- uint32_t x32 = 0;
- volatile uint32_t *x32p = &x32;
- atomic_fetchadd_32(x32p, 1);
- }
- {
- unsigned long xlong = 0;
- volatile unsigned long *xlongp = &xlong;
- atomic_fetchadd_long(xlongp, 1);
- }
-], [je_cv_atomic9])
-if test "x${je_cv_atomic9}" = "xyes" ; then
- AC_DEFINE([JEMALLOC_ATOMIC9])
-fi
-
-dnl ============================================================================
-dnl Check for atomic(3) operations as provided on Darwin.
-
-JE_COMPILABLE([Darwin OSAtomic*()], [
-#include <libkern/OSAtomic.h>
-#include <inttypes.h>
-], [
- {
- int32_t x32 = 0;
- volatile int32_t *x32p = &x32;
- OSAtomicAdd32(1, x32p);
- }
- {
- int64_t x64 = 0;
- volatile int64_t *x64p = &x64;
- OSAtomicAdd64(1, x64p);
- }
-], [je_cv_osatomic])
-if test "x${je_cv_osatomic}" = "xyes" ; then
- AC_DEFINE([JEMALLOC_OSATOMIC], [ ])
-fi
-
-dnl ============================================================================
-dnl Check whether __sync_{add,sub}_and_fetch() are available despite
-dnl __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros being undefined.
-
-AC_DEFUN([JE_SYNC_COMPARE_AND_SWAP_CHECK],[
- AC_CACHE_CHECK([whether to force $1-bit __sync_{add,sub}_and_fetch()],
- [je_cv_sync_compare_and_swap_$2],
- [AC_LINK_IFELSE([AC_LANG_PROGRAM([
- #include <stdint.h>
- ],
- [
- #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2
- {
- uint$1_t x$1 = 0;
- __sync_add_and_fetch(&x$1, 42);
- __sync_sub_and_fetch(&x$1, 1);
- }
- #else
- #error __GCC_HAVE_SYNC_COMPARE_AND_SWAP_$2 is defined, no need to force
- #endif
- ])],
- [je_cv_sync_compare_and_swap_$2=yes],
- [je_cv_sync_compare_and_swap_$2=no])])
-
- if test "x${je_cv_sync_compare_and_swap_$2}" = "xyes" ; then
- AC_DEFINE([JE_FORCE_SYNC_COMPARE_AND_SWAP_$2], [ ])
- fi
-])
-
-if test "x${je_cv_atomic9}" != "xyes" -a "x${je_cv_osatomic}" != "xyes" ; then
- JE_SYNC_COMPARE_AND_SWAP_CHECK(32, 4)
- JE_SYNC_COMPARE_AND_SWAP_CHECK(64, 8)
-fi
-
-dnl ============================================================================
-dnl Check for spinlock(3) operations as provided on Darwin.
-
-JE_COMPILABLE([Darwin OSSpin*()], [
-#include <libkern/OSAtomic.h>
-#include <inttypes.h>
-], [
- OSSpinLock lock = 0;
- OSSpinLockLock(&lock);
- OSSpinLockUnlock(&lock);
-], [je_cv_osspin])
-if test "x${je_cv_osspin}" = "xyes" ; then
- AC_DEFINE([JEMALLOC_OSSPIN], [ ])
-fi
-
-dnl ============================================================================
-dnl Darwin-related configuration.
-
-AC_ARG_ENABLE([zone-allocator],
- [AS_HELP_STRING([--disable-zone-allocator],
- [Disable zone allocator for Darwin])],
-[if test "x$enable_zone_allocator" = "xno" ; then
- enable_zone_allocator="0"
-else
- enable_zone_allocator="1"
-fi
-],
-[if test "x${abi}" = "xmacho"; then
- enable_zone_allocator="1"
-fi
-]
-)
-AC_SUBST([enable_zone_allocator])
-
-if test "x${enable_zone_allocator}" = "x1" ; then
- if test "x${abi}" != "xmacho"; then
- AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin])
- fi
- AC_DEFINE([JEMALLOC_IVSALLOC], [ ])
- AC_DEFINE([JEMALLOC_ZONE], [ ])
-
- dnl The szone version jumped from 3 to 6 between the OS X 10.5.x and 10.6
- dnl releases. malloc_zone_t and malloc_introspection_t have new fields in
- dnl 10.6, which is the only source-level indication of the change.
- AC_MSG_CHECKING([malloc zone version])
- AC_DEFUN([JE_ZONE_PROGRAM],
- [AC_LANG_PROGRAM(
- [#include <malloc/malloc.h>],
- [static foo[[sizeof($1) $2 sizeof(void *) * $3 ? 1 : -1]]]
- )])
-
- AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,14)],[JEMALLOC_ZONE_VERSION=3],[
- AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,15)],[JEMALLOC_ZONE_VERSION=5],[
- AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,16)],[
- AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,9)],[JEMALLOC_ZONE_VERSION=6],[
- AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,13)],[JEMALLOC_ZONE_VERSION=7],[JEMALLOC_ZONE_VERSION=]
- )])],[
- AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,17)],[JEMALLOC_ZONE_VERSION=8],[
- AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,>,17)],[JEMALLOC_ZONE_VERSION=9],[JEMALLOC_ZONE_VERSION=]
- )])])])])
- if test "x${JEMALLOC_ZONE_VERSION}" = "x"; then
- AC_MSG_RESULT([unsupported])
- AC_MSG_ERROR([Unsupported malloc zone version])
- fi
- if test "${JEMALLOC_ZONE_VERSION}" = 9; then
- JEMALLOC_ZONE_VERSION=8
- AC_MSG_RESULT([> 8])
- else
- AC_MSG_RESULT([$JEMALLOC_ZONE_VERSION])
- fi
- AC_DEFINE_UNQUOTED(JEMALLOC_ZONE_VERSION, [$JEMALLOC_ZONE_VERSION])
-fi
-
-dnl ============================================================================
-dnl Check for typedefs, structures, and compiler characteristics.
-AC_HEADER_STDBOOL
-
-AC_CONFIG_COMMANDS([include/jemalloc/internal/size_classes.h], [
- mkdir -p "include/jemalloc/internal"
- "${srcdir}/include/jemalloc/internal/size_classes.sh" > "${objroot}include/jemalloc/internal/size_classes.h"
-])
-
-dnl Process .in files.
-AC_SUBST([cfghdrs_in])
-AC_SUBST([cfghdrs_out])
-AC_CONFIG_HEADERS([$cfghdrs_tup])
-
-dnl ============================================================================
-dnl Generate outputs.
-AC_CONFIG_FILES([$cfgoutputs_tup config.stamp bin/jemalloc.sh])
-AC_SUBST([cfgoutputs_in])
-AC_SUBST([cfgoutputs_out])
-AC_OUTPUT
-
-dnl ============================================================================
-dnl Print out the results of configuration.
-AC_MSG_RESULT([===============================================================================])
-AC_MSG_RESULT([jemalloc version : ${jemalloc_version}])
-AC_MSG_RESULT([library revision : ${rev}])
-AC_MSG_RESULT([])
-AC_MSG_RESULT([CC : ${CC}])
-AC_MSG_RESULT([CPPFLAGS : ${CPPFLAGS}])
-AC_MSG_RESULT([CFLAGS : ${CFLAGS}])
-AC_MSG_RESULT([LDFLAGS : ${LDFLAGS}])
-AC_MSG_RESULT([LIBS : ${LIBS}])
-AC_MSG_RESULT([RPATH_EXTRA : ${RPATH_EXTRA}])
-AC_MSG_RESULT([])
-AC_MSG_RESULT([XSLTPROC : ${XSLTPROC}])
-AC_MSG_RESULT([XSLROOT : ${XSLROOT}])
-AC_MSG_RESULT([])
-AC_MSG_RESULT([PREFIX : ${PREFIX}])
-AC_MSG_RESULT([BINDIR : ${BINDIR}])
-AC_MSG_RESULT([INCLUDEDIR : ${INCLUDEDIR}])
-AC_MSG_RESULT([LIBDIR : ${LIBDIR}])
-AC_MSG_RESULT([DATADIR : ${DATADIR}])
-AC_MSG_RESULT([MANDIR : ${MANDIR}])
-AC_MSG_RESULT([])
-AC_MSG_RESULT([srcroot : ${srcroot}])
-AC_MSG_RESULT([abs_srcroot : ${abs_srcroot}])
-AC_MSG_RESULT([objroot : ${objroot}])
-AC_MSG_RESULT([abs_objroot : ${abs_objroot}])
-AC_MSG_RESULT([])
-AC_MSG_RESULT([JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}])
-AC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE])
-AC_MSG_RESULT([ : ${JEMALLOC_PRIVATE_NAMESPACE}])
-AC_MSG_RESULT([install_suffix : ${install_suffix}])
-AC_MSG_RESULT([autogen : ${enable_autogen}])
-AC_MSG_RESULT([experimental : ${enable_experimental}])
-AC_MSG_RESULT([cc-silence : ${enable_cc_silence}])
-AC_MSG_RESULT([debug : ${enable_debug}])
-AC_MSG_RESULT([stats : ${enable_stats}])
-AC_MSG_RESULT([prof : ${enable_prof}])
-AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}])
-AC_MSG_RESULT([prof-libgcc : ${enable_prof_libgcc}])
-AC_MSG_RESULT([prof-gcc : ${enable_prof_gcc}])
-AC_MSG_RESULT([tcache : ${enable_tcache}])
-AC_MSG_RESULT([fill : ${enable_fill}])
-AC_MSG_RESULT([utrace : ${enable_utrace}])
-AC_MSG_RESULT([valgrind : ${enable_valgrind}])
-AC_MSG_RESULT([xmalloc : ${enable_xmalloc}])
-AC_MSG_RESULT([mremap : ${enable_mremap}])
-AC_MSG_RESULT([munmap : ${enable_munmap}])
-AC_MSG_RESULT([dss : ${enable_dss}])
-AC_MSG_RESULT([lazy_lock : ${enable_lazy_lock}])
-AC_MSG_RESULT([tls : ${enable_tls}])
-AC_MSG_RESULT([===============================================================================])
diff --git a/extra/jemalloc/doc/html.xsl.in b/extra/jemalloc/doc/html.xsl.in
deleted file mode 100644
index a91d9746f62..00000000000
--- a/extra/jemalloc/doc/html.xsl.in
+++ /dev/null
@@ -1,4 +0,0 @@
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
- <xsl:import href="@XSLROOT@/html/docbook.xsl"/>
- <xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
-</xsl:stylesheet>
diff --git a/extra/jemalloc/doc/jemalloc.3 b/extra/jemalloc/doc/jemalloc.3
deleted file mode 100644
index 1462e2c2b34..00000000000
--- a/extra/jemalloc/doc/jemalloc.3
+++ /dev/null
@@ -1,1482 +0,0 @@
-'\" t
-.\" Title: JEMALLOC
-.\" Author: Jason Evans
-.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
-.\" Date: 03/06/2013
-.\" Manual: User Manual
-.\" Source: jemalloc 3.3.1-0-g9ef9d9e8c271cdf14f664b871a8f98c827714784
-.\" Language: English
-.\"
-.TH "JEMALLOC" "3" "03/06/2013" "jemalloc 3.3.1-0-g9ef9d9e8c271" "User Manual"
-.\" -----------------------------------------------------------------
-.\" * Define some portability stuff
-.\" -----------------------------------------------------------------
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.\" http://bugs.debian.org/507673
-.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\" -----------------------------------------------------------------
-.\" * set default formatting
-.\" -----------------------------------------------------------------
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.\" -----------------------------------------------------------------
-.\" * MAIN CONTENT STARTS HERE *
-.\" -----------------------------------------------------------------
-.SH "NAME"
-jemalloc \- general purpose memory allocation functions
-.SH "LIBRARY"
-.PP
-This manual describes jemalloc 3\&.3\&.1\-0\-g9ef9d9e8c271cdf14f664b871a8f98c827714784\&. More information can be found at the
-\m[blue]\fBjemalloc website\fR\m[]\&\s-2\u[1]\d\s+2\&.
-.SH "SYNOPSIS"
-.sp
-.ft B
-.nf
-#include <stdlib\&.h>
-#include <jemalloc/jemalloc\&.h>
-.fi
-.ft
-.SS "Standard API"
-.HP \w'void\ *malloc('u
-.BI "void *malloc(size_t\ " "size" ");"
-.HP \w'void\ *calloc('u
-.BI "void *calloc(size_t\ " "number" ", size_t\ " "size" ");"
-.HP \w'int\ posix_memalign('u
-.BI "int posix_memalign(void\ **" "ptr" ", size_t\ " "alignment" ", size_t\ " "size" ");"
-.HP \w'void\ *aligned_alloc('u
-.BI "void *aligned_alloc(size_t\ " "alignment" ", size_t\ " "size" ");"
-.HP \w'void\ *realloc('u
-.BI "void *realloc(void\ *" "ptr" ", size_t\ " "size" ");"
-.HP \w'void\ free('u
-.BI "void free(void\ *" "ptr" ");"
-.SS "Non\-standard API"
-.HP \w'size_t\ malloc_usable_size('u
-.BI "size_t malloc_usable_size(const\ void\ *" "ptr" ");"
-.HP \w'void\ malloc_stats_print('u
-.BI "void malloc_stats_print(void\ " "(*write_cb)" "\ (void\ *,\ const\ char\ *), void\ *" "cbopaque" ", const\ char\ *" "opts" ");"
-.HP \w'int\ mallctl('u
-.BI "int mallctl(const\ char\ *" "name" ", void\ *" "oldp" ", size_t\ *" "oldlenp" ", void\ *" "newp" ", size_t\ " "newlen" ");"
-.HP \w'int\ mallctlnametomib('u
-.BI "int mallctlnametomib(const\ char\ *" "name" ", size_t\ *" "mibp" ", size_t\ *" "miblenp" ");"
-.HP \w'int\ mallctlbymib('u
-.BI "int mallctlbymib(const\ size_t\ *" "mib" ", size_t\ " "miblen" ", void\ *" "oldp" ", size_t\ *" "oldlenp" ", void\ *" "newp" ", size_t\ " "newlen" ");"
-.HP \w'void\ (*malloc_message)('u
-.BI "void (*malloc_message)(void\ *" "cbopaque" ", const\ char\ *" "s" ");"
-.PP
-const char *\fImalloc_conf\fR;
-.SS "Experimental API"
-.HP \w'int\ allocm('u
-.BI "int allocm(void\ **" "ptr" ", size_t\ *" "rsize" ", size_t\ " "size" ", int\ " "flags" ");"
-.HP \w'int\ rallocm('u
-.BI "int rallocm(void\ **" "ptr" ", size_t\ *" "rsize" ", size_t\ " "size" ", size_t\ " "extra" ", int\ " "flags" ");"
-.HP \w'int\ sallocm('u
-.BI "int sallocm(const\ void\ *" "ptr" ", size_t\ *" "rsize" ", int\ " "flags" ");"
-.HP \w'int\ dallocm('u
-.BI "int dallocm(void\ *" "ptr" ", int\ " "flags" ");"
-.HP \w'int\ nallocm('u
-.BI "int nallocm(size_t\ *" "rsize" ", size_t\ " "size" ", int\ " "flags" ");"
-.SH "DESCRIPTION"
-.SS "Standard API"
-.PP
-The
-\fBmalloc\fR\fB\fR
-function allocates
-\fIsize\fR
-bytes of uninitialized memory\&. The allocated space is suitably aligned (after possible pointer coercion) for storage of any type of object\&.
-.PP
-The
-\fBcalloc\fR\fB\fR
-function allocates space for
-\fInumber\fR
-objects, each
-\fIsize\fR
-bytes in length\&. The result is identical to calling
-\fBmalloc\fR\fB\fR
-with an argument of
-\fInumber\fR
-*
-\fIsize\fR, with the exception that the allocated memory is explicitly initialized to zero bytes\&.
-.PP
-The
-\fBposix_memalign\fR\fB\fR
-function allocates
-\fIsize\fR
-bytes of memory such that the allocation\*(Aqs base address is an even multiple of
-\fIalignment\fR, and returns the allocation in the value pointed to by
-\fIptr\fR\&. The requested
-\fIalignment\fR
-must be a power of 2 at least as large as
-sizeof(\fBvoid *\fR)\&.
-.PP
-The
-\fBaligned_alloc\fR\fB\fR
-function allocates
-\fIsize\fR
-bytes of memory such that the allocation\*(Aqs base address is an even multiple of
-\fIalignment\fR\&. The requested
-\fIalignment\fR
-must be a power of 2\&. Behavior is undefined if
-\fIsize\fR
-is not an integral multiple of
-\fIalignment\fR\&.
-.PP
-The
-\fBrealloc\fR\fB\fR
-function changes the size of the previously allocated memory referenced by
-\fIptr\fR
-to
-\fIsize\fR
-bytes\&. The contents of the memory are unchanged up to the lesser of the new and old sizes\&. If the new size is larger, the contents of the newly allocated portion of the memory are undefined\&. Upon success, the memory referenced by
-\fIptr\fR
-is freed and a pointer to the newly allocated memory is returned\&. Note that
-\fBrealloc\fR\fB\fR
-may move the memory allocation, resulting in a different return value than
-\fIptr\fR\&. If
-\fIptr\fR
-is
-\fBNULL\fR, the
-\fBrealloc\fR\fB\fR
-function behaves identically to
-\fBmalloc\fR\fB\fR
-for the specified size\&.
-.PP
-The
-\fBfree\fR\fB\fR
-function causes the allocated memory referenced by
-\fIptr\fR
-to be made available for future allocations\&. If
-\fIptr\fR
-is
-\fBNULL\fR, no action occurs\&.
-.SS "Non\-standard API"
-.PP
-The
-\fBmalloc_usable_size\fR\fB\fR
-function returns the usable size of the allocation pointed to by
-\fIptr\fR\&. The return value may be larger than the size that was requested during allocation\&. The
-\fBmalloc_usable_size\fR\fB\fR
-function is not a mechanism for in\-place
-\fBrealloc\fR\fB\fR; rather it is provided solely as a tool for introspection purposes\&. Any discrepancy between the requested allocation size and the size reported by
-\fBmalloc_usable_size\fR\fB\fR
-should not be depended on, since such behavior is entirely implementation\-dependent\&.
-.PP
-The
-\fBmalloc_stats_print\fR\fB\fR
-function writes human\-readable summary statistics via the
-\fIwrite_cb\fR
-callback function pointer and
-\fIcbopaque\fR
-data passed to
-\fIwrite_cb\fR, or
-\fBmalloc_message\fR\fB\fR
-if
-\fIwrite_cb\fR
-is
-\fBNULL\fR\&. This function can be called repeatedly\&. General information that never changes during execution can be omitted by specifying "g" as a character within the
-\fIopts\fR
-string\&. Note that
-\fBmalloc_message\fR\fB\fR
-uses the
-\fBmallctl*\fR\fB\fR
-functions internally, so inconsistent statistics can be reported if multiple threads use these functions simultaneously\&. If
-\fB\-\-enable\-stats\fR
-is specified during configuration, \(lqm\(rq and \(lqa\(rq can be specified to omit merged arena and per arena statistics, respectively; \(lqb\(rq and \(lql\(rq can be specified to omit per size class statistics for bins and large objects, respectively\&. Unrecognized characters are silently ignored\&. Note that thread caching may prevent some statistics from being completely up to date, since extra locking would be required to merge counters that track thread cache operations\&.
-.PP
-The
-\fBmallctl\fR\fB\fR
-function provides a general interface for introspecting the memory allocator, as well as setting modifiable parameters and triggering actions\&. The period\-separated
-\fIname\fR
-argument specifies a location in a tree\-structured namespace; see the
-MALLCTL NAMESPACE
-section for documentation on the tree contents\&. To read a value, pass a pointer via
-\fIoldp\fR
-to adequate space to contain the value, and a pointer to its length via
-\fIoldlenp\fR; otherwise pass
-\fBNULL\fR
-and
-\fBNULL\fR\&. Similarly, to write a value, pass a pointer to the value via
-\fInewp\fR, and its length via
-\fInewlen\fR; otherwise pass
-\fBNULL\fR
-and
-\fB0\fR\&.
-.PP
-The
-\fBmallctlnametomib\fR\fB\fR
-function provides a way to avoid repeated name lookups for applications that repeatedly query the same portion of the namespace, by translating a name to a \(lqManagement Information Base\(rq (MIB) that can be passed repeatedly to
-\fBmallctlbymib\fR\fB\fR\&. Upon successful return from
-\fBmallctlnametomib\fR\fB\fR,
-\fImibp\fR
-contains an array of
-\fI*miblenp\fR
-integers, where
-\fI*miblenp\fR
-is the lesser of the number of components in
-\fIname\fR
-and the input value of
-\fI*miblenp\fR\&. Thus it is possible to pass a
-\fI*miblenp\fR
-that is smaller than the number of period\-separated name components, which results in a partial MIB that can be used as the basis for constructing a complete MIB\&. For name components that are integers (e\&.g\&. the 2 in
-"arenas\&.bin\&.2\&.size"), the corresponding MIB component will always be that integer\&. Therefore, it is legitimate to construct code like the following:
-.sp
-.if n \{\
-.RS 4
-.\}
-.nf
-unsigned nbins, i;
-
-int mib[4];
-size_t len, miblen;
-
-len = sizeof(nbins);
-mallctl("arenas\&.nbins", &nbins, &len, NULL, 0);
-
-miblen = 4;
-mallnametomib("arenas\&.bin\&.0\&.size", mib, &miblen);
-for (i = 0; i < nbins; i++) {
- size_t bin_size;
-
- mib[2] = i;
- len = sizeof(bin_size);
- mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);
- /* Do something with bin_size\&.\&.\&. */
-}
-.fi
-.if n \{\
-.RE
-.\}
-.SS "Experimental API"
-.PP
-The experimental API is subject to change or removal without regard for backward compatibility\&. If
-\fB\-\-disable\-experimental\fR
-is specified during configuration, the experimental API is omitted\&.
-.PP
-The
-\fBallocm\fR\fB\fR,
-\fBrallocm\fR\fB\fR,
-\fBsallocm\fR\fB\fR,
-\fBdallocm\fR\fB\fR, and
-\fBnallocm\fR\fB\fR
-functions all have a
-\fIflags\fR
-argument that can be used to specify options\&. The functions only check the options that are contextually relevant\&. Use bitwise or (|) operations to specify one or more of the following:
-.PP
-\fBALLOCM_LG_ALIGN(\fR\fB\fIla\fR\fR\fB) \fR
-.RS 4
-Align the memory allocation to start at an address that is a multiple of
-(1 << \fIla\fR)\&. This macro does not validate that
-\fIla\fR
-is within the valid range\&.
-.RE
-.PP
-\fBALLOCM_ALIGN(\fR\fB\fIa\fR\fR\fB) \fR
-.RS 4
-Align the memory allocation to start at an address that is a multiple of
-\fIa\fR, where
-\fIa\fR
-is a power of two\&. This macro does not validate that
-\fIa\fR
-is a power of 2\&.
-.RE
-.PP
-\fBALLOCM_ZERO\fR
-.RS 4
-Initialize newly allocated memory to contain zero bytes\&. In the growing reallocation case, the real size prior to reallocation defines the boundary between untouched bytes and those that are initialized to contain zero bytes\&. If this option is absent, newly allocated memory is uninitialized\&.
-.RE
-.PP
-\fBALLOCM_NO_MOVE\fR
-.RS 4
-For reallocation, fail rather than moving the object\&. This constraint can apply to both growth and shrinkage\&.
-.RE
-.PP
-\fBALLOCM_ARENA(\fR\fB\fIa\fR\fR\fB) \fR
-.RS 4
-Use the arena specified by the index
-\fIa\fR\&. This macro does not validate that
-\fIa\fR
-specifies an arena in the valid range\&.
-.RE
-.PP
-The
-\fBallocm\fR\fB\fR
-function allocates at least
-\fIsize\fR
-bytes of memory, sets
-\fI*ptr\fR
-to the base address of the allocation, and sets
-\fI*rsize\fR
-to the real size of the allocation if
-\fIrsize\fR
-is not
-\fBNULL\fR\&. Behavior is undefined if
-\fIsize\fR
-is
-\fB0\fR\&.
-.PP
-The
-\fBrallocm\fR\fB\fR
-function resizes the allocation at
-\fI*ptr\fR
-to be at least
-\fIsize\fR
-bytes, sets
-\fI*ptr\fR
-to the base address of the allocation if it moved, and sets
-\fI*rsize\fR
-to the real size of the allocation if
-\fIrsize\fR
-is not
-\fBNULL\fR\&. If
-\fIextra\fR
-is non\-zero, an attempt is made to resize the allocation to be at least
-\fIsize\fR + \fIextra\fR)
-bytes, though inability to allocate the extra byte(s) will not by itself result in failure\&. Behavior is undefined if
-\fIsize\fR
-is
-\fB0\fR, or if
-(\fIsize\fR + \fIextra\fR > \fBSIZE_T_MAX\fR)\&.
-.PP
-The
-\fBsallocm\fR\fB\fR
-function sets
-\fI*rsize\fR
-to the real size of the allocation\&.
-.PP
-The
-\fBdallocm\fR\fB\fR
-function causes the memory referenced by
-\fIptr\fR
-to be made available for future allocations\&.
-.PP
-The
-\fBnallocm\fR\fB\fR
-function allocates no memory, but it performs the same size computation as the
-\fBallocm\fR\fB\fR
-function, and if
-\fIrsize\fR
-is not
-\fBNULL\fR
-it sets
-\fI*rsize\fR
-to the real size of the allocation that would result from the equivalent
-\fBallocm\fR\fB\fR
-function call\&. Behavior is undefined if
-\fIsize\fR
-is
-\fB0\fR\&.
-.SH "TUNING"
-.PP
-Once, when the first call is made to one of the memory allocation routines, the allocator initializes its internals based in part on various options that can be specified at compile\- or run\-time\&.
-.PP
-The string pointed to by the global variable
-\fImalloc_conf\fR, the \(lqname\(rq of the file referenced by the symbolic link named
-/etc/malloc\&.conf, and the value of the environment variable
-\fBMALLOC_CONF\fR, will be interpreted, in that order, from left to right as options\&.
-.PP
-An options string is a comma\-separated list of option:value pairs\&. There is one key corresponding to each
-"opt\&.*"
-mallctl (see the
-MALLCTL NAMESPACE
-section for options documentation)\&. For example,
-abort:true,narenas:1
-sets the
-"opt\&.abort"
-and
-"opt\&.narenas"
-options\&. Some options have boolean values (true/false), others have integer values (base 8, 10, or 16, depending on prefix), and yet others have raw string values\&.
-.SH "IMPLEMENTATION NOTES"
-.PP
-Traditionally, allocators have used
-\fBsbrk\fR(2)
-to obtain memory, which is suboptimal for several reasons, including race conditions, increased fragmentation, and artificial limitations on maximum usable memory\&. If
-\fB\-\-enable\-dss\fR
-is specified during configuration, this allocator uses both
-\fBmmap\fR(2)
-and
-\fBsbrk\fR(2), in that order of preference; otherwise only
-\fBmmap\fR(2)
-is used\&.
-.PP
-This allocator uses multiple arenas in order to reduce lock contention for threaded programs on multi\-processor systems\&. This works well with regard to threading scalability, but incurs some costs\&. There is a small fixed per\-arena overhead, and additionally, arenas manage memory completely independently of each other, which means a small fixed increase in overall memory fragmentation\&. These overheads are not generally an issue, given the number of arenas normally used\&. Note that using substantially more arenas than the default is not likely to improve performance, mainly due to reduced cache performance\&. However, it may make sense to reduce the number of arenas if an application does not make much use of the allocation functions\&.
-.PP
-In addition to multiple arenas, unless
-\fB\-\-disable\-tcache\fR
-is specified during configuration, this allocator supports thread\-specific caching for small and large objects, in order to make it possible to completely avoid synchronization for most allocation requests\&. Such caching allows very fast allocation in the common case, but it increases memory usage and fragmentation, since a bounded number of objects can remain allocated in each thread cache\&.
-.PP
-Memory is conceptually broken into equal\-sized chunks, where the chunk size is a power of two that is greater than the page size\&. Chunks are always aligned to multiples of the chunk size\&. This alignment makes it possible to find metadata for user objects very quickly\&.
-.PP
-User objects are broken into three categories according to size: small, large, and huge\&. Small objects are smaller than one page\&. Large objects are smaller than the chunk size\&. Huge objects are a multiple of the chunk size\&. Small and large objects are managed by arenas; huge objects are managed separately in a single data structure that is shared by all threads\&. Huge objects are used by applications infrequently enough that this single data structure is not a scalability issue\&.
-.PP
-Each chunk that is managed by an arena tracks its contents as runs of contiguous pages (unused, backing a set of small objects, or backing one large object)\&. The combination of chunk alignment and chunk page maps makes it possible to determine all metadata regarding small and large allocations in constant time\&.
-.PP
-Small objects are managed in groups by page runs\&. Each run maintains a frontier and free list to track which regions are in use\&. Allocation requests that are no more than half the quantum (8 or 16, depending on architecture) are rounded up to the nearest power of two that is at least
-sizeof(\fBdouble\fR)\&. All other small object size classes are multiples of the quantum, spaced such that internal fragmentation is limited to approximately 25% for all but the smallest size classes\&. Allocation requests that are larger than the maximum small size class, but small enough to fit in an arena\-managed chunk (see the
-"opt\&.lg_chunk"
-option), are rounded up to the nearest run size\&. Allocation requests that are too large to fit in an arena\-managed chunk are rounded up to the nearest multiple of the chunk size\&.
-.PP
-Allocations are packed tightly together, which can be an issue for multi\-threaded applications\&. If you need to assure that allocations do not suffer from cacheline sharing, round your allocation requests up to the nearest multiple of the cacheline size, or specify cacheline alignment when allocating\&.
-.PP
-Assuming 4 MiB chunks, 4 KiB pages, and a 16\-byte quantum on a 64\-bit system, the size classes in each category are as shown in
-Table 1\&.
-.sp
-.it 1 an-trap
-.nr an-no-space-flag 1
-.nr an-break-flag 1
-.br
-.B Table\ \&1.\ \&Size classes
-.TS
-allbox tab(:);
-lB rB lB.
-T{
-Category
-T}:T{
-Spacing
-T}:T{
-Size
-T}
-.T&
-l r l
-^ r l
-^ r l
-^ r l
-^ r l
-^ r l
-^ r l
-l r l
-l r l.
-T{
-Small
-T}:T{
-lg
-T}:T{
-[8]
-T}
-:T{
-16
-T}:T{
-[16, 32, 48, \&.\&.\&., 128]
-T}
-:T{
-32
-T}:T{
-[160, 192, 224, 256]
-T}
-:T{
-64
-T}:T{
-[320, 384, 448, 512]
-T}
-:T{
-128
-T}:T{
-[640, 768, 896, 1024]
-T}
-:T{
-256
-T}:T{
-[1280, 1536, 1792, 2048]
-T}
-:T{
-512
-T}:T{
-[2560, 3072, 3584]
-T}
-T{
-Large
-T}:T{
-4 KiB
-T}:T{
-[4 KiB, 8 KiB, 12 KiB, \&.\&.\&., 4072 KiB]
-T}
-T{
-Huge
-T}:T{
-4 MiB
-T}:T{
-[4 MiB, 8 MiB, 12 MiB, \&.\&.\&.]
-T}
-.TE
-.sp 1
-.SH "MALLCTL NAMESPACE"
-.PP
-The following names are defined in the namespace accessible via the
-\fBmallctl*\fR\fB\fR
-functions\&. Value types are specified in parentheses, their readable/writable statuses are encoded as
-rw,
-r\-,
-\-w, or
-\-\-, and required build configuration flags follow, if any\&. A name element encoded as
-<i>
-or
-<j>
-indicates an integer component, where the integer varies from 0 to some upper value that must be determined via introspection\&. In the case of
-"stats\&.arenas\&.<i>\&.*",
-<i>
-equal to
-"arenas\&.narenas"
-can be used to access the summation of statistics from all arenas\&. Take special note of the
-"epoch"
-mallctl, which controls refreshing of cached dynamic statistics\&.
-.PP
-"version" (\fBconst char *\fR) r\-
-.RS 4
-Return the jemalloc version string\&.
-.RE
-.PP
-"epoch" (\fBuint64_t\fR) rw
-.RS 4
-If a value is passed in, refresh the data from which the
-\fBmallctl*\fR\fB\fR
-functions report values, and increment the epoch\&. Return the current epoch\&. This is useful for detecting whether another thread caused a refresh\&.
-.RE
-.PP
-"config\&.debug" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-debug\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.dss" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-dss\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.fill" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-fill\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.lazy_lock" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-lazy\-lock\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.mremap" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-mremap\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.munmap" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-munmap\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.prof" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-prof\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.prof_libgcc" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-disable\-prof\-libgcc\fR
-was not specified during build configuration\&.
-.RE
-.PP
-"config\&.prof_libunwind" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-prof\-libunwind\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.stats" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-stats\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.tcache" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-disable\-tcache\fR
-was not specified during build configuration\&.
-.RE
-.PP
-"config\&.tls" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-disable\-tls\fR
-was not specified during build configuration\&.
-.RE
-.PP
-"config\&.utrace" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-utrace\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.valgrind" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-valgrind\fR
-was specified during build configuration\&.
-.RE
-.PP
-"config\&.xmalloc" (\fBbool\fR) r\-
-.RS 4
-\fB\-\-enable\-xmalloc\fR
-was specified during build configuration\&.
-.RE
-.PP
-"opt\&.abort" (\fBbool\fR) r\-
-.RS 4
-Abort\-on\-warning enabled/disabled\&. If true, most warnings are fatal\&. The process will call
-\fBabort\fR(3)
-in these cases\&. This option is disabled by default unless
-\fB\-\-enable\-debug\fR
-is specified during configuration, in which case it is enabled by default\&.
-.RE
-.PP
-"opt\&.lg_chunk" (\fBsize_t\fR) r\-
-.RS 4
-Virtual memory chunk size (log base 2)\&. If a chunk size outside the supported size range is specified, the size is silently clipped to the minimum/maximum supported size\&. The default chunk size is 4 MiB (2^22)\&.
-.RE
-.PP
-"opt\&.dss" (\fBconst char *\fR) r\-
-.RS 4
-dss (\fBsbrk\fR(2)) allocation precedence as related to
-\fBmmap\fR(2)
-allocation\&. The following settings are supported: \(lqdisabled\(rq, \(lqprimary\(rq, and \(lqsecondary\(rq (default)\&.
-.RE
-.PP
-"opt\&.narenas" (\fBsize_t\fR) r\-
-.RS 4
-Maximum number of arenas to use for automatic multiplexing of threads and arenas\&. The default is four times the number of CPUs, or one if there is a single CPU\&.
-.RE
-.PP
-"opt\&.lg_dirty_mult" (\fBssize_t\fR) r\-
-.RS 4
-Per\-arena minimum ratio (log base 2) of active to dirty pages\&. Some dirty unused pages may be allowed to accumulate, within the limit set by the ratio (or one chunk worth of dirty pages, whichever is greater), before informing the kernel about some of those pages via
-\fBmadvise\fR(2)
-or a similar system call\&. This provides the kernel with sufficient information to recycle dirty pages if physical memory becomes scarce and the pages remain unused\&. The default minimum ratio is 8:1 (2^3:1); an option value of \-1 will disable dirty page purging\&.
-.RE
-.PP
-"opt\&.stats_print" (\fBbool\fR) r\-
-.RS 4
-Enable/disable statistics printing at exit\&. If enabled, the
-\fBmalloc_stats_print\fR\fB\fR
-function is called at program exit via an
-\fBatexit\fR(3)
-function\&. If
-\fB\-\-enable\-stats\fR
-is specified during configuration, this has the potential to cause deadlock for a multi\-threaded process that exits while one or more threads are executing in the memory allocation functions\&. Therefore, this option should only be used with care; it is primarily intended as a performance tuning aid during application development\&. This option is disabled by default\&.
-.RE
-.PP
-"opt\&.junk" (\fBbool\fR) r\- [\fB\-\-enable\-fill\fR]
-.RS 4
-Junk filling enabled/disabled\&. If enabled, each byte of uninitialized allocated memory will be initialized to
-0xa5\&. All deallocated memory will be initialized to
-0x5a\&. This is intended for debugging and will impact performance negatively\&. This option is disabled by default unless
-\fB\-\-enable\-debug\fR
-is specified during configuration, in which case it is enabled by default unless running inside
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2\&.
-.RE
-.PP
-"opt\&.quarantine" (\fBsize_t\fR) r\- [\fB\-\-enable\-fill\fR]
-.RS 4
-Per thread quarantine size in bytes\&. If non\-zero, each thread maintains a FIFO object quarantine that stores up to the specified number of bytes of memory\&. The quarantined memory is not freed until it is released from quarantine, though it is immediately junk\-filled if the
-"opt\&.junk"
-option is enabled\&. This feature is of particular use in combination with
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2, which can detect attempts to access quarantined objects\&. This is intended for debugging and will impact performance negatively\&. The default quarantine size is 0 unless running inside Valgrind, in which case the default is 16 MiB\&.
-.RE
-.PP
-"opt\&.redzone" (\fBbool\fR) r\- [\fB\-\-enable\-fill\fR]
-.RS 4
-Redzones enabled/disabled\&. If enabled, small allocations have redzones before and after them\&. Furthermore, if the
-"opt\&.junk"
-option is enabled, the redzones are checked for corruption during deallocation\&. However, the primary intended purpose of this feature is to be used in combination with
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2, which needs redzones in order to do effective buffer overflow/underflow detection\&. This option is intended for debugging and will impact performance negatively\&. This option is disabled by default unless running inside Valgrind\&.
-.RE
-.PP
-"opt\&.zero" (\fBbool\fR) r\- [\fB\-\-enable\-fill\fR]
-.RS 4
-Zero filling enabled/disabled\&. If enabled, each byte of uninitialized allocated memory will be initialized to 0\&. Note that this initialization only happens once for each byte, so
-\fBrealloc\fR\fB\fR
-and
-\fBrallocm\fR\fB\fR
-calls do not zero memory that was previously allocated\&. This is intended for debugging and will impact performance negatively\&. This option is disabled by default\&.
-.RE
-.PP
-"opt\&.utrace" (\fBbool\fR) r\- [\fB\-\-enable\-utrace\fR]
-.RS 4
-Allocation tracing based on
-\fButrace\fR(2)
-enabled/disabled\&. This option is disabled by default\&.
-.RE
-.PP
-"opt\&.valgrind" (\fBbool\fR) r\- [\fB\-\-enable\-valgrind\fR]
-.RS 4
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2
-support enabled/disabled\&. This option is vestigal because jemalloc auto\-detects whether it is running inside Valgrind\&. This option is disabled by default, unless running inside Valgrind\&.
-.RE
-.PP
-"opt\&.xmalloc" (\fBbool\fR) r\- [\fB\-\-enable\-xmalloc\fR]
-.RS 4
-Abort\-on\-out\-of\-memory enabled/disabled\&. If enabled, rather than returning failure for any allocation function, display a diagnostic message on
-\fBSTDERR_FILENO\fR
-and cause the program to drop core (using
-\fBabort\fR(3))\&. If an application is designed to depend on this behavior, set the option at compile time by including the following in the source code:
-.sp
-.if n \{\
-.RS 4
-.\}
-.nf
-malloc_conf = "xmalloc:true";
-.fi
-.if n \{\
-.RE
-.\}
-.sp
-This option is disabled by default\&.
-.RE
-.PP
-"opt\&.tcache" (\fBbool\fR) r\- [\fB\-\-enable\-tcache\fR]
-.RS 4
-Thread\-specific caching enabled/disabled\&. When there are multiple threads, each thread uses a thread\-specific cache for objects up to a certain size\&. Thread\-specific caching allows many allocations to be satisfied without performing any thread synchronization, at the cost of increased memory use\&. See the
-"opt\&.lg_tcache_max"
-option for related tuning information\&. This option is enabled by default unless running inside
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2\&.
-.RE
-.PP
-"opt\&.lg_tcache_max" (\fBsize_t\fR) r\- [\fB\-\-enable\-tcache\fR]
-.RS 4
-Maximum size class (log base 2) to cache in the thread\-specific cache\&. At a minimum, all small size classes are cached, and at a maximum all large size classes are cached\&. The default maximum is 32 KiB (2^15)\&.
-.RE
-.PP
-"opt\&.prof" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Memory profiling enabled/disabled\&. If enabled, profile memory allocation activity\&. See the
-"opt\&.prof_active"
-option for on\-the\-fly activation/deactivation\&. See the
-"opt\&.lg_prof_sample"
-option for probabilistic sampling control\&. See the
-"opt\&.prof_accum"
-option for control of cumulative sample reporting\&. See the
-"opt\&.lg_prof_interval"
-option for information on interval\-triggered profile dumping, the
-"opt\&.prof_gdump"
-option for information on high\-water\-triggered profile dumping, and the
-"opt\&.prof_final"
-option for final profile dumping\&. Profile output is compatible with the included
-\fBpprof\fR
-Perl script, which originates from the
-\m[blue]\fBgperftools package\fR\m[]\&\s-2\u[3]\d\s+2\&.
-.RE
-.PP
-"opt\&.prof_prefix" (\fBconst char *\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Filename prefix for profile dumps\&. If the prefix is set to the empty string, no automatic dumps will occur; this is primarily useful for disabling the automatic final heap dump (which also disables leak reporting, if enabled)\&. The default prefix is
-jeprof\&.
-.RE
-.PP
-"opt\&.prof_active" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Profiling activated/deactivated\&. This is a secondary control mechanism that makes it possible to start the application with profiling enabled (see the
-"opt\&.prof"
-option) but inactive, then toggle profiling at any time during program execution with the
-"prof\&.active"
-mallctl\&. This option is enabled by default\&.
-.RE
-.PP
-"opt\&.lg_prof_sample" (\fBssize_t\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Average interval (log base 2) between allocation samples, as measured in bytes of allocation activity\&. Increasing the sampling interval decreases profile fidelity, but also decreases the computational overhead\&. The default sample interval is 512 KiB (2^19 B)\&.
-.RE
-.PP
-"opt\&.prof_accum" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Reporting of cumulative object/byte counts in profile dumps enabled/disabled\&. If this option is enabled, every unique backtrace must be stored for the duration of execution\&. Depending on the application, this can impose a large memory overhead, and the cumulative counts are not always of interest\&. This option is disabled by default\&.
-.RE
-.PP
-"opt\&.lg_prof_interval" (\fBssize_t\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Average interval (log base 2) between memory profile dumps, as measured in bytes of allocation activity\&. The actual interval between dumps may be sporadic because decentralized allocation counters are used to avoid synchronization bottlenecks\&. Profiles are dumped to files named according to the pattern
-<prefix>\&.<pid>\&.<seq>\&.i<iseq>\&.heap, where
-<prefix>
-is controlled by the
-"opt\&.prof_prefix"
-option\&. By default, interval\-triggered profile dumping is disabled (encoded as \-1)\&.
-.RE
-.PP
-"opt\&.prof_gdump" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Trigger a memory profile dump every time the total virtual memory exceeds the previous maximum\&. Profiles are dumped to files named according to the pattern
-<prefix>\&.<pid>\&.<seq>\&.u<useq>\&.heap, where
-<prefix>
-is controlled by the
-"opt\&.prof_prefix"
-option\&. This option is disabled by default\&.
-.RE
-.PP
-"opt\&.prof_final" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Use an
-\fBatexit\fR(3)
-function to dump final memory usage to a file named according to the pattern
-<prefix>\&.<pid>\&.<seq>\&.f\&.heap, where
-<prefix>
-is controlled by the
-"opt\&.prof_prefix"
-option\&. This option is enabled by default\&.
-.RE
-.PP
-"opt\&.prof_leak" (\fBbool\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Leak reporting enabled/disabled\&. If enabled, use an
-\fBatexit\fR(3)
-function to report memory leaks detected by allocation sampling\&. See the
-"opt\&.prof"
-option for information on analyzing heap profile output\&. This option is disabled by default\&.
-.RE
-.PP
-"thread\&.arena" (\fBunsigned\fR) rw
-.RS 4
-Get or set the arena associated with the calling thread\&. If the specified arena was not initialized beforehand (see the
-"arenas\&.initialized"
-mallctl), it will be automatically initialized as a side effect of calling this interface\&.
-.RE
-.PP
-"thread\&.allocated" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Get the total number of bytes ever allocated by the calling thread\&. This counter has the potential to wrap around; it is up to the application to appropriately interpret the counter in such cases\&.
-.RE
-.PP
-"thread\&.allocatedp" (\fBuint64_t *\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Get a pointer to the the value that is returned by the
-"thread\&.allocated"
-mallctl\&. This is useful for avoiding the overhead of repeated
-\fBmallctl*\fR\fB\fR
-calls\&.
-.RE
-.PP
-"thread\&.deallocated" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Get the total number of bytes ever deallocated by the calling thread\&. This counter has the potential to wrap around; it is up to the application to appropriately interpret the counter in such cases\&.
-.RE
-.PP
-"thread\&.deallocatedp" (\fBuint64_t *\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Get a pointer to the the value that is returned by the
-"thread\&.deallocated"
-mallctl\&. This is useful for avoiding the overhead of repeated
-\fBmallctl*\fR\fB\fR
-calls\&.
-.RE
-.PP
-"thread\&.tcache\&.enabled" (\fBbool\fR) rw [\fB\-\-enable\-tcache\fR]
-.RS 4
-Enable/disable calling thread\*(Aqs tcache\&. The tcache is implicitly flushed as a side effect of becoming disabled (see
-"thread\&.tcache\&.flush")\&.
-.RE
-.PP
-"thread\&.tcache\&.flush" (\fBvoid\fR) \-\- [\fB\-\-enable\-tcache\fR]
-.RS 4
-Flush calling thread\*(Aqs tcache\&. This interface releases all cached objects and internal data structures associated with the calling thread\*(Aqs thread\-specific cache\&. Ordinarily, this interface need not be called, since automatic periodic incremental garbage collection occurs, and the thread cache is automatically discarded when a thread exits\&. However, garbage collection is triggered by allocation activity, so it is possible for a thread that stops allocating/deallocating to retain its cache indefinitely, in which case the developer may find manual flushing useful\&.
-.RE
-.PP
-"arena\&.<i>\&.purge" (\fBunsigned\fR) \-\-
-.RS 4
-Purge unused dirty pages for arena <i>, or for all arenas if <i> equals
-"arenas\&.narenas"\&.
-.RE
-.PP
-"arena\&.<i>\&.dss" (\fBconst char *\fR) rw
-.RS 4
-Set the precedence of dss allocation as related to mmap allocation for arena <i>, or for all arenas if <i> equals
-"arenas\&.narenas"\&. See
-"opt\&.dss"
-for supported settings\&.
-.RE
-.PP
-"arenas\&.narenas" (\fBunsigned\fR) r\-
-.RS 4
-Current limit on number of arenas\&.
-.RE
-.PP
-"arenas\&.initialized" (\fBbool *\fR) r\-
-.RS 4
-An array of
-"arenas\&.narenas"
-booleans\&. Each boolean indicates whether the corresponding arena is initialized\&.
-.RE
-.PP
-"arenas\&.quantum" (\fBsize_t\fR) r\-
-.RS 4
-Quantum size\&.
-.RE
-.PP
-"arenas\&.page" (\fBsize_t\fR) r\-
-.RS 4
-Page size\&.
-.RE
-.PP
-"arenas\&.tcache_max" (\fBsize_t\fR) r\- [\fB\-\-enable\-tcache\fR]
-.RS 4
-Maximum thread\-cached size class\&.
-.RE
-.PP
-"arenas\&.nbins" (\fBunsigned\fR) r\-
-.RS 4
-Number of bin size classes\&.
-.RE
-.PP
-"arenas\&.nhbins" (\fBunsigned\fR) r\- [\fB\-\-enable\-tcache\fR]
-.RS 4
-Total number of thread cache bin size classes\&.
-.RE
-.PP
-"arenas\&.bin\&.<i>\&.size" (\fBsize_t\fR) r\-
-.RS 4
-Maximum size supported by size class\&.
-.RE
-.PP
-"arenas\&.bin\&.<i>\&.nregs" (\fBuint32_t\fR) r\-
-.RS 4
-Number of regions per page run\&.
-.RE
-.PP
-"arenas\&.bin\&.<i>\&.run_size" (\fBsize_t\fR) r\-
-.RS 4
-Number of bytes per page run\&.
-.RE
-.PP
-"arenas\&.nlruns" (\fBsize_t\fR) r\-
-.RS 4
-Total number of large size classes\&.
-.RE
-.PP
-"arenas\&.lrun\&.<i>\&.size" (\fBsize_t\fR) r\-
-.RS 4
-Maximum size supported by this large size class\&.
-.RE
-.PP
-"arenas\&.purge" (\fBunsigned\fR) \-w
-.RS 4
-Purge unused dirty pages for the specified arena, or for all arenas if none is specified\&.
-.RE
-.PP
-"arenas\&.extend" (\fBunsigned\fR) r\-
-.RS 4
-Extend the array of arenas by appending a new arena, and returning the new arena index\&.
-.RE
-.PP
-"prof\&.active" (\fBbool\fR) rw [\fB\-\-enable\-prof\fR]
-.RS 4
-Control whether sampling is currently active\&. See the
-"opt\&.prof_active"
-option for additional information\&.
-.RE
-.PP
-"prof\&.dump" (\fBconst char *\fR) \-w [\fB\-\-enable\-prof\fR]
-.RS 4
-Dump a memory profile to the specified file, or if NULL is specified, to a file according to the pattern
-<prefix>\&.<pid>\&.<seq>\&.m<mseq>\&.heap, where
-<prefix>
-is controlled by the
-"opt\&.prof_prefix"
-option\&.
-.RE
-.PP
-"prof\&.interval" (\fBuint64_t\fR) r\- [\fB\-\-enable\-prof\fR]
-.RS 4
-Average number of bytes allocated between inverval\-based profile dumps\&. See the
-"opt\&.lg_prof_interval"
-option for additional information\&.
-.RE
-.PP
-"stats\&.cactive" (\fBsize_t *\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Pointer to a counter that contains an approximate count of the current number of bytes in active pages\&. The estimate may be high, but never low, because each arena rounds up to the nearest multiple of the chunk size when computing its contribution to the counter\&. Note that the
-"epoch"
-mallctl has no bearing on this counter\&. Furthermore, counter consistency is maintained via atomic operations, so it is necessary to use an atomic operation in order to guarantee a consistent read when dereferencing the pointer\&.
-.RE
-.PP
-"stats\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Total number of bytes allocated by the application\&.
-.RE
-.PP
-"stats\&.active" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Total number of bytes in active pages allocated by the application\&. This is a multiple of the page size, and greater than or equal to
-"stats\&.allocated"\&. This does not include
-"stats\&.arenas\&.<i>\&.pdirty"
-and pages entirely devoted to allocator metadata\&.
-.RE
-.PP
-"stats\&.mapped" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Total number of bytes in chunks mapped on behalf of the application\&. This is a multiple of the chunk size, and is at least as large as
-"stats\&.active"\&. This does not include inactive chunks\&.
-.RE
-.PP
-"stats\&.chunks\&.current" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Total number of chunks actively mapped on behalf of the application\&. This does not include inactive chunks\&.
-.RE
-.PP
-"stats\&.chunks\&.total" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of chunks allocated\&.
-.RE
-.PP
-"stats\&.chunks\&.high" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Maximum number of active chunks at any time thus far\&.
-.RE
-.PP
-"stats\&.huge\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Number of bytes currently allocated by huge objects\&.
-.RE
-.PP
-"stats\&.huge\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of huge allocation requests\&.
-.RE
-.PP
-"stats\&.huge\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of huge deallocation requests\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.dss" (\fBconst char *\fR) r\-
-.RS 4
-dss (\fBsbrk\fR(2)) allocation precedence as related to
-\fBmmap\fR(2)
-allocation\&. See
-"opt\&.dss"
-for details\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.nthreads" (\fBunsigned\fR) r\-
-.RS 4
-Number of threads currently assigned to arena\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.pactive" (\fBsize_t\fR) r\-
-.RS 4
-Number of pages in active runs\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.pdirty" (\fBsize_t\fR) r\-
-.RS 4
-Number of pages within unused runs that are potentially dirty, and for which
-\fBmadvise\fR\fB\fI\&.\&.\&.\fR\fR\fB \fR\fB\fI\fBMADV_DONTNEED\fR\fR\fR
-or similar has not been called\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.mapped" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Number of mapped bytes\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.npurge" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Number of dirty page purge sweeps performed\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.nmadvise" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Number of
-\fBmadvise\fR\fB\fI\&.\&.\&.\fR\fR\fB \fR\fB\fI\fBMADV_DONTNEED\fR\fR\fR
-or similar calls made to purge dirty pages\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.npurged" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Number of pages purged\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.small\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Number of bytes currently allocated by small objects\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.small\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of allocation requests served by small bins\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.small\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of small objects returned to bins\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.small\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of small allocation requests\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.large\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Number of bytes currently allocated by large objects\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.large\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of large allocation requests served directly by the arena\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.large\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of large deallocation requests served directly by the arena\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.large\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of large allocation requests\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.allocated" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Current number of bytes allocated by bin\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of allocations served by bin\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of allocations returned to bin\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of allocation requests\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.nfills" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR \fB\-\-enable\-tcache\fR]
-.RS 4
-Cumulative number of tcache fills\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.nflushes" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR \fB\-\-enable\-tcache\fR]
-.RS 4
-Cumulative number of tcache flushes\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.nruns" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of runs created\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.nreruns" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of times the current run from which to allocate changed\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.bins\&.<j>\&.curruns" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Current number of runs\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.lruns\&.<j>\&.nmalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of allocation requests for this size class served directly by the arena\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.lruns\&.<j>\&.ndalloc" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of deallocation requests for this size class served directly by the arena\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.lruns\&.<j>\&.nrequests" (\fBuint64_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Cumulative number of allocation requests for this size class\&.
-.RE
-.PP
-"stats\&.arenas\&.<i>\&.lruns\&.<j>\&.curruns" (\fBsize_t\fR) r\- [\fB\-\-enable\-stats\fR]
-.RS 4
-Current number of runs for this size class\&.
-.RE
-.SH "DEBUGGING MALLOC PROBLEMS"
-.PP
-When debugging, it is a good idea to configure/build jemalloc with the
-\fB\-\-enable\-debug\fR
-and
-\fB\-\-enable\-fill\fR
-options, and recompile the program with suitable options and symbols for debugger support\&. When so configured, jemalloc incorporates a wide variety of run\-time assertions that catch application errors such as double\-free, write\-after\-free, etc\&.
-.PP
-Programs often accidentally depend on \(lquninitialized\(rq memory actually being filled with zero bytes\&. Junk filling (see the
-"opt\&.junk"
-option) tends to expose such bugs in the form of obviously incorrect results and/or coredumps\&. Conversely, zero filling (see the
-"opt\&.zero"
-option) eliminates the symptoms of such bugs\&. Between these two options, it is usually possible to quickly detect, diagnose, and eliminate such bugs\&.
-.PP
-This implementation does not provide much detail about the problems it detects, because the performance impact for storing such information would be prohibitive\&. However, jemalloc does integrate with the most excellent
-\m[blue]\fBValgrind\fR\m[]\&\s-2\u[2]\d\s+2
-tool if the
-\fB\-\-enable\-valgrind\fR
-configuration option is enabled\&.
-.SH "DIAGNOSTIC MESSAGES"
-.PP
-If any of the memory allocation/deallocation functions detect an error or warning condition, a message will be printed to file descriptor
-\fBSTDERR_FILENO\fR\&. Errors will result in the process dumping core\&. If the
-"opt\&.abort"
-option is set, most warnings are treated as errors\&.
-.PP
-The
-\fImalloc_message\fR
-variable allows the programmer to override the function which emits the text strings forming the errors and warnings if for some reason the
-\fBSTDERR_FILENO\fR
-file descriptor is not suitable for this\&.
-\fBmalloc_message\fR\fB\fR
-takes the
-\fIcbopaque\fR
-pointer argument that is
-\fBNULL\fR
-unless overridden by the arguments in a call to
-\fBmalloc_stats_print\fR\fB\fR, followed by a string pointer\&. Please note that doing anything which tries to allocate memory in this function is likely to result in a crash or deadlock\&.
-.PP
-All messages are prefixed by \(lq<jemalloc>:\(rq\&.
-.SH "RETURN VALUES"
-.SS "Standard API"
-.PP
-The
-\fBmalloc\fR\fB\fR
-and
-\fBcalloc\fR\fB\fR
-functions return a pointer to the allocated memory if successful; otherwise a
-\fBNULL\fR
-pointer is returned and
-\fIerrno\fR
-is set to
-ENOMEM\&.
-.PP
-The
-\fBposix_memalign\fR\fB\fR
-function returns the value 0 if successful; otherwise it returns an error value\&. The
-\fBposix_memalign\fR\fB\fR
-function will fail if:
-.PP
-EINVAL
-.RS 4
-The
-\fIalignment\fR
-parameter is not a power of 2 at least as large as
-sizeof(\fBvoid *\fR)\&.
-.RE
-.PP
-ENOMEM
-.RS 4
-Memory allocation error\&.
-.RE
-.PP
-The
-\fBaligned_alloc\fR\fB\fR
-function returns a pointer to the allocated memory if successful; otherwise a
-\fBNULL\fR
-pointer is returned and
-\fIerrno\fR
-is set\&. The
-\fBaligned_alloc\fR\fB\fR
-function will fail if:
-.PP
-EINVAL
-.RS 4
-The
-\fIalignment\fR
-parameter is not a power of 2\&.
-.RE
-.PP
-ENOMEM
-.RS 4
-Memory allocation error\&.
-.RE
-.PP
-The
-\fBrealloc\fR\fB\fR
-function returns a pointer, possibly identical to
-\fIptr\fR, to the allocated memory if successful; otherwise a
-\fBNULL\fR
-pointer is returned, and
-\fIerrno\fR
-is set to
-ENOMEM
-if the error was the result of an allocation failure\&. The
-\fBrealloc\fR\fB\fR
-function always leaves the original buffer intact when an error occurs\&.
-.PP
-The
-\fBfree\fR\fB\fR
-function returns no value\&.
-.SS "Non\-standard API"
-.PP
-The
-\fBmalloc_usable_size\fR\fB\fR
-function returns the usable size of the allocation pointed to by
-\fIptr\fR\&.
-.PP
-The
-\fBmallctl\fR\fB\fR,
-\fBmallctlnametomib\fR\fB\fR, and
-\fBmallctlbymib\fR\fB\fR
-functions return 0 on success; otherwise they return an error value\&. The functions will fail if:
-.PP
-EINVAL
-.RS 4
-\fInewp\fR
-is not
-\fBNULL\fR, and
-\fInewlen\fR
-is too large or too small\&. Alternatively,
-\fI*oldlenp\fR
-is too large or too small; in this case as much data as possible are read despite the error\&.
-.RE
-.PP
-ENOMEM
-.RS 4
-\fI*oldlenp\fR
-is too short to hold the requested value\&.
-.RE
-.PP
-ENOENT
-.RS 4
-\fIname\fR
-or
-\fImib\fR
-specifies an unknown/invalid value\&.
-.RE
-.PP
-EPERM
-.RS 4
-Attempt to read or write void value, or attempt to write read\-only value\&.
-.RE
-.PP
-EAGAIN
-.RS 4
-A memory allocation failure occurred\&.
-.RE
-.PP
-EFAULT
-.RS 4
-An interface with side effects failed in some way not directly related to
-\fBmallctl*\fR\fB\fR
-read/write processing\&.
-.RE
-.SS "Experimental API"
-.PP
-The
-\fBallocm\fR\fB\fR,
-\fBrallocm\fR\fB\fR,
-\fBsallocm\fR\fB\fR,
-\fBdallocm\fR\fB\fR, and
-\fBnallocm\fR\fB\fR
-functions return
-\fBALLOCM_SUCCESS\fR
-on success; otherwise they return an error value\&. The
-\fBallocm\fR\fB\fR,
-\fBrallocm\fR\fB\fR, and
-\fBnallocm\fR\fB\fR
-functions will fail if:
-.PP
-ALLOCM_ERR_OOM
-.RS 4
-Out of memory\&. Insufficient contiguous memory was available to service the allocation request\&. The
-\fBallocm\fR\fB\fR
-function additionally sets
-\fI*ptr\fR
-to
-\fBNULL\fR, whereas the
-\fBrallocm\fR\fB\fR
-function leaves
-\fB*ptr\fR
-unmodified\&.
-.RE
-The
-\fBrallocm\fR\fB\fR
-function will also fail if:
-.PP
-ALLOCM_ERR_NOT_MOVED
-.RS 4
-\fBALLOCM_NO_MOVE\fR
-was specified, but the reallocation request could not be serviced without moving the object\&.
-.RE
-.SH "ENVIRONMENT"
-.PP
-The following environment variable affects the execution of the allocation functions:
-.PP
-\fBMALLOC_CONF\fR
-.RS 4
-If the environment variable
-\fBMALLOC_CONF\fR
-is set, the characters it contains will be interpreted as options\&.
-.RE
-.SH "EXAMPLES"
-.PP
-To dump core whenever a problem occurs:
-.sp
-.if n \{\
-.RS 4
-.\}
-.nf
-ln \-s \*(Aqabort:true\*(Aq /etc/malloc\&.conf
-.fi
-.if n \{\
-.RE
-.\}
-.PP
-To specify in the source a chunk size that is 16 MiB:
-.sp
-.if n \{\
-.RS 4
-.\}
-.nf
-malloc_conf = "lg_chunk:24";
-.fi
-.if n \{\
-.RE
-.\}
-.SH "SEE ALSO"
-.PP
-\fBmadvise\fR(2),
-\fBmmap\fR(2),
-\fBsbrk\fR(2),
-\fButrace\fR(2),
-\fBalloca\fR(3),
-\fBatexit\fR(3),
-\fBgetpagesize\fR(3)
-.SH "STANDARDS"
-.PP
-The
-\fBmalloc\fR\fB\fR,
-\fBcalloc\fR\fB\fR,
-\fBrealloc\fR\fB\fR, and
-\fBfree\fR\fB\fR
-functions conform to ISO/IEC 9899:1990 (\(lqISO C90\(rq)\&.
-.PP
-The
-\fBposix_memalign\fR\fB\fR
-function conforms to IEEE Std 1003\&.1\-2001 (\(lqPOSIX\&.1\(rq)\&.
-.SH "AUTHOR"
-.PP
-\fBJason Evans\fR
-.RS 4
-.RE
-.SH "NOTES"
-.IP " 1." 4
-jemalloc website
-.RS 4
-\%http://www.canonware.com/jemalloc/
-.RE
-.IP " 2." 4
-Valgrind
-.RS 4
-\%http://valgrind.org/
-.RE
-.IP " 3." 4
-gperftools package
-.RS 4
-\%http://code.google.com/p/gperftools/
-.RE
diff --git a/extra/jemalloc/doc/jemalloc.html b/extra/jemalloc/doc/jemalloc.html
deleted file mode 100644
index 3e0fe26d1bd..00000000000
--- a/extra/jemalloc/doc/jemalloc.html
+++ /dev/null
@@ -1,1417 +0,0 @@
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>JEMALLOC</title><meta name="generator" content="DocBook XSL Stylesheets V1.76.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" title="JEMALLOC"><a name="id286949159"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>jemalloc &#8212; general purpose memory allocation functions</p></div><div class="refsect1" title="LIBRARY"><a name="library"></a><h2>LIBRARY</h2><p>This manual describes jemalloc 3.3.1-0-g9ef9d9e8c271cdf14f664b871a8f98c827714784. More information
- can be found at the <a class="ulink" href="http://www.canonware.com/jemalloc/" target="_top">jemalloc website</a>.</p></div><div class="refsynopsisdiv" title="SYNOPSIS"><h2>SYNOPSIS</h2><div class="funcsynopsis"><pre class="funcsynopsisinfo">#include &lt;<code class="filename">stdlib.h</code>&gt;
-#include &lt;<code class="filename">jemalloc/jemalloc.h</code>&gt;</pre><div class="refsect2" title="Standard API"><a name="id286901505"></a><h3>Standard API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">malloc</b>(</code></td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">calloc</b>(</code></td><td>size_t <var class="pdparam">number</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">posix_memalign</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">alignment</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">aligned_alloc</b>(</code></td><td>size_t <var class="pdparam">alignment</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">realloc</b>(</code></td><td>void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">free</b>(</code></td><td>void *<var class="pdparam">ptr</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div></div><div class="refsect2" title="Non-standard API"><a name="id286900549"></a><h3>Non-standard API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">size_t <b class="fsfunc">malloc_usable_size</b>(</code></td><td>const void *<var class="pdparam">ptr</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">malloc_stats_print</b>(</code></td><td>void <var class="pdparam">(*write_cb)</var>
- <code>(</code>void *, const char *<code>)</code>
- , </td></tr><tr><td> </td><td>void *<var class="pdparam">cbopaque</var>, </td></tr><tr><td> </td><td>const char *<var class="pdparam">opts</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctl</b>(</code></td><td>const char *<var class="pdparam">name</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">oldp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">oldlenp</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">newp</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">newlen</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctlnametomib</b>(</code></td><td>const char *<var class="pdparam">name</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">mibp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">miblenp</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctlbymib</b>(</code></td><td>const size_t *<var class="pdparam">mib</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">miblen</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">oldp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">oldlenp</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">newp</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">newlen</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">(*malloc_message)</b>(</code></td><td>void *<var class="pdparam">cbopaque</var>, </td></tr><tr><td> </td><td>const char *<var class="pdparam">s</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><p><span class="type">const char *</span><code class="varname">malloc_conf</code>;</p></div><div class="refsect2" title="Experimental API"><a name="id286900756"></a><h3>Experimental API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">allocm</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">rallocm</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">extra</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">sallocm</b>(</code></td><td>const void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">dallocm</b>(</code></td><td>void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">nallocm</b>(</code></td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div></div></div></div><div class="refsect1" title="DESCRIPTION"><a name="description"></a><h2>DESCRIPTION</h2><div class="refsect2" title="Standard API"><a name="id286949297"></a><h3>Standard API</h3><p>The <code class="function">malloc</code>(<em class="parameter"><code></code></em>) function allocates
- <em class="parameter"><code>size</code></em> bytes of uninitialized memory. The allocated
- space is suitably aligned (after possible pointer coercion) for storage
- of any type of object.</p><p>The <code class="function">calloc</code>(<em class="parameter"><code></code></em>) function allocates
- space for <em class="parameter"><code>number</code></em> objects, each
- <em class="parameter"><code>size</code></em> bytes in length. The result is identical to
- calling <code class="function">malloc</code>(<em class="parameter"><code></code></em>) with an argument of
- <em class="parameter"><code>number</code></em> * <em class="parameter"><code>size</code></em>, with the
- exception that the allocated memory is explicitly initialized to zero
- bytes.</p><p>The <code class="function">posix_memalign</code>(<em class="parameter"><code></code></em>) function
- allocates <em class="parameter"><code>size</code></em> bytes of memory such that the
- allocation's base address is an even multiple of
- <em class="parameter"><code>alignment</code></em>, and returns the allocation in the value
- pointed to by <em class="parameter"><code>ptr</code></em>. The requested
- <em class="parameter"><code>alignment</code></em> must be a power of 2 at least as large
- as <code class="code">sizeof(<span class="type">void *</span>)</code>.</p><p>The <code class="function">aligned_alloc</code>(<em class="parameter"><code></code></em>) function
- allocates <em class="parameter"><code>size</code></em> bytes of memory such that the
- allocation's base address is an even multiple of
- <em class="parameter"><code>alignment</code></em>. The requested
- <em class="parameter"><code>alignment</code></em> must be a power of 2. Behavior is
- undefined if <em class="parameter"><code>size</code></em> is not an integral multiple of
- <em class="parameter"><code>alignment</code></em>.</p><p>The <code class="function">realloc</code>(<em class="parameter"><code></code></em>) function changes the
- size of the previously allocated memory referenced by
- <em class="parameter"><code>ptr</code></em> to <em class="parameter"><code>size</code></em> bytes. The
- contents of the memory are unchanged up to the lesser of the new and old
- sizes. If the new size is larger, the contents of the newly allocated
- portion of the memory are undefined. Upon success, the memory referenced
- by <em class="parameter"><code>ptr</code></em> is freed and a pointer to the newly
- allocated memory is returned. Note that
- <code class="function">realloc</code>(<em class="parameter"><code></code></em>) may move the memory allocation,
- resulting in a different return value than <em class="parameter"><code>ptr</code></em>.
- If <em class="parameter"><code>ptr</code></em> is <code class="constant">NULL</code>, the
- <code class="function">realloc</code>(<em class="parameter"><code></code></em>) function behaves identically to
- <code class="function">malloc</code>(<em class="parameter"><code></code></em>) for the specified size.</p><p>The <code class="function">free</code>(<em class="parameter"><code></code></em>) function causes the
- allocated memory referenced by <em class="parameter"><code>ptr</code></em> to be made
- available for future allocations. If <em class="parameter"><code>ptr</code></em> is
- <code class="constant">NULL</code>, no action occurs.</p></div><div class="refsect2" title="Non-standard API"><a name="id286949561"></a><h3>Non-standard API</h3><p>The <code class="function">malloc_usable_size</code>(<em class="parameter"><code></code></em>) function
- returns the usable size of the allocation pointed to by
- <em class="parameter"><code>ptr</code></em>. The return value may be larger than the size
- that was requested during allocation. The
- <code class="function">malloc_usable_size</code>(<em class="parameter"><code></code></em>) function is not a
- mechanism for in-place <code class="function">realloc</code>(<em class="parameter"><code></code></em>); rather
- it is provided solely as a tool for introspection purposes. Any
- discrepancy between the requested allocation size and the size reported
- by <code class="function">malloc_usable_size</code>(<em class="parameter"><code></code></em>) should not be
- depended on, since such behavior is entirely implementation-dependent.
- </p><p>The <code class="function">malloc_stats_print</code>(<em class="parameter"><code></code></em>) function
- writes human-readable summary statistics via the
- <em class="parameter"><code>write_cb</code></em> callback function pointer and
- <em class="parameter"><code>cbopaque</code></em> data passed to
- <em class="parameter"><code>write_cb</code></em>, or
- <code class="function">malloc_message</code>(<em class="parameter"><code></code></em>) if
- <em class="parameter"><code>write_cb</code></em> is <code class="constant">NULL</code>. This
- function can be called repeatedly. General information that never
- changes during execution can be omitted by specifying "g" as a character
- within the <em class="parameter"><code>opts</code></em> string. Note that
- <code class="function">malloc_message</code>(<em class="parameter"><code></code></em>) uses the
- <code class="function">mallctl*</code>(<em class="parameter"><code></code></em>) functions internally, so
- inconsistent statistics can be reported if multiple threads use these
- functions simultaneously. If <code class="option">--enable-stats</code> is
- specified during configuration, &#8220;m&#8221; and &#8220;a&#8221; can
- be specified to omit merged arena and per arena statistics, respectively;
- &#8220;b&#8221; and &#8220;l&#8221; can be specified to omit per size
- class statistics for bins and large objects, respectively. Unrecognized
- characters are silently ignored. Note that thread caching may prevent
- some statistics from being completely up to date, since extra locking
- would be required to merge counters that track thread cache operations.
- </p><p>The <code class="function">mallctl</code>(<em class="parameter"><code></code></em>) function provides a
- general interface for introspecting the memory allocator, as well as
- setting modifiable parameters and triggering actions. The
- period-separated <em class="parameter"><code>name</code></em> argument specifies a
- location in a tree-structured namespace; see the <a class="xref" href="#mallctl_namespace" title="MALLCTL NAMESPACE">MALLCTL NAMESPACE</a> section for
- documentation on the tree contents. To read a value, pass a pointer via
- <em class="parameter"><code>oldp</code></em> to adequate space to contain the value, and a
- pointer to its length via <em class="parameter"><code>oldlenp</code></em>; otherwise pass
- <code class="constant">NULL</code> and <code class="constant">NULL</code>. Similarly, to
- write a value, pass a pointer to the value via
- <em class="parameter"><code>newp</code></em>, and its length via
- <em class="parameter"><code>newlen</code></em>; otherwise pass <code class="constant">NULL</code>
- and <code class="constant">0</code>.</p><p>The <code class="function">mallctlnametomib</code>(<em class="parameter"><code></code></em>) function
- provides a way to avoid repeated name lookups for applications that
- repeatedly query the same portion of the namespace, by translating a name
- to a &#8220;Management Information Base&#8221; (MIB) that can be passed
- repeatedly to <code class="function">mallctlbymib</code>(<em class="parameter"><code></code></em>). Upon
- successful return from <code class="function">mallctlnametomib</code>(<em class="parameter"><code></code></em>),
- <em class="parameter"><code>mibp</code></em> contains an array of
- <em class="parameter"><code>*miblenp</code></em> integers, where
- <em class="parameter"><code>*miblenp</code></em> is the lesser of the number of components
- in <em class="parameter"><code>name</code></em> and the input value of
- <em class="parameter"><code>*miblenp</code></em>. Thus it is possible to pass a
- <em class="parameter"><code>*miblenp</code></em> that is smaller than the number of
- period-separated name components, which results in a partial MIB that can
- be used as the basis for constructing a complete MIB. For name
- components that are integers (e.g. the 2 in
- <a class="link" href="#arenas.bin.i.size">
- "<code class="mallctl">arenas.bin.2.size</code>"
- </a>),
- the corresponding MIB component will always be that integer. Therefore,
- it is legitimate to construct code like the following: </p><pre class="programlisting">
-unsigned nbins, i;
-
-int mib[4];
-size_t len, miblen;
-
-len = sizeof(nbins);
-mallctl("arenas.nbins", &amp;nbins, &amp;len, NULL, 0);
-
-miblen = 4;
-mallnametomib("arenas.bin.0.size", mib, &amp;miblen);
-for (i = 0; i &lt; nbins; i++) {
- size_t bin_size;
-
- mib[2] = i;
- len = sizeof(bin_size);
- mallctlbymib(mib, miblen, &amp;bin_size, &amp;len, NULL, 0);
- /* Do something with bin_size... */
-}</pre></div><div class="refsect2" title="Experimental API"><a name="id286949870"></a><h3>Experimental API</h3><p>The experimental API is subject to change or removal without regard
- for backward compatibility. If <code class="option">--disable-experimental</code>
- is specified during configuration, the experimental API is
- omitted.</p><p>The <code class="function">allocm</code>(<em class="parameter"><code></code></em>),
- <code class="function">rallocm</code>(<em class="parameter"><code></code></em>),
- <code class="function">sallocm</code>(<em class="parameter"><code></code></em>),
- <code class="function">dallocm</code>(<em class="parameter"><code></code></em>), and
- <code class="function">nallocm</code>(<em class="parameter"><code></code></em>) functions all have a
- <em class="parameter"><code>flags</code></em> argument that can be used to specify
- options. The functions only check the options that are contextually
- relevant. Use bitwise or (<code class="code">|</code>) operations to
- specify one or more of the following:
- </p><div class="variablelist"><dl><dt><span class="term"><code class="constant">ALLOCM_LG_ALIGN(<em class="parameter"><code>la</code></em>)
- </code></span></dt><dd><p>Align the memory allocation to start at an address
- that is a multiple of <code class="code">(1 &lt;&lt;
- <em class="parameter"><code>la</code></em>)</code>. This macro does not validate
- that <em class="parameter"><code>la</code></em> is within the valid
- range.</p></dd><dt><span class="term"><code class="constant">ALLOCM_ALIGN(<em class="parameter"><code>a</code></em>)
- </code></span></dt><dd><p>Align the memory allocation to start at an address
- that is a multiple of <em class="parameter"><code>a</code></em>, where
- <em class="parameter"><code>a</code></em> is a power of two. This macro does not
- validate that <em class="parameter"><code>a</code></em> is a power of 2.
- </p></dd><dt><span class="term"><code class="constant">ALLOCM_ZERO</code></span></dt><dd><p>Initialize newly allocated memory to contain zero
- bytes. In the growing reallocation case, the real size prior to
- reallocation defines the boundary between untouched bytes and those
- that are initialized to contain zero bytes. If this option is
- absent, newly allocated memory is uninitialized.</p></dd><dt><span class="term"><code class="constant">ALLOCM_NO_MOVE</code></span></dt><dd><p>For reallocation, fail rather than moving the
- object. This constraint can apply to both growth and
- shrinkage.</p></dd><dt><span class="term"><code class="constant">ALLOCM_ARENA(<em class="parameter"><code>a</code></em>)
- </code></span></dt><dd><p>Use the arena specified by the index
- <em class="parameter"><code>a</code></em>. This macro does not validate that
- <em class="parameter"><code>a</code></em> specifies an arena in the valid
- range.</p></dd></dl></div><p>
- </p><p>The <code class="function">allocm</code>(<em class="parameter"><code></code></em>) function allocates at
- least <em class="parameter"><code>size</code></em> bytes of memory, sets
- <em class="parameter"><code>*ptr</code></em> to the base address of the allocation, and
- sets <em class="parameter"><code>*rsize</code></em> to the real size of the allocation if
- <em class="parameter"><code>rsize</code></em> is not <code class="constant">NULL</code>. Behavior
- is undefined if <em class="parameter"><code>size</code></em> is
- <code class="constant">0</code>.</p><p>The <code class="function">rallocm</code>(<em class="parameter"><code></code></em>) function resizes the
- allocation at <em class="parameter"><code>*ptr</code></em> to be at least
- <em class="parameter"><code>size</code></em> bytes, sets <em class="parameter"><code>*ptr</code></em> to
- the base address of the allocation if it moved, and sets
- <em class="parameter"><code>*rsize</code></em> to the real size of the allocation if
- <em class="parameter"><code>rsize</code></em> is not <code class="constant">NULL</code>. If
- <em class="parameter"><code>extra</code></em> is non-zero, an attempt is made to resize
- the allocation to be at least <code class="code"><em class="parameter"><code>size</code></em> +
- <em class="parameter"><code>extra</code></em>)</code> bytes, though inability to allocate
- the extra byte(s) will not by itself result in failure. Behavior is
- undefined if <em class="parameter"><code>size</code></em> is <code class="constant">0</code>, or if
- <code class="code">(<em class="parameter"><code>size</code></em> +
- <em class="parameter"><code>extra</code></em> &gt;
- <code class="constant">SIZE_T_MAX</code>)</code>.</p><p>The <code class="function">sallocm</code>(<em class="parameter"><code></code></em>) function sets
- <em class="parameter"><code>*rsize</code></em> to the real size of the allocation.</p><p>The <code class="function">dallocm</code>(<em class="parameter"><code></code></em>) function causes the
- memory referenced by <em class="parameter"><code>ptr</code></em> to be made available for
- future allocations.</p><p>The <code class="function">nallocm</code>(<em class="parameter"><code></code></em>) function allocates no
- memory, but it performs the same size computation as the
- <code class="function">allocm</code>(<em class="parameter"><code></code></em>) function, and if
- <em class="parameter"><code>rsize</code></em> is not <code class="constant">NULL</code> it sets
- <em class="parameter"><code>*rsize</code></em> to the real size of the allocation that
- would result from the equivalent <code class="function">allocm</code>(<em class="parameter"><code></code></em>)
- function call. Behavior is undefined if
- <em class="parameter"><code>size</code></em> is <code class="constant">0</code>.</p></div></div><div class="refsect1" title="TUNING"><a name="tuning"></a><h2>TUNING</h2><p>Once, when the first call is made to one of the memory allocation
- routines, the allocator initializes its internals based in part on various
- options that can be specified at compile- or run-time.</p><p>The string pointed to by the global variable
- <code class="varname">malloc_conf</code>, the &#8220;name&#8221; of the file
- referenced by the symbolic link named <code class="filename">/etc/malloc.conf</code>, and the value of the
- environment variable <code class="envar">MALLOC_CONF</code>, will be interpreted, in
- that order, from left to right as options.</p><p>An options string is a comma-separated list of option:value pairs.
- There is one key corresponding to each <a class="link" href="#opt.abort">
- "<code class="mallctl">opt.*</code>"
- </a> mallctl (see the <a class="xref" href="#mallctl_namespace" title="MALLCTL NAMESPACE">MALLCTL NAMESPACE</a> section for options
- documentation). For example, <code class="literal">abort:true,narenas:1</code> sets
- the <a class="link" href="#opt.abort">
- "<code class="mallctl">opt.abort</code>"
- </a> and <a class="link" href="#opt.narenas">
- "<code class="mallctl">opt.narenas</code>"
- </a> options. Some
- options have boolean values (true/false), others have integer values (base
- 8, 10, or 16, depending on prefix), and yet others have raw string
- values.</p></div><div class="refsect1" title="IMPLEMENTATION NOTES"><a name="implementation_notes"></a><h2>IMPLEMENTATION NOTES</h2><p>Traditionally, allocators have used
- <span class="citerefentry"><span class="refentrytitle">sbrk</span>(2)</span> to obtain memory, which is
- suboptimal for several reasons, including race conditions, increased
- fragmentation, and artificial limitations on maximum usable memory. If
- <code class="option">--enable-dss</code> is specified during configuration, this
- allocator uses both <span class="citerefentry"><span class="refentrytitle">mmap</span>(2)</span> and
- <span class="citerefentry"><span class="refentrytitle">sbrk</span>(2)</span>, in that order of preference;
- otherwise only <span class="citerefentry"><span class="refentrytitle">mmap</span>(2)</span> is used.</p><p>This allocator uses multiple arenas in order to reduce lock
- contention for threaded programs on multi-processor systems. This works
- well with regard to threading scalability, but incurs some costs. There is
- a small fixed per-arena overhead, and additionally, arenas manage memory
- completely independently of each other, which means a small fixed increase
- in overall memory fragmentation. These overheads are not generally an
- issue, given the number of arenas normally used. Note that using
- substantially more arenas than the default is not likely to improve
- performance, mainly due to reduced cache performance. However, it may make
- sense to reduce the number of arenas if an application does not make much
- use of the allocation functions.</p><p>In addition to multiple arenas, unless
- <code class="option">--disable-tcache</code> is specified during configuration, this
- allocator supports thread-specific caching for small and large objects, in
- order to make it possible to completely avoid synchronization for most
- allocation requests. Such caching allows very fast allocation in the
- common case, but it increases memory usage and fragmentation, since a
- bounded number of objects can remain allocated in each thread cache.</p><p>Memory is conceptually broken into equal-sized chunks, where the
- chunk size is a power of two that is greater than the page size. Chunks
- are always aligned to multiples of the chunk size. This alignment makes it
- possible to find metadata for user objects very quickly.</p><p>User objects are broken into three categories according to size:
- small, large, and huge. Small objects are smaller than one page. Large
- objects are smaller than the chunk size. Huge objects are a multiple of
- the chunk size. Small and large objects are managed by arenas; huge
- objects are managed separately in a single data structure that is shared by
- all threads. Huge objects are used by applications infrequently enough
- that this single data structure is not a scalability issue.</p><p>Each chunk that is managed by an arena tracks its contents as runs of
- contiguous pages (unused, backing a set of small objects, or backing one
- large object). The combination of chunk alignment and chunk page maps
- makes it possible to determine all metadata regarding small and large
- allocations in constant time.</p><p>Small objects are managed in groups by page runs. Each run maintains
- a frontier and free list to track which regions are in use. Allocation
- requests that are no more than half the quantum (8 or 16, depending on
- architecture) are rounded up to the nearest power of two that is at least
- <code class="code">sizeof(<span class="type">double</span>)</code>. All other small
- object size classes are multiples of the quantum, spaced such that internal
- fragmentation is limited to approximately 25% for all but the smallest size
- classes. Allocation requests that are larger than the maximum small size
- class, but small enough to fit in an arena-managed chunk (see the <a class="link" href="#opt.lg_chunk">
- "<code class="mallctl">opt.lg_chunk</code>"
- </a> option), are
- rounded up to the nearest run size. Allocation requests that are too large
- to fit in an arena-managed chunk are rounded up to the nearest multiple of
- the chunk size.</p><p>Allocations are packed tightly together, which can be an issue for
- multi-threaded applications. If you need to assure that allocations do not
- suffer from cacheline sharing, round your allocation requests up to the
- nearest multiple of the cacheline size, or specify cacheline alignment when
- allocating.</p><p>Assuming 4 MiB chunks, 4 KiB pages, and a 16-byte quantum on a 64-bit
- system, the size classes in each category are as shown in <a class="xref" href="#size_classes" title="Table 1. Size classes">Table 1</a>.</p><div class="table"><a name="size_classes"></a><p class="title"><b>Table 1. Size classes</b></p><div class="table-contents"><table summary="Size classes" border="1"><colgroup><col align="left" class="c1"><col align="right" class="c2"><col align="left" class="c3"></colgroup><thead><tr><th align="left">Category</th><th align="right">Spacing</th><th align="left">Size</th></tr></thead><tbody><tr><td rowspan="7" align="left">Small</td><td align="right">lg</td><td align="left">[8]</td></tr><tr><td align="right">16</td><td align="left">[16, 32, 48, ..., 128]</td></tr><tr><td align="right">32</td><td align="left">[160, 192, 224, 256]</td></tr><tr><td align="right">64</td><td align="left">[320, 384, 448, 512]</td></tr><tr><td align="right">128</td><td align="left">[640, 768, 896, 1024]</td></tr><tr><td align="right">256</td><td align="left">[1280, 1536, 1792, 2048]</td></tr><tr><td align="right">512</td><td align="left">[2560, 3072, 3584]</td></tr><tr><td align="left">Large</td><td align="right">4 KiB</td><td align="left">[4 KiB, 8 KiB, 12 KiB, ..., 4072 KiB]</td></tr><tr><td align="left">Huge</td><td align="right">4 MiB</td><td align="left">[4 MiB, 8 MiB, 12 MiB, ...]</td></tr></tbody></table></div></div><br class="table-break"></div><div class="refsect1" title="MALLCTL NAMESPACE"><a name="mallctl_namespace"></a><h2>MALLCTL NAMESPACE</h2><p>The following names are defined in the namespace accessible via the
- <code class="function">mallctl*</code>(<em class="parameter"><code></code></em>) functions. Value types are
- specified in parentheses, their readable/writable statuses are encoded as
- <code class="literal">rw</code>, <code class="literal">r-</code>, <code class="literal">-w</code>, or
- <code class="literal">--</code>, and required build configuration flags follow, if
- any. A name element encoded as <code class="literal">&lt;i&gt;</code> or
- <code class="literal">&lt;j&gt;</code> indicates an integer component, where the
- integer varies from 0 to some upper value that must be determined via
- introspection. In the case of
- "<code class="mallctl">stats.arenas.&lt;i&gt;.*</code>"
- ,
- <code class="literal">&lt;i&gt;</code> equal to <a class="link" href="#arenas.narenas">
- "<code class="mallctl">arenas.narenas</code>"
- </a> can be
- used to access the summation of statistics from all arenas. Take special
- note of the <a class="link" href="#epoch">
- "<code class="mallctl">epoch</code>"
- </a> mallctl,
- which controls refreshing of cached dynamic statistics.</p><div class="variablelist"><dl><dt><span class="term">
-
- "<code class="mallctl">version</code>"
-
- (<span class="type">const char *</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Return the jemalloc version string.</p></dd><dt><a name="epoch"></a><span class="term">
-
- "<code class="mallctl">epoch</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">rw</code>
- </span></dt><dd><p>If a value is passed in, refresh the data from which
- the <code class="function">mallctl*</code>(<em class="parameter"><code></code></em>) functions report values,
- and increment the epoch. Return the current epoch. This is useful for
- detecting whether another thread caused a refresh.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.debug</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-debug</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.dss</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-dss</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.fill</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-fill</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.lazy_lock</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-lazy-lock</code> was specified
- during build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.mremap</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-mremap</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.munmap</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-munmap</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.prof</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-prof</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.prof_libgcc</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--disable-prof-libgcc</code> was not
- specified during build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.prof_libunwind</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-prof-libunwind</code> was specified
- during build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.stats</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-stats</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.tcache</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--disable-tcache</code> was not specified
- during build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.tls</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--disable-tls</code> was not specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.utrace</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-utrace</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.valgrind</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-valgrind</code> was specified during
- build configuration.</p></dd><dt><span class="term">
-
- "<code class="mallctl">config.xmalloc</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p><code class="option">--enable-xmalloc</code> was specified during
- build configuration.</p></dd><dt><a name="opt.abort"></a><span class="term">
-
- "<code class="mallctl">opt.abort</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Abort-on-warning enabled/disabled. If true, most
- warnings are fatal. The process will call
- <span class="citerefentry"><span class="refentrytitle">abort</span>(3)</span> in these cases. This option is
- disabled by default unless <code class="option">--enable-debug</code> is
- specified during configuration, in which case it is enabled by default.
- </p></dd><dt><a name="opt.lg_chunk"></a><span class="term">
-
- "<code class="mallctl">opt.lg_chunk</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Virtual memory chunk size (log base 2). If a chunk
- size outside the supported size range is specified, the size is
- silently clipped to the minimum/maximum supported size. The default
- chunk size is 4 MiB (2^22).
- </p></dd><dt><a name="opt.dss"></a><span class="term">
-
- "<code class="mallctl">opt.dss</code>"
-
- (<span class="type">const char *</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>dss (<span class="citerefentry"><span class="refentrytitle">sbrk</span>(2)</span>) allocation precedence as
- related to <span class="citerefentry"><span class="refentrytitle">mmap</span>(2)</span> allocation. The following
- settings are supported: &#8220;disabled&#8221;, &#8220;primary&#8221;,
- and &#8220;secondary&#8221; (default).</p></dd><dt><a name="opt.narenas"></a><span class="term">
-
- "<code class="mallctl">opt.narenas</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Maximum number of arenas to use for automatic
- multiplexing of threads and arenas. The default is four times the
- number of CPUs, or one if there is a single CPU.</p></dd><dt><a name="opt.lg_dirty_mult"></a><span class="term">
-
- "<code class="mallctl">opt.lg_dirty_mult</code>"
-
- (<span class="type">ssize_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Per-arena minimum ratio (log base 2) of active to dirty
- pages. Some dirty unused pages may be allowed to accumulate, within
- the limit set by the ratio (or one chunk worth of dirty pages,
- whichever is greater), before informing the kernel about some of those
- pages via <span class="citerefentry"><span class="refentrytitle">madvise</span>(2)</span> or a similar system call. This
- provides the kernel with sufficient information to recycle dirty pages
- if physical memory becomes scarce and the pages remain unused. The
- default minimum ratio is 8:1 (2^3:1); an option value of -1 will
- disable dirty page purging.</p></dd><dt><a name="opt.stats_print"></a><span class="term">
-
- "<code class="mallctl">opt.stats_print</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Enable/disable statistics printing at exit. If
- enabled, the <code class="function">malloc_stats_print</code>(<em class="parameter"><code></code></em>)
- function is called at program exit via an
- <span class="citerefentry"><span class="refentrytitle">atexit</span>(3)</span> function. If
- <code class="option">--enable-stats</code> is specified during configuration, this
- has the potential to cause deadlock for a multi-threaded process that
- exits while one or more threads are executing in the memory allocation
- functions. Therefore, this option should only be used with care; it is
- primarily intended as a performance tuning aid during application
- development. This option is disabled by default.</p></dd><dt><a name="opt.junk"></a><span class="term">
-
- "<code class="mallctl">opt.junk</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-fill</code>]
- </span></dt><dd><p>Junk filling enabled/disabled. If enabled, each byte
- of uninitialized allocated memory will be initialized to
- <code class="literal">0xa5</code>. All deallocated memory will be initialized to
- <code class="literal">0x5a</code>. This is intended for debugging and will
- impact performance negatively. This option is disabled by default
- unless <code class="option">--enable-debug</code> is specified during
- configuration, in which case it is enabled by default unless running
- inside <a class="ulink" href="http://valgrind.org/" target="_top">Valgrind</a>.</p></dd><dt><a name="opt.quarantine"></a><span class="term">
-
- "<code class="mallctl">opt.quarantine</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-fill</code>]
- </span></dt><dd><p>Per thread quarantine size in bytes. If non-zero, each
- thread maintains a FIFO object quarantine that stores up to the
- specified number of bytes of memory. The quarantined memory is not
- freed until it is released from quarantine, though it is immediately
- junk-filled if the <a class="link" href="#opt.junk">
- "<code class="mallctl">opt.junk</code>"
- </a> option is
- enabled. This feature is of particular use in combination with <a class="ulink" href="http://valgrind.org/" target="_top">Valgrind</a>, which can detect attempts
- to access quarantined objects. This is intended for debugging and will
- impact performance negatively. The default quarantine size is 0 unless
- running inside Valgrind, in which case the default is 16
- MiB.</p></dd><dt><a name="opt.redzone"></a><span class="term">
-
- "<code class="mallctl">opt.redzone</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-fill</code>]
- </span></dt><dd><p>Redzones enabled/disabled. If enabled, small
- allocations have redzones before and after them. Furthermore, if the
- <a class="link" href="#opt.junk">
- "<code class="mallctl">opt.junk</code>"
- </a> option is
- enabled, the redzones are checked for corruption during deallocation.
- However, the primary intended purpose of this feature is to be used in
- combination with <a class="ulink" href="http://valgrind.org/" target="_top">Valgrind</a>,
- which needs redzones in order to do effective buffer overflow/underflow
- detection. This option is intended for debugging and will impact
- performance negatively. This option is disabled by
- default unless running inside Valgrind.</p></dd><dt><a name="opt.zero"></a><span class="term">
-
- "<code class="mallctl">opt.zero</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-fill</code>]
- </span></dt><dd><p>Zero filling enabled/disabled. If enabled, each byte
- of uninitialized allocated memory will be initialized to 0. Note that
- this initialization only happens once for each byte, so
- <code class="function">realloc</code>(<em class="parameter"><code></code></em>) and
- <code class="function">rallocm</code>(<em class="parameter"><code></code></em>) calls do not zero memory that
- was previously allocated. This is intended for debugging and will
- impact performance negatively. This option is disabled by default.
- </p></dd><dt><a name="opt.utrace"></a><span class="term">
-
- "<code class="mallctl">opt.utrace</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-utrace</code>]
- </span></dt><dd><p>Allocation tracing based on
- <span class="citerefentry"><span class="refentrytitle">utrace</span>(2)</span> enabled/disabled. This option
- is disabled by default.</p></dd><dt><a name="opt.valgrind"></a><span class="term">
-
- "<code class="mallctl">opt.valgrind</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-valgrind</code>]
- </span></dt><dd><p><a class="ulink" href="http://valgrind.org/" target="_top">Valgrind</a>
- support enabled/disabled. This option is vestigal because jemalloc
- auto-detects whether it is running inside Valgrind. This option is
- disabled by default, unless running inside Valgrind.</p></dd><dt><a name="opt.xmalloc"></a><span class="term">
-
- "<code class="mallctl">opt.xmalloc</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-xmalloc</code>]
- </span></dt><dd><p>Abort-on-out-of-memory enabled/disabled. If enabled,
- rather than returning failure for any allocation function, display a
- diagnostic message on <code class="constant">STDERR_FILENO</code> and cause the
- program to drop core (using
- <span class="citerefentry"><span class="refentrytitle">abort</span>(3)</span>). If an application is
- designed to depend on this behavior, set the option at compile time by
- including the following in the source code:
- </p><pre class="programlisting">
-malloc_conf = "xmalloc:true";</pre><p>
- This option is disabled by default.</p></dd><dt><a name="opt.tcache"></a><span class="term">
-
- "<code class="mallctl">opt.tcache</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-tcache</code>]
- </span></dt><dd><p>Thread-specific caching enabled/disabled. When there
- are multiple threads, each thread uses a thread-specific cache for
- objects up to a certain size. Thread-specific caching allows many
- allocations to be satisfied without performing any thread
- synchronization, at the cost of increased memory use. See the
- <a class="link" href="#opt.lg_tcache_max">
- "<code class="mallctl">opt.lg_tcache_max</code>"
- </a>
- option for related tuning information. This option is enabled by
- default unless running inside <a class="ulink" href="http://valgrind.org/" target="_top">Valgrind</a>.</p></dd><dt><a name="opt.lg_tcache_max"></a><span class="term">
-
- "<code class="mallctl">opt.lg_tcache_max</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-tcache</code>]
- </span></dt><dd><p>Maximum size class (log base 2) to cache in the
- thread-specific cache. At a minimum, all small size classes are
- cached, and at a maximum all large size classes are cached. The
- default maximum is 32 KiB (2^15).</p></dd><dt><a name="opt.prof"></a><span class="term">
-
- "<code class="mallctl">opt.prof</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Memory profiling enabled/disabled. If enabled, profile
- memory allocation activity. See the <a class="link" href="#opt.prof_active">
- "<code class="mallctl">opt.prof_active</code>"
- </a>
- option for on-the-fly activation/deactivation. See the <a class="link" href="#opt.lg_prof_sample">
- "<code class="mallctl">opt.lg_prof_sample</code>"
- </a>
- option for probabilistic sampling control. See the <a class="link" href="#opt.prof_accum">
- "<code class="mallctl">opt.prof_accum</code>"
- </a>
- option for control of cumulative sample reporting. See the <a class="link" href="#opt.lg_prof_interval">
- "<code class="mallctl">opt.lg_prof_interval</code>"
- </a>
- option for information on interval-triggered profile dumping, the <a class="link" href="#opt.prof_gdump">
- "<code class="mallctl">opt.prof_gdump</code>"
- </a>
- option for information on high-water-triggered profile dumping, and the
- <a class="link" href="#opt.prof_final">
- "<code class="mallctl">opt.prof_final</code>"
- </a>
- option for final profile dumping. Profile output is compatible with
- the included <span class="command"><strong>pprof</strong></span> Perl script, which originates
- from the <a class="ulink" href="http://code.google.com/p/gperftools/" target="_top">gperftools
- package</a>.</p></dd><dt><a name="opt.prof_prefix"></a><span class="term">
-
- "<code class="mallctl">opt.prof_prefix</code>"
-
- (<span class="type">const char *</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Filename prefix for profile dumps. If the prefix is
- set to the empty string, no automatic dumps will occur; this is
- primarily useful for disabling the automatic final heap dump (which
- also disables leak reporting, if enabled). The default prefix is
- <code class="filename">jeprof</code>.</p></dd><dt><a name="opt.prof_active"></a><span class="term">
-
- "<code class="mallctl">opt.prof_active</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Profiling activated/deactivated. This is a secondary
- control mechanism that makes it possible to start the application with
- profiling enabled (see the <a class="link" href="#opt.prof">
- "<code class="mallctl">opt.prof</code>"
- </a> option) but
- inactive, then toggle profiling at any time during program execution
- with the <a class="link" href="#prof.active">
- "<code class="mallctl">prof.active</code>"
- </a> mallctl.
- This option is enabled by default.</p></dd><dt><a name="opt.lg_prof_sample"></a><span class="term">
-
- "<code class="mallctl">opt.lg_prof_sample</code>"
-
- (<span class="type">ssize_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Average interval (log base 2) between allocation
- samples, as measured in bytes of allocation activity. Increasing the
- sampling interval decreases profile fidelity, but also decreases the
- computational overhead. The default sample interval is 512 KiB (2^19
- B).</p></dd><dt><a name="opt.prof_accum"></a><span class="term">
-
- "<code class="mallctl">opt.prof_accum</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Reporting of cumulative object/byte counts in profile
- dumps enabled/disabled. If this option is enabled, every unique
- backtrace must be stored for the duration of execution. Depending on
- the application, this can impose a large memory overhead, and the
- cumulative counts are not always of interest. This option is disabled
- by default.</p></dd><dt><a name="opt.lg_prof_interval"></a><span class="term">
-
- "<code class="mallctl">opt.lg_prof_interval</code>"
-
- (<span class="type">ssize_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Average interval (log base 2) between memory profile
- dumps, as measured in bytes of allocation activity. The actual
- interval between dumps may be sporadic because decentralized allocation
- counters are used to avoid synchronization bottlenecks. Profiles are
- dumped to files named according to the pattern
- <code class="filename">&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.i&lt;iseq&gt;.heap</code>,
- where <code class="literal">&lt;prefix&gt;</code> is controlled by the
- <a class="link" href="#opt.prof_prefix">
- "<code class="mallctl">opt.prof_prefix</code>"
- </a>
- option. By default, interval-triggered profile dumping is disabled
- (encoded as -1).
- </p></dd><dt><a name="opt.prof_gdump"></a><span class="term">
-
- "<code class="mallctl">opt.prof_gdump</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Trigger a memory profile dump every time the total
- virtual memory exceeds the previous maximum. Profiles are dumped to
- files named according to the pattern
- <code class="filename">&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.u&lt;useq&gt;.heap</code>,
- where <code class="literal">&lt;prefix&gt;</code> is controlled by the <a class="link" href="#opt.prof_prefix">
- "<code class="mallctl">opt.prof_prefix</code>"
- </a>
- option. This option is disabled by default.</p></dd><dt><a name="opt.prof_final"></a><span class="term">
-
- "<code class="mallctl">opt.prof_final</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Use an
- <span class="citerefentry"><span class="refentrytitle">atexit</span>(3)</span> function to dump final memory
- usage to a file named according to the pattern
- <code class="filename">&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.f.heap</code>,
- where <code class="literal">&lt;prefix&gt;</code> is controlled by the <a class="link" href="#opt.prof_prefix">
- "<code class="mallctl">opt.prof_prefix</code>"
- </a>
- option. This option is enabled by default.</p></dd><dt><a name="opt.prof_leak"></a><span class="term">
-
- "<code class="mallctl">opt.prof_leak</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Leak reporting enabled/disabled. If enabled, use an
- <span class="citerefentry"><span class="refentrytitle">atexit</span>(3)</span> function to report memory leaks
- detected by allocation sampling. See the
- <a class="link" href="#opt.prof">
- "<code class="mallctl">opt.prof</code>"
- </a> option for
- information on analyzing heap profile output. This option is disabled
- by default.</p></dd><dt><span class="term">
-
- "<code class="mallctl">thread.arena</code>"
-
- (<span class="type">unsigned</span>)
- <code class="literal">rw</code>
- </span></dt><dd><p>Get or set the arena associated with the calling
- thread. If the specified arena was not initialized beforehand (see the
- <a class="link" href="#arenas.initialized">
- "<code class="mallctl">arenas.initialized</code>"
- </a>
- mallctl), it will be automatically initialized as a side effect of
- calling this interface.</p></dd><dt><a name="thread.allocated"></a><span class="term">
-
- "<code class="mallctl">thread.allocated</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Get the total number of bytes ever allocated by the
- calling thread. This counter has the potential to wrap around; it is
- up to the application to appropriately interpret the counter in such
- cases.</p></dd><dt><span class="term">
-
- "<code class="mallctl">thread.allocatedp</code>"
-
- (<span class="type">uint64_t *</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Get a pointer to the the value that is returned by the
- <a class="link" href="#thread.allocated">
- "<code class="mallctl">thread.allocated</code>"
- </a>
- mallctl. This is useful for avoiding the overhead of repeated
- <code class="function">mallctl*</code>(<em class="parameter"><code></code></em>) calls.</p></dd><dt><a name="thread.deallocated"></a><span class="term">
-
- "<code class="mallctl">thread.deallocated</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Get the total number of bytes ever deallocated by the
- calling thread. This counter has the potential to wrap around; it is
- up to the application to appropriately interpret the counter in such
- cases.</p></dd><dt><span class="term">
-
- "<code class="mallctl">thread.deallocatedp</code>"
-
- (<span class="type">uint64_t *</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Get a pointer to the the value that is returned by the
- <a class="link" href="#thread.deallocated">
- "<code class="mallctl">thread.deallocated</code>"
- </a>
- mallctl. This is useful for avoiding the overhead of repeated
- <code class="function">mallctl*</code>(<em class="parameter"><code></code></em>) calls.</p></dd><dt><span class="term">
-
- "<code class="mallctl">thread.tcache.enabled</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">rw</code>
- [<code class="option">--enable-tcache</code>]
- </span></dt><dd><p>Enable/disable calling thread's tcache. The tcache is
- implicitly flushed as a side effect of becoming
- disabled (see
- "<code class="mallctl">thread.tcache.flush</code>"
- ).
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">thread.tcache.flush</code>"
-
- (<span class="type">void</span>)
- <code class="literal">--</code>
- [<code class="option">--enable-tcache</code>]
- </span></dt><dd><p>Flush calling thread's tcache. This interface releases
- all cached objects and internal data structures associated with the
- calling thread's thread-specific cache. Ordinarily, this interface
- need not be called, since automatic periodic incremental garbage
- collection occurs, and the thread cache is automatically discarded when
- a thread exits. However, garbage collection is triggered by allocation
- activity, so it is possible for a thread that stops
- allocating/deallocating to retain its cache indefinitely, in which case
- the developer may find manual flushing useful.</p></dd><dt><a name="arena.i.purge"></a><span class="term">
-
- "<code class="mallctl">arena.&lt;i&gt;.purge</code>"
-
- (<span class="type">unsigned</span>)
- <code class="literal">--</code>
- </span></dt><dd><p>Purge unused dirty pages for arena &lt;i&gt;, or for
- all arenas if &lt;i&gt; equals <a class="link" href="#arenas.narenas">
- "<code class="mallctl">arenas.narenas</code>"
- </a>.
- </p></dd><dt><a name="arena.i.dss"></a><span class="term">
-
- "<code class="mallctl">arena.&lt;i&gt;.dss</code>"
-
- (<span class="type">const char *</span>)
- <code class="literal">rw</code>
- </span></dt><dd><p>Set the precedence of dss allocation as related to mmap
- allocation for arena &lt;i&gt;, or for all arenas if &lt;i&gt; equals
- <a class="link" href="#arenas.narenas">
- "<code class="mallctl">arenas.narenas</code>"
- </a>. See
- <a class="link" href="#opt.dss">
- "<code class="mallctl">opt.dss</code>"
- </a> for supported
- settings.
- </p></dd><dt><a name="arenas.narenas"></a><span class="term">
-
- "<code class="mallctl">arenas.narenas</code>"
-
- (<span class="type">unsigned</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Current limit on number of arenas.</p></dd><dt><a name="arenas.initialized"></a><span class="term">
-
- "<code class="mallctl">arenas.initialized</code>"
-
- (<span class="type">bool *</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>An array of <a class="link" href="#arenas.narenas">
- "<code class="mallctl">arenas.narenas</code>"
- </a>
- booleans. Each boolean indicates whether the corresponding arena is
- initialized.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.quantum</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Quantum size.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.page</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Page size.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.tcache_max</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-tcache</code>]
- </span></dt><dd><p>Maximum thread-cached size class.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.nbins</code>"
-
- (<span class="type">unsigned</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Number of bin size classes.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.nhbins</code>"
-
- (<span class="type">unsigned</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-tcache</code>]
- </span></dt><dd><p>Total number of thread cache bin size
- classes.</p></dd><dt><a name="arenas.bin.i.size"></a><span class="term">
-
- "<code class="mallctl">arenas.bin.&lt;i&gt;.size</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Maximum size supported by size class.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.bin.&lt;i&gt;.nregs</code>"
-
- (<span class="type">uint32_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Number of regions per page run.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.bin.&lt;i&gt;.run_size</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Number of bytes per page run.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.nlruns</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Total number of large size classes.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.lrun.&lt;i&gt;.size</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Maximum size supported by this large size
- class.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.purge</code>"
-
- (<span class="type">unsigned</span>)
- <code class="literal">-w</code>
- </span></dt><dd><p>Purge unused dirty pages for the specified arena, or
- for all arenas if none is specified.</p></dd><dt><span class="term">
-
- "<code class="mallctl">arenas.extend</code>"
-
- (<span class="type">unsigned</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Extend the array of arenas by appending a new arena,
- and returning the new arena index.</p></dd><dt><a name="prof.active"></a><span class="term">
-
- "<code class="mallctl">prof.active</code>"
-
- (<span class="type">bool</span>)
- <code class="literal">rw</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Control whether sampling is currently active. See the
- <a class="link" href="#opt.prof_active">
- "<code class="mallctl">opt.prof_active</code>"
- </a>
- option for additional information.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">prof.dump</code>"
-
- (<span class="type">const char *</span>)
- <code class="literal">-w</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Dump a memory profile to the specified file, or if NULL
- is specified, to a file according to the pattern
- <code class="filename">&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.m&lt;mseq&gt;.heap</code>,
- where <code class="literal">&lt;prefix&gt;</code> is controlled by the
- <a class="link" href="#opt.prof_prefix">
- "<code class="mallctl">opt.prof_prefix</code>"
- </a>
- option.</p></dd><dt><span class="term">
-
- "<code class="mallctl">prof.interval</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-prof</code>]
- </span></dt><dd><p>Average number of bytes allocated between
- inverval-based profile dumps. See the
- <a class="link" href="#opt.lg_prof_interval">
- "<code class="mallctl">opt.lg_prof_interval</code>"
- </a>
- option for additional information.</p></dd><dt><a name="stats.cactive"></a><span class="term">
-
- "<code class="mallctl">stats.cactive</code>"
-
- (<span class="type">size_t *</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Pointer to a counter that contains an approximate count
- of the current number of bytes in active pages. The estimate may be
- high, but never low, because each arena rounds up to the nearest
- multiple of the chunk size when computing its contribution to the
- counter. Note that the <a class="link" href="#epoch">
- "<code class="mallctl">epoch</code>"
- </a> mallctl has no bearing
- on this counter. Furthermore, counter consistency is maintained via
- atomic operations, so it is necessary to use an atomic operation in
- order to guarantee a consistent read when dereferencing the pointer.
- </p></dd><dt><a name="stats.allocated"></a><span class="term">
-
- "<code class="mallctl">stats.allocated</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Total number of bytes allocated by the
- application.</p></dd><dt><a name="stats.active"></a><span class="term">
-
- "<code class="mallctl">stats.active</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Total number of bytes in active pages allocated by the
- application. This is a multiple of the page size, and greater than or
- equal to <a class="link" href="#stats.allocated">
- "<code class="mallctl">stats.allocated</code>"
- </a>.
- This does not include <a class="link" href="#stats.arenas.i.pdirty">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.pdirty</code>"
- </a> and pages
- entirely devoted to allocator metadata.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.mapped</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Total number of bytes in chunks mapped on behalf of the
- application. This is a multiple of the chunk size, and is at least as
- large as <a class="link" href="#stats.active">
- "<code class="mallctl">stats.active</code>"
- </a>. This
- does not include inactive chunks.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.chunks.current</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Total number of chunks actively mapped on behalf of the
- application. This does not include inactive chunks.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.chunks.total</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of chunks allocated.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.chunks.high</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Maximum number of active chunks at any time thus far.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.huge.allocated</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Number of bytes currently allocated by huge objects.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.huge.nmalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of huge allocation requests.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.huge.ndalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of huge deallocation requests.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.dss</code>"
-
- (<span class="type">const char *</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>dss (<span class="citerefentry"><span class="refentrytitle">sbrk</span>(2)</span>) allocation precedence as
- related to <span class="citerefentry"><span class="refentrytitle">mmap</span>(2)</span> allocation. See <a class="link" href="#opt.dss">
- "<code class="mallctl">opt.dss</code>"
- </a> for details.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.nthreads</code>"
-
- (<span class="type">unsigned</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Number of threads currently assigned to
- arena.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.pactive</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Number of pages in active runs.</p></dd><dt><a name="stats.arenas.i.pdirty"></a><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.pdirty</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- </span></dt><dd><p>Number of pages within unused runs that are potentially
- dirty, and for which <code class="function">madvise</code>(<em class="parameter"><code>...</code></em>,
- <em class="parameter"><code><code class="constant">MADV_DONTNEED</code></code></em>) or
- similar has not been called.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.mapped</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Number of mapped bytes.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.npurge</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Number of dirty page purge sweeps performed.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.nmadvise</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Number of <code class="function">madvise</code>(<em class="parameter"><code>...</code></em>,
- <em class="parameter"><code><code class="constant">MADV_DONTNEED</code></code></em>) or
- similar calls made to purge dirty pages.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.npurged</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Number of pages purged.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.small.allocated</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Number of bytes currently allocated by small objects.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.small.nmalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of allocation requests served by
- small bins.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.small.ndalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of small objects returned to bins.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.small.nrequests</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of small allocation requests.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.large.allocated</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Number of bytes currently allocated by large objects.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.large.nmalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of large allocation requests served
- directly by the arena.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.large.ndalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of large deallocation requests served
- directly by the arena.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.large.nrequests</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of large allocation requests.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.allocated</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Current number of bytes allocated by
- bin.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nmalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of allocations served by bin.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.ndalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of allocations returned to bin.
- </p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nrequests</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of allocation
- requests.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nfills</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code> <code class="option">--enable-tcache</code>]
- </span></dt><dd><p>Cumulative number of tcache fills.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nflushes</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code> <code class="option">--enable-tcache</code>]
- </span></dt><dd><p>Cumulative number of tcache flushes.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nruns</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of runs created.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nreruns</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of times the current run from which
- to allocate changed.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.curruns</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Current number of runs.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nmalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of allocation requests for this size
- class served directly by the arena.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.ndalloc</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of deallocation requests for this
- size class served directly by the arena.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nrequests</code>"
-
- (<span class="type">uint64_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Cumulative number of allocation requests for this size
- class.</p></dd><dt><span class="term">
-
- "<code class="mallctl">stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.curruns</code>"
-
- (<span class="type">size_t</span>)
- <code class="literal">r-</code>
- [<code class="option">--enable-stats</code>]
- </span></dt><dd><p>Current number of runs for this size class.
- </p></dd></dl></div></div><div class="refsect1" title="DEBUGGING MALLOC PROBLEMS"><a name="debugging_malloc_problems"></a><h2>DEBUGGING MALLOC PROBLEMS</h2><p>When debugging, it is a good idea to configure/build jemalloc with
- the <code class="option">--enable-debug</code> and <code class="option">--enable-fill</code>
- options, and recompile the program with suitable options and symbols for
- debugger support. When so configured, jemalloc incorporates a wide variety
- of run-time assertions that catch application errors such as double-free,
- write-after-free, etc.</p><p>Programs often accidentally depend on &#8220;uninitialized&#8221;
- memory actually being filled with zero bytes. Junk filling
- (see the <a class="link" href="#opt.junk">
- "<code class="mallctl">opt.junk</code>"
- </a>
- option) tends to expose such bugs in the form of obviously incorrect
- results and/or coredumps. Conversely, zero
- filling (see the <a class="link" href="#opt.zero">
- "<code class="mallctl">opt.zero</code>"
- </a> option) eliminates
- the symptoms of such bugs. Between these two options, it is usually
- possible to quickly detect, diagnose, and eliminate such bugs.</p><p>This implementation does not provide much detail about the problems
- it detects, because the performance impact for storing such information
- would be prohibitive. However, jemalloc does integrate with the most
- excellent <a class="ulink" href="http://valgrind.org/" target="_top">Valgrind</a> tool if the
- <code class="option">--enable-valgrind</code> configuration option is enabled.</p></div><div class="refsect1" title="DIAGNOSTIC MESSAGES"><a name="diagnostic_messages"></a><h2>DIAGNOSTIC MESSAGES</h2><p>If any of the memory allocation/deallocation functions detect an
- error or warning condition, a message will be printed to file descriptor
- <code class="constant">STDERR_FILENO</code>. Errors will result in the process
- dumping core. If the <a class="link" href="#opt.abort">
- "<code class="mallctl">opt.abort</code>"
- </a> option is set, most
- warnings are treated as errors.</p><p>The <code class="varname">malloc_message</code> variable allows the programmer
- to override the function which emits the text strings forming the errors
- and warnings if for some reason the <code class="constant">STDERR_FILENO</code> file
- descriptor is not suitable for this.
- <code class="function">malloc_message</code>(<em class="parameter"><code></code></em>) takes the
- <em class="parameter"><code>cbopaque</code></em> pointer argument that is
- <code class="constant">NULL</code> unless overridden by the arguments in a call to
- <code class="function">malloc_stats_print</code>(<em class="parameter"><code></code></em>), followed by a string
- pointer. Please note that doing anything which tries to allocate memory in
- this function is likely to result in a crash or deadlock.</p><p>All messages are prefixed by
- &#8220;<code class="computeroutput">&lt;jemalloc&gt;: </code>&#8221;.</p></div><div class="refsect1" title="RETURN VALUES"><a name="return_values"></a><h2>RETURN VALUES</h2><div class="refsect2" title="Standard API"><a name="id286954473"></a><h3>Standard API</h3><p>The <code class="function">malloc</code>(<em class="parameter"><code></code></em>) and
- <code class="function">calloc</code>(<em class="parameter"><code></code></em>) functions return a pointer to the
- allocated memory if successful; otherwise a <code class="constant">NULL</code>
- pointer is returned and <code class="varname">errno</code> is set to
- <span class="errorname">ENOMEM</span>.</p><p>The <code class="function">posix_memalign</code>(<em class="parameter"><code></code></em>) function
- returns the value 0 if successful; otherwise it returns an error value.
- The <code class="function">posix_memalign</code>(<em class="parameter"><code></code></em>) function will fail
- if:
- </p><div class="variablelist"><dl><dt><span class="term"><span class="errorname">EINVAL</span></span></dt><dd><p>The <em class="parameter"><code>alignment</code></em> parameter is
- not a power of 2 at least as large as
- <code class="code">sizeof(<span class="type">void *</span>)</code>.
- </p></dd><dt><span class="term"><span class="errorname">ENOMEM</span></span></dt><dd><p>Memory allocation error.</p></dd></dl></div><p>
- </p><p>The <code class="function">aligned_alloc</code>(<em class="parameter"><code></code></em>) function returns
- a pointer to the allocated memory if successful; otherwise a
- <code class="constant">NULL</code> pointer is returned and
- <code class="varname">errno</code> is set. The
- <code class="function">aligned_alloc</code>(<em class="parameter"><code></code></em>) function will fail if:
- </p><div class="variablelist"><dl><dt><span class="term"><span class="errorname">EINVAL</span></span></dt><dd><p>The <em class="parameter"><code>alignment</code></em> parameter is
- not a power of 2.
- </p></dd><dt><span class="term"><span class="errorname">ENOMEM</span></span></dt><dd><p>Memory allocation error.</p></dd></dl></div><p>
- </p><p>The <code class="function">realloc</code>(<em class="parameter"><code></code></em>) function returns a
- pointer, possibly identical to <em class="parameter"><code>ptr</code></em>, to the
- allocated memory if successful; otherwise a <code class="constant">NULL</code>
- pointer is returned, and <code class="varname">errno</code> is set to
- <span class="errorname">ENOMEM</span> if the error was the result of an
- allocation failure. The <code class="function">realloc</code>(<em class="parameter"><code></code></em>)
- function always leaves the original buffer intact when an error occurs.
- </p><p>The <code class="function">free</code>(<em class="parameter"><code></code></em>) function returns no
- value.</p></div><div class="refsect2" title="Non-standard API"><a name="id286954690"></a><h3>Non-standard API</h3><p>The <code class="function">malloc_usable_size</code>(<em class="parameter"><code></code></em>) function
- returns the usable size of the allocation pointed to by
- <em class="parameter"><code>ptr</code></em>. </p><p>The <code class="function">mallctl</code>(<em class="parameter"><code></code></em>),
- <code class="function">mallctlnametomib</code>(<em class="parameter"><code></code></em>), and
- <code class="function">mallctlbymib</code>(<em class="parameter"><code></code></em>) functions return 0 on
- success; otherwise they return an error value. The functions will fail
- if:
- </p><div class="variablelist"><dl><dt><span class="term"><span class="errorname">EINVAL</span></span></dt><dd><p><em class="parameter"><code>newp</code></em> is not
- <code class="constant">NULL</code>, and <em class="parameter"><code>newlen</code></em> is too
- large or too small. Alternatively, <em class="parameter"><code>*oldlenp</code></em>
- is too large or too small; in this case as much data as possible
- are read despite the error.</p></dd><dt><span class="term"><span class="errorname">ENOMEM</span></span></dt><dd><p><em class="parameter"><code>*oldlenp</code></em> is too short to
- hold the requested value.</p></dd><dt><span class="term"><span class="errorname">ENOENT</span></span></dt><dd><p><em class="parameter"><code>name</code></em> or
- <em class="parameter"><code>mib</code></em> specifies an unknown/invalid
- value.</p></dd><dt><span class="term"><span class="errorname">EPERM</span></span></dt><dd><p>Attempt to read or write void value, or attempt to
- write read-only value.</p></dd><dt><span class="term"><span class="errorname">EAGAIN</span></span></dt><dd><p>A memory allocation failure
- occurred.</p></dd><dt><span class="term"><span class="errorname">EFAULT</span></span></dt><dd><p>An interface with side effects failed in some way
- not directly related to <code class="function">mallctl*</code>(<em class="parameter"><code></code></em>)
- read/write processing.</p></dd></dl></div><p>
- </p></div><div class="refsect2" title="Experimental API"><a name="id286954842"></a><h3>Experimental API</h3><p>The <code class="function">allocm</code>(<em class="parameter"><code></code></em>),
- <code class="function">rallocm</code>(<em class="parameter"><code></code></em>),
- <code class="function">sallocm</code>(<em class="parameter"><code></code></em>),
- <code class="function">dallocm</code>(<em class="parameter"><code></code></em>), and
- <code class="function">nallocm</code>(<em class="parameter"><code></code></em>) functions return
- <code class="constant">ALLOCM_SUCCESS</code> on success; otherwise they return an
- error value. The <code class="function">allocm</code>(<em class="parameter"><code></code></em>),
- <code class="function">rallocm</code>(<em class="parameter"><code></code></em>), and
- <code class="function">nallocm</code>(<em class="parameter"><code></code></em>) functions will fail if:
- </p><div class="variablelist"><dl><dt><span class="term"><span class="errorname">ALLOCM_ERR_OOM</span></span></dt><dd><p>Out of memory. Insufficient contiguous memory was
- available to service the allocation request. The
- <code class="function">allocm</code>(<em class="parameter"><code></code></em>) function additionally sets
- <em class="parameter"><code>*ptr</code></em> to <code class="constant">NULL</code>, whereas
- the <code class="function">rallocm</code>(<em class="parameter"><code></code></em>) function leaves
- <code class="constant">*ptr</code> unmodified.</p></dd></dl></div><p>
- The <code class="function">rallocm</code>(<em class="parameter"><code></code></em>) function will also
- fail if:
- </p><div class="variablelist"><dl><dt><span class="term"><span class="errorname">ALLOCM_ERR_NOT_MOVED</span></span></dt><dd><p><code class="constant">ALLOCM_NO_MOVE</code> was specified,
- but the reallocation request could not be serviced without moving
- the object.</p></dd></dl></div><p>
- </p></div></div><div class="refsect1" title="ENVIRONMENT"><a name="environment"></a><h2>ENVIRONMENT</h2><p>The following environment variable affects the execution of the
- allocation functions:
- </p><div class="variablelist"><dl><dt><span class="term"><code class="envar">MALLOC_CONF</code></span></dt><dd><p>If the environment variable
- <code class="envar">MALLOC_CONF</code> is set, the characters it contains
- will be interpreted as options.</p></dd></dl></div><p>
- </p></div><div class="refsect1" title="EXAMPLES"><a name="examples"></a><h2>EXAMPLES</h2><p>To dump core whenever a problem occurs:
- </p><pre class="screen">ln -s 'abort:true' /etc/malloc.conf</pre><p>
- </p><p>To specify in the source a chunk size that is 16 MiB:
- </p><pre class="programlisting">
-malloc_conf = "lg_chunk:24";</pre></div><div class="refsect1" title="SEE ALSO"><a name="see_also"></a><h2>SEE ALSO</h2><p><span class="citerefentry"><span class="refentrytitle">madvise</span>(2)</span>,
- <span class="citerefentry"><span class="refentrytitle">mmap</span>(2)</span>,
- <span class="citerefentry"><span class="refentrytitle">sbrk</span>(2)</span>,
- <span class="citerefentry"><span class="refentrytitle">utrace</span>(2)</span>,
- <span class="citerefentry"><span class="refentrytitle">alloca</span>(3)</span>,
- <span class="citerefentry"><span class="refentrytitle">atexit</span>(3)</span>,
- <span class="citerefentry"><span class="refentrytitle">getpagesize</span>(3)</span></p></div><div class="refsect1" title="STANDARDS"><a name="standards"></a><h2>STANDARDS</h2><p>The <code class="function">malloc</code>(<em class="parameter"><code></code></em>),
- <code class="function">calloc</code>(<em class="parameter"><code></code></em>),
- <code class="function">realloc</code>(<em class="parameter"><code></code></em>), and
- <code class="function">free</code>(<em class="parameter"><code></code></em>) functions conform to ISO/IEC
- 9899:1990 (&#8220;ISO C90&#8221;).</p><p>The <code class="function">posix_memalign</code>(<em class="parameter"><code></code></em>) function conforms
- to IEEE Std 1003.1-2001 (&#8220;POSIX.1&#8221;).</p></div></div></body></html>
diff --git a/extra/jemalloc/doc/jemalloc.xml.in b/extra/jemalloc/doc/jemalloc.xml.in
deleted file mode 100644
index 09305801bab..00000000000
--- a/extra/jemalloc/doc/jemalloc.xml.in
+++ /dev/null
@@ -1,2176 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<?xml-stylesheet type="text/xsl"
- href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
- "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
-]>
-
-<refentry>
- <refentryinfo>
- <title>User Manual</title>
- <productname>jemalloc</productname>
- <releaseinfo role="version">@jemalloc_version@</releaseinfo>
- <authorgroup>
- <author>
- <firstname>Jason</firstname>
- <surname>Evans</surname>
- <personblurb>Author</personblurb>
- </author>
- </authorgroup>
- </refentryinfo>
- <refmeta>
- <refentrytitle>JEMALLOC</refentrytitle>
- <manvolnum>3</manvolnum>
- </refmeta>
- <refnamediv>
- <refdescriptor>jemalloc</refdescriptor>
- <refname>jemalloc</refname>
- <!-- Each refname causes a man page file to be created. Only if this were
- the system malloc(3) implementation would these files be appropriate.
- <refname>malloc</refname>
- <refname>calloc</refname>
- <refname>posix_memalign</refname>
- <refname>aligned_alloc</refname>
- <refname>realloc</refname>
- <refname>free</refname>
- <refname>malloc_usable_size</refname>
- <refname>malloc_stats_print</refname>
- <refname>mallctl</refname>
- <refname>mallctlnametomib</refname>
- <refname>mallctlbymib</refname>
- <refname>allocm</refname>
- <refname>rallocm</refname>
- <refname>sallocm</refname>
- <refname>dallocm</refname>
- <refname>nallocm</refname>
- -->
- <refpurpose>general purpose memory allocation functions</refpurpose>
- </refnamediv>
- <refsect1 id="library">
- <title>LIBRARY</title>
- <para>This manual describes jemalloc @jemalloc_version@. More information
- can be found at the <ulink
- url="http://www.canonware.com/jemalloc/">jemalloc website</ulink>.</para>
- </refsect1>
- <refsynopsisdiv>
- <title>SYNOPSIS</title>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;<filename class="headerfile">stdlib.h</filename>&gt;
-#include &lt;<filename class="headerfile">jemalloc/jemalloc.h</filename>&gt;</funcsynopsisinfo>
- <refsect2>
- <title>Standard API</title>
- <funcprototype>
- <funcdef>void *<function>malloc</function></funcdef>
- <paramdef>size_t <parameter>size</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>void *<function>calloc</function></funcdef>
- <paramdef>size_t <parameter>number</parameter></paramdef>
- <paramdef>size_t <parameter>size</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>int <function>posix_memalign</function></funcdef>
- <paramdef>void **<parameter>ptr</parameter></paramdef>
- <paramdef>size_t <parameter>alignment</parameter></paramdef>
- <paramdef>size_t <parameter>size</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>void *<function>aligned_alloc</function></funcdef>
- <paramdef>size_t <parameter>alignment</parameter></paramdef>
- <paramdef>size_t <parameter>size</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>void *<function>realloc</function></funcdef>
- <paramdef>void *<parameter>ptr</parameter></paramdef>
- <paramdef>size_t <parameter>size</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>void <function>free</function></funcdef>
- <paramdef>void *<parameter>ptr</parameter></paramdef>
- </funcprototype>
- </refsect2>
- <refsect2>
- <title>Non-standard API</title>
- <funcprototype>
- <funcdef>size_t <function>malloc_usable_size</function></funcdef>
- <paramdef>const void *<parameter>ptr</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>void <function>malloc_stats_print</function></funcdef>
- <paramdef>void <parameter>(*write_cb)</parameter>
- <funcparams>void *, const char *</funcparams>
- </paramdef>
- <paramdef>void *<parameter>cbopaque</parameter></paramdef>
- <paramdef>const char *<parameter>opts</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>int <function>mallctl</function></funcdef>
- <paramdef>const char *<parameter>name</parameter></paramdef>
- <paramdef>void *<parameter>oldp</parameter></paramdef>
- <paramdef>size_t *<parameter>oldlenp</parameter></paramdef>
- <paramdef>void *<parameter>newp</parameter></paramdef>
- <paramdef>size_t <parameter>newlen</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>int <function>mallctlnametomib</function></funcdef>
- <paramdef>const char *<parameter>name</parameter></paramdef>
- <paramdef>size_t *<parameter>mibp</parameter></paramdef>
- <paramdef>size_t *<parameter>miblenp</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>int <function>mallctlbymib</function></funcdef>
- <paramdef>const size_t *<parameter>mib</parameter></paramdef>
- <paramdef>size_t <parameter>miblen</parameter></paramdef>
- <paramdef>void *<parameter>oldp</parameter></paramdef>
- <paramdef>size_t *<parameter>oldlenp</parameter></paramdef>
- <paramdef>void *<parameter>newp</parameter></paramdef>
- <paramdef>size_t <parameter>newlen</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>void <function>(*malloc_message)</function></funcdef>
- <paramdef>void *<parameter>cbopaque</parameter></paramdef>
- <paramdef>const char *<parameter>s</parameter></paramdef>
- </funcprototype>
- <para><type>const char *</type><varname>malloc_conf</varname>;</para>
- </refsect2>
- <refsect2>
- <title>Experimental API</title>
- <funcprototype>
- <funcdef>int <function>allocm</function></funcdef>
- <paramdef>void **<parameter>ptr</parameter></paramdef>
- <paramdef>size_t *<parameter>rsize</parameter></paramdef>
- <paramdef>size_t <parameter>size</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>int <function>rallocm</function></funcdef>
- <paramdef>void **<parameter>ptr</parameter></paramdef>
- <paramdef>size_t *<parameter>rsize</parameter></paramdef>
- <paramdef>size_t <parameter>size</parameter></paramdef>
- <paramdef>size_t <parameter>extra</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>int <function>sallocm</function></funcdef>
- <paramdef>const void *<parameter>ptr</parameter></paramdef>
- <paramdef>size_t *<parameter>rsize</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>int <function>dallocm</function></funcdef>
- <paramdef>void *<parameter>ptr</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- <funcprototype>
- <funcdef>int <function>nallocm</function></funcdef>
- <paramdef>size_t *<parameter>rsize</parameter></paramdef>
- <paramdef>size_t <parameter>size</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- </refsect2>
- </funcsynopsis>
- </refsynopsisdiv>
- <refsect1 id="description">
- <title>DESCRIPTION</title>
- <refsect2>
- <title>Standard API</title>
-
- <para>The <function>malloc<parameter/></function> function allocates
- <parameter>size</parameter> bytes of uninitialized memory. The allocated
- space is suitably aligned (after possible pointer coercion) for storage
- of any type of object.</para>
-
- <para>The <function>calloc<parameter/></function> function allocates
- space for <parameter>number</parameter> objects, each
- <parameter>size</parameter> bytes in length. The result is identical to
- calling <function>malloc<parameter/></function> with an argument of
- <parameter>number</parameter> * <parameter>size</parameter>, with the
- exception that the allocated memory is explicitly initialized to zero
- bytes.</para>
-
- <para>The <function>posix_memalign<parameter/></function> function
- allocates <parameter>size</parameter> bytes of memory such that the
- allocation's base address is an even multiple of
- <parameter>alignment</parameter>, and returns the allocation in the value
- pointed to by <parameter>ptr</parameter>. The requested
- <parameter>alignment</parameter> must be a power of 2 at least as large
- as <code language="C">sizeof(<type>void *</type>)</code>.</para>
-
- <para>The <function>aligned_alloc<parameter/></function> function
- allocates <parameter>size</parameter> bytes of memory such that the
- allocation's base address is an even multiple of
- <parameter>alignment</parameter>. The requested
- <parameter>alignment</parameter> must be a power of 2. Behavior is
- undefined if <parameter>size</parameter> is not an integral multiple of
- <parameter>alignment</parameter>.</para>
-
- <para>The <function>realloc<parameter/></function> function changes the
- size of the previously allocated memory referenced by
- <parameter>ptr</parameter> to <parameter>size</parameter> bytes. The
- contents of the memory are unchanged up to the lesser of the new and old
- sizes. If the new size is larger, the contents of the newly allocated
- portion of the memory are undefined. Upon success, the memory referenced
- by <parameter>ptr</parameter> is freed and a pointer to the newly
- allocated memory is returned. Note that
- <function>realloc<parameter/></function> may move the memory allocation,
- resulting in a different return value than <parameter>ptr</parameter>.
- If <parameter>ptr</parameter> is <constant>NULL</constant>, the
- <function>realloc<parameter/></function> function behaves identically to
- <function>malloc<parameter/></function> for the specified size.</para>
-
- <para>The <function>free<parameter/></function> function causes the
- allocated memory referenced by <parameter>ptr</parameter> to be made
- available for future allocations. If <parameter>ptr</parameter> is
- <constant>NULL</constant>, no action occurs.</para>
- </refsect2>
- <refsect2>
- <title>Non-standard API</title>
-
- <para>The <function>malloc_usable_size<parameter/></function> function
- returns the usable size of the allocation pointed to by
- <parameter>ptr</parameter>. The return value may be larger than the size
- that was requested during allocation. The
- <function>malloc_usable_size<parameter/></function> function is not a
- mechanism for in-place <function>realloc<parameter/></function>; rather
- it is provided solely as a tool for introspection purposes. Any
- discrepancy between the requested allocation size and the size reported
- by <function>malloc_usable_size<parameter/></function> should not be
- depended on, since such behavior is entirely implementation-dependent.
- </para>
-
- <para>The <function>malloc_stats_print<parameter/></function> function
- writes human-readable summary statistics via the
- <parameter>write_cb</parameter> callback function pointer and
- <parameter>cbopaque</parameter> data passed to
- <parameter>write_cb</parameter>, or
- <function>malloc_message<parameter/></function> if
- <parameter>write_cb</parameter> is <constant>NULL</constant>. This
- function can be called repeatedly. General information that never
- changes during execution can be omitted by specifying "g" as a character
- within the <parameter>opts</parameter> string. Note that
- <function>malloc_message<parameter/></function> uses the
- <function>mallctl*<parameter/></function> functions internally, so
- inconsistent statistics can be reported if multiple threads use these
- functions simultaneously. If <option>--enable-stats</option> is
- specified during configuration, &ldquo;m&rdquo; and &ldquo;a&rdquo; can
- be specified to omit merged arena and per arena statistics, respectively;
- &ldquo;b&rdquo; and &ldquo;l&rdquo; can be specified to omit per size
- class statistics for bins and large objects, respectively. Unrecognized
- characters are silently ignored. Note that thread caching may prevent
- some statistics from being completely up to date, since extra locking
- would be required to merge counters that track thread cache operations.
- </para>
-
- <para>The <function>mallctl<parameter/></function> function provides a
- general interface for introspecting the memory allocator, as well as
- setting modifiable parameters and triggering actions. The
- period-separated <parameter>name</parameter> argument specifies a
- location in a tree-structured namespace; see the <xref
- linkend="mallctl_namespace" xrefstyle="template:%t"/> section for
- documentation on the tree contents. To read a value, pass a pointer via
- <parameter>oldp</parameter> to adequate space to contain the value, and a
- pointer to its length via <parameter>oldlenp</parameter>; otherwise pass
- <constant>NULL</constant> and <constant>NULL</constant>. Similarly, to
- write a value, pass a pointer to the value via
- <parameter>newp</parameter>, and its length via
- <parameter>newlen</parameter>; otherwise pass <constant>NULL</constant>
- and <constant>0</constant>.</para>
-
- <para>The <function>mallctlnametomib<parameter/></function> function
- provides a way to avoid repeated name lookups for applications that
- repeatedly query the same portion of the namespace, by translating a name
- to a &ldquo;Management Information Base&rdquo; (MIB) that can be passed
- repeatedly to <function>mallctlbymib<parameter/></function>. Upon
- successful return from <function>mallctlnametomib<parameter/></function>,
- <parameter>mibp</parameter> contains an array of
- <parameter>*miblenp</parameter> integers, where
- <parameter>*miblenp</parameter> is the lesser of the number of components
- in <parameter>name</parameter> and the input value of
- <parameter>*miblenp</parameter>. Thus it is possible to pass a
- <parameter>*miblenp</parameter> that is smaller than the number of
- period-separated name components, which results in a partial MIB that can
- be used as the basis for constructing a complete MIB. For name
- components that are integers (e.g. the 2 in
- <link
- linkend="arenas.bin.i.size"><mallctl>arenas.bin.2.size</mallctl></link>),
- the corresponding MIB component will always be that integer. Therefore,
- it is legitimate to construct code like the following: <programlisting
- language="C"><![CDATA[
-unsigned nbins, i;
-
-int mib[4];
-size_t len, miblen;
-
-len = sizeof(nbins);
-mallctl("arenas.nbins", &nbins, &len, NULL, 0);
-
-miblen = 4;
-mallnametomib("arenas.bin.0.size", mib, &miblen);
-for (i = 0; i < nbins; i++) {
- size_t bin_size;
-
- mib[2] = i;
- len = sizeof(bin_size);
- mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);
- /* Do something with bin_size... */
-}]]></programlisting></para>
- </refsect2>
- <refsect2>
- <title>Experimental API</title>
- <para>The experimental API is subject to change or removal without regard
- for backward compatibility. If <option>--disable-experimental</option>
- is specified during configuration, the experimental API is
- omitted.</para>
-
- <para>The <function>allocm<parameter/></function>,
- <function>rallocm<parameter/></function>,
- <function>sallocm<parameter/></function>,
- <function>dallocm<parameter/></function>, and
- <function>nallocm<parameter/></function> functions all have a
- <parameter>flags</parameter> argument that can be used to specify
- options. The functions only check the options that are contextually
- relevant. Use bitwise or (<code language="C">|</code>) operations to
- specify one or more of the following:
- <variablelist>
- <varlistentry>
- <term><constant>ALLOCM_LG_ALIGN(<parameter>la</parameter>)
- </constant></term>
-
- <listitem><para>Align the memory allocation to start at an address
- that is a multiple of <code language="C">(1 &lt;&lt;
- <parameter>la</parameter>)</code>. This macro does not validate
- that <parameter>la</parameter> is within the valid
- range.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><constant>ALLOCM_ALIGN(<parameter>a</parameter>)
- </constant></term>
-
- <listitem><para>Align the memory allocation to start at an address
- that is a multiple of <parameter>a</parameter>, where
- <parameter>a</parameter> is a power of two. This macro does not
- validate that <parameter>a</parameter> is a power of 2.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><constant>ALLOCM_ZERO</constant></term>
-
- <listitem><para>Initialize newly allocated memory to contain zero
- bytes. In the growing reallocation case, the real size prior to
- reallocation defines the boundary between untouched bytes and those
- that are initialized to contain zero bytes. If this option is
- absent, newly allocated memory is uninitialized.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><constant>ALLOCM_NO_MOVE</constant></term>
-
- <listitem><para>For reallocation, fail rather than moving the
- object. This constraint can apply to both growth and
- shrinkage.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><constant>ALLOCM_ARENA(<parameter>a</parameter>)
- </constant></term>
-
- <listitem><para>Use the arena specified by the index
- <parameter>a</parameter>. This macro does not validate that
- <parameter>a</parameter> specifies an arena in the valid
- range.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- <para>The <function>allocm<parameter/></function> function allocates at
- least <parameter>size</parameter> bytes of memory, sets
- <parameter>*ptr</parameter> to the base address of the allocation, and
- sets <parameter>*rsize</parameter> to the real size of the allocation if
- <parameter>rsize</parameter> is not <constant>NULL</constant>. Behavior
- is undefined if <parameter>size</parameter> is
- <constant>0</constant>.</para>
-
- <para>The <function>rallocm<parameter/></function> function resizes the
- allocation at <parameter>*ptr</parameter> to be at least
- <parameter>size</parameter> bytes, sets <parameter>*ptr</parameter> to
- the base address of the allocation if it moved, and sets
- <parameter>*rsize</parameter> to the real size of the allocation if
- <parameter>rsize</parameter> is not <constant>NULL</constant>. If
- <parameter>extra</parameter> is non-zero, an attempt is made to resize
- the allocation to be at least <code
- language="C"><parameter>size</parameter> +
- <parameter>extra</parameter>)</code> bytes, though inability to allocate
- the extra byte(s) will not by itself result in failure. Behavior is
- undefined if <parameter>size</parameter> is <constant>0</constant>, or if
- <code language="C">(<parameter>size</parameter> +
- <parameter>extra</parameter> &gt;
- <constant>SIZE_T_MAX</constant>)</code>.</para>
-
- <para>The <function>sallocm<parameter/></function> function sets
- <parameter>*rsize</parameter> to the real size of the allocation.</para>
-
- <para>The <function>dallocm<parameter/></function> function causes the
- memory referenced by <parameter>ptr</parameter> to be made available for
- future allocations.</para>
-
- <para>The <function>nallocm<parameter/></function> function allocates no
- memory, but it performs the same size computation as the
- <function>allocm<parameter/></function> function, and if
- <parameter>rsize</parameter> is not <constant>NULL</constant> it sets
- <parameter>*rsize</parameter> to the real size of the allocation that
- would result from the equivalent <function>allocm<parameter/></function>
- function call. Behavior is undefined if
- <parameter>size</parameter> is <constant>0</constant>.</para>
- </refsect2>
- </refsect1>
- <refsect1 id="tuning">
- <title>TUNING</title>
- <para>Once, when the first call is made to one of the memory allocation
- routines, the allocator initializes its internals based in part on various
- options that can be specified at compile- or run-time.</para>
-
- <para>The string pointed to by the global variable
- <varname>malloc_conf</varname>, the &ldquo;name&rdquo; of the file
- referenced by the symbolic link named <filename
- class="symlink">/etc/malloc.conf</filename>, and the value of the
- environment variable <envar>MALLOC_CONF</envar>, will be interpreted, in
- that order, from left to right as options.</para>
-
- <para>An options string is a comma-separated list of option:value pairs.
- There is one key corresponding to each <link
- linkend="opt.abort"><mallctl>opt.*</mallctl></link> mallctl (see the <xref
- linkend="mallctl_namespace" xrefstyle="template:%t"/> section for options
- documentation). For example, <literal>abort:true,narenas:1</literal> sets
- the <link linkend="opt.abort"><mallctl>opt.abort</mallctl></link> and <link
- linkend="opt.narenas"><mallctl>opt.narenas</mallctl></link> options. Some
- options have boolean values (true/false), others have integer values (base
- 8, 10, or 16, depending on prefix), and yet others have raw string
- values.</para>
- </refsect1>
- <refsect1 id="implementation_notes">
- <title>IMPLEMENTATION NOTES</title>
- <para>Traditionally, allocators have used
- <citerefentry><refentrytitle>sbrk</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry> to obtain memory, which is
- suboptimal for several reasons, including race conditions, increased
- fragmentation, and artificial limitations on maximum usable memory. If
- <option>--enable-dss</option> is specified during configuration, this
- allocator uses both <citerefentry><refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry> and
- <citerefentry><refentrytitle>sbrk</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry>, in that order of preference;
- otherwise only <citerefentry><refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry> is used.</para>
-
- <para>This allocator uses multiple arenas in order to reduce lock
- contention for threaded programs on multi-processor systems. This works
- well with regard to threading scalability, but incurs some costs. There is
- a small fixed per-arena overhead, and additionally, arenas manage memory
- completely independently of each other, which means a small fixed increase
- in overall memory fragmentation. These overheads are not generally an
- issue, given the number of arenas normally used. Note that using
- substantially more arenas than the default is not likely to improve
- performance, mainly due to reduced cache performance. However, it may make
- sense to reduce the number of arenas if an application does not make much
- use of the allocation functions.</para>
-
- <para>In addition to multiple arenas, unless
- <option>--disable-tcache</option> is specified during configuration, this
- allocator supports thread-specific caching for small and large objects, in
- order to make it possible to completely avoid synchronization for most
- allocation requests. Such caching allows very fast allocation in the
- common case, but it increases memory usage and fragmentation, since a
- bounded number of objects can remain allocated in each thread cache.</para>
-
- <para>Memory is conceptually broken into equal-sized chunks, where the
- chunk size is a power of two that is greater than the page size. Chunks
- are always aligned to multiples of the chunk size. This alignment makes it
- possible to find metadata for user objects very quickly.</para>
-
- <para>User objects are broken into three categories according to size:
- small, large, and huge. Small objects are smaller than one page. Large
- objects are smaller than the chunk size. Huge objects are a multiple of
- the chunk size. Small and large objects are managed by arenas; huge
- objects are managed separately in a single data structure that is shared by
- all threads. Huge objects are used by applications infrequently enough
- that this single data structure is not a scalability issue.</para>
-
- <para>Each chunk that is managed by an arena tracks its contents as runs of
- contiguous pages (unused, backing a set of small objects, or backing one
- large object). The combination of chunk alignment and chunk page maps
- makes it possible to determine all metadata regarding small and large
- allocations in constant time.</para>
-
- <para>Small objects are managed in groups by page runs. Each run maintains
- a frontier and free list to track which regions are in use. Allocation
- requests that are no more than half the quantum (8 or 16, depending on
- architecture) are rounded up to the nearest power of two that is at least
- <code language="C">sizeof(<type>double</type>)</code>. All other small
- object size classes are multiples of the quantum, spaced such that internal
- fragmentation is limited to approximately 25% for all but the smallest size
- classes. Allocation requests that are larger than the maximum small size
- class, but small enough to fit in an arena-managed chunk (see the <link
- linkend="opt.lg_chunk"><mallctl>opt.lg_chunk</mallctl></link> option), are
- rounded up to the nearest run size. Allocation requests that are too large
- to fit in an arena-managed chunk are rounded up to the nearest multiple of
- the chunk size.</para>
-
- <para>Allocations are packed tightly together, which can be an issue for
- multi-threaded applications. If you need to assure that allocations do not
- suffer from cacheline sharing, round your allocation requests up to the
- nearest multiple of the cacheline size, or specify cacheline alignment when
- allocating.</para>
-
- <para>Assuming 4 MiB chunks, 4 KiB pages, and a 16-byte quantum on a 64-bit
- system, the size classes in each category are as shown in <xref
- linkend="size_classes" xrefstyle="template:Table %n"/>.</para>
-
- <table xml:id="size_classes" frame="all">
- <title>Size classes</title>
- <tgroup cols="3" colsep="1" rowsep="1">
- <colspec colname="c1" align="left"/>
- <colspec colname="c2" align="right"/>
- <colspec colname="c3" align="left"/>
- <thead>
- <row>
- <entry>Category</entry>
- <entry>Spacing</entry>
- <entry>Size</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry morerows="6">Small</entry>
- <entry>lg</entry>
- <entry>[8]</entry>
- </row>
- <row>
- <entry>16</entry>
- <entry>[16, 32, 48, ..., 128]</entry>
- </row>
- <row>
- <entry>32</entry>
- <entry>[160, 192, 224, 256]</entry>
- </row>
- <row>
- <entry>64</entry>
- <entry>[320, 384, 448, 512]</entry>
- </row>
- <row>
- <entry>128</entry>
- <entry>[640, 768, 896, 1024]</entry>
- </row>
- <row>
- <entry>256</entry>
- <entry>[1280, 1536, 1792, 2048]</entry>
- </row>
- <row>
- <entry>512</entry>
- <entry>[2560, 3072, 3584]</entry>
- </row>
- <row>
- <entry>Large</entry>
- <entry>4 KiB</entry>
- <entry>[4 KiB, 8 KiB, 12 KiB, ..., 4072 KiB]</entry>
- </row>
- <row>
- <entry>Huge</entry>
- <entry>4 MiB</entry>
- <entry>[4 MiB, 8 MiB, 12 MiB, ...]</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
- <refsect1 id="mallctl_namespace">
- <title>MALLCTL NAMESPACE</title>
- <para>The following names are defined in the namespace accessible via the
- <function>mallctl*<parameter/></function> functions. Value types are
- specified in parentheses, their readable/writable statuses are encoded as
- <literal>rw</literal>, <literal>r-</literal>, <literal>-w</literal>, or
- <literal>--</literal>, and required build configuration flags follow, if
- any. A name element encoded as <literal>&lt;i&gt;</literal> or
- <literal>&lt;j&gt;</literal> indicates an integer component, where the
- integer varies from 0 to some upper value that must be determined via
- introspection. In the case of <mallctl>stats.arenas.&lt;i&gt;.*</mallctl>,
- <literal>&lt;i&gt;</literal> equal to <link
- linkend="arenas.narenas"><mallctl>arenas.narenas</mallctl></link> can be
- used to access the summation of statistics from all arenas. Take special
- note of the <link linkend="epoch"><mallctl>epoch</mallctl></link> mallctl,
- which controls refreshing of cached dynamic statistics.</para>
-
- <variablelist>
- <varlistentry>
- <term>
- <mallctl>version</mallctl>
- (<type>const char *</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Return the jemalloc version string.</para></listitem>
- </varlistentry>
-
- <varlistentry id="epoch">
- <term>
- <mallctl>epoch</mallctl>
- (<type>uint64_t</type>)
- <literal>rw</literal>
- </term>
- <listitem><para>If a value is passed in, refresh the data from which
- the <function>mallctl*<parameter/></function> functions report values,
- and increment the epoch. Return the current epoch. This is useful for
- detecting whether another thread caused a refresh.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.debug</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-debug</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.dss</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-dss</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.fill</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-fill</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.lazy_lock</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-lazy-lock</option> was specified
- during build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.mremap</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-mremap</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.munmap</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-munmap</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.prof</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-prof</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.prof_libgcc</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--disable-prof-libgcc</option> was not
- specified during build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.prof_libunwind</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-prof-libunwind</option> was specified
- during build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.stats</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-stats</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.tcache</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--disable-tcache</option> was not specified
- during build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.tls</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--disable-tls</option> was not specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.utrace</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-utrace</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.valgrind</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-valgrind</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>config.xmalloc</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para><option>--enable-xmalloc</option> was specified during
- build configuration.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.abort">
- <term>
- <mallctl>opt.abort</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Abort-on-warning enabled/disabled. If true, most
- warnings are fatal. The process will call
- <citerefentry><refentrytitle>abort</refentrytitle>
- <manvolnum>3</manvolnum></citerefentry> in these cases. This option is
- disabled by default unless <option>--enable-debug</option> is
- specified during configuration, in which case it is enabled by default.
- </para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.lg_chunk">
- <term>
- <mallctl>opt.lg_chunk</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Virtual memory chunk size (log base 2). If a chunk
- size outside the supported size range is specified, the size is
- silently clipped to the minimum/maximum supported size. The default
- chunk size is 4 MiB (2^22).
- </para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.dss">
- <term>
- <mallctl>opt.dss</mallctl>
- (<type>const char *</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry>) allocation precedence as
- related to <citerefentry><refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry> allocation. The following
- settings are supported: &ldquo;disabled&rdquo;, &ldquo;primary&rdquo;,
- and &ldquo;secondary&rdquo; (default).</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.narenas">
- <term>
- <mallctl>opt.narenas</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Maximum number of arenas to use for automatic
- multiplexing of threads and arenas. The default is four times the
- number of CPUs, or one if there is a single CPU.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.lg_dirty_mult">
- <term>
- <mallctl>opt.lg_dirty_mult</mallctl>
- (<type>ssize_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Per-arena minimum ratio (log base 2) of active to dirty
- pages. Some dirty unused pages may be allowed to accumulate, within
- the limit set by the ratio (or one chunk worth of dirty pages,
- whichever is greater), before informing the kernel about some of those
- pages via <citerefentry><refentrytitle>madvise</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry> or a similar system call. This
- provides the kernel with sufficient information to recycle dirty pages
- if physical memory becomes scarce and the pages remain unused. The
- default minimum ratio is 8:1 (2^3:1); an option value of -1 will
- disable dirty page purging.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.stats_print">
- <term>
- <mallctl>opt.stats_print</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Enable/disable statistics printing at exit. If
- enabled, the <function>malloc_stats_print<parameter/></function>
- function is called at program exit via an
- <citerefentry><refentrytitle>atexit</refentrytitle>
- <manvolnum>3</manvolnum></citerefentry> function. If
- <option>--enable-stats</option> is specified during configuration, this
- has the potential to cause deadlock for a multi-threaded process that
- exits while one or more threads are executing in the memory allocation
- functions. Therefore, this option should only be used with care; it is
- primarily intended as a performance tuning aid during application
- development. This option is disabled by default.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.junk">
- <term>
- <mallctl>opt.junk</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-fill</option>]
- </term>
- <listitem><para>Junk filling enabled/disabled. If enabled, each byte
- of uninitialized allocated memory will be initialized to
- <literal>0xa5</literal>. All deallocated memory will be initialized to
- <literal>0x5a</literal>. This is intended for debugging and will
- impact performance negatively. This option is disabled by default
- unless <option>--enable-debug</option> is specified during
- configuration, in which case it is enabled by default unless running
- inside <ulink
- url="http://valgrind.org/">Valgrind</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.quarantine">
- <term>
- <mallctl>opt.quarantine</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-fill</option>]
- </term>
- <listitem><para>Per thread quarantine size in bytes. If non-zero, each
- thread maintains a FIFO object quarantine that stores up to the
- specified number of bytes of memory. The quarantined memory is not
- freed until it is released from quarantine, though it is immediately
- junk-filled if the <link
- linkend="opt.junk"><mallctl>opt.junk</mallctl></link> option is
- enabled. This feature is of particular use in combination with <ulink
- url="http://valgrind.org/">Valgrind</ulink>, which can detect attempts
- to access quarantined objects. This is intended for debugging and will
- impact performance negatively. The default quarantine size is 0 unless
- running inside Valgrind, in which case the default is 16
- MiB.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.redzone">
- <term>
- <mallctl>opt.redzone</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-fill</option>]
- </term>
- <listitem><para>Redzones enabled/disabled. If enabled, small
- allocations have redzones before and after them. Furthermore, if the
- <link linkend="opt.junk"><mallctl>opt.junk</mallctl></link> option is
- enabled, the redzones are checked for corruption during deallocation.
- However, the primary intended purpose of this feature is to be used in
- combination with <ulink url="http://valgrind.org/">Valgrind</ulink>,
- which needs redzones in order to do effective buffer overflow/underflow
- detection. This option is intended for debugging and will impact
- performance negatively. This option is disabled by
- default unless running inside Valgrind.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.zero">
- <term>
- <mallctl>opt.zero</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-fill</option>]
- </term>
- <listitem><para>Zero filling enabled/disabled. If enabled, each byte
- of uninitialized allocated memory will be initialized to 0. Note that
- this initialization only happens once for each byte, so
- <function>realloc<parameter/></function> and
- <function>rallocm<parameter/></function> calls do not zero memory that
- was previously allocated. This is intended for debugging and will
- impact performance negatively. This option is disabled by default.
- </para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.utrace">
- <term>
- <mallctl>opt.utrace</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-utrace</option>]
- </term>
- <listitem><para>Allocation tracing based on
- <citerefentry><refentrytitle>utrace</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry> enabled/disabled. This option
- is disabled by default.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.valgrind">
- <term>
- <mallctl>opt.valgrind</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-valgrind</option>]
- </term>
- <listitem><para><ulink url="http://valgrind.org/">Valgrind</ulink>
- support enabled/disabled. This option is vestigal because jemalloc
- auto-detects whether it is running inside Valgrind. This option is
- disabled by default, unless running inside Valgrind.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.xmalloc">
- <term>
- <mallctl>opt.xmalloc</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-xmalloc</option>]
- </term>
- <listitem><para>Abort-on-out-of-memory enabled/disabled. If enabled,
- rather than returning failure for any allocation function, display a
- diagnostic message on <constant>STDERR_FILENO</constant> and cause the
- program to drop core (using
- <citerefentry><refentrytitle>abort</refentrytitle>
- <manvolnum>3</manvolnum></citerefentry>). If an application is
- designed to depend on this behavior, set the option at compile time by
- including the following in the source code:
- <programlisting language="C"><![CDATA[
-malloc_conf = "xmalloc:true";]]></programlisting>
- This option is disabled by default.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.tcache">
- <term>
- <mallctl>opt.tcache</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-tcache</option>]
- </term>
- <listitem><para>Thread-specific caching enabled/disabled. When there
- are multiple threads, each thread uses a thread-specific cache for
- objects up to a certain size. Thread-specific caching allows many
- allocations to be satisfied without performing any thread
- synchronization, at the cost of increased memory use. See the
- <link
- linkend="opt.lg_tcache_max"><mallctl>opt.lg_tcache_max</mallctl></link>
- option for related tuning information. This option is enabled by
- default unless running inside <ulink
- url="http://valgrind.org/">Valgrind</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.lg_tcache_max">
- <term>
- <mallctl>opt.lg_tcache_max</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-tcache</option>]
- </term>
- <listitem><para>Maximum size class (log base 2) to cache in the
- thread-specific cache. At a minimum, all small size classes are
- cached, and at a maximum all large size classes are cached. The
- default maximum is 32 KiB (2^15).</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.prof">
- <term>
- <mallctl>opt.prof</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Memory profiling enabled/disabled. If enabled, profile
- memory allocation activity. See the <link
- linkend="opt.prof_active"><mallctl>opt.prof_active</mallctl></link>
- option for on-the-fly activation/deactivation. See the <link
- linkend="opt.lg_prof_sample"><mallctl>opt.lg_prof_sample</mallctl></link>
- option for probabilistic sampling control. See the <link
- linkend="opt.prof_accum"><mallctl>opt.prof_accum</mallctl></link>
- option for control of cumulative sample reporting. See the <link
- linkend="opt.lg_prof_interval"><mallctl>opt.lg_prof_interval</mallctl></link>
- option for information on interval-triggered profile dumping, the <link
- linkend="opt.prof_gdump"><mallctl>opt.prof_gdump</mallctl></link>
- option for information on high-water-triggered profile dumping, and the
- <link linkend="opt.prof_final"><mallctl>opt.prof_final</mallctl></link>
- option for final profile dumping. Profile output is compatible with
- the included <command>pprof</command> Perl script, which originates
- from the <ulink url="http://code.google.com/p/gperftools/">gperftools
- package</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.prof_prefix">
- <term>
- <mallctl>opt.prof_prefix</mallctl>
- (<type>const char *</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Filename prefix for profile dumps. If the prefix is
- set to the empty string, no automatic dumps will occur; this is
- primarily useful for disabling the automatic final heap dump (which
- also disables leak reporting, if enabled). The default prefix is
- <filename>jeprof</filename>.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.prof_active">
- <term>
- <mallctl>opt.prof_active</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Profiling activated/deactivated. This is a secondary
- control mechanism that makes it possible to start the application with
- profiling enabled (see the <link
- linkend="opt.prof"><mallctl>opt.prof</mallctl></link> option) but
- inactive, then toggle profiling at any time during program execution
- with the <link
- linkend="prof.active"><mallctl>prof.active</mallctl></link> mallctl.
- This option is enabled by default.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.lg_prof_sample">
- <term>
- <mallctl>opt.lg_prof_sample</mallctl>
- (<type>ssize_t</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Average interval (log base 2) between allocation
- samples, as measured in bytes of allocation activity. Increasing the
- sampling interval decreases profile fidelity, but also decreases the
- computational overhead. The default sample interval is 512 KiB (2^19
- B).</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.prof_accum">
- <term>
- <mallctl>opt.prof_accum</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Reporting of cumulative object/byte counts in profile
- dumps enabled/disabled. If this option is enabled, every unique
- backtrace must be stored for the duration of execution. Depending on
- the application, this can impose a large memory overhead, and the
- cumulative counts are not always of interest. This option is disabled
- by default.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.lg_prof_interval">
- <term>
- <mallctl>opt.lg_prof_interval</mallctl>
- (<type>ssize_t</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Average interval (log base 2) between memory profile
- dumps, as measured in bytes of allocation activity. The actual
- interval between dumps may be sporadic because decentralized allocation
- counters are used to avoid synchronization bottlenecks. Profiles are
- dumped to files named according to the pattern
- <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.i&lt;iseq&gt;.heap</filename>,
- where <literal>&lt;prefix&gt;</literal> is controlled by the
- <link
- linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link>
- option. By default, interval-triggered profile dumping is disabled
- (encoded as -1).
- </para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.prof_gdump">
- <term>
- <mallctl>opt.prof_gdump</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Trigger a memory profile dump every time the total
- virtual memory exceeds the previous maximum. Profiles are dumped to
- files named according to the pattern
- <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.u&lt;useq&gt;.heap</filename>,
- where <literal>&lt;prefix&gt;</literal> is controlled by the <link
- linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link>
- option. This option is disabled by default.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.prof_final">
- <term>
- <mallctl>opt.prof_final</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Use an
- <citerefentry><refentrytitle>atexit</refentrytitle>
- <manvolnum>3</manvolnum></citerefentry> function to dump final memory
- usage to a file named according to the pattern
- <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.f.heap</filename>,
- where <literal>&lt;prefix&gt;</literal> is controlled by the <link
- linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link>
- option. This option is enabled by default.</para></listitem>
- </varlistentry>
-
- <varlistentry id="opt.prof_leak">
- <term>
- <mallctl>opt.prof_leak</mallctl>
- (<type>bool</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Leak reporting enabled/disabled. If enabled, use an
- <citerefentry><refentrytitle>atexit</refentrytitle>
- <manvolnum>3</manvolnum></citerefentry> function to report memory leaks
- detected by allocation sampling. See the
- <link linkend="opt.prof"><mallctl>opt.prof</mallctl></link> option for
- information on analyzing heap profile output. This option is disabled
- by default.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>thread.arena</mallctl>
- (<type>unsigned</type>)
- <literal>rw</literal>
- </term>
- <listitem><para>Get or set the arena associated with the calling
- thread. If the specified arena was not initialized beforehand (see the
- <link
- linkend="arenas.initialized"><mallctl>arenas.initialized</mallctl></link>
- mallctl), it will be automatically initialized as a side effect of
- calling this interface.</para></listitem>
- </varlistentry>
-
- <varlistentry id="thread.allocated">
- <term>
- <mallctl>thread.allocated</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Get the total number of bytes ever allocated by the
- calling thread. This counter has the potential to wrap around; it is
- up to the application to appropriately interpret the counter in such
- cases.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>thread.allocatedp</mallctl>
- (<type>uint64_t *</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Get a pointer to the the value that is returned by the
- <link
- linkend="thread.allocated"><mallctl>thread.allocated</mallctl></link>
- mallctl. This is useful for avoiding the overhead of repeated
- <function>mallctl*<parameter/></function> calls.</para></listitem>
- </varlistentry>
-
- <varlistentry id="thread.deallocated">
- <term>
- <mallctl>thread.deallocated</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Get the total number of bytes ever deallocated by the
- calling thread. This counter has the potential to wrap around; it is
- up to the application to appropriately interpret the counter in such
- cases.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>thread.deallocatedp</mallctl>
- (<type>uint64_t *</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Get a pointer to the the value that is returned by the
- <link
- linkend="thread.deallocated"><mallctl>thread.deallocated</mallctl></link>
- mallctl. This is useful for avoiding the overhead of repeated
- <function>mallctl*<parameter/></function> calls.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>thread.tcache.enabled</mallctl>
- (<type>bool</type>)
- <literal>rw</literal>
- [<option>--enable-tcache</option>]
- </term>
- <listitem><para>Enable/disable calling thread's tcache. The tcache is
- implicitly flushed as a side effect of becoming
- disabled (see <link
- lenkend="thread.tcache.flush"><mallctl>thread.tcache.flush</mallctl></link>).
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>thread.tcache.flush</mallctl>
- (<type>void</type>)
- <literal>--</literal>
- [<option>--enable-tcache</option>]
- </term>
- <listitem><para>Flush calling thread's tcache. This interface releases
- all cached objects and internal data structures associated with the
- calling thread's thread-specific cache. Ordinarily, this interface
- need not be called, since automatic periodic incremental garbage
- collection occurs, and the thread cache is automatically discarded when
- a thread exits. However, garbage collection is triggered by allocation
- activity, so it is possible for a thread that stops
- allocating/deallocating to retain its cache indefinitely, in which case
- the developer may find manual flushing useful.</para></listitem>
- </varlistentry>
-
- <varlistentry id="arena.i.purge">
- <term>
- <mallctl>arena.&lt;i&gt;.purge</mallctl>
- (<type>unsigned</type>)
- <literal>--</literal>
- </term>
- <listitem><para>Purge unused dirty pages for arena &lt;i&gt;, or for
- all arenas if &lt;i&gt; equals <link
- linkend="arenas.narenas"><mallctl>arenas.narenas</mallctl></link>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry id="arena.i.dss">
- <term>
- <mallctl>arena.&lt;i&gt;.dss</mallctl>
- (<type>const char *</type>)
- <literal>rw</literal>
- </term>
- <listitem><para>Set the precedence of dss allocation as related to mmap
- allocation for arena &lt;i&gt;, or for all arenas if &lt;i&gt; equals
- <link
- linkend="arenas.narenas"><mallctl>arenas.narenas</mallctl></link>. See
- <link linkend="opt.dss"><mallctl>opt.dss</mallctl></link> for supported
- settings.
- </para></listitem>
- </varlistentry>
-
- <varlistentry id="arenas.narenas">
- <term>
- <mallctl>arenas.narenas</mallctl>
- (<type>unsigned</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Current limit on number of arenas.</para></listitem>
- </varlistentry>
-
- <varlistentry id="arenas.initialized">
- <term>
- <mallctl>arenas.initialized</mallctl>
- (<type>bool *</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>An array of <link
- linkend="arenas.narenas"><mallctl>arenas.narenas</mallctl></link>
- booleans. Each boolean indicates whether the corresponding arena is
- initialized.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.quantum</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Quantum size.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.page</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Page size.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.tcache_max</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-tcache</option>]
- </term>
- <listitem><para>Maximum thread-cached size class.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.nbins</mallctl>
- (<type>unsigned</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Number of bin size classes.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.nhbins</mallctl>
- (<type>unsigned</type>)
- <literal>r-</literal>
- [<option>--enable-tcache</option>]
- </term>
- <listitem><para>Total number of thread cache bin size
- classes.</para></listitem>
- </varlistentry>
-
- <varlistentry id="arenas.bin.i.size">
- <term>
- <mallctl>arenas.bin.&lt;i&gt;.size</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Maximum size supported by size class.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.bin.&lt;i&gt;.nregs</mallctl>
- (<type>uint32_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Number of regions per page run.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.bin.&lt;i&gt;.run_size</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Number of bytes per page run.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.nlruns</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Total number of large size classes.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.lrun.&lt;i&gt;.size</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Maximum size supported by this large size
- class.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.purge</mallctl>
- (<type>unsigned</type>)
- <literal>-w</literal>
- </term>
- <listitem><para>Purge unused dirty pages for the specified arena, or
- for all arenas if none is specified.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>arenas.extend</mallctl>
- (<type>unsigned</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Extend the array of arenas by appending a new arena,
- and returning the new arena index.</para></listitem>
- </varlistentry>
-
- <varlistentry id="prof.active">
- <term>
- <mallctl>prof.active</mallctl>
- (<type>bool</type>)
- <literal>rw</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Control whether sampling is currently active. See the
- <link
- linkend="opt.prof_active"><mallctl>opt.prof_active</mallctl></link>
- option for additional information.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>prof.dump</mallctl>
- (<type>const char *</type>)
- <literal>-w</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Dump a memory profile to the specified file, or if NULL
- is specified, to a file according to the pattern
- <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.m&lt;mseq&gt;.heap</filename>,
- where <literal>&lt;prefix&gt;</literal> is controlled by the
- <link
- linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link>
- option.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>prof.interval</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-prof</option>]
- </term>
- <listitem><para>Average number of bytes allocated between
- inverval-based profile dumps. See the
- <link
- linkend="opt.lg_prof_interval"><mallctl>opt.lg_prof_interval</mallctl></link>
- option for additional information.</para></listitem>
- </varlistentry>
-
- <varlistentry id="stats.cactive">
- <term>
- <mallctl>stats.cactive</mallctl>
- (<type>size_t *</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Pointer to a counter that contains an approximate count
- of the current number of bytes in active pages. The estimate may be
- high, but never low, because each arena rounds up to the nearest
- multiple of the chunk size when computing its contribution to the
- counter. Note that the <link
- linkend="epoch"><mallctl>epoch</mallctl></link> mallctl has no bearing
- on this counter. Furthermore, counter consistency is maintained via
- atomic operations, so it is necessary to use an atomic operation in
- order to guarantee a consistent read when dereferencing the pointer.
- </para></listitem>
- </varlistentry>
-
- <varlistentry id="stats.allocated">
- <term>
- <mallctl>stats.allocated</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Total number of bytes allocated by the
- application.</para></listitem>
- </varlistentry>
-
- <varlistentry id="stats.active">
- <term>
- <mallctl>stats.active</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Total number of bytes in active pages allocated by the
- application. This is a multiple of the page size, and greater than or
- equal to <link
- linkend="stats.allocated"><mallctl>stats.allocated</mallctl></link>.
- This does not include <link linkend="stats.arenas.i.pdirty">
- <mallctl>stats.arenas.&lt;i&gt;.pdirty</mallctl></link> and pages
- entirely devoted to allocator metadata.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.mapped</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Total number of bytes in chunks mapped on behalf of the
- application. This is a multiple of the chunk size, and is at least as
- large as <link
- linkend="stats.active"><mallctl>stats.active</mallctl></link>. This
- does not include inactive chunks.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.chunks.current</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Total number of chunks actively mapped on behalf of the
- application. This does not include inactive chunks.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.chunks.total</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of chunks allocated.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.chunks.high</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Maximum number of active chunks at any time thus far.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.huge.allocated</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Number of bytes currently allocated by huge objects.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.huge.nmalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of huge allocation requests.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.huge.ndalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of huge deallocation requests.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.dss</mallctl>
- (<type>const char *</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry>) allocation precedence as
- related to <citerefentry><refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry> allocation. See <link
- linkend="opt.dss"><mallctl>opt.dss</mallctl></link> for details.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.nthreads</mallctl>
- (<type>unsigned</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Number of threads currently assigned to
- arena.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.pactive</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Number of pages in active runs.</para></listitem>
- </varlistentry>
-
- <varlistentry id="stats.arenas.i.pdirty">
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.pdirty</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- </term>
- <listitem><para>Number of pages within unused runs that are potentially
- dirty, and for which <function>madvise<parameter>...</parameter>
- <parameter><constant>MADV_DONTNEED</constant></parameter></function> or
- similar has not been called.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.mapped</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Number of mapped bytes.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.npurge</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Number of dirty page purge sweeps performed.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.nmadvise</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Number of <function>madvise<parameter>...</parameter>
- <parameter><constant>MADV_DONTNEED</constant></parameter></function> or
- similar calls made to purge dirty pages.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.npurged</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Number of pages purged.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.small.allocated</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Number of bytes currently allocated by small objects.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.small.nmalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of allocation requests served by
- small bins.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.small.ndalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of small objects returned to bins.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.small.nrequests</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of small allocation requests.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.large.allocated</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Number of bytes currently allocated by large objects.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.large.nmalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of large allocation requests served
- directly by the arena.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.large.ndalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of large deallocation requests served
- directly by the arena.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.large.nrequests</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of large allocation requests.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.allocated</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Current number of bytes allocated by
- bin.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nmalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of allocations served by bin.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.ndalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of allocations returned to bin.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nrequests</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of allocation
- requests.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nfills</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option> <option>--enable-tcache</option>]
- </term>
- <listitem><para>Cumulative number of tcache fills.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nflushes</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option> <option>--enable-tcache</option>]
- </term>
- <listitem><para>Cumulative number of tcache flushes.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nruns</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of runs created.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.nreruns</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of times the current run from which
- to allocate changed.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.bins.&lt;j&gt;.curruns</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Current number of runs.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nmalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of allocation requests for this size
- class served directly by the arena.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.ndalloc</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of deallocation requests for this
- size class served directly by the arena.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.nrequests</mallctl>
- (<type>uint64_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Cumulative number of allocation requests for this size
- class.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term>
- <mallctl>stats.arenas.&lt;i&gt;.lruns.&lt;j&gt;.curruns</mallctl>
- (<type>size_t</type>)
- <literal>r-</literal>
- [<option>--enable-stats</option>]
- </term>
- <listitem><para>Current number of runs for this size class.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
- <refsect1 id="debugging_malloc_problems">
- <title>DEBUGGING MALLOC PROBLEMS</title>
- <para>When debugging, it is a good idea to configure/build jemalloc with
- the <option>--enable-debug</option> and <option>--enable-fill</option>
- options, and recompile the program with suitable options and symbols for
- debugger support. When so configured, jemalloc incorporates a wide variety
- of run-time assertions that catch application errors such as double-free,
- write-after-free, etc.</para>
-
- <para>Programs often accidentally depend on &ldquo;uninitialized&rdquo;
- memory actually being filled with zero bytes. Junk filling
- (see the <link linkend="opt.junk"><mallctl>opt.junk</mallctl></link>
- option) tends to expose such bugs in the form of obviously incorrect
- results and/or coredumps. Conversely, zero
- filling (see the <link
- linkend="opt.zero"><mallctl>opt.zero</mallctl></link> option) eliminates
- the symptoms of such bugs. Between these two options, it is usually
- possible to quickly detect, diagnose, and eliminate such bugs.</para>
-
- <para>This implementation does not provide much detail about the problems
- it detects, because the performance impact for storing such information
- would be prohibitive. However, jemalloc does integrate with the most
- excellent <ulink url="http://valgrind.org/">Valgrind</ulink> tool if the
- <option>--enable-valgrind</option> configuration option is enabled.</para>
- </refsect1>
- <refsect1 id="diagnostic_messages">
- <title>DIAGNOSTIC MESSAGES</title>
- <para>If any of the memory allocation/deallocation functions detect an
- error or warning condition, a message will be printed to file descriptor
- <constant>STDERR_FILENO</constant>. Errors will result in the process
- dumping core. If the <link
- linkend="opt.abort"><mallctl>opt.abort</mallctl></link> option is set, most
- warnings are treated as errors.</para>
-
- <para>The <varname>malloc_message</varname> variable allows the programmer
- to override the function which emits the text strings forming the errors
- and warnings if for some reason the <constant>STDERR_FILENO</constant> file
- descriptor is not suitable for this.
- <function>malloc_message<parameter/></function> takes the
- <parameter>cbopaque</parameter> pointer argument that is
- <constant>NULL</constant> unless overridden by the arguments in a call to
- <function>malloc_stats_print<parameter/></function>, followed by a string
- pointer. Please note that doing anything which tries to allocate memory in
- this function is likely to result in a crash or deadlock.</para>
-
- <para>All messages are prefixed by
- &ldquo;<computeroutput>&lt;jemalloc&gt;: </computeroutput>&rdquo;.</para>
- </refsect1>
- <refsect1 id="return_values">
- <title>RETURN VALUES</title>
- <refsect2>
- <title>Standard API</title>
- <para>The <function>malloc<parameter/></function> and
- <function>calloc<parameter/></function> functions return a pointer to the
- allocated memory if successful; otherwise a <constant>NULL</constant>
- pointer is returned and <varname>errno</varname> is set to
- <errorname>ENOMEM</errorname>.</para>
-
- <para>The <function>posix_memalign<parameter/></function> function
- returns the value 0 if successful; otherwise it returns an error value.
- The <function>posix_memalign<parameter/></function> function will fail
- if:
- <variablelist>
- <varlistentry>
- <term><errorname>EINVAL</errorname></term>
-
- <listitem><para>The <parameter>alignment</parameter> parameter is
- not a power of 2 at least as large as
- <code language="C">sizeof(<type>void *</type>)</code>.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><errorname>ENOMEM</errorname></term>
-
- <listitem><para>Memory allocation error.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- <para>The <function>aligned_alloc<parameter/></function> function returns
- a pointer to the allocated memory if successful; otherwise a
- <constant>NULL</constant> pointer is returned and
- <varname>errno</varname> is set. The
- <function>aligned_alloc<parameter/></function> function will fail if:
- <variablelist>
- <varlistentry>
- <term><errorname>EINVAL</errorname></term>
-
- <listitem><para>The <parameter>alignment</parameter> parameter is
- not a power of 2.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><errorname>ENOMEM</errorname></term>
-
- <listitem><para>Memory allocation error.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- <para>The <function>realloc<parameter/></function> function returns a
- pointer, possibly identical to <parameter>ptr</parameter>, to the
- allocated memory if successful; otherwise a <constant>NULL</constant>
- pointer is returned, and <varname>errno</varname> is set to
- <errorname>ENOMEM</errorname> if the error was the result of an
- allocation failure. The <function>realloc<parameter/></function>
- function always leaves the original buffer intact when an error occurs.
- </para>
-
- <para>The <function>free<parameter/></function> function returns no
- value.</para>
- </refsect2>
- <refsect2>
- <title>Non-standard API</title>
- <para>The <function>malloc_usable_size<parameter/></function> function
- returns the usable size of the allocation pointed to by
- <parameter>ptr</parameter>. </para>
-
- <para>The <function>mallctl<parameter/></function>,
- <function>mallctlnametomib<parameter/></function>, and
- <function>mallctlbymib<parameter/></function> functions return 0 on
- success; otherwise they return an error value. The functions will fail
- if:
- <variablelist>
- <varlistentry>
- <term><errorname>EINVAL</errorname></term>
-
- <listitem><para><parameter>newp</parameter> is not
- <constant>NULL</constant>, and <parameter>newlen</parameter> is too
- large or too small. Alternatively, <parameter>*oldlenp</parameter>
- is too large or too small; in this case as much data as possible
- are read despite the error.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><errorname>ENOMEM</errorname></term>
-
- <listitem><para><parameter>*oldlenp</parameter> is too short to
- hold the requested value.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><errorname>ENOENT</errorname></term>
-
- <listitem><para><parameter>name</parameter> or
- <parameter>mib</parameter> specifies an unknown/invalid
- value.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><errorname>EPERM</errorname></term>
-
- <listitem><para>Attempt to read or write void value, or attempt to
- write read-only value.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><errorname>EAGAIN</errorname></term>
-
- <listitem><para>A memory allocation failure
- occurred.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><errorname>EFAULT</errorname></term>
-
- <listitem><para>An interface with side effects failed in some way
- not directly related to <function>mallctl*<parameter/></function>
- read/write processing.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
- </refsect2>
- <refsect2>
- <title>Experimental API</title>
- <para>The <function>allocm<parameter/></function>,
- <function>rallocm<parameter/></function>,
- <function>sallocm<parameter/></function>,
- <function>dallocm<parameter/></function>, and
- <function>nallocm<parameter/></function> functions return
- <constant>ALLOCM_SUCCESS</constant> on success; otherwise they return an
- error value. The <function>allocm<parameter/></function>,
- <function>rallocm<parameter/></function>, and
- <function>nallocm<parameter/></function> functions will fail if:
- <variablelist>
- <varlistentry>
- <term><errorname>ALLOCM_ERR_OOM</errorname></term>
-
- <listitem><para>Out of memory. Insufficient contiguous memory was
- available to service the allocation request. The
- <function>allocm<parameter/></function> function additionally sets
- <parameter>*ptr</parameter> to <constant>NULL</constant>, whereas
- the <function>rallocm<parameter/></function> function leaves
- <constant>*ptr</constant> unmodified.</para></listitem>
- </varlistentry>
- </variablelist>
- The <function>rallocm<parameter/></function> function will also
- fail if:
- <variablelist>
- <varlistentry>
- <term><errorname>ALLOCM_ERR_NOT_MOVED</errorname></term>
-
- <listitem><para><constant>ALLOCM_NO_MOVE</constant> was specified,
- but the reallocation request could not be serviced without moving
- the object.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
- </refsect2>
- </refsect1>
- <refsect1 id="environment">
- <title>ENVIRONMENT</title>
- <para>The following environment variable affects the execution of the
- allocation functions:
- <variablelist>
- <varlistentry>
- <term><envar>MALLOC_CONF</envar></term>
-
- <listitem><para>If the environment variable
- <envar>MALLOC_CONF</envar> is set, the characters it contains
- will be interpreted as options.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
- </refsect1>
- <refsect1 id="examples">
- <title>EXAMPLES</title>
- <para>To dump core whenever a problem occurs:
- <screen>ln -s 'abort:true' /etc/malloc.conf</screen>
- </para>
- <para>To specify in the source a chunk size that is 16 MiB:
- <programlisting language="C"><![CDATA[
-malloc_conf = "lg_chunk:24";]]></programlisting></para>
- </refsect1>
- <refsect1 id="see_also">
- <title>SEE ALSO</title>
- <para><citerefentry><refentrytitle>madvise</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sbrk</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>utrace</refentrytitle>
- <manvolnum>2</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>alloca</refentrytitle>
- <manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>atexit</refentrytitle>
- <manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>getpagesize</refentrytitle>
- <manvolnum>3</manvolnum></citerefentry></para>
- </refsect1>
- <refsect1 id="standards">
- <title>STANDARDS</title>
- <para>The <function>malloc<parameter/></function>,
- <function>calloc<parameter/></function>,
- <function>realloc<parameter/></function>, and
- <function>free<parameter/></function> functions conform to ISO/IEC
- 9899:1990 (&ldquo;ISO C90&rdquo;).</para>
-
- <para>The <function>posix_memalign<parameter/></function> function conforms
- to IEEE Std 1003.1-2001 (&ldquo;POSIX.1&rdquo;).</para>
- </refsect1>
-</refentry>
diff --git a/extra/jemalloc/doc/manpages.xsl.in b/extra/jemalloc/doc/manpages.xsl.in
deleted file mode 100644
index 88b2626b958..00000000000
--- a/extra/jemalloc/doc/manpages.xsl.in
+++ /dev/null
@@ -1,4 +0,0 @@
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
- <xsl:import href="@XSLROOT@/manpages/docbook.xsl"/>
- <xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
-</xsl:stylesheet>
diff --git a/extra/jemalloc/doc/stylesheet.xsl b/extra/jemalloc/doc/stylesheet.xsl
deleted file mode 100644
index 4e334a86f87..00000000000
--- a/extra/jemalloc/doc/stylesheet.xsl
+++ /dev/null
@@ -1,7 +0,0 @@
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
- <xsl:param name="funcsynopsis.style">ansi</xsl:param>
- <xsl:param name="function.parens" select="1"/>
- <xsl:template match="mallctl">
- "<xsl:call-template name="inline.monoseq"/>"
- </xsl:template>
-</xsl:stylesheet>
diff --git a/extra/jemalloc/include/jemalloc/internal/arena.h b/extra/jemalloc/include/jemalloc/internal/arena.h
deleted file mode 100644
index bbcfedacead..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/arena.h
+++ /dev/null
@@ -1,1038 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-/*
- * RUN_MAX_OVRHD indicates maximum desired run header overhead. Runs are sized
- * as small as possible such that this setting is still honored, without
- * violating other constraints. The goal is to make runs as small as possible
- * without exceeding a per run external fragmentation threshold.
- *
- * We use binary fixed point math for overhead computations, where the binary
- * point is implicitly RUN_BFP bits to the left.
- *
- * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
- * honored for some/all object sizes, since when heap profiling is enabled
- * there is one pointer of header overhead per object (plus a constant). This
- * constraint is relaxed (ignored) for runs that are so small that the
- * per-region overhead is greater than:
- *
- * (RUN_MAX_OVRHD / (reg_interval << (3+RUN_BFP))
- */
-#define RUN_BFP 12
-/* \/ Implicit binary fixed point. */
-#define RUN_MAX_OVRHD 0x0000003dU
-#define RUN_MAX_OVRHD_RELAX 0x00001800U
-
-/* Maximum number of regions in one run. */
-#define LG_RUN_MAXREGS 11
-#define RUN_MAXREGS (1U << LG_RUN_MAXREGS)
-
-/*
- * Minimum redzone size. Redzones may be larger than this if necessary to
- * preserve region alignment.
- */
-#define REDZONE_MINSIZE 16
-
-/*
- * The minimum ratio of active:dirty pages per arena is computed as:
- *
- * (nactive >> opt_lg_dirty_mult) >= ndirty
- *
- * So, supposing that opt_lg_dirty_mult is 3, there can be no less than 8 times
- * as many active pages as dirty pages.
- */
-#define LG_DIRTY_MULT_DEFAULT 3
-
-typedef struct arena_chunk_map_s arena_chunk_map_t;
-typedef struct arena_chunk_s arena_chunk_t;
-typedef struct arena_run_s arena_run_t;
-typedef struct arena_bin_info_s arena_bin_info_t;
-typedef struct arena_bin_s arena_bin_t;
-typedef struct arena_s arena_t;
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-/* Each element of the chunk map corresponds to one page within the chunk. */
-struct arena_chunk_map_s {
-#ifndef JEMALLOC_PROF
- /*
- * Overlay prof_ctx in order to allow it to be referenced by dead code.
- * Such antics aren't warranted for per arena data structures, but
- * chunk map overhead accounts for a percentage of memory, rather than
- * being just a fixed cost.
- */
- union {
-#endif
- union {
- /*
- * Linkage for run trees. There are two disjoint uses:
- *
- * 1) arena_t's runs_avail tree.
- * 2) arena_run_t conceptually uses this linkage for in-use
- * non-full runs, rather than directly embedding linkage.
- */
- rb_node(arena_chunk_map_t) rb_link;
- /*
- * List of runs currently in purgatory. arena_chunk_purge()
- * temporarily allocates runs that contain dirty pages while
- * purging, so that other threads cannot use the runs while the
- * purging thread is operating without the arena lock held.
- */
- ql_elm(arena_chunk_map_t) ql_link;
- } u;
-
- /* Profile counters, used for large object runs. */
- prof_ctx_t *prof_ctx;
-#ifndef JEMALLOC_PROF
- }; /* union { ... }; */
-#endif
-
- /*
- * Run address (or size) and various flags are stored together. The bit
- * layout looks like (assuming 32-bit system):
- *
- * ???????? ???????? ????nnnn nnnndula
- *
- * ? : Unallocated: Run address for first/last pages, unset for internal
- * pages.
- * Small: Run page offset.
- * Large: Run size for first page, unset for trailing pages.
- * n : binind for small size class, BININD_INVALID for large size class.
- * d : dirty?
- * u : unzeroed?
- * l : large?
- * a : allocated?
- *
- * Following are example bit patterns for the three types of runs.
- *
- * p : run page offset
- * s : run size
- * n : binind for size class; large objects set these to BININD_INVALID
- * except for promoted allocations (see prof_promote)
- * x : don't care
- * - : 0
- * + : 1
- * [DULA] : bit set
- * [dula] : bit unset
- *
- * Unallocated (clean):
- * ssssssss ssssssss ssss++++ ++++du-a
- * xxxxxxxx xxxxxxxx xxxxxxxx xxxx-Uxx
- * ssssssss ssssssss ssss++++ ++++dU-a
- *
- * Unallocated (dirty):
- * ssssssss ssssssss ssss++++ ++++D--a
- * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
- * ssssssss ssssssss ssss++++ ++++D--a
- *
- * Small:
- * pppppppp pppppppp ppppnnnn nnnnd--A
- * pppppppp pppppppp ppppnnnn nnnn---A
- * pppppppp pppppppp ppppnnnn nnnnd--A
- *
- * Large:
- * ssssssss ssssssss ssss++++ ++++D-LA
- * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
- * -------- -------- ----++++ ++++D-LA
- *
- * Large (sampled, size <= PAGE):
- * ssssssss ssssssss ssssnnnn nnnnD-LA
- *
- * Large (not sampled, size == PAGE):
- * ssssssss ssssssss ssss++++ ++++D-LA
- */
- size_t bits;
-#define CHUNK_MAP_BININD_SHIFT 4
-#define BININD_INVALID ((size_t)0xffU)
-/* CHUNK_MAP_BININD_MASK == (BININD_INVALID << CHUNK_MAP_BININD_SHIFT) */
-#define CHUNK_MAP_BININD_MASK ((size_t)0xff0U)
-#define CHUNK_MAP_BININD_INVALID CHUNK_MAP_BININD_MASK
-#define CHUNK_MAP_FLAGS_MASK ((size_t)0xcU)
-#define CHUNK_MAP_DIRTY ((size_t)0x8U)
-#define CHUNK_MAP_UNZEROED ((size_t)0x4U)
-#define CHUNK_MAP_LARGE ((size_t)0x2U)
-#define CHUNK_MAP_ALLOCATED ((size_t)0x1U)
-#define CHUNK_MAP_KEY CHUNK_MAP_ALLOCATED
-};
-typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t;
-typedef rb_tree(arena_chunk_map_t) arena_run_tree_t;
-
-/* Arena chunk header. */
-struct arena_chunk_s {
- /* Arena that owns the chunk. */
- arena_t *arena;
-
- /* Linkage for tree of arena chunks that contain dirty runs. */
- rb_node(arena_chunk_t) dirty_link;
-
- /* Number of dirty pages. */
- size_t ndirty;
-
- /* Number of available runs. */
- size_t nruns_avail;
-
- /*
- * Number of available run adjacencies. Clean and dirty available runs
- * are not coalesced, which causes virtual memory fragmentation. The
- * ratio of (nruns_avail-nruns_adjac):nruns_adjac is used for tracking
- * this fragmentation.
- * */
- size_t nruns_adjac;
-
- /*
- * Map of pages within chunk that keeps track of free/large/small. The
- * first map_bias entries are omitted, since the chunk header does not
- * need to be tracked in the map. This omission saves a header page
- * for common chunk sizes (e.g. 4 MiB).
- */
- arena_chunk_map_t map[1]; /* Dynamically sized. */
-};
-typedef rb_tree(arena_chunk_t) arena_chunk_tree_t;
-
-struct arena_run_s {
- /* Bin this run is associated with. */
- arena_bin_t *bin;
-
- /* Index of next region that has never been allocated, or nregs. */
- uint32_t nextind;
-
- /* Number of free regions in run. */
- unsigned nfree;
-};
-
-/*
- * Read-only information associated with each element of arena_t's bins array
- * is stored separately, partly to reduce memory usage (only one copy, rather
- * than one per arena), but mainly to avoid false cacheline sharing.
- *
- * Each run has the following layout:
- *
- * /--------------------\
- * | arena_run_t header |
- * | ... |
- * bitmap_offset | bitmap |
- * | ... |
- * ctx0_offset | ctx map |
- * | ... |
- * |--------------------|
- * | redzone |
- * reg0_offset | region 0 |
- * | redzone |
- * |--------------------| \
- * | redzone | |
- * | region 1 | > reg_interval
- * | redzone | /
- * |--------------------|
- * | ... |
- * | ... |
- * | ... |
- * |--------------------|
- * | redzone |
- * | region nregs-1 |
- * | redzone |
- * |--------------------|
- * | alignment pad? |
- * \--------------------/
- *
- * reg_interval has at least the same minimum alignment as reg_size; this
- * preserves the alignment constraint that sa2u() depends on. Alignment pad is
- * either 0 or redzone_size; it is present only if needed to align reg0_offset.
- */
-struct arena_bin_info_s {
- /* Size of regions in a run for this bin's size class. */
- size_t reg_size;
-
- /* Redzone size. */
- size_t redzone_size;
-
- /* Interval between regions (reg_size + (redzone_size << 1)). */
- size_t reg_interval;
-
- /* Total size of a run for this bin's size class. */
- size_t run_size;
-
- /* Total number of regions in a run for this bin's size class. */
- uint32_t nregs;
-
- /*
- * Offset of first bitmap_t element in a run header for this bin's size
- * class.
- */
- uint32_t bitmap_offset;
-
- /*
- * Metadata used to manipulate bitmaps for runs associated with this
- * bin.
- */
- bitmap_info_t bitmap_info;
-
- /*
- * Offset of first (prof_ctx_t *) in a run header for this bin's size
- * class, or 0 if (config_prof == false || opt_prof == false).
- */
- uint32_t ctx0_offset;
-
- /* Offset of first region in a run for this bin's size class. */
- uint32_t reg0_offset;
-};
-
-struct arena_bin_s {
- /*
- * All operations on runcur, runs, and stats require that lock be
- * locked. Run allocation/deallocation are protected by the arena lock,
- * which may be acquired while holding one or more bin locks, but not
- * vise versa.
- */
- malloc_mutex_t lock;
-
- /*
- * Current run being used to service allocations of this bin's size
- * class.
- */
- arena_run_t *runcur;
-
- /*
- * Tree of non-full runs. This tree is used when looking for an
- * existing run when runcur is no longer usable. We choose the
- * non-full run that is lowest in memory; this policy tends to keep
- * objects packed well, and it can also help reduce the number of
- * almost-empty chunks.
- */
- arena_run_tree_t runs;
-
- /* Bin statistics. */
- malloc_bin_stats_t stats;
-};
-
-struct arena_s {
- /* This arena's index within the arenas array. */
- unsigned ind;
-
- /*
- * Number of threads currently assigned to this arena. This field is
- * protected by arenas_lock.
- */
- unsigned nthreads;
-
- /*
- * There are three classes of arena operations from a locking
- * perspective:
- * 1) Thread asssignment (modifies nthreads) is protected by
- * arenas_lock.
- * 2) Bin-related operations are protected by bin locks.
- * 3) Chunk- and run-related operations are protected by this mutex.
- */
- malloc_mutex_t lock;
-
- arena_stats_t stats;
- /*
- * List of tcaches for extant threads associated with this arena.
- * Stats from these are merged incrementally, and at exit.
- */
- ql_head(tcache_t) tcache_ql;
-
- uint64_t prof_accumbytes;
-
- dss_prec_t dss_prec;
-
- /* Tree of dirty-page-containing chunks this arena manages. */
- arena_chunk_tree_t chunks_dirty;
-
- /*
- * In order to avoid rapid chunk allocation/deallocation when an arena
- * oscillates right on the cusp of needing a new chunk, cache the most
- * recently freed chunk. The spare is left in the arena's chunk trees
- * until it is deleted.
- *
- * There is one spare chunk per arena, rather than one spare total, in
- * order to avoid interactions between multiple threads that could make
- * a single spare inadequate.
- */
- arena_chunk_t *spare;
-
- /* Number of pages in active runs. */
- size_t nactive;
-
- /*
- * Current count of pages within unused runs that are potentially
- * dirty, and for which madvise(... MADV_DONTNEED) has not been called.
- * By tracking this, we can institute a limit on how much dirty unused
- * memory is mapped for each arena.
- */
- size_t ndirty;
-
- /*
- * Approximate number of pages being purged. It is possible for
- * multiple threads to purge dirty pages concurrently, and they use
- * npurgatory to indicate the total number of pages all threads are
- * attempting to purge.
- */
- size_t npurgatory;
-
- /*
- * Size/address-ordered trees of this arena's available runs. The trees
- * are used for first-best-fit run allocation.
- */
- arena_avail_tree_t runs_avail;
-
- /* bins is used to store trees of free regions. */
- arena_bin_t bins[NBINS];
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-extern ssize_t opt_lg_dirty_mult;
-/*
- * small_size2bin is a compact lookup table that rounds request sizes up to
- * size classes. In order to reduce cache footprint, the table is compressed,
- * and all accesses are via the SMALL_SIZE2BIN macro.
- */
-extern uint8_t const small_size2bin[];
-#define SMALL_SIZE2BIN(s) (small_size2bin[(s-1) >> LG_TINY_MIN])
-
-extern arena_bin_info_t arena_bin_info[NBINS];
-
-/* Number of large size classes. */
-#define nlclasses (chunk_npages - map_bias)
-
-void arena_purge_all(arena_t *arena);
-void arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin,
- size_t binind, uint64_t prof_accumbytes);
-void arena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info,
- bool zero);
-void arena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info);
-void *arena_malloc_small(arena_t *arena, size_t size, bool zero);
-void *arena_malloc_large(arena_t *arena, size_t size, bool zero);
-void *arena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero);
-void arena_prof_promoted(const void *ptr, size_t size);
-void arena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- arena_chunk_map_t *mapelm);
-void arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t pageind, arena_chunk_map_t *mapelm);
-void arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t pageind);
-void arena_dalloc_large_locked(arena_t *arena, arena_chunk_t *chunk,
- void *ptr);
-void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr);
-void *arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size,
- size_t extra, bool zero);
-void *arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size,
- size_t extra, size_t alignment, bool zero, bool try_tcache_alloc,
- bool try_tcache_dalloc);
-dss_prec_t arena_dss_prec_get(arena_t *arena);
-void arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec);
-void arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive,
- size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats,
- malloc_large_stats_t *lstats);
-bool arena_new(arena_t *arena, unsigned ind);
-void arena_boot(void);
-void arena_prefork(arena_t *arena);
-void arena_postfork_parent(arena_t *arena);
-void arena_postfork_child(arena_t *arena);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-arena_chunk_map_t *arena_mapp_get(arena_chunk_t *chunk, size_t pageind);
-size_t *arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind);
-size_t arena_mapbitsp_read(size_t *mapbitsp);
-size_t arena_mapbits_get(arena_chunk_t *chunk, size_t pageind);
-size_t arena_mapbits_unallocated_size_get(arena_chunk_t *chunk,
- size_t pageind);
-size_t arena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind);
-size_t arena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind);
-size_t arena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind);
-size_t arena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind);
-size_t arena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind);
-size_t arena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind);
-size_t arena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind);
-void arena_mapbitsp_write(size_t *mapbitsp, size_t mapbits);
-void arena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind,
- size_t size, size_t flags);
-void arena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,
- size_t size);
-void arena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind,
- size_t size, size_t flags);
-void arena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,
- size_t binind);
-void arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind,
- size_t runind, size_t binind, size_t flags);
-void arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,
- size_t unzeroed);
-bool arena_prof_accum_impl(arena_t *arena, uint64_t accumbytes);
-bool arena_prof_accum_locked(arena_t *arena, uint64_t accumbytes);
-bool arena_prof_accum(arena_t *arena, uint64_t accumbytes);
-size_t arena_ptr_small_binind_get(const void *ptr, size_t mapbits);
-size_t arena_bin_index(arena_t *arena, arena_bin_t *bin);
-unsigned arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info,
- const void *ptr);
-prof_ctx_t *arena_prof_ctx_get(const void *ptr);
-void arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
-void *arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache);
-size_t arena_salloc(const void *ptr, bool demote);
-void arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- bool try_tcache);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ARENA_C_))
-# ifdef JEMALLOC_ARENA_INLINE_A
-JEMALLOC_ALWAYS_INLINE arena_chunk_map_t *
-arena_mapp_get(arena_chunk_t *chunk, size_t pageind)
-{
-
- assert(pageind >= map_bias);
- assert(pageind < chunk_npages);
-
- return (&chunk->map[pageind-map_bias]);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t *
-arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind)
-{
-
- return (&arena_mapp_get(chunk, pageind)->bits);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbitsp_read(size_t *mapbitsp)
-{
-
- return (*mapbitsp);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_get(arena_chunk_t *chunk, size_t pageind)
-{
-
- return (arena_mapbitsp_read(arena_mapbitsp_get(chunk, pageind)));
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_unallocated_size_get(arena_chunk_t *chunk, size_t pageind)
-{
- size_t mapbits;
-
- mapbits = arena_mapbits_get(chunk, pageind);
- assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);
- return (mapbits & ~PAGE_MASK);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind)
-{
- size_t mapbits;
-
- mapbits = arena_mapbits_get(chunk, pageind);
- assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==
- (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED));
- return (mapbits & ~PAGE_MASK);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind)
-{
- size_t mapbits;
-
- mapbits = arena_mapbits_get(chunk, pageind);
- assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==
- CHUNK_MAP_ALLOCATED);
- return (mapbits >> LG_PAGE);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind)
-{
- size_t mapbits;
- size_t binind;
-
- mapbits = arena_mapbits_get(chunk, pageind);
- binind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;
- assert(binind < NBINS || binind == BININD_INVALID);
- return (binind);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind)
-{
- size_t mapbits;
-
- mapbits = arena_mapbits_get(chunk, pageind);
- return (mapbits & CHUNK_MAP_DIRTY);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind)
-{
- size_t mapbits;
-
- mapbits = arena_mapbits_get(chunk, pageind);
- return (mapbits & CHUNK_MAP_UNZEROED);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind)
-{
- size_t mapbits;
-
- mapbits = arena_mapbits_get(chunk, pageind);
- return (mapbits & CHUNK_MAP_LARGE);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind)
-{
- size_t mapbits;
-
- mapbits = arena_mapbits_get(chunk, pageind);
- return (mapbits & CHUNK_MAP_ALLOCATED);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-arena_mapbitsp_write(size_t *mapbitsp, size_t mapbits)
-{
-
- *mapbitsp = mapbits;
-}
-
-JEMALLOC_ALWAYS_INLINE void
-arena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, size_t size,
- size_t flags)
-{
- size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
-
- assert((size & PAGE_MASK) == 0);
- assert((flags & ~CHUNK_MAP_FLAGS_MASK) == 0);
- assert((flags & (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == flags);
- arena_mapbitsp_write(mapbitsp, size | CHUNK_MAP_BININD_INVALID | flags);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-arena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,
- size_t size)
-{
- size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
- size_t mapbits = arena_mapbitsp_read(mapbitsp);
-
- assert((size & PAGE_MASK) == 0);
- assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);
- arena_mapbitsp_write(mapbitsp, size | (mapbits & PAGE_MASK));
-}
-
-JEMALLOC_ALWAYS_INLINE void
-arena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, size_t size,
- size_t flags)
-{
- size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
- size_t mapbits = arena_mapbitsp_read(mapbitsp);
- size_t unzeroed;
-
- assert((size & PAGE_MASK) == 0);
- assert((flags & CHUNK_MAP_DIRTY) == flags);
- unzeroed = mapbits & CHUNK_MAP_UNZEROED; /* Preserve unzeroed. */
- arena_mapbitsp_write(mapbitsp, size | CHUNK_MAP_BININD_INVALID | flags
- | unzeroed | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-arena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,
- size_t binind)
-{
- size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
- size_t mapbits = arena_mapbitsp_read(mapbitsp);
-
- assert(binind <= BININD_INVALID);
- assert(arena_mapbits_large_size_get(chunk, pageind) == PAGE);
- arena_mapbitsp_write(mapbitsp, (mapbits & ~CHUNK_MAP_BININD_MASK) |
- (binind << CHUNK_MAP_BININD_SHIFT));
-}
-
-JEMALLOC_ALWAYS_INLINE void
-arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, size_t runind,
- size_t binind, size_t flags)
-{
- size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
- size_t mapbits = arena_mapbitsp_read(mapbitsp);
- size_t unzeroed;
-
- assert(binind < BININD_INVALID);
- assert(pageind - runind >= map_bias);
- assert((flags & CHUNK_MAP_DIRTY) == flags);
- unzeroed = mapbits & CHUNK_MAP_UNZEROED; /* Preserve unzeroed. */
- arena_mapbitsp_write(mapbitsp, (runind << LG_PAGE) | (binind <<
- CHUNK_MAP_BININD_SHIFT) | flags | unzeroed | CHUNK_MAP_ALLOCATED);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,
- size_t unzeroed)
-{
- size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
- size_t mapbits = arena_mapbitsp_read(mapbitsp);
-
- arena_mapbitsp_write(mapbitsp, (mapbits & ~CHUNK_MAP_UNZEROED) |
- unzeroed);
-}
-
-JEMALLOC_INLINE bool
-arena_prof_accum_impl(arena_t *arena, uint64_t accumbytes)
-{
-
- cassert(config_prof);
- assert(prof_interval != 0);
-
- arena->prof_accumbytes += accumbytes;
- if (arena->prof_accumbytes >= prof_interval) {
- arena->prof_accumbytes -= prof_interval;
- return (true);
- }
- return (false);
-}
-
-JEMALLOC_INLINE bool
-arena_prof_accum_locked(arena_t *arena, uint64_t accumbytes)
-{
-
- cassert(config_prof);
-
- if (prof_interval == 0)
- return (false);
- return (arena_prof_accum_impl(arena, accumbytes));
-}
-
-JEMALLOC_INLINE bool
-arena_prof_accum(arena_t *arena, uint64_t accumbytes)
-{
-
- cassert(config_prof);
-
- if (prof_interval == 0)
- return (false);
-
- {
- bool ret;
-
- malloc_mutex_lock(&arena->lock);
- ret = arena_prof_accum_impl(arena, accumbytes);
- malloc_mutex_unlock(&arena->lock);
- return (ret);
- }
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-arena_ptr_small_binind_get(const void *ptr, size_t mapbits)
-{
- size_t binind;
-
- binind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;
-
- if (config_debug) {
- arena_chunk_t *chunk;
- arena_t *arena;
- size_t pageind;
- size_t actual_mapbits;
- arena_run_t *run;
- arena_bin_t *bin;
- size_t actual_binind;
- arena_bin_info_t *bin_info;
-
- assert(binind != BININD_INVALID);
- assert(binind < NBINS);
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- arena = chunk->arena;
- pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- actual_mapbits = arena_mapbits_get(chunk, pageind);
- assert(mapbits == actual_mapbits);
- assert(arena_mapbits_large_get(chunk, pageind) == 0);
- assert(arena_mapbits_allocated_get(chunk, pageind) != 0);
- run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
- (actual_mapbits >> LG_PAGE)) << LG_PAGE));
- bin = run->bin;
- actual_binind = bin - arena->bins;
- assert(binind == actual_binind);
- bin_info = &arena_bin_info[actual_binind];
- assert(((uintptr_t)ptr - ((uintptr_t)run +
- (uintptr_t)bin_info->reg0_offset)) % bin_info->reg_interval
- == 0);
- }
-
- return (binind);
-}
-# endif /* JEMALLOC_ARENA_INLINE_A */
-
-# ifdef JEMALLOC_ARENA_INLINE_B
-JEMALLOC_INLINE size_t
-arena_bin_index(arena_t *arena, arena_bin_t *bin)
-{
- size_t binind = bin - arena->bins;
- assert(binind < NBINS);
- return (binind);
-}
-
-JEMALLOC_INLINE unsigned
-arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, const void *ptr)
-{
- unsigned shift, diff, regind;
- size_t interval;
-
- /*
- * Freeing a pointer lower than region zero can cause assertion
- * failure.
- */
- assert((uintptr_t)ptr >= (uintptr_t)run +
- (uintptr_t)bin_info->reg0_offset);
-
- /*
- * Avoid doing division with a variable divisor if possible. Using
- * actual division here can reduce allocator throughput by over 20%!
- */
- diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run -
- bin_info->reg0_offset);
-
- /* Rescale (factor powers of 2 out of the numerator and denominator). */
- interval = bin_info->reg_interval;
- shift = ffs(interval) - 1;
- diff >>= shift;
- interval >>= shift;
-
- if (interval == 1) {
- /* The divisor was a power of 2. */
- regind = diff;
- } else {
- /*
- * To divide by a number D that is not a power of two we
- * multiply by (2^21 / D) and then right shift by 21 positions.
- *
- * X / D
- *
- * becomes
- *
- * (X * interval_invs[D - 3]) >> SIZE_INV_SHIFT
- *
- * We can omit the first three elements, because we never
- * divide by 0, and 1 and 2 are both powers of two, which are
- * handled above.
- */
-#define SIZE_INV_SHIFT ((sizeof(unsigned) << 3) - LG_RUN_MAXREGS)
-#define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1)
- static const unsigned interval_invs[] = {
- SIZE_INV(3),
- SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),
- SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),
- SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),
- SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),
- SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),
- SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),
- SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)
- };
-
- if (interval <= ((sizeof(interval_invs) / sizeof(unsigned)) +
- 2)) {
- regind = (diff * interval_invs[interval - 3]) >>
- SIZE_INV_SHIFT;
- } else
- regind = diff / interval;
-#undef SIZE_INV
-#undef SIZE_INV_SHIFT
- }
- assert(diff == regind * interval);
- assert(regind < bin_info->nregs);
-
- return (regind);
-}
-
-JEMALLOC_INLINE prof_ctx_t *
-arena_prof_ctx_get(const void *ptr)
-{
- prof_ctx_t *ret;
- arena_chunk_t *chunk;
- size_t pageind, mapbits;
-
- cassert(config_prof);
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- mapbits = arena_mapbits_get(chunk, pageind);
- assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
- if ((mapbits & CHUNK_MAP_LARGE) == 0) {
- if (prof_promote)
- ret = (prof_ctx_t *)(uintptr_t)1U;
- else {
- arena_run_t *run = (arena_run_t *)((uintptr_t)chunk +
- (uintptr_t)((pageind - (mapbits >> LG_PAGE)) <<
- LG_PAGE));
- size_t binind = arena_ptr_small_binind_get(ptr,
- mapbits);
- arena_bin_info_t *bin_info = &arena_bin_info[binind];
- unsigned regind;
-
- regind = arena_run_regind(run, bin_info, ptr);
- ret = *(prof_ctx_t **)((uintptr_t)run +
- bin_info->ctx0_offset + (regind *
- sizeof(prof_ctx_t *)));
- }
- } else
- ret = arena_mapp_get(chunk, pageind)->prof_ctx;
-
- return (ret);
-}
-
-JEMALLOC_INLINE void
-arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx)
-{
- arena_chunk_t *chunk;
- size_t pageind, mapbits;
-
- cassert(config_prof);
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- mapbits = arena_mapbits_get(chunk, pageind);
- assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
- if ((mapbits & CHUNK_MAP_LARGE) == 0) {
- if (prof_promote == false) {
- arena_run_t *run = (arena_run_t *)((uintptr_t)chunk +
- (uintptr_t)((pageind - (mapbits >> LG_PAGE)) <<
- LG_PAGE));
- size_t binind;
- arena_bin_info_t *bin_info;
- unsigned regind;
-
- binind = arena_ptr_small_binind_get(ptr, mapbits);
- bin_info = &arena_bin_info[binind];
- regind = arena_run_regind(run, bin_info, ptr);
-
- *((prof_ctx_t **)((uintptr_t)run + bin_info->ctx0_offset
- + (regind * sizeof(prof_ctx_t *)))) = ctx;
- } else
- assert((uintptr_t)ctx == (uintptr_t)1U);
- } else
- arena_mapp_get(chunk, pageind)->prof_ctx = ctx;
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache)
-{
- tcache_t *tcache;
-
- assert(size != 0);
- assert(size <= arena_maxclass);
-
- if (size <= SMALL_MAXCLASS) {
- if (try_tcache && (tcache = tcache_get(true)) != NULL)
- return (tcache_alloc_small(tcache, size, zero));
- else {
- return (arena_malloc_small(choose_arena(arena), size,
- zero));
- }
- } else {
- /*
- * Initialize tcache after checking size in order to avoid
- * infinite recursion during tcache initialization.
- */
- if (try_tcache && size <= tcache_maxclass && (tcache =
- tcache_get(true)) != NULL)
- return (tcache_alloc_large(tcache, size, zero));
- else {
- return (arena_malloc_large(choose_arena(arena), size,
- zero));
- }
- }
-}
-
-/* Return the size of the allocation pointed to by ptr. */
-JEMALLOC_ALWAYS_INLINE size_t
-arena_salloc(const void *ptr, bool demote)
-{
- size_t ret;
- arena_chunk_t *chunk;
- size_t pageind, binind;
-
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- assert(arena_mapbits_allocated_get(chunk, pageind) != 0);
- binind = arena_mapbits_binind_get(chunk, pageind);
- if (binind == BININD_INVALID || (config_prof && demote == false &&
- prof_promote && arena_mapbits_large_get(chunk, pageind) != 0)) {
- /*
- * Large allocation. In the common case (demote == true), and
- * as this is an inline function, most callers will only end up
- * looking at binind to determine that ptr is a small
- * allocation.
- */
- assert(((uintptr_t)ptr & PAGE_MASK) == 0);
- ret = arena_mapbits_large_size_get(chunk, pageind);
- assert(ret != 0);
- assert(pageind + (ret>>LG_PAGE) <= chunk_npages);
- assert(ret == PAGE || arena_mapbits_large_size_get(chunk,
- pageind+(ret>>LG_PAGE)-1) == 0);
- assert(binind == arena_mapbits_binind_get(chunk,
- pageind+(ret>>LG_PAGE)-1));
- assert(arena_mapbits_dirty_get(chunk, pageind) ==
- arena_mapbits_dirty_get(chunk, pageind+(ret>>LG_PAGE)-1));
- } else {
- /*
- * Small allocation (possibly promoted to a large object due to
- * prof_promote).
- */
- assert(arena_mapbits_large_get(chunk, pageind) != 0 ||
- arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk,
- pageind)) == binind);
- ret = arena_bin_info[binind].reg_size;
- }
-
- return (ret);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr, bool try_tcache)
-{
- size_t pageind, mapbits;
- tcache_t *tcache;
-
- assert(arena != NULL);
- assert(chunk->arena == arena);
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
-
- pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- mapbits = arena_mapbits_get(chunk, pageind);
- assert(arena_mapbits_allocated_get(chunk, pageind) != 0);
- if ((mapbits & CHUNK_MAP_LARGE) == 0) {
- /* Small allocation. */
- if (try_tcache && (tcache = tcache_get(false)) != NULL) {
- size_t binind;
-
- binind = arena_ptr_small_binind_get(ptr, mapbits);
- tcache_dalloc_small(tcache, ptr, binind);
- } else
- arena_dalloc_small(arena, chunk, ptr, pageind);
- } else {
- size_t size = arena_mapbits_large_size_get(chunk, pageind);
-
- assert(((uintptr_t)ptr & PAGE_MASK) == 0);
-
- if (try_tcache && size <= tcache_maxclass && (tcache =
- tcache_get(false)) != NULL) {
- tcache_dalloc_large(tcache, ptr, size);
- } else
- arena_dalloc_large(arena, chunk, ptr);
- }
-}
-# endif /* JEMALLOC_ARENA_INLINE_B */
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/atomic.h b/extra/jemalloc/include/jemalloc/internal/atomic.h
deleted file mode 100644
index 11a7b47fe0f..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/atomic.h
+++ /dev/null
@@ -1,304 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-#define atomic_read_uint64(p) atomic_add_uint64(p, 0)
-#define atomic_read_uint32(p) atomic_add_uint32(p, 0)
-#define atomic_read_z(p) atomic_add_z(p, 0)
-#define atomic_read_u(p) atomic_add_u(p, 0)
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-uint64_t atomic_add_uint64(uint64_t *p, uint64_t x);
-uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x);
-uint32_t atomic_add_uint32(uint32_t *p, uint32_t x);
-uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x);
-size_t atomic_add_z(size_t *p, size_t x);
-size_t atomic_sub_z(size_t *p, size_t x);
-unsigned atomic_add_u(unsigned *p, unsigned x);
-unsigned atomic_sub_u(unsigned *p, unsigned x);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))
-/******************************************************************************/
-/* 64-bit operations. */
-#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
-# ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
-JEMALLOC_INLINE uint64_t
-atomic_add_uint64(uint64_t *p, uint64_t x)
-{
-
- return (__sync_add_and_fetch(p, x));
-}
-
-JEMALLOC_INLINE uint64_t
-atomic_sub_uint64(uint64_t *p, uint64_t x)
-{
-
- return (__sync_sub_and_fetch(p, x));
-}
-#elif (defined(_MSC_VER))
-JEMALLOC_INLINE uint64_t
-atomic_add_uint64(uint64_t *p, uint64_t x)
-{
-
- return (InterlockedExchangeAdd64(p, x));
-}
-
-JEMALLOC_INLINE uint64_t
-atomic_sub_uint64(uint64_t *p, uint64_t x)
-{
-
- return (InterlockedExchangeAdd64(p, -((int64_t)x)));
-}
-#elif (defined(JEMALLOC_OSATOMIC))
-JEMALLOC_INLINE uint64_t
-atomic_add_uint64(uint64_t *p, uint64_t x)
-{
-
- return (OSAtomicAdd64((int64_t)x, (int64_t *)p));
-}
-
-JEMALLOC_INLINE uint64_t
-atomic_sub_uint64(uint64_t *p, uint64_t x)
-{
-
- return (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));
-}
-# elif (defined(__amd64__) || defined(__x86_64__))
-JEMALLOC_INLINE uint64_t
-atomic_add_uint64(uint64_t *p, uint64_t x)
-{
-
- asm volatile (
- "lock; xaddq %0, %1;"
- : "+r" (x), "=m" (*p) /* Outputs. */
- : "m" (*p) /* Inputs. */
- );
-
- return (x);
-}
-
-JEMALLOC_INLINE uint64_t
-atomic_sub_uint64(uint64_t *p, uint64_t x)
-{
-
- x = (uint64_t)(-(int64_t)x);
- asm volatile (
- "lock; xaddq %0, %1;"
- : "+r" (x), "=m" (*p) /* Outputs. */
- : "m" (*p) /* Inputs. */
- );
-
- return (x);
-}
-# elif (defined(JEMALLOC_ATOMIC9))
-JEMALLOC_INLINE uint64_t
-atomic_add_uint64(uint64_t *p, uint64_t x)
-{
-
- /*
- * atomic_fetchadd_64() doesn't exist, but we only ever use this
- * function on LP64 systems, so atomic_fetchadd_long() will do.
- */
- assert(sizeof(uint64_t) == sizeof(unsigned long));
-
- return (atomic_fetchadd_long(p, (unsigned long)x) + x);
-}
-
-JEMALLOC_INLINE uint64_t
-atomic_sub_uint64(uint64_t *p, uint64_t x)
-{
-
- assert(sizeof(uint64_t) == sizeof(unsigned long));
-
- return (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x);
-}
-# elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))
-JEMALLOC_INLINE uint64_t
-atomic_add_uint64(uint64_t *p, uint64_t x)
-{
-
- return (__sync_add_and_fetch(p, x));
-}
-
-JEMALLOC_INLINE uint64_t
-atomic_sub_uint64(uint64_t *p, uint64_t x)
-{
-
- return (__sync_sub_and_fetch(p, x));
-}
-# else
-# error "Missing implementation for 64-bit atomic operations"
-# endif
-#endif
-
-/******************************************************************************/
-/* 32-bit operations. */
-#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
-JEMALLOC_INLINE uint32_t
-atomic_add_uint32(uint32_t *p, uint32_t x)
-{
-
- return (__sync_add_and_fetch(p, x));
-}
-
-JEMALLOC_INLINE uint32_t
-atomic_sub_uint32(uint32_t *p, uint32_t x)
-{
-
- return (__sync_sub_and_fetch(p, x));
-}
-#elif (defined(_MSC_VER))
-JEMALLOC_INLINE uint32_t
-atomic_add_uint32(uint32_t *p, uint32_t x)
-{
-
- return (InterlockedExchangeAdd(p, x));
-}
-
-JEMALLOC_INLINE uint32_t
-atomic_sub_uint32(uint32_t *p, uint32_t x)
-{
-
- return (InterlockedExchangeAdd(p, -((int32_t)x)));
-}
-#elif (defined(JEMALLOC_OSATOMIC))
-JEMALLOC_INLINE uint32_t
-atomic_add_uint32(uint32_t *p, uint32_t x)
-{
-
- return (OSAtomicAdd32((int32_t)x, (int32_t *)p));
-}
-
-JEMALLOC_INLINE uint32_t
-atomic_sub_uint32(uint32_t *p, uint32_t x)
-{
-
- return (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));
-}
-#elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
-JEMALLOC_INLINE uint32_t
-atomic_add_uint32(uint32_t *p, uint32_t x)
-{
-
- asm volatile (
- "lock; xaddl %0, %1;"
- : "+r" (x), "=m" (*p) /* Outputs. */
- : "m" (*p) /* Inputs. */
- );
-
- return (x);
-}
-
-JEMALLOC_INLINE uint32_t
-atomic_sub_uint32(uint32_t *p, uint32_t x)
-{
-
- x = (uint32_t)(-(int32_t)x);
- asm volatile (
- "lock; xaddl %0, %1;"
- : "+r" (x), "=m" (*p) /* Outputs. */
- : "m" (*p) /* Inputs. */
- );
-
- return (x);
-}
-#elif (defined(JEMALLOC_ATOMIC9))
-JEMALLOC_INLINE uint32_t
-atomic_add_uint32(uint32_t *p, uint32_t x)
-{
-
- return (atomic_fetchadd_32(p, x) + x);
-}
-
-JEMALLOC_INLINE uint32_t
-atomic_sub_uint32(uint32_t *p, uint32_t x)
-{
-
- return (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x);
-}
-#elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
-JEMALLOC_INLINE uint32_t
-atomic_add_uint32(uint32_t *p, uint32_t x)
-{
-
- return (__sync_add_and_fetch(p, x));
-}
-
-JEMALLOC_INLINE uint32_t
-atomic_sub_uint32(uint32_t *p, uint32_t x)
-{
-
- return (__sync_sub_and_fetch(p, x));
-}
-#else
-# error "Missing implementation for 32-bit atomic operations"
-#endif
-
-/******************************************************************************/
-/* size_t operations. */
-JEMALLOC_INLINE size_t
-atomic_add_z(size_t *p, size_t x)
-{
-
-#if (LG_SIZEOF_PTR == 3)
- return ((size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x));
-#elif (LG_SIZEOF_PTR == 2)
- return ((size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x));
-#endif
-}
-
-JEMALLOC_INLINE size_t
-atomic_sub_z(size_t *p, size_t x)
-{
-
-#if (LG_SIZEOF_PTR == 3)
- return ((size_t)atomic_add_uint64((uint64_t *)p,
- (uint64_t)-((int64_t)x)));
-#elif (LG_SIZEOF_PTR == 2)
- return ((size_t)atomic_add_uint32((uint32_t *)p,
- (uint32_t)-((int32_t)x)));
-#endif
-}
-
-/******************************************************************************/
-/* unsigned operations. */
-JEMALLOC_INLINE unsigned
-atomic_add_u(unsigned *p, unsigned x)
-{
-
-#if (LG_SIZEOF_INT == 3)
- return ((unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x));
-#elif (LG_SIZEOF_INT == 2)
- return ((unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x));
-#endif
-}
-
-JEMALLOC_INLINE unsigned
-atomic_sub_u(unsigned *p, unsigned x)
-{
-
-#if (LG_SIZEOF_INT == 3)
- return ((unsigned)atomic_add_uint64((uint64_t *)p,
- (uint64_t)-((int64_t)x)));
-#elif (LG_SIZEOF_INT == 2)
- return ((unsigned)atomic_add_uint32((uint32_t *)p,
- (uint32_t)-((int32_t)x)));
-#endif
-}
-/******************************************************************************/
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/base.h b/extra/jemalloc/include/jemalloc/internal/base.h
deleted file mode 100644
index 9cf75ffb0b3..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/base.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-void *base_alloc(size_t size);
-void *base_calloc(size_t number, size_t size);
-extent_node_t *base_node_alloc(void);
-void base_node_dealloc(extent_node_t *node);
-bool base_boot(void);
-void base_prefork(void);
-void base_postfork_parent(void);
-void base_postfork_child(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/bitmap.h b/extra/jemalloc/include/jemalloc/internal/bitmap.h
deleted file mode 100644
index 605ebac58c1..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/bitmap.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-/* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */
-#define LG_BITMAP_MAXBITS LG_RUN_MAXREGS
-
-typedef struct bitmap_level_s bitmap_level_t;
-typedef struct bitmap_info_s bitmap_info_t;
-typedef unsigned long bitmap_t;
-#define LG_SIZEOF_BITMAP LG_SIZEOF_LONG
-
-/* Number of bits per group. */
-#define LG_BITMAP_GROUP_NBITS (LG_SIZEOF_BITMAP + 3)
-#define BITMAP_GROUP_NBITS (ZU(1) << LG_BITMAP_GROUP_NBITS)
-#define BITMAP_GROUP_NBITS_MASK (BITMAP_GROUP_NBITS-1)
-
-/* Maximum number of levels possible. */
-#define BITMAP_MAX_LEVELS \
- (LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP) \
- + !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP)
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-struct bitmap_level_s {
- /* Offset of this level's groups within the array of groups. */
- size_t group_offset;
-};
-
-struct bitmap_info_s {
- /* Logical number of bits in bitmap (stored at bottom level). */
- size_t nbits;
-
- /* Number of levels necessary for nbits. */
- unsigned nlevels;
-
- /*
- * Only the first (nlevels+1) elements are used, and levels are ordered
- * bottom to top (e.g. the bottom level is stored in levels[0]).
- */
- bitmap_level_t levels[BITMAP_MAX_LEVELS+1];
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-void bitmap_info_init(bitmap_info_t *binfo, size_t nbits);
-size_t bitmap_info_ngroups(const bitmap_info_t *binfo);
-size_t bitmap_size(size_t nbits);
-void bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-bool bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo);
-bool bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);
-void bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);
-size_t bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo);
-void bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_BITMAP_C_))
-JEMALLOC_INLINE bool
-bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo)
-{
- unsigned rgoff = binfo->levels[binfo->nlevels].group_offset - 1;
- bitmap_t rg = bitmap[rgoff];
- /* The bitmap is full iff the root group is 0. */
- return (rg == 0);
-}
-
-JEMALLOC_INLINE bool
-bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)
-{
- size_t goff;
- bitmap_t g;
-
- assert(bit < binfo->nbits);
- goff = bit >> LG_BITMAP_GROUP_NBITS;
- g = bitmap[goff];
- return (!(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))));
-}
-
-JEMALLOC_INLINE void
-bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)
-{
- size_t goff;
- bitmap_t *gp;
- bitmap_t g;
-
- assert(bit < binfo->nbits);
- assert(bitmap_get(bitmap, binfo, bit) == false);
- goff = bit >> LG_BITMAP_GROUP_NBITS;
- gp = &bitmap[goff];
- g = *gp;
- assert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)));
- g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);
- *gp = g;
- assert(bitmap_get(bitmap, binfo, bit));
- /* Propagate group state transitions up the tree. */
- if (g == 0) {
- unsigned i;
- for (i = 1; i < binfo->nlevels; i++) {
- bit = goff;
- goff = bit >> LG_BITMAP_GROUP_NBITS;
- gp = &bitmap[binfo->levels[i].group_offset + goff];
- g = *gp;
- assert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)));
- g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);
- *gp = g;
- if (g != 0)
- break;
- }
- }
-}
-
-/* sfu: set first unset. */
-JEMALLOC_INLINE size_t
-bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo)
-{
- size_t bit;
- bitmap_t g;
- unsigned i;
-
- assert(bitmap_full(bitmap, binfo) == false);
-
- i = binfo->nlevels - 1;
- g = bitmap[binfo->levels[i].group_offset];
- bit = ffsl(g) - 1;
- while (i > 0) {
- i--;
- g = bitmap[binfo->levels[i].group_offset + bit];
- bit = (bit << LG_BITMAP_GROUP_NBITS) + (ffsl(g) - 1);
- }
-
- bitmap_set(bitmap, binfo, bit);
- return (bit);
-}
-
-JEMALLOC_INLINE void
-bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)
-{
- size_t goff;
- bitmap_t *gp;
- bitmap_t g;
- bool propagate;
-
- assert(bit < binfo->nbits);
- assert(bitmap_get(bitmap, binfo, bit));
- goff = bit >> LG_BITMAP_GROUP_NBITS;
- gp = &bitmap[goff];
- g = *gp;
- propagate = (g == 0);
- assert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))) == 0);
- g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);
- *gp = g;
- assert(bitmap_get(bitmap, binfo, bit) == false);
- /* Propagate group state transitions up the tree. */
- if (propagate) {
- unsigned i;
- for (i = 1; i < binfo->nlevels; i++) {
- bit = goff;
- goff = bit >> LG_BITMAP_GROUP_NBITS;
- gp = &bitmap[binfo->levels[i].group_offset + goff];
- g = *gp;
- propagate = (g == 0);
- assert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)))
- == 0);
- g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);
- *gp = g;
- if (propagate == false)
- break;
- }
- }
-}
-
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/chunk.h b/extra/jemalloc/include/jemalloc/internal/chunk.h
deleted file mode 100644
index 87d8700dac8..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/chunk.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-/*
- * Size and alignment of memory chunks that are allocated by the OS's virtual
- * memory system.
- */
-#define LG_CHUNK_DEFAULT 22
-
-/* Return the chunk address for allocation address a. */
-#define CHUNK_ADDR2BASE(a) \
- ((void *)((uintptr_t)(a) & ~chunksize_mask))
-
-/* Return the chunk offset of address a. */
-#define CHUNK_ADDR2OFFSET(a) \
- ((size_t)((uintptr_t)(a) & chunksize_mask))
-
-/* Return the smallest chunk multiple that is >= s. */
-#define CHUNK_CEILING(s) \
- (((s) + chunksize_mask) & ~chunksize_mask)
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-extern size_t opt_lg_chunk;
-extern const char *opt_dss;
-
-/* Protects stats_chunks; currently not used for any other purpose. */
-extern malloc_mutex_t chunks_mtx;
-/* Chunk statistics. */
-extern chunk_stats_t stats_chunks;
-
-extern rtree_t *chunks_rtree;
-
-extern size_t chunksize;
-extern size_t chunksize_mask; /* (chunksize - 1). */
-extern size_t chunk_npages;
-extern size_t map_bias; /* Number of arena chunk header pages. */
-extern size_t arena_maxclass; /* Max size class for arenas. */
-
-void *chunk_alloc(size_t size, size_t alignment, bool base, bool *zero,
- dss_prec_t dss_prec);
-void chunk_unmap(void *chunk, size_t size);
-void chunk_dealloc(void *chunk, size_t size, bool unmap);
-bool chunk_boot(void);
-void chunk_prefork(void);
-void chunk_postfork_parent(void);
-void chunk_postfork_child(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
-
-#include "jemalloc/internal/chunk_dss.h"
-#include "jemalloc/internal/chunk_mmap.h"
diff --git a/extra/jemalloc/include/jemalloc/internal/chunk_dss.h b/extra/jemalloc/include/jemalloc/internal/chunk_dss.h
deleted file mode 100644
index 6585f071bbe..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/chunk_dss.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef enum {
- dss_prec_disabled = 0,
- dss_prec_primary = 1,
- dss_prec_secondary = 2,
-
- dss_prec_limit = 3
-} dss_prec_t ;
-#define DSS_PREC_DEFAULT dss_prec_secondary
-#define DSS_DEFAULT "secondary"
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-extern const char *dss_prec_names[];
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-dss_prec_t chunk_dss_prec_get(void);
-bool chunk_dss_prec_set(dss_prec_t dss_prec);
-void *chunk_alloc_dss(size_t size, size_t alignment, bool *zero);
-bool chunk_in_dss(void *chunk);
-bool chunk_dss_boot(void);
-void chunk_dss_prefork(void);
-void chunk_dss_postfork_parent(void);
-void chunk_dss_postfork_child(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/chunk_mmap.h b/extra/jemalloc/include/jemalloc/internal/chunk_mmap.h
deleted file mode 100644
index f24abac7538..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/chunk_mmap.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-bool pages_purge(void *addr, size_t length);
-
-void *chunk_alloc_mmap(size_t size, size_t alignment, bool *zero);
-bool chunk_dealloc_mmap(void *chunk, size_t size);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/ckh.h b/extra/jemalloc/include/jemalloc/internal/ckh.h
deleted file mode 100644
index 50c39ed9581..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/ckh.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct ckh_s ckh_t;
-typedef struct ckhc_s ckhc_t;
-
-/* Typedefs to allow easy function pointer passing. */
-typedef void ckh_hash_t (const void *, size_t[2]);
-typedef bool ckh_keycomp_t (const void *, const void *);
-
-/* Maintain counters used to get an idea of performance. */
-/* #define CKH_COUNT */
-/* Print counter values in ckh_delete() (requires CKH_COUNT). */
-/* #define CKH_VERBOSE */
-
-/*
- * There are 2^LG_CKH_BUCKET_CELLS cells in each hash table bucket. Try to fit
- * one bucket per L1 cache line.
- */
-#define LG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1)
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-/* Hash table cell. */
-struct ckhc_s {
- const void *key;
- const void *data;
-};
-
-struct ckh_s {
-#ifdef CKH_COUNT
- /* Counters used to get an idea of performance. */
- uint64_t ngrows;
- uint64_t nshrinks;
- uint64_t nshrinkfails;
- uint64_t ninserts;
- uint64_t nrelocs;
-#endif
-
- /* Used for pseudo-random number generation. */
-#define CKH_A 1103515241
-#define CKH_C 12347
- uint32_t prng_state;
-
- /* Total number of items. */
- size_t count;
-
- /*
- * Minimum and current number of hash table buckets. There are
- * 2^LG_CKH_BUCKET_CELLS cells per bucket.
- */
- unsigned lg_minbuckets;
- unsigned lg_curbuckets;
-
- /* Hash and comparison functions. */
- ckh_hash_t *hash;
- ckh_keycomp_t *keycomp;
-
- /* Hash table with 2^lg_curbuckets buckets. */
- ckhc_t *tab;
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-bool ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash,
- ckh_keycomp_t *keycomp);
-void ckh_delete(ckh_t *ckh);
-size_t ckh_count(ckh_t *ckh);
-bool ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data);
-bool ckh_insert(ckh_t *ckh, const void *key, const void *data);
-bool ckh_remove(ckh_t *ckh, const void *searchkey, void **key,
- void **data);
-bool ckh_search(ckh_t *ckh, const void *seachkey, void **key, void **data);
-void ckh_string_hash(const void *key, size_t r_hash[2]);
-bool ckh_string_keycomp(const void *k1, const void *k2);
-void ckh_pointer_hash(const void *key, size_t r_hash[2]);
-bool ckh_pointer_keycomp(const void *k1, const void *k2);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/ctl.h b/extra/jemalloc/include/jemalloc/internal/ctl.h
deleted file mode 100644
index 0ffecc5f2a2..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/ctl.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct ctl_node_s ctl_node_t;
-typedef struct ctl_named_node_s ctl_named_node_t;
-typedef struct ctl_indexed_node_s ctl_indexed_node_t;
-typedef struct ctl_arena_stats_s ctl_arena_stats_t;
-typedef struct ctl_stats_s ctl_stats_t;
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-struct ctl_node_s {
- bool named;
-};
-
-struct ctl_named_node_s {
- struct ctl_node_s node;
- const char *name;
- /* If (nchildren == 0), this is a terminal node. */
- unsigned nchildren;
- const ctl_node_t *children;
- int (*ctl)(const size_t *, size_t, void *, size_t *,
- void *, size_t);
-};
-
-struct ctl_indexed_node_s {
- struct ctl_node_s node;
- const ctl_named_node_t *(*index)(const size_t *, size_t, size_t);
-};
-
-struct ctl_arena_stats_s {
- bool initialized;
- unsigned nthreads;
- const char *dss;
- size_t pactive;
- size_t pdirty;
- arena_stats_t astats;
-
- /* Aggregate stats for small size classes, based on bin stats. */
- size_t allocated_small;
- uint64_t nmalloc_small;
- uint64_t ndalloc_small;
- uint64_t nrequests_small;
-
- malloc_bin_stats_t bstats[NBINS];
- malloc_large_stats_t *lstats; /* nlclasses elements. */
-};
-
-struct ctl_stats_s {
- size_t allocated;
- size_t active;
- size_t mapped;
- struct {
- size_t current; /* stats_chunks.curchunks */
- uint64_t total; /* stats_chunks.nchunks */
- size_t high; /* stats_chunks.highchunks */
- } chunks;
- struct {
- size_t allocated; /* huge_allocated */
- uint64_t nmalloc; /* huge_nmalloc */
- uint64_t ndalloc; /* huge_ndalloc */
- } huge;
- unsigned narenas;
- ctl_arena_stats_t *arenas; /* (narenas + 1) elements. */
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-int ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,
- size_t newlen);
-int ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp);
-
-int ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen);
-bool ctl_boot(void);
-void ctl_prefork(void);
-void ctl_postfork_parent(void);
-void ctl_postfork_child(void);
-
-#define xmallctl(name, oldp, oldlenp, newp, newlen) do { \
- if (je_mallctl(name, oldp, oldlenp, newp, newlen) \
- != 0) { \
- malloc_printf( \
- "<jemalloc>: Failure in xmallctl(\"%s\", ...)\n", \
- name); \
- abort(); \
- } \
-} while (0)
-
-#define xmallctlnametomib(name, mibp, miblenp) do { \
- if (je_mallctlnametomib(name, mibp, miblenp) != 0) { \
- malloc_printf("<jemalloc>: Failure in " \
- "xmallctlnametomib(\"%s\", ...)\n", name); \
- abort(); \
- } \
-} while (0)
-
-#define xmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do { \
- if (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp, \
- newlen) != 0) { \
- malloc_write( \
- "<jemalloc>: Failure in xmallctlbymib()\n"); \
- abort(); \
- } \
-} while (0)
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
-
diff --git a/extra/jemalloc/include/jemalloc/internal/extent.h b/extra/jemalloc/include/jemalloc/internal/extent.h
deleted file mode 100644
index ba95ca816bd..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/extent.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct extent_node_s extent_node_t;
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-/* Tree of extents. */
-struct extent_node_s {
- /* Linkage for the size/address-ordered tree. */
- rb_node(extent_node_t) link_szad;
-
- /* Linkage for the address-ordered tree. */
- rb_node(extent_node_t) link_ad;
-
- /* Profile counters, used for huge objects. */
- prof_ctx_t *prof_ctx;
-
- /* Pointer to the extent that this tree node is responsible for. */
- void *addr;
-
- /* Total region size. */
- size_t size;
-
- /* True if zero-filled; used by chunk recycling code. */
- bool zeroed;
-};
-typedef rb_tree(extent_node_t) extent_tree_t;
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-rb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t)
-
-rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
-
diff --git a/extra/jemalloc/include/jemalloc/internal/hash.h b/extra/jemalloc/include/jemalloc/internal/hash.h
deleted file mode 100644
index 56ecc793b36..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/hash.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * The following hash function is based on MurmurHash3, placed into the public
- * domain by Austin Appleby. See http://code.google.com/p/smhasher/ for
- * details.
- */
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-void hash(const void *key, size_t len, const uint32_t seed,
- size_t r_hash[2]);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_HASH_C_))
-/******************************************************************************/
-/* Internal implementation. */
-JEMALLOC_INLINE uint32_t
-hash_rotl_32(uint32_t x, int8_t r)
-{
-
- return (x << r) | (x >> (32 - r));
-}
-
-JEMALLOC_INLINE uint64_t
-hash_rotl_64(uint64_t x, int8_t r)
-{
- return (x << r) | (x >> (64 - r));
-}
-
-JEMALLOC_INLINE uint32_t
-hash_get_block_32(const uint32_t *p, int i)
-{
-
- return p[i];
-}
-
-JEMALLOC_INLINE uint64_t
-hash_get_block_64(const uint64_t *p, int i)
-{
-
- return p[i];
-}
-
-JEMALLOC_INLINE uint32_t
-hash_fmix_32(uint32_t h)
-{
-
- h ^= h >> 16;
- h *= 0x85ebca6b;
- h ^= h >> 13;
- h *= 0xc2b2ae35;
- h ^= h >> 16;
-
- return h;
-}
-
-JEMALLOC_INLINE uint64_t
-hash_fmix_64(uint64_t k)
-{
-
- k ^= k >> 33;
- k *= QU(0xff51afd7ed558ccdLLU);
- k ^= k >> 33;
- k *= QU(0xc4ceb9fe1a85ec53LLU);
- k ^= k >> 33;
-
- return k;
-}
-
-JEMALLOC_INLINE uint32_t
-hash_x86_32(const void *key, int len, uint32_t seed)
-{
- const uint8_t *data = (const uint8_t *) key;
- const int nblocks = len / 4;
-
- uint32_t h1 = seed;
-
- const uint32_t c1 = 0xcc9e2d51;
- const uint32_t c2 = 0x1b873593;
-
- /* body */
- {
- const uint32_t *blocks = (const uint32_t *) (data + nblocks*4);
- int i;
-
- for (i = -nblocks; i; i++) {
- uint32_t k1 = hash_get_block_32(blocks, i);
-
- k1 *= c1;
- k1 = hash_rotl_32(k1, 15);
- k1 *= c2;
-
- h1 ^= k1;
- h1 = hash_rotl_32(h1, 13);
- h1 = h1*5 + 0xe6546b64;
- }
- }
-
- /* tail */
- {
- const uint8_t *tail = (const uint8_t *) (data + nblocks*4);
-
- uint32_t k1 = 0;
-
- switch (len & 3) {
- case 3: k1 ^= tail[2] << 16;
- case 2: k1 ^= tail[1] << 8;
- case 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15);
- k1 *= c2; h1 ^= k1;
- }
- }
-
- /* finalization */
- h1 ^= len;
-
- h1 = hash_fmix_32(h1);
-
- return h1;
-}
-
-UNUSED JEMALLOC_INLINE void
-hash_x86_128(const void *key, const int len, uint32_t seed,
- uint64_t r_out[2])
-{
- const uint8_t * data = (const uint8_t *) key;
- const int nblocks = len / 16;
-
- uint32_t h1 = seed;
- uint32_t h2 = seed;
- uint32_t h3 = seed;
- uint32_t h4 = seed;
-
- const uint32_t c1 = 0x239b961b;
- const uint32_t c2 = 0xab0e9789;
- const uint32_t c3 = 0x38b34ae5;
- const uint32_t c4 = 0xa1e38b93;
-
- /* body */
- {
- const uint32_t *blocks = (const uint32_t *) (data + nblocks*16);
- int i;
-
- for (i = -nblocks; i; i++) {
- uint32_t k1 = hash_get_block_32(blocks, i*4 + 0);
- uint32_t k2 = hash_get_block_32(blocks, i*4 + 1);
- uint32_t k3 = hash_get_block_32(blocks, i*4 + 2);
- uint32_t k4 = hash_get_block_32(blocks, i*4 + 3);
-
- k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;
-
- h1 = hash_rotl_32(h1, 19); h1 += h2;
- h1 = h1*5 + 0x561ccd1b;
-
- k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;
-
- h2 = hash_rotl_32(h2, 17); h2 += h3;
- h2 = h2*5 + 0x0bcaa747;
-
- k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;
-
- h3 = hash_rotl_32(h3, 15); h3 += h4;
- h3 = h3*5 + 0x96cd1c35;
-
- k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;
-
- h4 = hash_rotl_32(h4, 13); h4 += h1;
- h4 = h4*5 + 0x32ac3b17;
- }
- }
-
- /* tail */
- {
- const uint8_t *tail = (const uint8_t *) (data + nblocks*16);
- uint32_t k1 = 0;
- uint32_t k2 = 0;
- uint32_t k3 = 0;
- uint32_t k4 = 0;
-
- switch (len & 15) {
- case 15: k4 ^= tail[14] << 16;
- case 14: k4 ^= tail[13] << 8;
- case 13: k4 ^= tail[12] << 0;
- k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;
-
- case 12: k3 ^= tail[11] << 24;
- case 11: k3 ^= tail[10] << 16;
- case 10: k3 ^= tail[ 9] << 8;
- case 9: k3 ^= tail[ 8] << 0;
- k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;
-
- case 8: k2 ^= tail[ 7] << 24;
- case 7: k2 ^= tail[ 6] << 16;
- case 6: k2 ^= tail[ 5] << 8;
- case 5: k2 ^= tail[ 4] << 0;
- k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;
-
- case 4: k1 ^= tail[ 3] << 24;
- case 3: k1 ^= tail[ 2] << 16;
- case 2: k1 ^= tail[ 1] << 8;
- case 1: k1 ^= tail[ 0] << 0;
- k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;
- }
- }
-
- /* finalization */
- h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
-
- h1 += h2; h1 += h3; h1 += h4;
- h2 += h1; h3 += h1; h4 += h1;
-
- h1 = hash_fmix_32(h1);
- h2 = hash_fmix_32(h2);
- h3 = hash_fmix_32(h3);
- h4 = hash_fmix_32(h4);
-
- h1 += h2; h1 += h3; h1 += h4;
- h2 += h1; h3 += h1; h4 += h1;
-
- r_out[0] = (((uint64_t) h2) << 32) | h1;
- r_out[1] = (((uint64_t) h4) << 32) | h3;
-}
-
-UNUSED JEMALLOC_INLINE void
-hash_x64_128(const void *key, const int len, const uint32_t seed,
- uint64_t r_out[2])
-{
- const uint8_t *data = (const uint8_t *) key;
- const int nblocks = len / 16;
-
- uint64_t h1 = seed;
- uint64_t h2 = seed;
-
- const uint64_t c1 = QU(0x87c37b91114253d5LLU);
- const uint64_t c2 = QU(0x4cf5ad432745937fLLU);
-
- /* body */
- {
- const uint64_t *blocks = (const uint64_t *) (data);
- int i;
-
- for (i = 0; i < nblocks; i++) {
- uint64_t k1 = hash_get_block_64(blocks, i*2 + 0);
- uint64_t k2 = hash_get_block_64(blocks, i*2 + 1);
-
- k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;
-
- h1 = hash_rotl_64(h1, 27); h1 += h2;
- h1 = h1*5 + 0x52dce729;
-
- k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;
-
- h2 = hash_rotl_64(h2, 31); h2 += h1;
- h2 = h2*5 + 0x38495ab5;
- }
- }
-
- /* tail */
- {
- const uint8_t *tail = (const uint8_t*)(data + nblocks*16);
- uint64_t k1 = 0;
- uint64_t k2 = 0;
-
- switch (len & 15) {
- case 15: k2 ^= ((uint64_t)(tail[14])) << 48;
- case 14: k2 ^= ((uint64_t)(tail[13])) << 40;
- case 13: k2 ^= ((uint64_t)(tail[12])) << 32;
- case 12: k2 ^= ((uint64_t)(tail[11])) << 24;
- case 11: k2 ^= ((uint64_t)(tail[10])) << 16;
- case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8;
- case 9: k2 ^= ((uint64_t)(tail[ 8])) << 0;
- k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;
-
- case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56;
- case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48;
- case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40;
- case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32;
- case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24;
- case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16;
- case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8;
- case 1: k1 ^= ((uint64_t)(tail[ 0])) << 0;
- k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;
- }
- }
-
- /* finalization */
- h1 ^= len; h2 ^= len;
-
- h1 += h2;
- h2 += h1;
-
- h1 = hash_fmix_64(h1);
- h2 = hash_fmix_64(h2);
-
- h1 += h2;
- h2 += h1;
-
- r_out[0] = h1;
- r_out[1] = h2;
-}
-
-
-/******************************************************************************/
-/* API. */
-JEMALLOC_INLINE void
-hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2])
-{
-#if (LG_SIZEOF_PTR == 3)
- hash_x64_128(key, len, seed, (uint64_t *)r_hash);
-#else
- uint64_t hashes[2];
- hash_x86_128(key, len, seed, hashes);
- r_hash[0] = (size_t)hashes[0];
- r_hash[1] = (size_t)hashes[1];
-#endif
-}
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/huge.h b/extra/jemalloc/include/jemalloc/internal/huge.h
deleted file mode 100644
index d987d370767..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/huge.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-/* Huge allocation statistics. */
-extern uint64_t huge_nmalloc;
-extern uint64_t huge_ndalloc;
-extern size_t huge_allocated;
-
-/* Protects chunk-related data structures. */
-extern malloc_mutex_t huge_mtx;
-
-void *huge_malloc(size_t size, bool zero);
-void *huge_palloc(size_t size, size_t alignment, bool zero);
-void *huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size,
- size_t extra);
-void *huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
- size_t alignment, bool zero, bool try_tcache_dalloc);
-void huge_dalloc(void *ptr, bool unmap);
-size_t huge_salloc(const void *ptr);
-prof_ctx_t *huge_prof_ctx_get(const void *ptr);
-void huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
-bool huge_boot(void);
-void huge_prefork(void);
-void huge_postfork_parent(void);
-void huge_postfork_child(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in b/extra/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
deleted file mode 100644
index 124ec34bddf..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
+++ /dev/null
@@ -1,1030 +0,0 @@
-#ifndef JEMALLOC_INTERNAL_H
-#define JEMALLOC_INTERNAL_H
-#include <math.h>
-#ifdef _WIN32
-# include <windows.h>
-# define ENOENT ERROR_PATH_NOT_FOUND
-# define EINVAL ERROR_BAD_ARGUMENTS
-# define EAGAIN ERROR_OUTOFMEMORY
-# define EPERM ERROR_WRITE_FAULT
-# define EFAULT ERROR_INVALID_ADDRESS
-# define ENOMEM ERROR_NOT_ENOUGH_MEMORY
-# undef ERANGE
-# define ERANGE ERROR_INVALID_DATA
-#else
-# include <sys/param.h>
-# include <sys/mman.h>
-# include <sys/syscall.h>
-# if !defined(SYS_write) && defined(__NR_write)
-# define SYS_write __NR_write
-# endif
-# include <sys/uio.h>
-# include <pthread.h>
-# include <errno.h>
-#endif
-#include <sys/types.h>
-
-#include <limits.h>
-#ifndef SIZE_T_MAX
-# define SIZE_T_MAX SIZE_MAX
-#endif
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stddef.h>
-#ifndef offsetof
-# define offsetof(type, member) ((size_t)&(((type *)NULL)->member))
-#endif
-#include <inttypes.h>
-#include <string.h>
-#include <strings.h>
-#include <ctype.h>
-#ifdef _MSC_VER
-# include <io.h>
-typedef intptr_t ssize_t;
-# define PATH_MAX 1024
-# define STDERR_FILENO 2
-# define __func__ __FUNCTION__
-/* Disable warnings about deprecated system functions */
-# pragma warning(disable: 4996)
-#else
-# include <unistd.h>
-#endif
-#include <fcntl.h>
-
-#define JEMALLOC_NO_DEMANGLE
-#include "../jemalloc@install_suffix@.h"
-
-#ifdef JEMALLOC_UTRACE
-#include <sys/ktrace.h>
-#endif
-
-#ifdef JEMALLOC_VALGRIND
-#include <valgrind/valgrind.h>
-#include <valgrind/memcheck.h>
-#endif
-
-#include "jemalloc/internal/private_namespace.h"
-
-#ifdef JEMALLOC_CC_SILENCE
-#define UNUSED JEMALLOC_ATTR(unused)
-#else
-#define UNUSED
-#endif
-
-static const bool config_debug =
-#ifdef JEMALLOC_DEBUG
- true
-#else
- false
-#endif
- ;
-static const bool config_dss =
-#ifdef JEMALLOC_DSS
- true
-#else
- false
-#endif
- ;
-static const bool config_fill =
-#ifdef JEMALLOC_FILL
- true
-#else
- false
-#endif
- ;
-static const bool config_lazy_lock =
-#ifdef JEMALLOC_LAZY_LOCK
- true
-#else
- false
-#endif
- ;
-static const bool config_prof =
-#ifdef JEMALLOC_PROF
- true
-#else
- false
-#endif
- ;
-static const bool config_prof_libgcc =
-#ifdef JEMALLOC_PROF_LIBGCC
- true
-#else
- false
-#endif
- ;
-static const bool config_prof_libunwind =
-#ifdef JEMALLOC_PROF_LIBUNWIND
- true
-#else
- false
-#endif
- ;
-static const bool config_mremap =
-#ifdef JEMALLOC_MREMAP
- true
-#else
- false
-#endif
- ;
-static const bool config_munmap =
-#ifdef JEMALLOC_MUNMAP
- true
-#else
- false
-#endif
- ;
-static const bool config_stats =
-#ifdef JEMALLOC_STATS
- true
-#else
- false
-#endif
- ;
-static const bool config_tcache =
-#ifdef JEMALLOC_TCACHE
- true
-#else
- false
-#endif
- ;
-static const bool config_tls =
-#ifdef JEMALLOC_TLS
- true
-#else
- false
-#endif
- ;
-static const bool config_utrace =
-#ifdef JEMALLOC_UTRACE
- true
-#else
- false
-#endif
- ;
-static const bool config_valgrind =
-#ifdef JEMALLOC_VALGRIND
- true
-#else
- false
-#endif
- ;
-static const bool config_xmalloc =
-#ifdef JEMALLOC_XMALLOC
- true
-#else
- false
-#endif
- ;
-static const bool config_ivsalloc =
-#ifdef JEMALLOC_IVSALLOC
- true
-#else
- false
-#endif
- ;
-
-#ifdef JEMALLOC_ATOMIC9
-#include <machine/atomic.h>
-#endif
-
-#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))
-#include <libkern/OSAtomic.h>
-#endif
-
-#ifdef JEMALLOC_ZONE
-#include <mach/mach_error.h>
-#include <mach/mach_init.h>
-#include <mach/vm_map.h>
-#include <malloc/malloc.h>
-#endif
-
-#define RB_COMPACT
-#include "jemalloc/internal/rb.h"
-#include "jemalloc/internal/qr.h"
-#include "jemalloc/internal/ql.h"
-
-/*
- * jemalloc can conceptually be broken into components (arena, tcache, etc.),
- * but there are circular dependencies that cannot be broken without
- * substantial performance degradation. In order to reduce the effect on
- * visual code flow, read the header files in multiple passes, with one of the
- * following cpp variables defined during each pass:
- *
- * JEMALLOC_H_TYPES : Preprocessor-defined constants and psuedo-opaque data
- * types.
- * JEMALLOC_H_STRUCTS : Data structures.
- * JEMALLOC_H_EXTERNS : Extern data declarations and function prototypes.
- * JEMALLOC_H_INLINES : Inline functions.
- */
-/******************************************************************************/
-#define JEMALLOC_H_TYPES
-
-#define ALLOCM_LG_ALIGN_MASK ((int)0x3f)
-
-#define ZU(z) ((size_t)z)
-#define QU(q) ((uint64_t)q)
-
-#ifndef __DECONST
-# define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
-#endif
-
-#ifdef JEMALLOC_DEBUG
- /* Disable inlining to make debugging easier. */
-# define JEMALLOC_ALWAYS_INLINE
-# define JEMALLOC_ALWAYS_INLINE_C static
-# define JEMALLOC_INLINE
-# define inline
-#else
-# define JEMALLOC_ENABLE_INLINE
-# ifdef JEMALLOC_HAVE_ATTR
-# define JEMALLOC_ALWAYS_INLINE \
- static inline JEMALLOC_ATTR(unused) JEMALLOC_ATTR(always_inline)
-# define JEMALLOC_ALWAYS_INLINE_C \
- static inline JEMALLOC_ATTR(always_inline)
-# else
-# define JEMALLOC_ALWAYS_INLINE static inline
-# define JEMALLOC_ALWAYS_INLINE_C static inline
-# endif
-# define JEMALLOC_INLINE static inline
-# ifdef _MSC_VER
-# define inline _inline
-# endif
-#endif
-
-/* Smallest size class to support. */
-#define LG_TINY_MIN 3
-#define TINY_MIN (1U << LG_TINY_MIN)
-
-/*
- * Minimum alignment of allocations is 2^LG_QUANTUM bytes (ignoring tiny size
- * classes).
- */
-#ifndef LG_QUANTUM
-# if (defined(__i386__) || defined(_M_IX86))
-# define LG_QUANTUM 4
-# endif
-# ifdef __ia64__
-# define LG_QUANTUM 4
-# endif
-# ifdef __alpha__
-# define LG_QUANTUM 4
-# endif
-# ifdef __sparc64__
-# define LG_QUANTUM 4
-# endif
-# if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))
-# define LG_QUANTUM 4
-# endif
-# ifdef __arm__
-# define LG_QUANTUM 3
-# endif
-# ifdef __hppa__
-# define LG_QUANTUM 4
-# endif
-# ifdef __mips__
-# define LG_QUANTUM 3
-# endif
-# ifdef __powerpc__
-# define LG_QUANTUM 4
-# endif
-# ifdef __s390__
-# define LG_QUANTUM 4
-# endif
-# ifdef __SH4__
-# define LG_QUANTUM 4
-# endif
-# ifdef __tile__
-# define LG_QUANTUM 4
-# endif
-# ifndef LG_QUANTUM
-# error "No LG_QUANTUM definition for architecture; specify via CPPFLAGS"
-# endif
-#endif
-
-#define QUANTUM ((size_t)(1U << LG_QUANTUM))
-#define QUANTUM_MASK (QUANTUM - 1)
-
-/* Return the smallest quantum multiple that is >= a. */
-#define QUANTUM_CEILING(a) \
- (((a) + QUANTUM_MASK) & ~QUANTUM_MASK)
-
-#define LONG ((size_t)(1U << LG_SIZEOF_LONG))
-#define LONG_MASK (LONG - 1)
-
-/* Return the smallest long multiple that is >= a. */
-#define LONG_CEILING(a) \
- (((a) + LONG_MASK) & ~LONG_MASK)
-
-#define SIZEOF_PTR (1U << LG_SIZEOF_PTR)
-#define PTR_MASK (SIZEOF_PTR - 1)
-
-/* Return the smallest (void *) multiple that is >= a. */
-#define PTR_CEILING(a) \
- (((a) + PTR_MASK) & ~PTR_MASK)
-
-/*
- * Maximum size of L1 cache line. This is used to avoid cache line aliasing.
- * In addition, this controls the spacing of cacheline-spaced size classes.
- *
- * CACHELINE cannot be based on LG_CACHELINE because __declspec(align()) can
- * only handle raw constants.
- */
-#define LG_CACHELINE 6
-#define CACHELINE 64
-#define CACHELINE_MASK (CACHELINE - 1)
-
-/* Return the smallest cacheline multiple that is >= s. */
-#define CACHELINE_CEILING(s) \
- (((s) + CACHELINE_MASK) & ~CACHELINE_MASK)
-
-/* Page size. STATIC_PAGE_SHIFT is determined by the configure script. */
-#ifdef PAGE_MASK
-# undef PAGE_MASK
-#endif
-#define LG_PAGE STATIC_PAGE_SHIFT
-#define PAGE ((size_t)(1U << STATIC_PAGE_SHIFT))
-#define PAGE_MASK ((size_t)(PAGE - 1))
-
-/* Return the smallest pagesize multiple that is >= s. */
-#define PAGE_CEILING(s) \
- (((s) + PAGE_MASK) & ~PAGE_MASK)
-
-/* Return the nearest aligned address at or below a. */
-#define ALIGNMENT_ADDR2BASE(a, alignment) \
- ((void *)((uintptr_t)(a) & (-(alignment))))
-
-/* Return the offset between a and the nearest aligned address at or below a. */
-#define ALIGNMENT_ADDR2OFFSET(a, alignment) \
- ((size_t)((uintptr_t)(a) & (alignment - 1)))
-
-/* Return the smallest alignment multiple that is >= s. */
-#define ALIGNMENT_CEILING(s, alignment) \
- (((s) + (alignment - 1)) & (-(alignment)))
-
-/* Declare a variable length array */
-#if __STDC_VERSION__ < 199901L
-# ifdef _MSC_VER
-# include <malloc.h>
-# define alloca _alloca
-# else
-# ifdef JEMALLOC_HAS_ALLOCA_H
-# include <alloca.h>
-# else
-# include <stdlib.h>
-# endif
-# endif
-# define VARIABLE_ARRAY(type, name, count) \
- type *name = alloca(sizeof(type) * count)
-#else
-# define VARIABLE_ARRAY(type, name, count) type name[count]
-#endif
-
-#ifdef JEMALLOC_VALGRIND
-/*
- * The JEMALLOC_VALGRIND_*() macros must be macros rather than functions
- * so that when Valgrind reports errors, there are no extra stack frames
- * in the backtraces.
- *
- * The size that is reported to valgrind must be consistent through a chain of
- * malloc..realloc..realloc calls. Request size isn't recorded anywhere in
- * jemalloc, so it is critical that all callers of these macros provide usize
- * rather than request size. As a result, buffer overflow detection is
- * technically weakened for the standard API, though it is generally accepted
- * practice to consider any extra bytes reported by malloc_usable_size() as
- * usable space.
- */
-#define JEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do { \
- if (config_valgrind && opt_valgrind && cond) \
- VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, p2rz(ptr), zero); \
-} while (0)
-#define JEMALLOC_VALGRIND_REALLOC(ptr, usize, old_ptr, old_usize, \
- old_rzsize, zero) do { \
- if (config_valgrind && opt_valgrind) { \
- size_t rzsize = p2rz(ptr); \
- \
- if (ptr == old_ptr) { \
- VALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize, \
- usize, rzsize); \
- if (zero && old_usize < usize) { \
- VALGRIND_MAKE_MEM_DEFINED( \
- (void *)((uintptr_t)ptr + \
- old_usize), usize - old_usize); \
- } \
- } else { \
- if (old_ptr != NULL) { \
- VALGRIND_FREELIKE_BLOCK(old_ptr, \
- old_rzsize); \
- } \
- if (ptr != NULL) { \
- size_t copy_size = (old_usize < usize) \
- ? old_usize : usize; \
- size_t tail_size = usize - copy_size; \
- VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, \
- rzsize, false); \
- if (copy_size > 0) { \
- VALGRIND_MAKE_MEM_DEFINED(ptr, \
- copy_size); \
- } \
- if (zero && tail_size > 0) { \
- VALGRIND_MAKE_MEM_DEFINED( \
- (void *)((uintptr_t)ptr + \
- copy_size), tail_size); \
- } \
- } \
- } \
- } \
-} while (0)
-#define JEMALLOC_VALGRIND_FREE(ptr, rzsize) do { \
- if (config_valgrind && opt_valgrind) \
- VALGRIND_FREELIKE_BLOCK(ptr, rzsize); \
-} while (0)
-#else
-#define RUNNING_ON_VALGRIND ((unsigned)0)
-#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
- do {} while (0)
-#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
- do {} while (0)
-#define VALGRIND_FREELIKE_BLOCK(addr, rzB) do {} while (0)
-#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len) do {} while (0)
-#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len) do {} while (0)
-#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len) do {} while (0)
-#define JEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do {} while (0)
-#define JEMALLOC_VALGRIND_REALLOC(ptr, usize, old_ptr, old_usize, \
- old_rzsize, zero) do {} while (0)
-#define JEMALLOC_VALGRIND_FREE(ptr, rzsize) do {} while (0)
-#endif
-
-#include "jemalloc/internal/util.h"
-#include "jemalloc/internal/atomic.h"
-#include "jemalloc/internal/prng.h"
-#include "jemalloc/internal/ckh.h"
-#include "jemalloc/internal/size_classes.h"
-#include "jemalloc/internal/stats.h"
-#include "jemalloc/internal/ctl.h"
-#include "jemalloc/internal/mutex.h"
-#include "jemalloc/internal/tsd.h"
-#include "jemalloc/internal/mb.h"
-#include "jemalloc/internal/extent.h"
-#include "jemalloc/internal/arena.h"
-#include "jemalloc/internal/bitmap.h"
-#include "jemalloc/internal/base.h"
-#include "jemalloc/internal/chunk.h"
-#include "jemalloc/internal/huge.h"
-#include "jemalloc/internal/rtree.h"
-#include "jemalloc/internal/tcache.h"
-#include "jemalloc/internal/hash.h"
-#include "jemalloc/internal/quarantine.h"
-#include "jemalloc/internal/prof.h"
-
-#undef JEMALLOC_H_TYPES
-/******************************************************************************/
-#define JEMALLOC_H_STRUCTS
-
-#include "jemalloc/internal/util.h"
-#include "jemalloc/internal/atomic.h"
-#include "jemalloc/internal/prng.h"
-#include "jemalloc/internal/ckh.h"
-#include "jemalloc/internal/size_classes.h"
-#include "jemalloc/internal/stats.h"
-#include "jemalloc/internal/ctl.h"
-#include "jemalloc/internal/mutex.h"
-#include "jemalloc/internal/tsd.h"
-#include "jemalloc/internal/mb.h"
-#include "jemalloc/internal/bitmap.h"
-#include "jemalloc/internal/extent.h"
-#include "jemalloc/internal/arena.h"
-#include "jemalloc/internal/base.h"
-#include "jemalloc/internal/chunk.h"
-#include "jemalloc/internal/huge.h"
-#include "jemalloc/internal/rtree.h"
-#include "jemalloc/internal/tcache.h"
-#include "jemalloc/internal/hash.h"
-#include "jemalloc/internal/quarantine.h"
-#include "jemalloc/internal/prof.h"
-
-typedef struct {
- uint64_t allocated;
- uint64_t deallocated;
-} thread_allocated_t;
-/*
- * The JEMALLOC_CONCAT() wrapper is necessary to pass {0, 0} via a cpp macro
- * argument.
- */
-#define THREAD_ALLOCATED_INITIALIZER JEMALLOC_CONCAT({0, 0})
-
-#undef JEMALLOC_H_STRUCTS
-/******************************************************************************/
-#define JEMALLOC_H_EXTERNS
-
-extern bool opt_abort;
-extern bool opt_junk;
-extern size_t opt_quarantine;
-extern bool opt_redzone;
-extern bool opt_utrace;
-extern bool opt_valgrind;
-extern bool opt_xmalloc;
-extern bool opt_zero;
-extern size_t opt_narenas;
-
-/* Number of CPUs. */
-extern unsigned ncpus;
-
-/* Protects arenas initialization (arenas, arenas_total). */
-extern malloc_mutex_t arenas_lock;
-/*
- * Arenas that are used to service external requests. Not all elements of the
- * arenas array are necessarily used; arenas are created lazily as needed.
- *
- * arenas[0..narenas_auto) are used for automatic multiplexing of threads and
- * arenas. arenas[narenas_auto..narenas_total) are only used if the application
- * takes some action to create them and allocate from them.
- */
-extern arena_t **arenas;
-extern unsigned narenas_total;
-extern unsigned narenas_auto; /* Read-only after initialization. */
-
-arena_t *arenas_extend(unsigned ind);
-void arenas_cleanup(void *arg);
-arena_t *choose_arena_hard(void);
-void jemalloc_prefork(void);
-void jemalloc_postfork_parent(void);
-void jemalloc_postfork_child(void);
-
-#include "jemalloc/internal/util.h"
-#include "jemalloc/internal/atomic.h"
-#include "jemalloc/internal/prng.h"
-#include "jemalloc/internal/ckh.h"
-#include "jemalloc/internal/size_classes.h"
-#include "jemalloc/internal/stats.h"
-#include "jemalloc/internal/ctl.h"
-#include "jemalloc/internal/mutex.h"
-#include "jemalloc/internal/tsd.h"
-#include "jemalloc/internal/mb.h"
-#include "jemalloc/internal/bitmap.h"
-#include "jemalloc/internal/extent.h"
-#include "jemalloc/internal/arena.h"
-#include "jemalloc/internal/base.h"
-#include "jemalloc/internal/chunk.h"
-#include "jemalloc/internal/huge.h"
-#include "jemalloc/internal/rtree.h"
-#include "jemalloc/internal/tcache.h"
-#include "jemalloc/internal/hash.h"
-#include "jemalloc/internal/quarantine.h"
-#include "jemalloc/internal/prof.h"
-
-#undef JEMALLOC_H_EXTERNS
-/******************************************************************************/
-#define JEMALLOC_H_INLINES
-
-#include "jemalloc/internal/util.h"
-#include "jemalloc/internal/atomic.h"
-#include "jemalloc/internal/prng.h"
-#include "jemalloc/internal/ckh.h"
-#include "jemalloc/internal/size_classes.h"
-#include "jemalloc/internal/stats.h"
-#include "jemalloc/internal/ctl.h"
-#include "jemalloc/internal/mutex.h"
-#include "jemalloc/internal/tsd.h"
-#include "jemalloc/internal/mb.h"
-#include "jemalloc/internal/extent.h"
-#include "jemalloc/internal/base.h"
-#include "jemalloc/internal/chunk.h"
-#include "jemalloc/internal/huge.h"
-
-#ifndef JEMALLOC_ENABLE_INLINE
-malloc_tsd_protos(JEMALLOC_ATTR(unused), arenas, arena_t *)
-
-size_t s2u(size_t size);
-size_t sa2u(size_t size, size_t alignment);
-unsigned narenas_total_get(void);
-arena_t *choose_arena(arena_t *arena);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
-/*
- * Map of pthread_self() --> arenas[???], used for selecting an arena to use
- * for allocations.
- */
-malloc_tsd_externs(arenas, arena_t *)
-malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, arenas, arena_t *, NULL,
- arenas_cleanup)
-
-/*
- * Compute usable size that would result from allocating an object with the
- * specified size.
- */
-JEMALLOC_ALWAYS_INLINE size_t
-s2u(size_t size)
-{
-
- if (size <= SMALL_MAXCLASS)
- return (arena_bin_info[SMALL_SIZE2BIN(size)].reg_size);
- if (size <= arena_maxclass)
- return (PAGE_CEILING(size));
- return (CHUNK_CEILING(size));
-}
-
-/*
- * Compute usable size that would result from allocating an object with the
- * specified size and alignment.
- */
-JEMALLOC_ALWAYS_INLINE size_t
-sa2u(size_t size, size_t alignment)
-{
- size_t usize;
-
- assert(alignment != 0 && ((alignment - 1) & alignment) == 0);
-
- /*
- * Round size up to the nearest multiple of alignment.
- *
- * This done, we can take advantage of the fact that for each small
- * size class, every object is aligned at the smallest power of two
- * that is non-zero in the base two representation of the size. For
- * example:
- *
- * Size | Base 2 | Minimum alignment
- * -----+----------+------------------
- * 96 | 1100000 | 32
- * 144 | 10100000 | 32
- * 192 | 11000000 | 64
- */
- usize = ALIGNMENT_CEILING(size, alignment);
- /*
- * (usize < size) protects against the combination of maximal
- * alignment and size greater than maximal alignment.
- */
- if (usize < size) {
- /* size_t overflow. */
- return (0);
- }
-
- if (usize <= arena_maxclass && alignment <= PAGE) {
- if (usize <= SMALL_MAXCLASS)
- return (arena_bin_info[SMALL_SIZE2BIN(usize)].reg_size);
- return (PAGE_CEILING(usize));
- } else {
- size_t run_size;
-
- /*
- * We can't achieve subpage alignment, so round up alignment
- * permanently; it makes later calculations simpler.
- */
- alignment = PAGE_CEILING(alignment);
- usize = PAGE_CEILING(size);
- /*
- * (usize < size) protects against very large sizes within
- * PAGE of SIZE_T_MAX.
- *
- * (usize + alignment < usize) protects against the
- * combination of maximal alignment and usize large enough
- * to cause overflow. This is similar to the first overflow
- * check above, but it needs to be repeated due to the new
- * usize value, which may now be *equal* to maximal
- * alignment, whereas before we only detected overflow if the
- * original size was *greater* than maximal alignment.
- */
- if (usize < size || usize + alignment < usize) {
- /* size_t overflow. */
- return (0);
- }
-
- /*
- * Calculate the size of the over-size run that arena_palloc()
- * would need to allocate in order to guarantee the alignment.
- * If the run wouldn't fit within a chunk, round up to a huge
- * allocation size.
- */
- run_size = usize + alignment - PAGE;
- if (run_size <= arena_maxclass)
- return (PAGE_CEILING(usize));
- return (CHUNK_CEILING(usize));
- }
-}
-
-JEMALLOC_INLINE unsigned
-narenas_total_get(void)
-{
- unsigned narenas;
-
- malloc_mutex_lock(&arenas_lock);
- narenas = narenas_total;
- malloc_mutex_unlock(&arenas_lock);
-
- return (narenas);
-}
-
-/* Choose an arena based on a per-thread value. */
-JEMALLOC_INLINE arena_t *
-choose_arena(arena_t *arena)
-{
- arena_t *ret;
-
- if (arena != NULL)
- return (arena);
-
- if ((ret = *arenas_tsd_get()) == NULL) {
- ret = choose_arena_hard();
- assert(ret != NULL);
- }
-
- return (ret);
-}
-#endif
-
-#include "jemalloc/internal/bitmap.h"
-#include "jemalloc/internal/rtree.h"
-/*
- * Include arena.h twice in order to resolve circular dependencies with
- * tcache.h.
- */
-#define JEMALLOC_ARENA_INLINE_A
-#include "jemalloc/internal/arena.h"
-#undef JEMALLOC_ARENA_INLINE_A
-#include "jemalloc/internal/tcache.h"
-#define JEMALLOC_ARENA_INLINE_B
-#include "jemalloc/internal/arena.h"
-#undef JEMALLOC_ARENA_INLINE_B
-#include "jemalloc/internal/hash.h"
-#include "jemalloc/internal/quarantine.h"
-
-#ifndef JEMALLOC_ENABLE_INLINE
-void *imallocx(size_t size, bool try_tcache, arena_t *arena);
-void *imalloc(size_t size);
-void *icallocx(size_t size, bool try_tcache, arena_t *arena);
-void *icalloc(size_t size);
-void *ipallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,
- arena_t *arena);
-void *ipalloc(size_t usize, size_t alignment, bool zero);
-size_t isalloc(const void *ptr, bool demote);
-size_t ivsalloc(const void *ptr, bool demote);
-size_t u2rz(size_t usize);
-size_t p2rz(const void *ptr);
-void idallocx(void *ptr, bool try_tcache);
-void idalloc(void *ptr);
-void iqallocx(void *ptr, bool try_tcache);
-void iqalloc(void *ptr);
-void *irallocx(void *ptr, size_t size, size_t extra, size_t alignment,
- bool zero, bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc,
- arena_t *arena);
-void *iralloc(void *ptr, size_t size, size_t extra, size_t alignment,
- bool zero, bool no_move);
-malloc_tsd_protos(JEMALLOC_ATTR(unused), thread_allocated, thread_allocated_t)
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
-JEMALLOC_ALWAYS_INLINE void *
-imallocx(size_t size, bool try_tcache, arena_t *arena)
-{
-
- assert(size != 0);
-
- if (size <= arena_maxclass)
- return (arena_malloc(arena, size, false, try_tcache));
- else
- return (huge_malloc(size, false));
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-imalloc(size_t size)
-{
-
- return (imallocx(size, true, NULL));
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-icallocx(size_t size, bool try_tcache, arena_t *arena)
-{
-
- if (size <= arena_maxclass)
- return (arena_malloc(arena, size, true, try_tcache));
- else
- return (huge_malloc(size, true));
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-icalloc(size_t size)
-{
-
- return (icallocx(size, true, NULL));
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-ipallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,
- arena_t *arena)
-{
- void *ret;
-
- assert(usize != 0);
- assert(usize == sa2u(usize, alignment));
-
- if (usize <= arena_maxclass && alignment <= PAGE)
- ret = arena_malloc(arena, usize, zero, try_tcache);
- else {
- if (usize <= arena_maxclass) {
- ret = arena_palloc(choose_arena(arena), usize,
- alignment, zero);
- } else if (alignment <= chunksize)
- ret = huge_malloc(usize, zero);
- else
- ret = huge_palloc(usize, alignment, zero);
- }
-
- assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret);
- return (ret);
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-ipalloc(size_t usize, size_t alignment, bool zero)
-{
-
- return (ipallocx(usize, alignment, zero, true, NULL));
-}
-
-/*
- * Typical usage:
- * void *ptr = [...]
- * size_t sz = isalloc(ptr, config_prof);
- */
-JEMALLOC_ALWAYS_INLINE size_t
-isalloc(const void *ptr, bool demote)
-{
- size_t ret;
- arena_chunk_t *chunk;
-
- assert(ptr != NULL);
- /* Demotion only makes sense if config_prof is true. */
- assert(config_prof || demote == false);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk != ptr)
- ret = arena_salloc(ptr, demote);
- else
- ret = huge_salloc(ptr);
-
- return (ret);
-}
-
-JEMALLOC_ALWAYS_INLINE size_t
-ivsalloc(const void *ptr, bool demote)
-{
-
- /* Return 0 if ptr is not within a chunk managed by jemalloc. */
- if (rtree_get(chunks_rtree, (uintptr_t)CHUNK_ADDR2BASE(ptr)) == NULL)
- return (0);
-
- return (isalloc(ptr, demote));
-}
-
-JEMALLOC_INLINE size_t
-u2rz(size_t usize)
-{
- size_t ret;
-
- if (usize <= SMALL_MAXCLASS) {
- size_t binind = SMALL_SIZE2BIN(usize);
- ret = arena_bin_info[binind].redzone_size;
- } else
- ret = 0;
-
- return (ret);
-}
-
-JEMALLOC_INLINE size_t
-p2rz(const void *ptr)
-{
- size_t usize = isalloc(ptr, false);
-
- return (u2rz(usize));
-}
-
-JEMALLOC_ALWAYS_INLINE void
-idallocx(void *ptr, bool try_tcache)
-{
- arena_chunk_t *chunk;
-
- assert(ptr != NULL);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk != ptr)
- arena_dalloc(chunk->arena, chunk, ptr, try_tcache);
- else
- huge_dalloc(ptr, true);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-idalloc(void *ptr)
-{
-
- idallocx(ptr, true);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-iqallocx(void *ptr, bool try_tcache)
-{
-
- if (config_fill && opt_quarantine)
- quarantine(ptr);
- else
- idallocx(ptr, try_tcache);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-iqalloc(void *ptr)
-{
-
- iqallocx(ptr, true);
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-irallocx(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
- bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena)
-{
- void *ret;
- size_t oldsize;
-
- assert(ptr != NULL);
- assert(size != 0);
-
- oldsize = isalloc(ptr, config_prof);
-
- if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))
- != 0) {
- size_t usize, copysize;
-
- /*
- * Existing object alignment is inadequate; allocate new space
- * and copy.
- */
- if (no_move)
- return (NULL);
- usize = sa2u(size + extra, alignment);
- if (usize == 0)
- return (NULL);
- ret = ipallocx(usize, alignment, zero, try_tcache_alloc, arena);
- if (ret == NULL) {
- if (extra == 0)
- return (NULL);
- /* Try again, without extra this time. */
- usize = sa2u(size, alignment);
- if (usize == 0)
- return (NULL);
- ret = ipallocx(usize, alignment, zero, try_tcache_alloc,
- arena);
- if (ret == NULL)
- return (NULL);
- }
- /*
- * Copy at most size bytes (not size+extra), since the caller
- * has no expectation that the extra bytes will be reliably
- * preserved.
- */
- copysize = (size < oldsize) ? size : oldsize;
- memcpy(ret, ptr, copysize);
- iqallocx(ptr, try_tcache_dalloc);
- return (ret);
- }
-
- if (no_move) {
- if (size <= arena_maxclass) {
- return (arena_ralloc_no_move(ptr, oldsize, size,
- extra, zero));
- } else {
- return (huge_ralloc_no_move(ptr, oldsize, size,
- extra));
- }
- } else {
- if (size + extra <= arena_maxclass) {
- return (arena_ralloc(arena, ptr, oldsize, size, extra,
- alignment, zero, try_tcache_alloc,
- try_tcache_dalloc));
- } else {
- return (huge_ralloc(ptr, oldsize, size, extra,
- alignment, zero, try_tcache_dalloc));
- }
- }
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
- bool no_move)
-{
-
- return (irallocx(ptr, size, extra, alignment, zero, no_move, true, true,
- NULL));
-}
-
-malloc_tsd_externs(thread_allocated, thread_allocated_t)
-malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, thread_allocated, thread_allocated_t,
- THREAD_ALLOCATED_INITIALIZER, malloc_tsd_no_cleanup)
-#endif
-
-#include "jemalloc/internal/prof.h"
-
-#undef JEMALLOC_H_INLINES
-/******************************************************************************/
-#endif /* JEMALLOC_INTERNAL_H */
diff --git a/extra/jemalloc/include/jemalloc/internal/mb.h b/extra/jemalloc/include/jemalloc/internal/mb.h
deleted file mode 100644
index 3cfa7872942..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/mb.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-void mb_write(void);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MB_C_))
-#ifdef __i386__
-/*
- * According to the Intel Architecture Software Developer's Manual, current
- * processors execute instructions in order from the perspective of other
- * processors in a multiprocessor system, but 1) Intel reserves the right to
- * change that, and 2) the compiler's optimizer could re-order instructions if
- * there weren't some form of barrier. Therefore, even if running on an
- * architecture that does not need memory barriers (everything through at least
- * i686), an "optimizer barrier" is necessary.
- */
-JEMALLOC_INLINE void
-mb_write(void)
-{
-
-# if 0
- /* This is a true memory barrier. */
- asm volatile ("pusha;"
- "xor %%eax,%%eax;"
- "cpuid;"
- "popa;"
- : /* Outputs. */
- : /* Inputs. */
- : "memory" /* Clobbers. */
- );
-#else
- /*
- * This is hopefully enough to keep the compiler from reordering
- * instructions around this one.
- */
- asm volatile ("nop;"
- : /* Outputs. */
- : /* Inputs. */
- : "memory" /* Clobbers. */
- );
-#endif
-}
-#elif (defined(__amd64__) || defined(__x86_64__))
-JEMALLOC_INLINE void
-mb_write(void)
-{
-
- asm volatile ("sfence"
- : /* Outputs. */
- : /* Inputs. */
- : "memory" /* Clobbers. */
- );
-}
-#elif defined(__powerpc__)
-JEMALLOC_INLINE void
-mb_write(void)
-{
-
- asm volatile ("eieio"
- : /* Outputs. */
- : /* Inputs. */
- : "memory" /* Clobbers. */
- );
-}
-#elif defined(__sparc64__)
-JEMALLOC_INLINE void
-mb_write(void)
-{
-
- asm volatile ("membar #StoreStore"
- : /* Outputs. */
- : /* Inputs. */
- : "memory" /* Clobbers. */
- );
-}
-#elif defined(__tile__)
-JEMALLOC_INLINE void
-mb_write(void)
-{
-
- __sync_synchronize();
-}
-#else
-/*
- * This is much slower than a simple memory barrier, but the semantics of mutex
- * unlock make this work.
- */
-JEMALLOC_INLINE void
-mb_write(void)
-{
- malloc_mutex_t mtx;
-
- malloc_mutex_init(&mtx);
- malloc_mutex_lock(&mtx);
- malloc_mutex_unlock(&mtx);
-}
-#endif
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/mutex.h b/extra/jemalloc/include/jemalloc/internal/mutex.h
deleted file mode 100644
index de44e1435ad..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/mutex.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct malloc_mutex_s malloc_mutex_t;
-
-#ifdef _WIN32
-# define MALLOC_MUTEX_INITIALIZER
-#elif (defined(JEMALLOC_OSSPIN))
-# define MALLOC_MUTEX_INITIALIZER {0}
-#elif (defined(JEMALLOC_MUTEX_INIT_CB))
-# define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL}
-#else
-# if (defined(PTHREAD_MUTEX_ADAPTIVE_NP) && \
- defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP))
-# define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_ADAPTIVE_NP
-# define MALLOC_MUTEX_INITIALIZER {PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP}
-# else
-# define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT
-# define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER}
-# endif
-#endif
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-struct malloc_mutex_s {
-#ifdef _WIN32
- CRITICAL_SECTION lock;
-#elif (defined(JEMALLOC_OSSPIN))
- OSSpinLock lock;
-#elif (defined(JEMALLOC_MUTEX_INIT_CB))
- pthread_mutex_t lock;
- malloc_mutex_t *postponed_next;
-#else
- pthread_mutex_t lock;
-#endif
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-#ifdef JEMALLOC_LAZY_LOCK
-extern bool isthreaded;
-#else
-# undef isthreaded /* Undo private_namespace.h definition. */
-# define isthreaded true
-#endif
-
-bool malloc_mutex_init(malloc_mutex_t *mutex);
-void malloc_mutex_prefork(malloc_mutex_t *mutex);
-void malloc_mutex_postfork_parent(malloc_mutex_t *mutex);
-void malloc_mutex_postfork_child(malloc_mutex_t *mutex);
-bool mutex_boot(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-void malloc_mutex_lock(malloc_mutex_t *mutex);
-void malloc_mutex_unlock(malloc_mutex_t *mutex);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
-JEMALLOC_INLINE void
-malloc_mutex_lock(malloc_mutex_t *mutex)
-{
-
- if (isthreaded) {
-#ifdef _WIN32
- EnterCriticalSection(&mutex->lock);
-#elif (defined(JEMALLOC_OSSPIN))
- OSSpinLockLock(&mutex->lock);
-#else
- pthread_mutex_lock(&mutex->lock);
-#endif
- }
-}
-
-JEMALLOC_INLINE void
-malloc_mutex_unlock(malloc_mutex_t *mutex)
-{
-
- if (isthreaded) {
-#ifdef _WIN32
- LeaveCriticalSection(&mutex->lock);
-#elif (defined(JEMALLOC_OSSPIN))
- OSSpinLockUnlock(&mutex->lock);
-#else
- pthread_mutex_unlock(&mutex->lock);
-#endif
- }
-}
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/private_namespace.h b/extra/jemalloc/include/jemalloc/internal/private_namespace.h
deleted file mode 100644
index cdb0b0eb1c4..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/private_namespace.h
+++ /dev/null
@@ -1,392 +0,0 @@
-#define a0calloc JEMALLOC_N(a0calloc)
-#define a0free JEMALLOC_N(a0free)
-#define a0malloc JEMALLOC_N(a0malloc)
-#define arena_alloc_junk_small JEMALLOC_N(arena_alloc_junk_small)
-#define arena_bin_index JEMALLOC_N(arena_bin_index)
-#define arena_bin_info JEMALLOC_N(arena_bin_info)
-#define arena_boot JEMALLOC_N(arena_boot)
-#define arena_dalloc JEMALLOC_N(arena_dalloc)
-#define arena_dalloc_bin JEMALLOC_N(arena_dalloc_bin)
-#define arena_dalloc_bin_locked JEMALLOC_N(arena_dalloc_bin_locked)
-#define arena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small)
-#define arena_dalloc_large JEMALLOC_N(arena_dalloc_large)
-#define arena_dalloc_large_locked JEMALLOC_N(arena_dalloc_large_locked)
-#define arena_dalloc_small JEMALLOC_N(arena_dalloc_small)
-#define arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get)
-#define arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set)
-#define arena_malloc JEMALLOC_N(arena_malloc)
-#define arena_malloc_large JEMALLOC_N(arena_malloc_large)
-#define arena_malloc_small JEMALLOC_N(arena_malloc_small)
-#define arena_mapbits_allocated_get JEMALLOC_N(arena_mapbits_allocated_get)
-#define arena_mapbits_binind_get JEMALLOC_N(arena_mapbits_binind_get)
-#define arena_mapbits_dirty_get JEMALLOC_N(arena_mapbits_dirty_get)
-#define arena_mapbits_get JEMALLOC_N(arena_mapbits_get)
-#define arena_mapbits_large_binind_set JEMALLOC_N(arena_mapbits_large_binind_set)
-#define arena_mapbits_large_get JEMALLOC_N(arena_mapbits_large_get)
-#define arena_mapbits_large_set JEMALLOC_N(arena_mapbits_large_set)
-#define arena_mapbits_large_size_get JEMALLOC_N(arena_mapbits_large_size_get)
-#define arena_mapbits_small_runind_get JEMALLOC_N(arena_mapbits_small_runind_get)
-#define arena_mapbits_small_set JEMALLOC_N(arena_mapbits_small_set)
-#define arena_mapbits_unallocated_set JEMALLOC_N(arena_mapbits_unallocated_set)
-#define arena_mapbits_unallocated_size_get JEMALLOC_N(arena_mapbits_unallocated_size_get)
-#define arena_mapbits_unallocated_size_set JEMALLOC_N(arena_mapbits_unallocated_size_set)
-#define arena_mapbits_unzeroed_get JEMALLOC_N(arena_mapbits_unzeroed_get)
-#define arena_mapbits_unzeroed_set JEMALLOC_N(arena_mapbits_unzeroed_set)
-#define arena_mapbitsp_get JEMALLOC_N(arena_mapbitsp_get)
-#define arena_mapbitsp_read JEMALLOC_N(arena_mapbitsp_read)
-#define arena_mapbitsp_write JEMALLOC_N(arena_mapbitsp_write)
-#define arena_mapp_get JEMALLOC_N(arena_mapp_get)
-#define arena_maxclass JEMALLOC_N(arena_maxclass)
-#define arena_new JEMALLOC_N(arena_new)
-#define arena_palloc JEMALLOC_N(arena_palloc)
-#define arena_postfork_child JEMALLOC_N(arena_postfork_child)
-#define arena_postfork_parent JEMALLOC_N(arena_postfork_parent)
-#define arena_prefork JEMALLOC_N(arena_prefork)
-#define arena_prof_accum JEMALLOC_N(arena_prof_accum)
-#define arena_prof_accum_impl JEMALLOC_N(arena_prof_accum_impl)
-#define arena_prof_accum_locked JEMALLOC_N(arena_prof_accum_locked)
-#define arena_prof_ctx_get JEMALLOC_N(arena_prof_ctx_get)
-#define arena_prof_ctx_set JEMALLOC_N(arena_prof_ctx_set)
-#define arena_prof_promoted JEMALLOC_N(arena_prof_promoted)
-#define arena_ptr_small_binind_get JEMALLOC_N(arena_ptr_small_binind_get)
-#define arena_purge_all JEMALLOC_N(arena_purge_all)
-#define arena_ralloc JEMALLOC_N(arena_ralloc)
-#define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move)
-#define arena_run_regind JEMALLOC_N(arena_run_regind)
-#define arena_salloc JEMALLOC_N(arena_salloc)
-#define arena_stats_merge JEMALLOC_N(arena_stats_merge)
-#define arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small)
-#define arenas JEMALLOC_N(arenas)
-#define arenas_booted JEMALLOC_N(arenas_booted)
-#define arenas_cleanup JEMALLOC_N(arenas_cleanup)
-#define arenas_extend JEMALLOC_N(arenas_extend)
-#define arenas_initialized JEMALLOC_N(arenas_initialized)
-#define arenas_lock JEMALLOC_N(arenas_lock)
-#define arenas_tls JEMALLOC_N(arenas_tls)
-#define arenas_tsd JEMALLOC_N(arenas_tsd)
-#define arenas_tsd_boot JEMALLOC_N(arenas_tsd_boot)
-#define arenas_tsd_cleanup_wrapper JEMALLOC_N(arenas_tsd_cleanup_wrapper)
-#define arenas_tsd_get JEMALLOC_N(arenas_tsd_get)
-#define arenas_tsd_get_wrapper JEMALLOC_N(arenas_tsd_get_wrapper)
-#define arenas_tsd_set JEMALLOC_N(arenas_tsd_set)
-#define atomic_add_u JEMALLOC_N(atomic_add_u)
-#define atomic_add_uint32 JEMALLOC_N(atomic_add_uint32)
-#define atomic_add_uint64 JEMALLOC_N(atomic_add_uint64)
-#define atomic_add_z JEMALLOC_N(atomic_add_z)
-#define atomic_sub_u JEMALLOC_N(atomic_sub_u)
-#define atomic_sub_uint32 JEMALLOC_N(atomic_sub_uint32)
-#define atomic_sub_uint64 JEMALLOC_N(atomic_sub_uint64)
-#define atomic_sub_z JEMALLOC_N(atomic_sub_z)
-#define base_alloc JEMALLOC_N(base_alloc)
-#define base_boot JEMALLOC_N(base_boot)
-#define base_calloc JEMALLOC_N(base_calloc)
-#define base_node_alloc JEMALLOC_N(base_node_alloc)
-#define base_node_dealloc JEMALLOC_N(base_node_dealloc)
-#define base_postfork_child JEMALLOC_N(base_postfork_child)
-#define base_postfork_parent JEMALLOC_N(base_postfork_parent)
-#define base_prefork JEMALLOC_N(base_prefork)
-#define bitmap_full JEMALLOC_N(bitmap_full)
-#define bitmap_get JEMALLOC_N(bitmap_get)
-#define bitmap_info_init JEMALLOC_N(bitmap_info_init)
-#define bitmap_info_ngroups JEMALLOC_N(bitmap_info_ngroups)
-#define bitmap_init JEMALLOC_N(bitmap_init)
-#define bitmap_set JEMALLOC_N(bitmap_set)
-#define bitmap_sfu JEMALLOC_N(bitmap_sfu)
-#define bitmap_size JEMALLOC_N(bitmap_size)
-#define bitmap_unset JEMALLOC_N(bitmap_unset)
-#define bt_init JEMALLOC_N(bt_init)
-#define buferror JEMALLOC_N(buferror)
-#define choose_arena JEMALLOC_N(choose_arena)
-#define choose_arena_hard JEMALLOC_N(choose_arena_hard)
-#define chunk_alloc JEMALLOC_N(chunk_alloc)
-#define chunk_alloc_dss JEMALLOC_N(chunk_alloc_dss)
-#define chunk_alloc_mmap JEMALLOC_N(chunk_alloc_mmap)
-#define chunk_boot JEMALLOC_N(chunk_boot)
-#define chunk_dealloc JEMALLOC_N(chunk_dealloc)
-#define chunk_dealloc_mmap JEMALLOC_N(chunk_dealloc_mmap)
-#define chunk_dss_boot JEMALLOC_N(chunk_dss_boot)
-#define chunk_dss_postfork_child JEMALLOC_N(chunk_dss_postfork_child)
-#define chunk_dss_postfork_parent JEMALLOC_N(chunk_dss_postfork_parent)
-#define chunk_dss_prec_get JEMALLOC_N(chunk_dss_prec_get)
-#define chunk_dss_prec_set JEMALLOC_N(chunk_dss_prec_set)
-#define chunk_dss_prefork JEMALLOC_N(chunk_dss_prefork)
-#define chunk_in_dss JEMALLOC_N(chunk_in_dss)
-#define chunk_npages JEMALLOC_N(chunk_npages)
-#define chunk_postfork_child JEMALLOC_N(chunk_postfork_child)
-#define chunk_postfork_parent JEMALLOC_N(chunk_postfork_parent)
-#define chunk_prefork JEMALLOC_N(chunk_prefork)
-#define chunk_unmap JEMALLOC_N(chunk_unmap)
-#define chunks_mtx JEMALLOC_N(chunks_mtx)
-#define chunks_rtree JEMALLOC_N(chunks_rtree)
-#define chunksize JEMALLOC_N(chunksize)
-#define chunksize_mask JEMALLOC_N(chunksize_mask)
-#define ckh_bucket_search JEMALLOC_N(ckh_bucket_search)
-#define ckh_count JEMALLOC_N(ckh_count)
-#define ckh_delete JEMALLOC_N(ckh_delete)
-#define ckh_evict_reloc_insert JEMALLOC_N(ckh_evict_reloc_insert)
-#define ckh_insert JEMALLOC_N(ckh_insert)
-#define ckh_isearch JEMALLOC_N(ckh_isearch)
-#define ckh_iter JEMALLOC_N(ckh_iter)
-#define ckh_new JEMALLOC_N(ckh_new)
-#define ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash)
-#define ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp)
-#define ckh_rebuild JEMALLOC_N(ckh_rebuild)
-#define ckh_remove JEMALLOC_N(ckh_remove)
-#define ckh_search JEMALLOC_N(ckh_search)
-#define ckh_string_hash JEMALLOC_N(ckh_string_hash)
-#define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp)
-#define ckh_try_bucket_insert JEMALLOC_N(ckh_try_bucket_insert)
-#define ckh_try_insert JEMALLOC_N(ckh_try_insert)
-#define ctl_boot JEMALLOC_N(ctl_boot)
-#define ctl_bymib JEMALLOC_N(ctl_bymib)
-#define ctl_byname JEMALLOC_N(ctl_byname)
-#define ctl_nametomib JEMALLOC_N(ctl_nametomib)
-#define ctl_postfork_child JEMALLOC_N(ctl_postfork_child)
-#define ctl_postfork_parent JEMALLOC_N(ctl_postfork_parent)
-#define ctl_prefork JEMALLOC_N(ctl_prefork)
-#define dss_prec_names JEMALLOC_N(dss_prec_names)
-#define extent_tree_ad_first JEMALLOC_N(extent_tree_ad_first)
-#define extent_tree_ad_insert JEMALLOC_N(extent_tree_ad_insert)
-#define extent_tree_ad_iter JEMALLOC_N(extent_tree_ad_iter)
-#define extent_tree_ad_iter_recurse JEMALLOC_N(extent_tree_ad_iter_recurse)
-#define extent_tree_ad_iter_start JEMALLOC_N(extent_tree_ad_iter_start)
-#define extent_tree_ad_last JEMALLOC_N(extent_tree_ad_last)
-#define extent_tree_ad_new JEMALLOC_N(extent_tree_ad_new)
-#define extent_tree_ad_next JEMALLOC_N(extent_tree_ad_next)
-#define extent_tree_ad_nsearch JEMALLOC_N(extent_tree_ad_nsearch)
-#define extent_tree_ad_prev JEMALLOC_N(extent_tree_ad_prev)
-#define extent_tree_ad_psearch JEMALLOC_N(extent_tree_ad_psearch)
-#define extent_tree_ad_remove JEMALLOC_N(extent_tree_ad_remove)
-#define extent_tree_ad_reverse_iter JEMALLOC_N(extent_tree_ad_reverse_iter)
-#define extent_tree_ad_reverse_iter_recurse JEMALLOC_N(extent_tree_ad_reverse_iter_recurse)
-#define extent_tree_ad_reverse_iter_start JEMALLOC_N(extent_tree_ad_reverse_iter_start)
-#define extent_tree_ad_search JEMALLOC_N(extent_tree_ad_search)
-#define extent_tree_szad_first JEMALLOC_N(extent_tree_szad_first)
-#define extent_tree_szad_insert JEMALLOC_N(extent_tree_szad_insert)
-#define extent_tree_szad_iter JEMALLOC_N(extent_tree_szad_iter)
-#define extent_tree_szad_iter_recurse JEMALLOC_N(extent_tree_szad_iter_recurse)
-#define extent_tree_szad_iter_start JEMALLOC_N(extent_tree_szad_iter_start)
-#define extent_tree_szad_last JEMALLOC_N(extent_tree_szad_last)
-#define extent_tree_szad_new JEMALLOC_N(extent_tree_szad_new)
-#define extent_tree_szad_next JEMALLOC_N(extent_tree_szad_next)
-#define extent_tree_szad_nsearch JEMALLOC_N(extent_tree_szad_nsearch)
-#define extent_tree_szad_prev JEMALLOC_N(extent_tree_szad_prev)
-#define extent_tree_szad_psearch JEMALLOC_N(extent_tree_szad_psearch)
-#define extent_tree_szad_remove JEMALLOC_N(extent_tree_szad_remove)
-#define extent_tree_szad_reverse_iter JEMALLOC_N(extent_tree_szad_reverse_iter)
-#define extent_tree_szad_reverse_iter_recurse JEMALLOC_N(extent_tree_szad_reverse_iter_recurse)
-#define extent_tree_szad_reverse_iter_start JEMALLOC_N(extent_tree_szad_reverse_iter_start)
-#define extent_tree_szad_search JEMALLOC_N(extent_tree_szad_search)
-#define get_errno JEMALLOC_N(get_errno)
-#define hash JEMALLOC_N(hash)
-#define hash_fmix_32 JEMALLOC_N(hash_fmix_32)
-#define hash_fmix_64 JEMALLOC_N(hash_fmix_64)
-#define hash_get_block_32 JEMALLOC_N(hash_get_block_32)
-#define hash_get_block_64 JEMALLOC_N(hash_get_block_64)
-#define hash_rotl_32 JEMALLOC_N(hash_rotl_32)
-#define hash_rotl_64 JEMALLOC_N(hash_rotl_64)
-#define hash_x64_128 JEMALLOC_N(hash_x64_128)
-#define hash_x86_128 JEMALLOC_N(hash_x86_128)
-#define hash_x86_32 JEMALLOC_N(hash_x86_32)
-#define huge_allocated JEMALLOC_N(huge_allocated)
-#define huge_boot JEMALLOC_N(huge_boot)
-#define huge_dalloc JEMALLOC_N(huge_dalloc)
-#define huge_malloc JEMALLOC_N(huge_malloc)
-#define huge_mtx JEMALLOC_N(huge_mtx)
-#define huge_ndalloc JEMALLOC_N(huge_ndalloc)
-#define huge_nmalloc JEMALLOC_N(huge_nmalloc)
-#define huge_palloc JEMALLOC_N(huge_palloc)
-#define huge_postfork_child JEMALLOC_N(huge_postfork_child)
-#define huge_postfork_parent JEMALLOC_N(huge_postfork_parent)
-#define huge_prefork JEMALLOC_N(huge_prefork)
-#define huge_prof_ctx_get JEMALLOC_N(huge_prof_ctx_get)
-#define huge_prof_ctx_set JEMALLOC_N(huge_prof_ctx_set)
-#define huge_ralloc JEMALLOC_N(huge_ralloc)
-#define huge_ralloc_no_move JEMALLOC_N(huge_ralloc_no_move)
-#define huge_salloc JEMALLOC_N(huge_salloc)
-#define iallocm JEMALLOC_N(iallocm)
-#define icalloc JEMALLOC_N(icalloc)
-#define icallocx JEMALLOC_N(icallocx)
-#define idalloc JEMALLOC_N(idalloc)
-#define idallocx JEMALLOC_N(idallocx)
-#define imalloc JEMALLOC_N(imalloc)
-#define imallocx JEMALLOC_N(imallocx)
-#define ipalloc JEMALLOC_N(ipalloc)
-#define ipallocx JEMALLOC_N(ipallocx)
-#define iqalloc JEMALLOC_N(iqalloc)
-#define iqallocx JEMALLOC_N(iqallocx)
-#define iralloc JEMALLOC_N(iralloc)
-#define irallocx JEMALLOC_N(irallocx)
-#define isalloc JEMALLOC_N(isalloc)
-#define isthreaded JEMALLOC_N(isthreaded)
-#define ivsalloc JEMALLOC_N(ivsalloc)
-#define jemalloc_postfork_child JEMALLOC_N(jemalloc_postfork_child)
-#define jemalloc_postfork_parent JEMALLOC_N(jemalloc_postfork_parent)
-#define jemalloc_prefork JEMALLOC_N(jemalloc_prefork)
-#define malloc_cprintf JEMALLOC_N(malloc_cprintf)
-#define malloc_mutex_init JEMALLOC_N(malloc_mutex_init)
-#define malloc_mutex_lock JEMALLOC_N(malloc_mutex_lock)
-#define malloc_mutex_postfork_child JEMALLOC_N(malloc_mutex_postfork_child)
-#define malloc_mutex_postfork_parent JEMALLOC_N(malloc_mutex_postfork_parent)
-#define malloc_mutex_prefork JEMALLOC_N(malloc_mutex_prefork)
-#define malloc_mutex_unlock JEMALLOC_N(malloc_mutex_unlock)
-#define malloc_printf JEMALLOC_N(malloc_printf)
-#define malloc_snprintf JEMALLOC_N(malloc_snprintf)
-#define malloc_strtoumax JEMALLOC_N(malloc_strtoumax)
-#define malloc_tsd_boot JEMALLOC_N(malloc_tsd_boot)
-#define malloc_tsd_cleanup_register JEMALLOC_N(malloc_tsd_cleanup_register)
-#define malloc_tsd_dalloc JEMALLOC_N(malloc_tsd_dalloc)
-#define malloc_tsd_malloc JEMALLOC_N(malloc_tsd_malloc)
-#define malloc_tsd_no_cleanup JEMALLOC_N(malloc_tsd_no_cleanup)
-#define malloc_vcprintf JEMALLOC_N(malloc_vcprintf)
-#define malloc_vsnprintf JEMALLOC_N(malloc_vsnprintf)
-#define malloc_write JEMALLOC_N(malloc_write)
-#define map_bias JEMALLOC_N(map_bias)
-#define mb_write JEMALLOC_N(mb_write)
-#define mutex_boot JEMALLOC_N(mutex_boot)
-#define narenas_auto JEMALLOC_N(narenas_auto)
-#define narenas_total JEMALLOC_N(narenas_total)
-#define narenas_total_get JEMALLOC_N(narenas_total_get)
-#define ncpus JEMALLOC_N(ncpus)
-#define nhbins JEMALLOC_N(nhbins)
-#define opt_abort JEMALLOC_N(opt_abort)
-#define opt_junk JEMALLOC_N(opt_junk)
-#define opt_lg_chunk JEMALLOC_N(opt_lg_chunk)
-#define opt_lg_dirty_mult JEMALLOC_N(opt_lg_dirty_mult)
-#define opt_lg_prof_interval JEMALLOC_N(opt_lg_prof_interval)
-#define opt_lg_prof_sample JEMALLOC_N(opt_lg_prof_sample)
-#define opt_lg_tcache_max JEMALLOC_N(opt_lg_tcache_max)
-#define opt_narenas JEMALLOC_N(opt_narenas)
-#define opt_prof JEMALLOC_N(opt_prof)
-#define opt_prof_accum JEMALLOC_N(opt_prof_accum)
-#define opt_prof_active JEMALLOC_N(opt_prof_active)
-#define opt_prof_final JEMALLOC_N(opt_prof_final)
-#define opt_prof_gdump JEMALLOC_N(opt_prof_gdump)
-#define opt_prof_leak JEMALLOC_N(opt_prof_leak)
-#define opt_prof_prefix JEMALLOC_N(opt_prof_prefix)
-#define opt_quarantine JEMALLOC_N(opt_quarantine)
-#define opt_redzone JEMALLOC_N(opt_redzone)
-#define opt_stats_print JEMALLOC_N(opt_stats_print)
-#define opt_tcache JEMALLOC_N(opt_tcache)
-#define opt_utrace JEMALLOC_N(opt_utrace)
-#define opt_valgrind JEMALLOC_N(opt_valgrind)
-#define opt_xmalloc JEMALLOC_N(opt_xmalloc)
-#define opt_zero JEMALLOC_N(opt_zero)
-#define p2rz JEMALLOC_N(p2rz)
-#define pages_purge JEMALLOC_N(pages_purge)
-#define pow2_ceil JEMALLOC_N(pow2_ceil)
-#define prof_backtrace JEMALLOC_N(prof_backtrace)
-#define prof_boot0 JEMALLOC_N(prof_boot0)
-#define prof_boot1 JEMALLOC_N(prof_boot1)
-#define prof_boot2 JEMALLOC_N(prof_boot2)
-#define prof_ctx_get JEMALLOC_N(prof_ctx_get)
-#define prof_ctx_set JEMALLOC_N(prof_ctx_set)
-#define prof_free JEMALLOC_N(prof_free)
-#define prof_gdump JEMALLOC_N(prof_gdump)
-#define prof_idump JEMALLOC_N(prof_idump)
-#define prof_interval JEMALLOC_N(prof_interval)
-#define prof_lookup JEMALLOC_N(prof_lookup)
-#define prof_malloc JEMALLOC_N(prof_malloc)
-#define prof_mdump JEMALLOC_N(prof_mdump)
-#define prof_postfork_child JEMALLOC_N(prof_postfork_child)
-#define prof_postfork_parent JEMALLOC_N(prof_postfork_parent)
-#define prof_prefork JEMALLOC_N(prof_prefork)
-#define prof_promote JEMALLOC_N(prof_promote)
-#define prof_realloc JEMALLOC_N(prof_realloc)
-#define prof_sample_accum_update JEMALLOC_N(prof_sample_accum_update)
-#define prof_sample_threshold_update JEMALLOC_N(prof_sample_threshold_update)
-#define prof_tdata_booted JEMALLOC_N(prof_tdata_booted)
-#define prof_tdata_cleanup JEMALLOC_N(prof_tdata_cleanup)
-#define prof_tdata_get JEMALLOC_N(prof_tdata_get)
-#define prof_tdata_init JEMALLOC_N(prof_tdata_init)
-#define prof_tdata_initialized JEMALLOC_N(prof_tdata_initialized)
-#define prof_tdata_tls JEMALLOC_N(prof_tdata_tls)
-#define prof_tdata_tsd JEMALLOC_N(prof_tdata_tsd)
-#define prof_tdata_tsd_boot JEMALLOC_N(prof_tdata_tsd_boot)
-#define prof_tdata_tsd_cleanup_wrapper JEMALLOC_N(prof_tdata_tsd_cleanup_wrapper)
-#define prof_tdata_tsd_get JEMALLOC_N(prof_tdata_tsd_get)
-#define prof_tdata_tsd_get_wrapper JEMALLOC_N(prof_tdata_tsd_get_wrapper)
-#define prof_tdata_tsd_set JEMALLOC_N(prof_tdata_tsd_set)
-#define quarantine JEMALLOC_N(quarantine)
-#define quarantine_alloc_hook JEMALLOC_N(quarantine_alloc_hook)
-#define quarantine_boot JEMALLOC_N(quarantine_boot)
-#define quarantine_booted JEMALLOC_N(quarantine_booted)
-#define quarantine_cleanup JEMALLOC_N(quarantine_cleanup)
-#define quarantine_init JEMALLOC_N(quarantine_init)
-#define quarantine_tls JEMALLOC_N(quarantine_tls)
-#define quarantine_tsd JEMALLOC_N(quarantine_tsd)
-#define quarantine_tsd_boot JEMALLOC_N(quarantine_tsd_boot)
-#define quarantine_tsd_cleanup_wrapper JEMALLOC_N(quarantine_tsd_cleanup_wrapper)
-#define quarantine_tsd_get JEMALLOC_N(quarantine_tsd_get)
-#define quarantine_tsd_get_wrapper JEMALLOC_N(quarantine_tsd_get_wrapper)
-#define quarantine_tsd_set JEMALLOC_N(quarantine_tsd_set)
-#define register_zone JEMALLOC_N(register_zone)
-#define rtree_get JEMALLOC_N(rtree_get)
-#define rtree_get_locked JEMALLOC_N(rtree_get_locked)
-#define rtree_new JEMALLOC_N(rtree_new)
-#define rtree_postfork_child JEMALLOC_N(rtree_postfork_child)
-#define rtree_postfork_parent JEMALLOC_N(rtree_postfork_parent)
-#define rtree_prefork JEMALLOC_N(rtree_prefork)
-#define rtree_set JEMALLOC_N(rtree_set)
-#define s2u JEMALLOC_N(s2u)
-#define sa2u JEMALLOC_N(sa2u)
-#define set_errno JEMALLOC_N(set_errno)
-#define stats_cactive JEMALLOC_N(stats_cactive)
-#define stats_cactive_add JEMALLOC_N(stats_cactive_add)
-#define stats_cactive_get JEMALLOC_N(stats_cactive_get)
-#define stats_cactive_sub JEMALLOC_N(stats_cactive_sub)
-#define stats_chunks JEMALLOC_N(stats_chunks)
-#define stats_print JEMALLOC_N(stats_print)
-#define tcache_alloc_easy JEMALLOC_N(tcache_alloc_easy)
-#define tcache_alloc_large JEMALLOC_N(tcache_alloc_large)
-#define tcache_alloc_small JEMALLOC_N(tcache_alloc_small)
-#define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard)
-#define tcache_arena_associate JEMALLOC_N(tcache_arena_associate)
-#define tcache_arena_dissociate JEMALLOC_N(tcache_arena_dissociate)
-#define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large)
-#define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small)
-#define tcache_bin_info JEMALLOC_N(tcache_bin_info)
-#define tcache_boot0 JEMALLOC_N(tcache_boot0)
-#define tcache_boot1 JEMALLOC_N(tcache_boot1)
-#define tcache_booted JEMALLOC_N(tcache_booted)
-#define tcache_create JEMALLOC_N(tcache_create)
-#define tcache_dalloc_large JEMALLOC_N(tcache_dalloc_large)
-#define tcache_dalloc_small JEMALLOC_N(tcache_dalloc_small)
-#define tcache_destroy JEMALLOC_N(tcache_destroy)
-#define tcache_enabled_booted JEMALLOC_N(tcache_enabled_booted)
-#define tcache_enabled_get JEMALLOC_N(tcache_enabled_get)
-#define tcache_enabled_initialized JEMALLOC_N(tcache_enabled_initialized)
-#define tcache_enabled_set JEMALLOC_N(tcache_enabled_set)
-#define tcache_enabled_tls JEMALLOC_N(tcache_enabled_tls)
-#define tcache_enabled_tsd JEMALLOC_N(tcache_enabled_tsd)
-#define tcache_enabled_tsd_boot JEMALLOC_N(tcache_enabled_tsd_boot)
-#define tcache_enabled_tsd_cleanup_wrapper JEMALLOC_N(tcache_enabled_tsd_cleanup_wrapper)
-#define tcache_enabled_tsd_get JEMALLOC_N(tcache_enabled_tsd_get)
-#define tcache_enabled_tsd_get_wrapper JEMALLOC_N(tcache_enabled_tsd_get_wrapper)
-#define tcache_enabled_tsd_set JEMALLOC_N(tcache_enabled_tsd_set)
-#define tcache_event JEMALLOC_N(tcache_event)
-#define tcache_event_hard JEMALLOC_N(tcache_event_hard)
-#define tcache_flush JEMALLOC_N(tcache_flush)
-#define tcache_get JEMALLOC_N(tcache_get)
-#define tcache_initialized JEMALLOC_N(tcache_initialized)
-#define tcache_maxclass JEMALLOC_N(tcache_maxclass)
-#define tcache_salloc JEMALLOC_N(tcache_salloc)
-#define tcache_stats_merge JEMALLOC_N(tcache_stats_merge)
-#define tcache_thread_cleanup JEMALLOC_N(tcache_thread_cleanup)
-#define tcache_tls JEMALLOC_N(tcache_tls)
-#define tcache_tsd JEMALLOC_N(tcache_tsd)
-#define tcache_tsd_boot JEMALLOC_N(tcache_tsd_boot)
-#define tcache_tsd_cleanup_wrapper JEMALLOC_N(tcache_tsd_cleanup_wrapper)
-#define tcache_tsd_get JEMALLOC_N(tcache_tsd_get)
-#define tcache_tsd_get_wrapper JEMALLOC_N(tcache_tsd_get_wrapper)
-#define tcache_tsd_set JEMALLOC_N(tcache_tsd_set)
-#define thread_allocated_booted JEMALLOC_N(thread_allocated_booted)
-#define thread_allocated_initialized JEMALLOC_N(thread_allocated_initialized)
-#define thread_allocated_tls JEMALLOC_N(thread_allocated_tls)
-#define thread_allocated_tsd JEMALLOC_N(thread_allocated_tsd)
-#define thread_allocated_tsd_boot JEMALLOC_N(thread_allocated_tsd_boot)
-#define thread_allocated_tsd_cleanup_wrapper JEMALLOC_N(thread_allocated_tsd_cleanup_wrapper)
-#define thread_allocated_tsd_get JEMALLOC_N(thread_allocated_tsd_get)
-#define thread_allocated_tsd_get_wrapper JEMALLOC_N(thread_allocated_tsd_get_wrapper)
-#define thread_allocated_tsd_set JEMALLOC_N(thread_allocated_tsd_set)
-#define u2rz JEMALLOC_N(u2rz)
diff --git a/extra/jemalloc/include/jemalloc/internal/prng.h b/extra/jemalloc/include/jemalloc/internal/prng.h
deleted file mode 100644
index 83a5462b4dd..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/prng.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-/*
- * Simple linear congruential pseudo-random number generator:
- *
- * prng(y) = (a*x + c) % m
- *
- * where the following constants ensure maximal period:
- *
- * a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4.
- * c == Odd number (relatively prime to 2^n).
- * m == 2^32
- *
- * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.
- *
- * This choice of m has the disadvantage that the quality of the bits is
- * proportional to bit position. For example. the lowest bit has a cycle of 2,
- * the next has a cycle of 4, etc. For this reason, we prefer to use the upper
- * bits.
- *
- * Macro parameters:
- * uint32_t r : Result.
- * unsigned lg_range : (0..32], number of least significant bits to return.
- * uint32_t state : Seed value.
- * const uint32_t a, c : See above discussion.
- */
-#define prng32(r, lg_range, state, a, c) do { \
- assert(lg_range > 0); \
- assert(lg_range <= 32); \
- \
- r = (state * (a)) + (c); \
- state = r; \
- r >>= (32 - lg_range); \
-} while (false)
-
-/* Same as prng32(), but 64 bits of pseudo-randomness, using uint64_t. */
-#define prng64(r, lg_range, state, a, c) do { \
- assert(lg_range > 0); \
- assert(lg_range <= 64); \
- \
- r = (state * (a)) + (c); \
- state = r; \
- r >>= (64 - lg_range); \
-} while (false)
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/prof.h b/extra/jemalloc/include/jemalloc/internal/prof.h
deleted file mode 100644
index 119a5b1bcb7..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/prof.h
+++ /dev/null
@@ -1,579 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct prof_bt_s prof_bt_t;
-typedef struct prof_cnt_s prof_cnt_t;
-typedef struct prof_thr_cnt_s prof_thr_cnt_t;
-typedef struct prof_ctx_s prof_ctx_t;
-typedef struct prof_tdata_s prof_tdata_t;
-
-/* Option defaults. */
-#define PROF_PREFIX_DEFAULT "jeprof"
-#define LG_PROF_SAMPLE_DEFAULT 19
-#define LG_PROF_INTERVAL_DEFAULT -1
-
-/*
- * Hard limit on stack backtrace depth. The version of prof_backtrace() that
- * is based on __builtin_return_address() necessarily has a hard-coded number
- * of backtrace frame handlers, and should be kept in sync with this setting.
- */
-#define PROF_BT_MAX 128
-
-/* Maximum number of backtraces to store in each per thread LRU cache. */
-#define PROF_TCMAX 1024
-
-/* Initial hash table size. */
-#define PROF_CKH_MINITEMS 64
-
-/* Size of memory buffer to use when writing dump files. */
-#define PROF_DUMP_BUFSIZE 65536
-
-/* Size of stack-allocated buffer used by prof_printf(). */
-#define PROF_PRINTF_BUFSIZE 128
-
-/*
- * Number of mutexes shared among all ctx's. No space is allocated for these
- * unless profiling is enabled, so it's okay to over-provision.
- */
-#define PROF_NCTX_LOCKS 1024
-
-/*
- * prof_tdata pointers close to NULL are used to encode state information that
- * is used for cleaning up during thread shutdown.
- */
-#define PROF_TDATA_STATE_REINCARNATED ((prof_tdata_t *)(uintptr_t)1)
-#define PROF_TDATA_STATE_PURGATORY ((prof_tdata_t *)(uintptr_t)2)
-#define PROF_TDATA_STATE_MAX PROF_TDATA_STATE_PURGATORY
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-struct prof_bt_s {
- /* Backtrace, stored as len program counters. */
- void **vec;
- unsigned len;
-};
-
-#ifdef JEMALLOC_PROF_LIBGCC
-/* Data structure passed to libgcc _Unwind_Backtrace() callback functions. */
-typedef struct {
- prof_bt_t *bt;
- unsigned nignore;
- unsigned max;
-} prof_unwind_data_t;
-#endif
-
-struct prof_cnt_s {
- /*
- * Profiling counters. An allocation/deallocation pair can operate on
- * different prof_thr_cnt_t objects that are linked into the same
- * prof_ctx_t cnts_ql, so it is possible for the cur* counters to go
- * negative. In principle it is possible for the *bytes counters to
- * overflow/underflow, but a general solution would require something
- * like 128-bit counters; this implementation doesn't bother to solve
- * that problem.
- */
- int64_t curobjs;
- int64_t curbytes;
- uint64_t accumobjs;
- uint64_t accumbytes;
-};
-
-struct prof_thr_cnt_s {
- /* Linkage into prof_ctx_t's cnts_ql. */
- ql_elm(prof_thr_cnt_t) cnts_link;
-
- /* Linkage into thread's LRU. */
- ql_elm(prof_thr_cnt_t) lru_link;
-
- /*
- * Associated context. If a thread frees an object that it did not
- * allocate, it is possible that the context is not cached in the
- * thread's hash table, in which case it must be able to look up the
- * context, insert a new prof_thr_cnt_t into the thread's hash table,
- * and link it into the prof_ctx_t's cnts_ql.
- */
- prof_ctx_t *ctx;
-
- /*
- * Threads use memory barriers to update the counters. Since there is
- * only ever one writer, the only challenge is for the reader to get a
- * consistent read of the counters.
- *
- * The writer uses this series of operations:
- *
- * 1) Increment epoch to an odd number.
- * 2) Update counters.
- * 3) Increment epoch to an even number.
- *
- * The reader must assure 1) that the epoch is even while it reads the
- * counters, and 2) that the epoch doesn't change between the time it
- * starts and finishes reading the counters.
- */
- unsigned epoch;
-
- /* Profiling counters. */
- prof_cnt_t cnts;
-};
-
-struct prof_ctx_s {
- /* Associated backtrace. */
- prof_bt_t *bt;
-
- /* Protects nlimbo, cnt_merged, and cnts_ql. */
- malloc_mutex_t *lock;
-
- /*
- * Number of threads that currently cause this ctx to be in a state of
- * limbo due to one of:
- * - Initializing per thread counters associated with this ctx.
- * - Preparing to destroy this ctx.
- * nlimbo must be 1 (single destroyer) in order to safely destroy the
- * ctx.
- */
- unsigned nlimbo;
-
- /* Temporary storage for summation during dump. */
- prof_cnt_t cnt_summed;
-
- /* When threads exit, they merge their stats into cnt_merged. */
- prof_cnt_t cnt_merged;
-
- /*
- * List of profile counters, one for each thread that has allocated in
- * this context.
- */
- ql_head(prof_thr_cnt_t) cnts_ql;
-};
-
-struct prof_tdata_s {
- /*
- * Hash of (prof_bt_t *)-->(prof_thr_cnt_t *). Each thread keeps a
- * cache of backtraces, with associated thread-specific prof_thr_cnt_t
- * objects. Other threads may read the prof_thr_cnt_t contents, but no
- * others will ever write them.
- *
- * Upon thread exit, the thread must merge all the prof_thr_cnt_t
- * counter data into the associated prof_ctx_t objects, and unlink/free
- * the prof_thr_cnt_t objects.
- */
- ckh_t bt2cnt;
-
- /* LRU for contents of bt2cnt. */
- ql_head(prof_thr_cnt_t) lru_ql;
-
- /* Backtrace vector, used for calls to prof_backtrace(). */
- void **vec;
-
- /* Sampling state. */
- uint64_t prng_state;
- uint64_t threshold;
- uint64_t accum;
-
- /* State used to avoid dumping while operating on prof internals. */
- bool enq;
- bool enq_idump;
- bool enq_gdump;
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-extern bool opt_prof;
-/*
- * Even if opt_prof is true, sampling can be temporarily disabled by setting
- * opt_prof_active to false. No locking is used when updating opt_prof_active,
- * so there are no guarantees regarding how long it will take for all threads
- * to notice state changes.
- */
-extern bool opt_prof_active;
-extern size_t opt_lg_prof_sample; /* Mean bytes between samples. */
-extern ssize_t opt_lg_prof_interval; /* lg(prof_interval). */
-extern bool opt_prof_gdump; /* High-water memory dumping. */
-extern bool opt_prof_final; /* Final profile dumping. */
-extern bool opt_prof_leak; /* Dump leak summary at exit. */
-extern bool opt_prof_accum; /* Report cumulative bytes. */
-extern char opt_prof_prefix[PATH_MAX + 1];
-
-/*
- * Profile dump interval, measured in bytes allocated. Each arena triggers a
- * profile dump when it reaches this threshold. The effect is that the
- * interval between profile dumps averages prof_interval, though the actual
- * interval between dumps will tend to be sporadic, and the interval will be a
- * maximum of approximately (prof_interval * narenas).
- */
-extern uint64_t prof_interval;
-
-/*
- * If true, promote small sampled objects to large objects, since small run
- * headers do not have embedded profile context pointers.
- */
-extern bool prof_promote;
-
-void bt_init(prof_bt_t *bt, void **vec);
-void prof_backtrace(prof_bt_t *bt, unsigned nignore);
-prof_thr_cnt_t *prof_lookup(prof_bt_t *bt);
-void prof_idump(void);
-bool prof_mdump(const char *filename);
-void prof_gdump(void);
-prof_tdata_t *prof_tdata_init(void);
-void prof_tdata_cleanup(void *arg);
-void prof_boot0(void);
-void prof_boot1(void);
-bool prof_boot2(void);
-void prof_prefork(void);
-void prof_postfork_parent(void);
-void prof_postfork_child(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#define PROF_ALLOC_PREP(nignore, size, ret) do { \
- prof_tdata_t *prof_tdata; \
- prof_bt_t bt; \
- \
- assert(size == s2u(size)); \
- \
- prof_tdata = prof_tdata_get(true); \
- if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) { \
- if (prof_tdata != NULL) \
- ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
- else \
- ret = NULL; \
- break; \
- } \
- \
- if (opt_prof_active == false) { \
- /* Sampling is currently inactive, so avoid sampling. */\
- ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
- } else if (opt_lg_prof_sample == 0) { \
- /* Don't bother with sampling logic, since sampling */\
- /* interval is 1. */\
- bt_init(&bt, prof_tdata->vec); \
- prof_backtrace(&bt, nignore); \
- ret = prof_lookup(&bt); \
- } else { \
- if (prof_tdata->threshold == 0) { \
- /* Initialize. Seed the prng differently for */\
- /* each thread. */\
- prof_tdata->prng_state = \
- (uint64_t)(uintptr_t)&size; \
- prof_sample_threshold_update(prof_tdata); \
- } \
- \
- /* Determine whether to capture a backtrace based on */\
- /* whether size is enough for prof_accum to reach */\
- /* prof_tdata->threshold. However, delay updating */\
- /* these variables until prof_{m,re}alloc(), because */\
- /* we don't know for sure that the allocation will */\
- /* succeed. */\
- /* */\
- /* Use subtraction rather than addition to avoid */\
- /* potential integer overflow. */\
- if (size >= prof_tdata->threshold - \
- prof_tdata->accum) { \
- bt_init(&bt, prof_tdata->vec); \
- prof_backtrace(&bt, nignore); \
- ret = prof_lookup(&bt); \
- } else \
- ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
- } \
-} while (0)
-
-#ifndef JEMALLOC_ENABLE_INLINE
-malloc_tsd_protos(JEMALLOC_ATTR(unused), prof_tdata, prof_tdata_t *)
-
-prof_tdata_t *prof_tdata_get(bool create);
-void prof_sample_threshold_update(prof_tdata_t *prof_tdata);
-prof_ctx_t *prof_ctx_get(const void *ptr);
-void prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
-bool prof_sample_accum_update(size_t size);
-void prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt);
-void prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt,
- size_t old_size, prof_ctx_t *old_ctx);
-void prof_free(const void *ptr, size_t size);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PROF_C_))
-/* Thread-specific backtrace cache, used to reduce bt2ctx contention. */
-malloc_tsd_externs(prof_tdata, prof_tdata_t *)
-malloc_tsd_funcs(JEMALLOC_INLINE, prof_tdata, prof_tdata_t *, NULL,
- prof_tdata_cleanup)
-
-JEMALLOC_INLINE prof_tdata_t *
-prof_tdata_get(bool create)
-{
- prof_tdata_t *prof_tdata;
-
- cassert(config_prof);
-
- prof_tdata = *prof_tdata_tsd_get();
- if (create && prof_tdata == NULL)
- prof_tdata = prof_tdata_init();
-
- return (prof_tdata);
-}
-
-JEMALLOC_INLINE void
-prof_sample_threshold_update(prof_tdata_t *prof_tdata)
-{
- uint64_t r;
- double u;
-
- cassert(config_prof);
-
- /*
- * Compute sample threshold as a geometrically distributed random
- * variable with mean (2^opt_lg_prof_sample).
- *
- * __ __
- * | log(u) | 1
- * prof_tdata->threshold = | -------- |, where p = -------------------
- * | log(1-p) | opt_lg_prof_sample
- * 2
- *
- * For more information on the math, see:
- *
- * Non-Uniform Random Variate Generation
- * Luc Devroye
- * Springer-Verlag, New York, 1986
- * pp 500
- * (http://cg.scs.carleton.ca/~luc/rnbookindex.html)
- */
- prng64(r, 53, prof_tdata->prng_state,
- UINT64_C(6364136223846793005), UINT64_C(1442695040888963407));
- u = (double)r * (1.0/9007199254740992.0L);
- prof_tdata->threshold = (uint64_t)(log(u) /
- log(1.0 - (1.0 / (double)((uint64_t)1U << opt_lg_prof_sample))))
- + (uint64_t)1U;
-}
-
-JEMALLOC_INLINE prof_ctx_t *
-prof_ctx_get(const void *ptr)
-{
- prof_ctx_t *ret;
- arena_chunk_t *chunk;
-
- cassert(config_prof);
- assert(ptr != NULL);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk != ptr) {
- /* Region. */
- ret = arena_prof_ctx_get(ptr);
- } else
- ret = huge_prof_ctx_get(ptr);
-
- return (ret);
-}
-
-JEMALLOC_INLINE void
-prof_ctx_set(const void *ptr, prof_ctx_t *ctx)
-{
- arena_chunk_t *chunk;
-
- cassert(config_prof);
- assert(ptr != NULL);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk != ptr) {
- /* Region. */
- arena_prof_ctx_set(ptr, ctx);
- } else
- huge_prof_ctx_set(ptr, ctx);
-}
-
-JEMALLOC_INLINE bool
-prof_sample_accum_update(size_t size)
-{
- prof_tdata_t *prof_tdata;
-
- cassert(config_prof);
- /* Sampling logic is unnecessary if the interval is 1. */
- assert(opt_lg_prof_sample != 0);
-
- prof_tdata = prof_tdata_get(false);
- if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
- return (true);
-
- /* Take care to avoid integer overflow. */
- if (size >= prof_tdata->threshold - prof_tdata->accum) {
- prof_tdata->accum -= (prof_tdata->threshold - size);
- /* Compute new sample threshold. */
- prof_sample_threshold_update(prof_tdata);
- while (prof_tdata->accum >= prof_tdata->threshold) {
- prof_tdata->accum -= prof_tdata->threshold;
- prof_sample_threshold_update(prof_tdata);
- }
- return (false);
- } else {
- prof_tdata->accum += size;
- return (true);
- }
-}
-
-JEMALLOC_INLINE void
-prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt)
-{
-
- cassert(config_prof);
- assert(ptr != NULL);
- assert(size == isalloc(ptr, true));
-
- if (opt_lg_prof_sample != 0) {
- if (prof_sample_accum_update(size)) {
- /*
- * Don't sample. For malloc()-like allocation, it is
- * always possible to tell in advance how large an
- * object's usable size will be, so there should never
- * be a difference between the size passed to
- * PROF_ALLOC_PREP() and prof_malloc().
- */
- assert((uintptr_t)cnt == (uintptr_t)1U);
- }
- }
-
- if ((uintptr_t)cnt > (uintptr_t)1U) {
- prof_ctx_set(ptr, cnt->ctx);
-
- cnt->epoch++;
- /*********/
- mb_write();
- /*********/
- cnt->cnts.curobjs++;
- cnt->cnts.curbytes += size;
- if (opt_prof_accum) {
- cnt->cnts.accumobjs++;
- cnt->cnts.accumbytes += size;
- }
- /*********/
- mb_write();
- /*********/
- cnt->epoch++;
- /*********/
- mb_write();
- /*********/
- } else
- prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U);
-}
-
-JEMALLOC_INLINE void
-prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt,
- size_t old_size, prof_ctx_t *old_ctx)
-{
- prof_thr_cnt_t *told_cnt;
-
- cassert(config_prof);
- assert(ptr != NULL || (uintptr_t)cnt <= (uintptr_t)1U);
-
- if (ptr != NULL) {
- assert(size == isalloc(ptr, true));
- if (opt_lg_prof_sample != 0) {
- if (prof_sample_accum_update(size)) {
- /*
- * Don't sample. The size passed to
- * PROF_ALLOC_PREP() was larger than what
- * actually got allocated, so a backtrace was
- * captured for this allocation, even though
- * its actual size was insufficient to cross
- * the sample threshold.
- */
- cnt = (prof_thr_cnt_t *)(uintptr_t)1U;
- }
- }
- }
-
- if ((uintptr_t)old_ctx > (uintptr_t)1U) {
- told_cnt = prof_lookup(old_ctx->bt);
- if (told_cnt == NULL) {
- /*
- * It's too late to propagate OOM for this realloc(),
- * so operate directly on old_cnt->ctx->cnt_merged.
- */
- malloc_mutex_lock(old_ctx->lock);
- old_ctx->cnt_merged.curobjs--;
- old_ctx->cnt_merged.curbytes -= old_size;
- malloc_mutex_unlock(old_ctx->lock);
- told_cnt = (prof_thr_cnt_t *)(uintptr_t)1U;
- }
- } else
- told_cnt = (prof_thr_cnt_t *)(uintptr_t)1U;
-
- if ((uintptr_t)told_cnt > (uintptr_t)1U)
- told_cnt->epoch++;
- if ((uintptr_t)cnt > (uintptr_t)1U) {
- prof_ctx_set(ptr, cnt->ctx);
- cnt->epoch++;
- } else if (ptr != NULL)
- prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U);
- /*********/
- mb_write();
- /*********/
- if ((uintptr_t)told_cnt > (uintptr_t)1U) {
- told_cnt->cnts.curobjs--;
- told_cnt->cnts.curbytes -= old_size;
- }
- if ((uintptr_t)cnt > (uintptr_t)1U) {
- cnt->cnts.curobjs++;
- cnt->cnts.curbytes += size;
- if (opt_prof_accum) {
- cnt->cnts.accumobjs++;
- cnt->cnts.accumbytes += size;
- }
- }
- /*********/
- mb_write();
- /*********/
- if ((uintptr_t)told_cnt > (uintptr_t)1U)
- told_cnt->epoch++;
- if ((uintptr_t)cnt > (uintptr_t)1U)
- cnt->epoch++;
- /*********/
- mb_write(); /* Not strictly necessary. */
-}
-
-JEMALLOC_INLINE void
-prof_free(const void *ptr, size_t size)
-{
- prof_ctx_t *ctx = prof_ctx_get(ptr);
-
- cassert(config_prof);
-
- if ((uintptr_t)ctx > (uintptr_t)1) {
- prof_thr_cnt_t *tcnt;
- assert(size == isalloc(ptr, true));
- tcnt = prof_lookup(ctx->bt);
-
- if (tcnt != NULL) {
- tcnt->epoch++;
- /*********/
- mb_write();
- /*********/
- tcnt->cnts.curobjs--;
- tcnt->cnts.curbytes -= size;
- /*********/
- mb_write();
- /*********/
- tcnt->epoch++;
- /*********/
- mb_write();
- /*********/
- } else {
- /*
- * OOM during free() cannot be propagated, so operate
- * directly on cnt->ctx->cnt_merged.
- */
- malloc_mutex_lock(ctx->lock);
- ctx->cnt_merged.curobjs--;
- ctx->cnt_merged.curbytes -= size;
- malloc_mutex_unlock(ctx->lock);
- }
- }
-}
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/ql.h b/extra/jemalloc/include/jemalloc/internal/ql.h
deleted file mode 100644
index a9ed2393f0c..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/ql.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * List definitions.
- */
-#define ql_head(a_type) \
-struct { \
- a_type *qlh_first; \
-}
-
-#define ql_head_initializer(a_head) {NULL}
-
-#define ql_elm(a_type) qr(a_type)
-
-/* List functions. */
-#define ql_new(a_head) do { \
- (a_head)->qlh_first = NULL; \
-} while (0)
-
-#define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field)
-
-#define ql_first(a_head) ((a_head)->qlh_first)
-
-#define ql_last(a_head, a_field) \
- ((ql_first(a_head) != NULL) \
- ? qr_prev(ql_first(a_head), a_field) : NULL)
-
-#define ql_next(a_head, a_elm, a_field) \
- ((ql_last(a_head, a_field) != (a_elm)) \
- ? qr_next((a_elm), a_field) : NULL)
-
-#define ql_prev(a_head, a_elm, a_field) \
- ((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field) \
- : NULL)
-
-#define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \
- qr_before_insert((a_qlelm), (a_elm), a_field); \
- if (ql_first(a_head) == (a_qlelm)) { \
- ql_first(a_head) = (a_elm); \
- } \
-} while (0)
-
-#define ql_after_insert(a_qlelm, a_elm, a_field) \
- qr_after_insert((a_qlelm), (a_elm), a_field)
-
-#define ql_head_insert(a_head, a_elm, a_field) do { \
- if (ql_first(a_head) != NULL) { \
- qr_before_insert(ql_first(a_head), (a_elm), a_field); \
- } \
- ql_first(a_head) = (a_elm); \
-} while (0)
-
-#define ql_tail_insert(a_head, a_elm, a_field) do { \
- if (ql_first(a_head) != NULL) { \
- qr_before_insert(ql_first(a_head), (a_elm), a_field); \
- } \
- ql_first(a_head) = qr_next((a_elm), a_field); \
-} while (0)
-
-#define ql_remove(a_head, a_elm, a_field) do { \
- if (ql_first(a_head) == (a_elm)) { \
- ql_first(a_head) = qr_next(ql_first(a_head), a_field); \
- } \
- if (ql_first(a_head) != (a_elm)) { \
- qr_remove((a_elm), a_field); \
- } else { \
- ql_first(a_head) = NULL; \
- } \
-} while (0)
-
-#define ql_head_remove(a_head, a_type, a_field) do { \
- a_type *t = ql_first(a_head); \
- ql_remove((a_head), t, a_field); \
-} while (0)
-
-#define ql_tail_remove(a_head, a_type, a_field) do { \
- a_type *t = ql_last(a_head, a_field); \
- ql_remove((a_head), t, a_field); \
-} while (0)
-
-#define ql_foreach(a_var, a_head, a_field) \
- qr_foreach((a_var), ql_first(a_head), a_field)
-
-#define ql_reverse_foreach(a_var, a_head, a_field) \
- qr_reverse_foreach((a_var), ql_first(a_head), a_field)
diff --git a/extra/jemalloc/include/jemalloc/internal/qr.h b/extra/jemalloc/include/jemalloc/internal/qr.h
deleted file mode 100644
index fe22352fedd..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/qr.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Ring definitions. */
-#define qr(a_type) \
-struct { \
- a_type *qre_next; \
- a_type *qre_prev; \
-}
-
-/* Ring functions. */
-#define qr_new(a_qr, a_field) do { \
- (a_qr)->a_field.qre_next = (a_qr); \
- (a_qr)->a_field.qre_prev = (a_qr); \
-} while (0)
-
-#define qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next)
-
-#define qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev)
-
-#define qr_before_insert(a_qrelm, a_qr, a_field) do { \
- (a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev; \
- (a_qr)->a_field.qre_next = (a_qrelm); \
- (a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr); \
- (a_qrelm)->a_field.qre_prev = (a_qr); \
-} while (0)
-
-#define qr_after_insert(a_qrelm, a_qr, a_field) \
- do \
- { \
- (a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next; \
- (a_qr)->a_field.qre_prev = (a_qrelm); \
- (a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr); \
- (a_qrelm)->a_field.qre_next = (a_qr); \
- } while (0)
-
-#define qr_meld(a_qr_a, a_qr_b, a_field) do { \
- void *t; \
- (a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b); \
- (a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a); \
- t = (a_qr_a)->a_field.qre_prev; \
- (a_qr_a)->a_field.qre_prev = (a_qr_b)->a_field.qre_prev; \
- (a_qr_b)->a_field.qre_prev = t; \
-} while (0)
-
-/* qr_meld() and qr_split() are functionally equivalent, so there's no need to
- * have two copies of the code. */
-#define qr_split(a_qr_a, a_qr_b, a_field) \
- qr_meld((a_qr_a), (a_qr_b), a_field)
-
-#define qr_remove(a_qr, a_field) do { \
- (a_qr)->a_field.qre_prev->a_field.qre_next \
- = (a_qr)->a_field.qre_next; \
- (a_qr)->a_field.qre_next->a_field.qre_prev \
- = (a_qr)->a_field.qre_prev; \
- (a_qr)->a_field.qre_next = (a_qr); \
- (a_qr)->a_field.qre_prev = (a_qr); \
-} while (0)
-
-#define qr_foreach(var, a_qr, a_field) \
- for ((var) = (a_qr); \
- (var) != NULL; \
- (var) = (((var)->a_field.qre_next != (a_qr)) \
- ? (var)->a_field.qre_next : NULL))
-
-#define qr_reverse_foreach(var, a_qr, a_field) \
- for ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL; \
- (var) != NULL; \
- (var) = (((var) != (a_qr)) \
- ? (var)->a_field.qre_prev : NULL))
diff --git a/extra/jemalloc/include/jemalloc/internal/quarantine.h b/extra/jemalloc/include/jemalloc/internal/quarantine.h
deleted file mode 100644
index 16f677f73da..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/quarantine.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct quarantine_obj_s quarantine_obj_t;
-typedef struct quarantine_s quarantine_t;
-
-/* Default per thread quarantine size if valgrind is enabled. */
-#define JEMALLOC_VALGRIND_QUARANTINE_DEFAULT (ZU(1) << 24)
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-struct quarantine_obj_s {
- void *ptr;
- size_t usize;
-};
-
-struct quarantine_s {
- size_t curbytes;
- size_t curobjs;
- size_t first;
-#define LG_MAXOBJS_INIT 10
- size_t lg_maxobjs;
- quarantine_obj_t objs[1]; /* Dynamically sized ring buffer. */
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-quarantine_t *quarantine_init(size_t lg_maxobjs);
-void quarantine(void *ptr);
-void quarantine_cleanup(void *arg);
-bool quarantine_boot(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-malloc_tsd_protos(JEMALLOC_ATTR(unused), quarantine, quarantine_t *)
-
-void quarantine_alloc_hook(void);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_QUARANTINE_C_))
-malloc_tsd_externs(quarantine, quarantine_t *)
-malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, quarantine, quarantine_t *, NULL,
- quarantine_cleanup)
-
-JEMALLOC_ALWAYS_INLINE void
-quarantine_alloc_hook(void)
-{
- quarantine_t *quarantine;
-
- assert(config_fill && opt_quarantine);
-
- quarantine = *quarantine_tsd_get();
- if (quarantine == NULL)
- quarantine_init(LG_MAXOBJS_INIT);
-}
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
-
diff --git a/extra/jemalloc/include/jemalloc/internal/rb.h b/extra/jemalloc/include/jemalloc/internal/rb.h
deleted file mode 100644
index 7b675f09051..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/rb.h
+++ /dev/null
@@ -1,973 +0,0 @@
-/*-
- *******************************************************************************
- *
- * cpp macro implementation of left-leaning 2-3 red-black trees. Parent
- * pointers are not used, and color bits are stored in the least significant
- * bit of right-child pointers (if RB_COMPACT is defined), thus making node
- * linkage as compact as is possible for red-black trees.
- *
- * Usage:
- *
- * #include <stdint.h>
- * #include <stdbool.h>
- * #define NDEBUG // (Optional, see assert(3).)
- * #include <assert.h>
- * #define RB_COMPACT // (Optional, embed color bits in right-child pointers.)
- * #include <rb.h>
- * ...
- *
- *******************************************************************************
- */
-
-#ifndef RB_H_
-#define RB_H_
-
-#if 0
-__FBSDID("$FreeBSD: head/lib/libc/stdlib/rb.h 204493 2010-02-28 22:57:13Z jasone $");
-#endif
-
-#ifdef RB_COMPACT
-/* Node structure. */
-#define rb_node(a_type) \
-struct { \
- a_type *rbn_left; \
- a_type *rbn_right_red; \
-}
-#else
-#define rb_node(a_type) \
-struct { \
- a_type *rbn_left; \
- a_type *rbn_right; \
- bool rbn_red; \
-}
-#endif
-
-/* Root structure. */
-#define rb_tree(a_type) \
-struct { \
- a_type *rbt_root; \
- a_type rbt_nil; \
-}
-
-/* Left accessors. */
-#define rbtn_left_get(a_type, a_field, a_node) \
- ((a_node)->a_field.rbn_left)
-#define rbtn_left_set(a_type, a_field, a_node, a_left) do { \
- (a_node)->a_field.rbn_left = a_left; \
-} while (0)
-
-#ifdef RB_COMPACT
-/* Right accessors. */
-#define rbtn_right_get(a_type, a_field, a_node) \
- ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red) \
- & ((ssize_t)-2)))
-#define rbtn_right_set(a_type, a_field, a_node, a_right) do { \
- (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right) \
- | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1))); \
-} while (0)
-
-/* Color accessors. */
-#define rbtn_red_get(a_type, a_field, a_node) \
- ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red) \
- & ((size_t)1)))
-#define rbtn_color_set(a_type, a_field, a_node, a_red) do { \
- (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t) \
- (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)) \
- | ((ssize_t)a_red)); \
-} while (0)
-#define rbtn_red_set(a_type, a_field, a_node) do { \
- (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) \
- (a_node)->a_field.rbn_right_red) | ((size_t)1)); \
-} while (0)
-#define rbtn_black_set(a_type, a_field, a_node) do { \
- (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t) \
- (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)); \
-} while (0)
-#else
-/* Right accessors. */
-#define rbtn_right_get(a_type, a_field, a_node) \
- ((a_node)->a_field.rbn_right)
-#define rbtn_right_set(a_type, a_field, a_node, a_right) do { \
- (a_node)->a_field.rbn_right = a_right; \
-} while (0)
-
-/* Color accessors. */
-#define rbtn_red_get(a_type, a_field, a_node) \
- ((a_node)->a_field.rbn_red)
-#define rbtn_color_set(a_type, a_field, a_node, a_red) do { \
- (a_node)->a_field.rbn_red = (a_red); \
-} while (0)
-#define rbtn_red_set(a_type, a_field, a_node) do { \
- (a_node)->a_field.rbn_red = true; \
-} while (0)
-#define rbtn_black_set(a_type, a_field, a_node) do { \
- (a_node)->a_field.rbn_red = false; \
-} while (0)
-#endif
-
-/* Node initializer. */
-#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
- rbtn_left_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \
- rbtn_right_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \
- rbtn_red_set(a_type, a_field, (a_node)); \
-} while (0)
-
-/* Tree initializer. */
-#define rb_new(a_type, a_field, a_rbt) do { \
- (a_rbt)->rbt_root = &(a_rbt)->rbt_nil; \
- rbt_node_new(a_type, a_field, a_rbt, &(a_rbt)->rbt_nil); \
- rbtn_black_set(a_type, a_field, &(a_rbt)->rbt_nil); \
-} while (0)
-
-/* Internal utility macros. */
-#define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do { \
- (r_node) = (a_root); \
- if ((r_node) != &(a_rbt)->rbt_nil) { \
- for (; \
- rbtn_left_get(a_type, a_field, (r_node)) != &(a_rbt)->rbt_nil;\
- (r_node) = rbtn_left_get(a_type, a_field, (r_node))) { \
- } \
- } \
-} while (0)
-
-#define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do { \
- (r_node) = (a_root); \
- if ((r_node) != &(a_rbt)->rbt_nil) { \
- for (; rbtn_right_get(a_type, a_field, (r_node)) != \
- &(a_rbt)->rbt_nil; (r_node) = rbtn_right_get(a_type, a_field, \
- (r_node))) { \
- } \
- } \
-} while (0)
-
-#define rbtn_rotate_left(a_type, a_field, a_node, r_node) do { \
- (r_node) = rbtn_right_get(a_type, a_field, (a_node)); \
- rbtn_right_set(a_type, a_field, (a_node), \
- rbtn_left_get(a_type, a_field, (r_node))); \
- rbtn_left_set(a_type, a_field, (r_node), (a_node)); \
-} while (0)
-
-#define rbtn_rotate_right(a_type, a_field, a_node, r_node) do { \
- (r_node) = rbtn_left_get(a_type, a_field, (a_node)); \
- rbtn_left_set(a_type, a_field, (a_node), \
- rbtn_right_get(a_type, a_field, (r_node))); \
- rbtn_right_set(a_type, a_field, (r_node), (a_node)); \
-} while (0)
-
-/*
- * The rb_proto() macro generates function prototypes that correspond to the
- * functions generated by an equivalently parameterized call to rb_gen().
- */
-
-#define rb_proto(a_attr, a_prefix, a_rbt_type, a_type) \
-a_attr void \
-a_prefix##new(a_rbt_type *rbtree); \
-a_attr a_type * \
-a_prefix##first(a_rbt_type *rbtree); \
-a_attr a_type * \
-a_prefix##last(a_rbt_type *rbtree); \
-a_attr a_type * \
-a_prefix##next(a_rbt_type *rbtree, a_type *node); \
-a_attr a_type * \
-a_prefix##prev(a_rbt_type *rbtree, a_type *node); \
-a_attr a_type * \
-a_prefix##search(a_rbt_type *rbtree, a_type *key); \
-a_attr a_type * \
-a_prefix##nsearch(a_rbt_type *rbtree, a_type *key); \
-a_attr a_type * \
-a_prefix##psearch(a_rbt_type *rbtree, a_type *key); \
-a_attr void \
-a_prefix##insert(a_rbt_type *rbtree, a_type *node); \
-a_attr void \
-a_prefix##remove(a_rbt_type *rbtree, a_type *node); \
-a_attr a_type * \
-a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \
- a_rbt_type *, a_type *, void *), void *arg); \
-a_attr a_type * \
-a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \
- a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg);
-
-/*
- * The rb_gen() macro generates a type-specific red-black tree implementation,
- * based on the above cpp macros.
- *
- * Arguments:
- *
- * a_attr : Function attribute for generated functions (ex: static).
- * a_prefix : Prefix for generated functions (ex: ex_).
- * a_rb_type : Type for red-black tree data structure (ex: ex_t).
- * a_type : Type for red-black tree node data structure (ex: ex_node_t).
- * a_field : Name of red-black tree node linkage (ex: ex_link).
- * a_cmp : Node comparison function name, with the following prototype:
- * int (a_cmp *)(a_type *a_node, a_type *a_other);
- * ^^^^^^
- * or a_key
- * Interpretation of comparision function return values:
- * -1 : a_node < a_other
- * 0 : a_node == a_other
- * 1 : a_node > a_other
- * In all cases, the a_node or a_key macro argument is the first
- * argument to the comparison function, which makes it possible
- * to write comparison functions that treat the first argument
- * specially.
- *
- * Assuming the following setup:
- *
- * typedef struct ex_node_s ex_node_t;
- * struct ex_node_s {
- * rb_node(ex_node_t) ex_link;
- * };
- * typedef rb_tree(ex_node_t) ex_t;
- * rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp)
- *
- * The following API is generated:
- *
- * static void
- * ex_new(ex_t *tree);
- * Description: Initialize a red-black tree structure.
- * Args:
- * tree: Pointer to an uninitialized red-black tree object.
- *
- * static ex_node_t *
- * ex_first(ex_t *tree);
- * static ex_node_t *
- * ex_last(ex_t *tree);
- * Description: Get the first/last node in tree.
- * Args:
- * tree: Pointer to an initialized red-black tree object.
- * Ret: First/last node in tree, or NULL if tree is empty.
- *
- * static ex_node_t *
- * ex_next(ex_t *tree, ex_node_t *node);
- * static ex_node_t *
- * ex_prev(ex_t *tree, ex_node_t *node);
- * Description: Get node's successor/predecessor.
- * Args:
- * tree: Pointer to an initialized red-black tree object.
- * node: A node in tree.
- * Ret: node's successor/predecessor in tree, or NULL if node is
- * last/first.
- *
- * static ex_node_t *
- * ex_search(ex_t *tree, ex_node_t *key);
- * Description: Search for node that matches key.
- * Args:
- * tree: Pointer to an initialized red-black tree object.
- * key : Search key.
- * Ret: Node in tree that matches key, or NULL if no match.
- *
- * static ex_node_t *
- * ex_nsearch(ex_t *tree, ex_node_t *key);
- * static ex_node_t *
- * ex_psearch(ex_t *tree, ex_node_t *key);
- * Description: Search for node that matches key. If no match is found,
- * return what would be key's successor/predecessor, were
- * key in tree.
- * Args:
- * tree: Pointer to an initialized red-black tree object.
- * key : Search key.
- * Ret: Node in tree that matches key, or if no match, hypothetical node's
- * successor/predecessor (NULL if no successor/predecessor).
- *
- * static void
- * ex_insert(ex_t *tree, ex_node_t *node);
- * Description: Insert node into tree.
- * Args:
- * tree: Pointer to an initialized red-black tree object.
- * node: Node to be inserted into tree.
- *
- * static void
- * ex_remove(ex_t *tree, ex_node_t *node);
- * Description: Remove node from tree.
- * Args:
- * tree: Pointer to an initialized red-black tree object.
- * node: Node in tree to be removed.
- *
- * static ex_node_t *
- * ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,
- * ex_node_t *, void *), void *arg);
- * static ex_node_t *
- * ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,
- * ex_node_t *, void *), void *arg);
- * Description: Iterate forward/backward over tree, starting at node. If
- * tree is modified, iteration must be immediately
- * terminated by the callback function that causes the
- * modification.
- * Args:
- * tree : Pointer to an initialized red-black tree object.
- * start: Node at which to start iteration, or NULL to start at
- * first/last node.
- * cb : Callback function, which is called for each node during
- * iteration. Under normal circumstances the callback function
- * should return NULL, which causes iteration to continue. If a
- * callback function returns non-NULL, iteration is immediately
- * terminated and the non-NULL return value is returned by the
- * iterator. This is useful for re-starting iteration after
- * modifying tree.
- * arg : Opaque pointer passed to cb().
- * Ret: NULL if iteration completed, or the non-NULL callback return value
- * that caused termination of the iteration.
- */
-#define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \
-a_attr void \
-a_prefix##new(a_rbt_type *rbtree) { \
- rb_new(a_type, a_field, rbtree); \
-} \
-a_attr a_type * \
-a_prefix##first(a_rbt_type *rbtree) { \
- a_type *ret; \
- rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
- if (ret == &rbtree->rbt_nil) { \
- ret = NULL; \
- } \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##last(a_rbt_type *rbtree) { \
- a_type *ret; \
- rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
- if (ret == &rbtree->rbt_nil) { \
- ret = NULL; \
- } \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##next(a_rbt_type *rbtree, a_type *node) { \
- a_type *ret; \
- if (rbtn_right_get(a_type, a_field, node) != &rbtree->rbt_nil) { \
- rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type, \
- a_field, node), ret); \
- } else { \
- a_type *tnode = rbtree->rbt_root; \
- assert(tnode != &rbtree->rbt_nil); \
- ret = &rbtree->rbt_nil; \
- while (true) { \
- int cmp = (a_cmp)(node, tnode); \
- if (cmp < 0) { \
- ret = tnode; \
- tnode = rbtn_left_get(a_type, a_field, tnode); \
- } else if (cmp > 0) { \
- tnode = rbtn_right_get(a_type, a_field, tnode); \
- } else { \
- break; \
- } \
- assert(tnode != &rbtree->rbt_nil); \
- } \
- } \
- if (ret == &rbtree->rbt_nil) { \
- ret = (NULL); \
- } \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \
- a_type *ret; \
- if (rbtn_left_get(a_type, a_field, node) != &rbtree->rbt_nil) { \
- rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type, \
- a_field, node), ret); \
- } else { \
- a_type *tnode = rbtree->rbt_root; \
- assert(tnode != &rbtree->rbt_nil); \
- ret = &rbtree->rbt_nil; \
- while (true) { \
- int cmp = (a_cmp)(node, tnode); \
- if (cmp < 0) { \
- tnode = rbtn_left_get(a_type, a_field, tnode); \
- } else if (cmp > 0) { \
- ret = tnode; \
- tnode = rbtn_right_get(a_type, a_field, tnode); \
- } else { \
- break; \
- } \
- assert(tnode != &rbtree->rbt_nil); \
- } \
- } \
- if (ret == &rbtree->rbt_nil) { \
- ret = (NULL); \
- } \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##search(a_rbt_type *rbtree, a_type *key) { \
- a_type *ret; \
- int cmp; \
- ret = rbtree->rbt_root; \
- while (ret != &rbtree->rbt_nil \
- && (cmp = (a_cmp)(key, ret)) != 0) { \
- if (cmp < 0) { \
- ret = rbtn_left_get(a_type, a_field, ret); \
- } else { \
- ret = rbtn_right_get(a_type, a_field, ret); \
- } \
- } \
- if (ret == &rbtree->rbt_nil) { \
- ret = (NULL); \
- } \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##nsearch(a_rbt_type *rbtree, a_type *key) { \
- a_type *ret; \
- a_type *tnode = rbtree->rbt_root; \
- ret = &rbtree->rbt_nil; \
- while (tnode != &rbtree->rbt_nil) { \
- int cmp = (a_cmp)(key, tnode); \
- if (cmp < 0) { \
- ret = tnode; \
- tnode = rbtn_left_get(a_type, a_field, tnode); \
- } else if (cmp > 0) { \
- tnode = rbtn_right_get(a_type, a_field, tnode); \
- } else { \
- ret = tnode; \
- break; \
- } \
- } \
- if (ret == &rbtree->rbt_nil) { \
- ret = (NULL); \
- } \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##psearch(a_rbt_type *rbtree, a_type *key) { \
- a_type *ret; \
- a_type *tnode = rbtree->rbt_root; \
- ret = &rbtree->rbt_nil; \
- while (tnode != &rbtree->rbt_nil) { \
- int cmp = (a_cmp)(key, tnode); \
- if (cmp < 0) { \
- tnode = rbtn_left_get(a_type, a_field, tnode); \
- } else if (cmp > 0) { \
- ret = tnode; \
- tnode = rbtn_right_get(a_type, a_field, tnode); \
- } else { \
- ret = tnode; \
- break; \
- } \
- } \
- if (ret == &rbtree->rbt_nil) { \
- ret = (NULL); \
- } \
- return (ret); \
-} \
-a_attr void \
-a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \
- struct { \
- a_type *node; \
- int cmp; \
- } path[sizeof(void *) << 4], *pathp; \
- rbt_node_new(a_type, a_field, rbtree, node); \
- /* Wind. */ \
- path->node = rbtree->rbt_root; \
- for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) { \
- int cmp = pathp->cmp = a_cmp(node, pathp->node); \
- assert(cmp != 0); \
- if (cmp < 0) { \
- pathp[1].node = rbtn_left_get(a_type, a_field, \
- pathp->node); \
- } else { \
- pathp[1].node = rbtn_right_get(a_type, a_field, \
- pathp->node); \
- } \
- } \
- pathp->node = node; \
- /* Unwind. */ \
- for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \
- a_type *cnode = pathp->node; \
- if (pathp->cmp < 0) { \
- a_type *left = pathp[1].node; \
- rbtn_left_set(a_type, a_field, cnode, left); \
- if (rbtn_red_get(a_type, a_field, left)) { \
- a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
- if (rbtn_red_get(a_type, a_field, leftleft)) { \
- /* Fix up 4-node. */ \
- a_type *tnode; \
- rbtn_black_set(a_type, a_field, leftleft); \
- rbtn_rotate_right(a_type, a_field, cnode, tnode); \
- cnode = tnode; \
- } \
- } else { \
- return; \
- } \
- } else { \
- a_type *right = pathp[1].node; \
- rbtn_right_set(a_type, a_field, cnode, right); \
- if (rbtn_red_get(a_type, a_field, right)) { \
- a_type *left = rbtn_left_get(a_type, a_field, cnode); \
- if (rbtn_red_get(a_type, a_field, left)) { \
- /* Split 4-node. */ \
- rbtn_black_set(a_type, a_field, left); \
- rbtn_black_set(a_type, a_field, right); \
- rbtn_red_set(a_type, a_field, cnode); \
- } else { \
- /* Lean left. */ \
- a_type *tnode; \
- bool tred = rbtn_red_get(a_type, a_field, cnode); \
- rbtn_rotate_left(a_type, a_field, cnode, tnode); \
- rbtn_color_set(a_type, a_field, tnode, tred); \
- rbtn_red_set(a_type, a_field, cnode); \
- cnode = tnode; \
- } \
- } else { \
- return; \
- } \
- } \
- pathp->node = cnode; \
- } \
- /* Set root, and make it black. */ \
- rbtree->rbt_root = path->node; \
- rbtn_black_set(a_type, a_field, rbtree->rbt_root); \
-} \
-a_attr void \
-a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
- struct { \
- a_type *node; \
- int cmp; \
- } *pathp, *nodep, path[sizeof(void *) << 4]; \
- /* Wind. */ \
- nodep = NULL; /* Silence compiler warning. */ \
- path->node = rbtree->rbt_root; \
- for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) { \
- int cmp = pathp->cmp = a_cmp(node, pathp->node); \
- if (cmp < 0) { \
- pathp[1].node = rbtn_left_get(a_type, a_field, \
- pathp->node); \
- } else { \
- pathp[1].node = rbtn_right_get(a_type, a_field, \
- pathp->node); \
- if (cmp == 0) { \
- /* Find node's successor, in preparation for swap. */ \
- pathp->cmp = 1; \
- nodep = pathp; \
- for (pathp++; pathp->node != &rbtree->rbt_nil; \
- pathp++) { \
- pathp->cmp = -1; \
- pathp[1].node = rbtn_left_get(a_type, a_field, \
- pathp->node); \
- } \
- break; \
- } \
- } \
- } \
- assert(nodep->node == node); \
- pathp--; \
- if (pathp->node != node) { \
- /* Swap node with its successor. */ \
- bool tred = rbtn_red_get(a_type, a_field, pathp->node); \
- rbtn_color_set(a_type, a_field, pathp->node, \
- rbtn_red_get(a_type, a_field, node)); \
- rbtn_left_set(a_type, a_field, pathp->node, \
- rbtn_left_get(a_type, a_field, node)); \
- /* If node's successor is its right child, the following code */\
- /* will do the wrong thing for the right child pointer. */\
- /* However, it doesn't matter, because the pointer will be */\
- /* properly set when the successor is pruned. */\
- rbtn_right_set(a_type, a_field, pathp->node, \
- rbtn_right_get(a_type, a_field, node)); \
- rbtn_color_set(a_type, a_field, node, tred); \
- /* The pruned leaf node's child pointers are never accessed */\
- /* again, so don't bother setting them to nil. */\
- nodep->node = pathp->node; \
- pathp->node = node; \
- if (nodep == path) { \
- rbtree->rbt_root = nodep->node; \
- } else { \
- if (nodep[-1].cmp < 0) { \
- rbtn_left_set(a_type, a_field, nodep[-1].node, \
- nodep->node); \
- } else { \
- rbtn_right_set(a_type, a_field, nodep[-1].node, \
- nodep->node); \
- } \
- } \
- } else { \
- a_type *left = rbtn_left_get(a_type, a_field, node); \
- if (left != &rbtree->rbt_nil) { \
- /* node has no successor, but it has a left child. */\
- /* Splice node out, without losing the left child. */\
- assert(rbtn_red_get(a_type, a_field, node) == false); \
- assert(rbtn_red_get(a_type, a_field, left)); \
- rbtn_black_set(a_type, a_field, left); \
- if (pathp == path) { \
- rbtree->rbt_root = left; \
- } else { \
- if (pathp[-1].cmp < 0) { \
- rbtn_left_set(a_type, a_field, pathp[-1].node, \
- left); \
- } else { \
- rbtn_right_set(a_type, a_field, pathp[-1].node, \
- left); \
- } \
- } \
- return; \
- } else if (pathp == path) { \
- /* The tree only contained one node. */ \
- rbtree->rbt_root = &rbtree->rbt_nil; \
- return; \
- } \
- } \
- if (rbtn_red_get(a_type, a_field, pathp->node)) { \
- /* Prune red node, which requires no fixup. */ \
- assert(pathp[-1].cmp < 0); \
- rbtn_left_set(a_type, a_field, pathp[-1].node, \
- &rbtree->rbt_nil); \
- return; \
- } \
- /* The node to be pruned is black, so unwind until balance is */\
- /* restored. */\
- pathp->node = &rbtree->rbt_nil; \
- for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \
- assert(pathp->cmp != 0); \
- if (pathp->cmp < 0) { \
- rbtn_left_set(a_type, a_field, pathp->node, \
- pathp[1].node); \
- assert(rbtn_red_get(a_type, a_field, pathp[1].node) \
- == false); \
- if (rbtn_red_get(a_type, a_field, pathp->node)) { \
- a_type *right = rbtn_right_get(a_type, a_field, \
- pathp->node); \
- a_type *rightleft = rbtn_left_get(a_type, a_field, \
- right); \
- a_type *tnode; \
- if (rbtn_red_get(a_type, a_field, rightleft)) { \
- /* In the following diagrams, ||, //, and \\ */\
- /* indicate the path to the removed node. */\
- /* */\
- /* || */\
- /* pathp(r) */\
- /* // \ */\
- /* (b) (b) */\
- /* / */\
- /* (r) */\
- /* */\
- rbtn_black_set(a_type, a_field, pathp->node); \
- rbtn_rotate_right(a_type, a_field, right, tnode); \
- rbtn_right_set(a_type, a_field, pathp->node, tnode);\
- rbtn_rotate_left(a_type, a_field, pathp->node, \
- tnode); \
- } else { \
- /* || */\
- /* pathp(r) */\
- /* // \ */\
- /* (b) (b) */\
- /* / */\
- /* (b) */\
- /* */\
- rbtn_rotate_left(a_type, a_field, pathp->node, \
- tnode); \
- } \
- /* Balance restored, but rotation modified subtree */\
- /* root. */\
- assert((uintptr_t)pathp > (uintptr_t)path); \
- if (pathp[-1].cmp < 0) { \
- rbtn_left_set(a_type, a_field, pathp[-1].node, \
- tnode); \
- } else { \
- rbtn_right_set(a_type, a_field, pathp[-1].node, \
- tnode); \
- } \
- return; \
- } else { \
- a_type *right = rbtn_right_get(a_type, a_field, \
- pathp->node); \
- a_type *rightleft = rbtn_left_get(a_type, a_field, \
- right); \
- if (rbtn_red_get(a_type, a_field, rightleft)) { \
- /* || */\
- /* pathp(b) */\
- /* // \ */\
- /* (b) (b) */\
- /* / */\
- /* (r) */\
- a_type *tnode; \
- rbtn_black_set(a_type, a_field, rightleft); \
- rbtn_rotate_right(a_type, a_field, right, tnode); \
- rbtn_right_set(a_type, a_field, pathp->node, tnode);\
- rbtn_rotate_left(a_type, a_field, pathp->node, \
- tnode); \
- /* Balance restored, but rotation modified */\
- /* subree root, which may actually be the tree */\
- /* root. */\
- if (pathp == path) { \
- /* Set root. */ \
- rbtree->rbt_root = tnode; \
- } else { \
- if (pathp[-1].cmp < 0) { \
- rbtn_left_set(a_type, a_field, \
- pathp[-1].node, tnode); \
- } else { \
- rbtn_right_set(a_type, a_field, \
- pathp[-1].node, tnode); \
- } \
- } \
- return; \
- } else { \
- /* || */\
- /* pathp(b) */\
- /* // \ */\
- /* (b) (b) */\
- /* / */\
- /* (b) */\
- a_type *tnode; \
- rbtn_red_set(a_type, a_field, pathp->node); \
- rbtn_rotate_left(a_type, a_field, pathp->node, \
- tnode); \
- pathp->node = tnode; \
- } \
- } \
- } else { \
- a_type *left; \
- rbtn_right_set(a_type, a_field, pathp->node, \
- pathp[1].node); \
- left = rbtn_left_get(a_type, a_field, pathp->node); \
- if (rbtn_red_get(a_type, a_field, left)) { \
- a_type *tnode; \
- a_type *leftright = rbtn_right_get(a_type, a_field, \
- left); \
- a_type *leftrightleft = rbtn_left_get(a_type, a_field, \
- leftright); \
- if (rbtn_red_get(a_type, a_field, leftrightleft)) { \
- /* || */\
- /* pathp(b) */\
- /* / \\ */\
- /* (r) (b) */\
- /* \ */\
- /* (b) */\
- /* / */\
- /* (r) */\
- a_type *unode; \
- rbtn_black_set(a_type, a_field, leftrightleft); \
- rbtn_rotate_right(a_type, a_field, pathp->node, \
- unode); \
- rbtn_rotate_right(a_type, a_field, pathp->node, \
- tnode); \
- rbtn_right_set(a_type, a_field, unode, tnode); \
- rbtn_rotate_left(a_type, a_field, unode, tnode); \
- } else { \
- /* || */\
- /* pathp(b) */\
- /* / \\ */\
- /* (r) (b) */\
- /* \ */\
- /* (b) */\
- /* / */\
- /* (b) */\
- assert(leftright != &rbtree->rbt_nil); \
- rbtn_red_set(a_type, a_field, leftright); \
- rbtn_rotate_right(a_type, a_field, pathp->node, \
- tnode); \
- rbtn_black_set(a_type, a_field, tnode); \
- } \
- /* Balance restored, but rotation modified subtree */\
- /* root, which may actually be the tree root. */\
- if (pathp == path) { \
- /* Set root. */ \
- rbtree->rbt_root = tnode; \
- } else { \
- if (pathp[-1].cmp < 0) { \
- rbtn_left_set(a_type, a_field, pathp[-1].node, \
- tnode); \
- } else { \
- rbtn_right_set(a_type, a_field, pathp[-1].node, \
- tnode); \
- } \
- } \
- return; \
- } else if (rbtn_red_get(a_type, a_field, pathp->node)) { \
- a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
- if (rbtn_red_get(a_type, a_field, leftleft)) { \
- /* || */\
- /* pathp(r) */\
- /* / \\ */\
- /* (b) (b) */\
- /* / */\
- /* (r) */\
- a_type *tnode; \
- rbtn_black_set(a_type, a_field, pathp->node); \
- rbtn_red_set(a_type, a_field, left); \
- rbtn_black_set(a_type, a_field, leftleft); \
- rbtn_rotate_right(a_type, a_field, pathp->node, \
- tnode); \
- /* Balance restored, but rotation modified */\
- /* subtree root. */\
- assert((uintptr_t)pathp > (uintptr_t)path); \
- if (pathp[-1].cmp < 0) { \
- rbtn_left_set(a_type, a_field, pathp[-1].node, \
- tnode); \
- } else { \
- rbtn_right_set(a_type, a_field, pathp[-1].node, \
- tnode); \
- } \
- return; \
- } else { \
- /* || */\
- /* pathp(r) */\
- /* / \\ */\
- /* (b) (b) */\
- /* / */\
- /* (b) */\
- rbtn_red_set(a_type, a_field, left); \
- rbtn_black_set(a_type, a_field, pathp->node); \
- /* Balance restored. */ \
- return; \
- } \
- } else { \
- a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
- if (rbtn_red_get(a_type, a_field, leftleft)) { \
- /* || */\
- /* pathp(b) */\
- /* / \\ */\
- /* (b) (b) */\
- /* / */\
- /* (r) */\
- a_type *tnode; \
- rbtn_black_set(a_type, a_field, leftleft); \
- rbtn_rotate_right(a_type, a_field, pathp->node, \
- tnode); \
- /* Balance restored, but rotation modified */\
- /* subtree root, which may actually be the tree */\
- /* root. */\
- if (pathp == path) { \
- /* Set root. */ \
- rbtree->rbt_root = tnode; \
- } else { \
- if (pathp[-1].cmp < 0) { \
- rbtn_left_set(a_type, a_field, \
- pathp[-1].node, tnode); \
- } else { \
- rbtn_right_set(a_type, a_field, \
- pathp[-1].node, tnode); \
- } \
- } \
- return; \
- } else { \
- /* || */\
- /* pathp(b) */\
- /* / \\ */\
- /* (b) (b) */\
- /* / */\
- /* (b) */\
- rbtn_red_set(a_type, a_field, left); \
- } \
- } \
- } \
- } \
- /* Set root. */ \
- rbtree->rbt_root = path->node; \
- assert(rbtn_red_get(a_type, a_field, rbtree->rbt_root) == false); \
-} \
-a_attr a_type * \
-a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node, \
- a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
- if (node == &rbtree->rbt_nil) { \
- return (&rbtree->rbt_nil); \
- } else { \
- a_type *ret; \
- if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type, \
- a_field, node), cb, arg)) != &rbtree->rbt_nil \
- || (ret = cb(rbtree, node, arg)) != NULL) { \
- return (ret); \
- } \
- return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
- a_field, node), cb, arg)); \
- } \
-} \
-a_attr a_type * \
-a_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node, \
- a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
- int cmp = a_cmp(start, node); \
- if (cmp < 0) { \
- a_type *ret; \
- if ((ret = a_prefix##iter_start(rbtree, start, \
- rbtn_left_get(a_type, a_field, node), cb, arg)) != \
- &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \
- return (ret); \
- } \
- return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
- a_field, node), cb, arg)); \
- } else if (cmp > 0) { \
- return (a_prefix##iter_start(rbtree, start, \
- rbtn_right_get(a_type, a_field, node), cb, arg)); \
- } else { \
- a_type *ret; \
- if ((ret = cb(rbtree, node, arg)) != NULL) { \
- return (ret); \
- } \
- return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
- a_field, node), cb, arg)); \
- } \
-} \
-a_attr a_type * \
-a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \
- a_rbt_type *, a_type *, void *), void *arg) { \
- a_type *ret; \
- if (start != NULL) { \
- ret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root, \
- cb, arg); \
- } else { \
- ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\
- } \
- if (ret == &rbtree->rbt_nil) { \
- ret = NULL; \
- } \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node, \
- a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
- if (node == &rbtree->rbt_nil) { \
- return (&rbtree->rbt_nil); \
- } else { \
- a_type *ret; \
- if ((ret = a_prefix##reverse_iter_recurse(rbtree, \
- rbtn_right_get(a_type, a_field, node), cb, arg)) != \
- &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \
- return (ret); \
- } \
- return (a_prefix##reverse_iter_recurse(rbtree, \
- rbtn_left_get(a_type, a_field, node), cb, arg)); \
- } \
-} \
-a_attr a_type * \
-a_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start, \
- a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *), \
- void *arg) { \
- int cmp = a_cmp(start, node); \
- if (cmp > 0) { \
- a_type *ret; \
- if ((ret = a_prefix##reverse_iter_start(rbtree, start, \
- rbtn_right_get(a_type, a_field, node), cb, arg)) != \
- &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \
- return (ret); \
- } \
- return (a_prefix##reverse_iter_recurse(rbtree, \
- rbtn_left_get(a_type, a_field, node), cb, arg)); \
- } else if (cmp < 0) { \
- return (a_prefix##reverse_iter_start(rbtree, start, \
- rbtn_left_get(a_type, a_field, node), cb, arg)); \
- } else { \
- a_type *ret; \
- if ((ret = cb(rbtree, node, arg)) != NULL) { \
- return (ret); \
- } \
- return (a_prefix##reverse_iter_recurse(rbtree, \
- rbtn_left_get(a_type, a_field, node), cb, arg)); \
- } \
-} \
-a_attr a_type * \
-a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \
- a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
- a_type *ret; \
- if (start != NULL) { \
- ret = a_prefix##reverse_iter_start(rbtree, start, \
- rbtree->rbt_root, cb, arg); \
- } else { \
- ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root, \
- cb, arg); \
- } \
- if (ret == &rbtree->rbt_nil) { \
- ret = NULL; \
- } \
- return (ret); \
-}
-
-#endif /* RB_H_ */
diff --git a/extra/jemalloc/include/jemalloc/internal/rtree.h b/extra/jemalloc/include/jemalloc/internal/rtree.h
deleted file mode 100644
index 9bd98548cfe..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/rtree.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * This radix tree implementation is tailored to the singular purpose of
- * tracking which chunks are currently owned by jemalloc. This functionality
- * is mandatory for OS X, where jemalloc must be able to respond to object
- * ownership queries.
- *
- *******************************************************************************
- */
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct rtree_s rtree_t;
-
-/*
- * Size of each radix tree node (must be a power of 2). This impacts tree
- * depth.
- */
-#if (LG_SIZEOF_PTR == 2)
-# define RTREE_NODESIZE (1U << 14)
-#else
-# define RTREE_NODESIZE CACHELINE
-#endif
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-struct rtree_s {
- malloc_mutex_t mutex;
- void **root;
- unsigned height;
- unsigned level2bits[1]; /* Dynamically sized. */
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-rtree_t *rtree_new(unsigned bits);
-void rtree_prefork(rtree_t *rtree);
-void rtree_postfork_parent(rtree_t *rtree);
-void rtree_postfork_child(rtree_t *rtree);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-#ifndef JEMALLOC_DEBUG
-void *rtree_get_locked(rtree_t *rtree, uintptr_t key);
-#endif
-void *rtree_get(rtree_t *rtree, uintptr_t key);
-bool rtree_set(rtree_t *rtree, uintptr_t key, void *val);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_RTREE_C_))
-#define RTREE_GET_GENERATE(f) \
-/* The least significant bits of the key are ignored. */ \
-JEMALLOC_INLINE void * \
-f(rtree_t *rtree, uintptr_t key) \
-{ \
- void *ret; \
- uintptr_t subkey; \
- unsigned i, lshift, height, bits; \
- void **node, **child; \
- \
- RTREE_LOCK(&rtree->mutex); \
- for (i = lshift = 0, height = rtree->height, node = rtree->root;\
- i < height - 1; \
- i++, lshift += bits, node = child) { \
- bits = rtree->level2bits[i]; \
- subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR + \
- 3)) - bits); \
- child = (void**)node[subkey]; \
- if (child == NULL) { \
- RTREE_UNLOCK(&rtree->mutex); \
- return (NULL); \
- } \
- } \
- \
- /* \
- * node is a leaf, so it contains values rather than node \
- * pointers. \
- */ \
- bits = rtree->level2bits[i]; \
- subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) - \
- bits); \
- ret = node[subkey]; \
- RTREE_UNLOCK(&rtree->mutex); \
- \
- RTREE_GET_VALIDATE \
- return (ret); \
-}
-
-#ifdef JEMALLOC_DEBUG
-# define RTREE_LOCK(l) malloc_mutex_lock(l)
-# define RTREE_UNLOCK(l) malloc_mutex_unlock(l)
-# define RTREE_GET_VALIDATE
-RTREE_GET_GENERATE(rtree_get_locked)
-# undef RTREE_LOCK
-# undef RTREE_UNLOCK
-# undef RTREE_GET_VALIDATE
-#endif
-
-#define RTREE_LOCK(l)
-#define RTREE_UNLOCK(l)
-#ifdef JEMALLOC_DEBUG
- /*
- * Suppose that it were possible for a jemalloc-allocated chunk to be
- * munmap()ped, followed by a different allocator in another thread re-using
- * overlapping virtual memory, all without invalidating the cached rtree
- * value. The result would be a false positive (the rtree would claim that
- * jemalloc owns memory that it had actually discarded). This scenario
- * seems impossible, but the following assertion is a prudent sanity check.
- */
-# define RTREE_GET_VALIDATE \
- assert(rtree_get_locked(rtree, key) == ret);
-#else
-# define RTREE_GET_VALIDATE
-#endif
-RTREE_GET_GENERATE(rtree_get)
-#undef RTREE_LOCK
-#undef RTREE_UNLOCK
-#undef RTREE_GET_VALIDATE
-
-JEMALLOC_INLINE bool
-rtree_set(rtree_t *rtree, uintptr_t key, void *val)
-{
- uintptr_t subkey;
- unsigned i, lshift, height, bits;
- void **node, **child;
-
- malloc_mutex_lock(&rtree->mutex);
- for (i = lshift = 0, height = rtree->height, node = rtree->root;
- i < height - 1;
- i++, lshift += bits, node = child) {
- bits = rtree->level2bits[i];
- subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) -
- bits);
- child = (void**)node[subkey];
- if (child == NULL) {
- child = (void**)base_alloc(sizeof(void *) <<
- rtree->level2bits[i+1]);
- if (child == NULL) {
- malloc_mutex_unlock(&rtree->mutex);
- return (true);
- }
- memset(child, 0, sizeof(void *) <<
- rtree->level2bits[i+1]);
- node[subkey] = child;
- }
- }
-
- /* node is a leaf, so it contains values rather than node pointers. */
- bits = rtree->level2bits[i];
- subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) - bits);
- node[subkey] = val;
- malloc_mutex_unlock(&rtree->mutex);
-
- return (false);
-}
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/size_classes.sh b/extra/jemalloc/include/jemalloc/internal/size_classes.sh
deleted file mode 100755
index 29c80c1fb8d..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/size_classes.sh
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/bin/sh
-
-# The following limits are chosen such that they cover all supported platforms.
-
-# Range of quanta.
-lg_qmin=3
-lg_qmax=4
-
-# The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)].
-lg_tmin=3
-
-# Range of page sizes.
-lg_pmin=12
-lg_pmax=16
-
-pow2() {
- e=$1
- pow2_result=1
- while [ ${e} -gt 0 ] ; do
- pow2_result=$((${pow2_result} + ${pow2_result}))
- e=$((${e} - 1))
- done
-}
-
-cat <<EOF
-/* This file was automatically generated by size_classes.sh. */
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-EOF
-
-lg_q=${lg_qmin}
-while [ ${lg_q} -le ${lg_qmax} ] ; do
- lg_t=${lg_tmin}
- while [ ${lg_t} -le ${lg_q} ] ; do
- lg_p=${lg_pmin}
- while [ ${lg_p} -le ${lg_pmax} ] ; do
- echo "#if (LG_TINY_MIN == ${lg_t} && LG_QUANTUM == ${lg_q} && LG_PAGE == ${lg_p})"
- echo "#define SIZE_CLASSES_DEFINED"
- pow2 ${lg_q}; q=${pow2_result}
- pow2 ${lg_t}; t=${pow2_result}
- pow2 ${lg_p}; p=${pow2_result}
- bin=0
- psz=0
- sz=${t}
- delta=$((${sz} - ${psz}))
- echo "/* SIZE_CLASS(bin, delta, sz) */"
- echo "#define SIZE_CLASSES \\"
-
- # Tiny size classes.
- while [ ${sz} -lt ${q} ] ; do
- echo " SIZE_CLASS(${bin}, ${delta}, ${sz}) \\"
- bin=$((${bin} + 1))
- psz=${sz}
- sz=$((${sz} + ${sz}))
- delta=$((${sz} - ${psz}))
- done
- # Quantum-multiple size classes. For each doubling of sz, as many as 4
- # size classes exist. Their spacing is the greater of:
- # - q
- # - sz/4, where sz is a power of 2
- while [ ${sz} -lt ${p} ] ; do
- if [ ${sz} -ge $((${q} * 4)) ] ; then
- i=$((${sz} / 4))
- else
- i=${q}
- fi
- next_2pow=$((${sz} * 2))
- while [ ${sz} -lt $next_2pow ] ; do
- echo " SIZE_CLASS(${bin}, ${delta}, ${sz}) \\"
- bin=$((${bin} + 1))
- psz=${sz}
- sz=$((${sz} + ${i}))
- delta=$((${sz} - ${psz}))
- done
- done
- echo
- echo "#define NBINS ${bin}"
- echo "#define SMALL_MAXCLASS ${psz}"
- echo "#endif"
- echo
- lg_p=$((${lg_p} + 1))
- done
- lg_t=$((${lg_t} + 1))
- done
- lg_q=$((${lg_q} + 1))
-done
-
-cat <<EOF
-#ifndef SIZE_CLASSES_DEFINED
-# error "No size class definitions match configuration"
-#endif
-#undef SIZE_CLASSES_DEFINED
-/*
- * The small_size2bin lookup table uses uint8_t to encode each bin index, so we
- * cannot support more than 256 small size classes. Further constrain NBINS to
- * 255 to support prof_promote, since all small size classes, plus a "not
- * small" size class must be stored in 8 bits of arena_chunk_map_t's bits
- * field.
- */
-#if (NBINS > 255)
-# error "Too many small size classes"
-#endif
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
-EOF
diff --git a/extra/jemalloc/include/jemalloc/internal/stats.h b/extra/jemalloc/include/jemalloc/internal/stats.h
deleted file mode 100644
index 27f68e3681c..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/stats.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct tcache_bin_stats_s tcache_bin_stats_t;
-typedef struct malloc_bin_stats_s malloc_bin_stats_t;
-typedef struct malloc_large_stats_s malloc_large_stats_t;
-typedef struct arena_stats_s arena_stats_t;
-typedef struct chunk_stats_s chunk_stats_t;
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-struct tcache_bin_stats_s {
- /*
- * Number of allocation requests that corresponded to the size of this
- * bin.
- */
- uint64_t nrequests;
-};
-
-struct malloc_bin_stats_s {
- /*
- * Current number of bytes allocated, including objects currently
- * cached by tcache.
- */
- size_t allocated;
-
- /*
- * Total number of allocation/deallocation requests served directly by
- * the bin. Note that tcache may allocate an object, then recycle it
- * many times, resulting many increments to nrequests, but only one
- * each to nmalloc and ndalloc.
- */
- uint64_t nmalloc;
- uint64_t ndalloc;
-
- /*
- * Number of allocation requests that correspond to the size of this
- * bin. This includes requests served by tcache, though tcache only
- * periodically merges into this counter.
- */
- uint64_t nrequests;
-
- /* Number of tcache fills from this bin. */
- uint64_t nfills;
-
- /* Number of tcache flushes to this bin. */
- uint64_t nflushes;
-
- /* Total number of runs created for this bin's size class. */
- uint64_t nruns;
-
- /*
- * Total number of runs reused by extracting them from the runs tree for
- * this bin's size class.
- */
- uint64_t reruns;
-
- /* Current number of runs in this bin. */
- size_t curruns;
-};
-
-struct malloc_large_stats_s {
- /*
- * Total number of allocation/deallocation requests served directly by
- * the arena. Note that tcache may allocate an object, then recycle it
- * many times, resulting many increments to nrequests, but only one
- * each to nmalloc and ndalloc.
- */
- uint64_t nmalloc;
- uint64_t ndalloc;
-
- /*
- * Number of allocation requests that correspond to this size class.
- * This includes requests served by tcache, though tcache only
- * periodically merges into this counter.
- */
- uint64_t nrequests;
-
- /* Current number of runs of this size class. */
- size_t curruns;
-};
-
-struct arena_stats_s {
- /* Number of bytes currently mapped. */
- size_t mapped;
-
- /*
- * Total number of purge sweeps, total number of madvise calls made,
- * and total pages purged in order to keep dirty unused memory under
- * control.
- */
- uint64_t npurge;
- uint64_t nmadvise;
- uint64_t purged;
-
- /* Per-size-category statistics. */
- size_t allocated_large;
- uint64_t nmalloc_large;
- uint64_t ndalloc_large;
- uint64_t nrequests_large;
-
- /*
- * One element for each possible size class, including sizes that
- * overlap with bin size classes. This is necessary because ipalloc()
- * sometimes has to use such large objects in order to assure proper
- * alignment.
- */
- malloc_large_stats_t *lstats;
-};
-
-struct chunk_stats_s {
- /* Number of chunks that were allocated. */
- uint64_t nchunks;
-
- /* High-water mark for number of chunks allocated. */
- size_t highchunks;
-
- /*
- * Current number of chunks allocated. This value isn't maintained for
- * any other purpose, so keep track of it in order to be able to set
- * highchunks.
- */
- size_t curchunks;
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-extern bool opt_stats_print;
-
-extern size_t stats_cactive;
-
-void stats_print(void (*write)(void *, const char *), void *cbopaque,
- const char *opts);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-size_t stats_cactive_get(void);
-void stats_cactive_add(size_t size);
-void stats_cactive_sub(size_t size);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_))
-JEMALLOC_INLINE size_t
-stats_cactive_get(void)
-{
-
- return (atomic_read_z(&stats_cactive));
-}
-
-JEMALLOC_INLINE void
-stats_cactive_add(size_t size)
-{
-
- atomic_add_z(&stats_cactive, size);
-}
-
-JEMALLOC_INLINE void
-stats_cactive_sub(size_t size)
-{
-
- atomic_sub_z(&stats_cactive, size);
-}
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/tcache.h b/extra/jemalloc/include/jemalloc/internal/tcache.h
deleted file mode 100644
index d4eecdee0dc..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/tcache.h
+++ /dev/null
@@ -1,442 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-typedef struct tcache_bin_info_s tcache_bin_info_t;
-typedef struct tcache_bin_s tcache_bin_t;
-typedef struct tcache_s tcache_t;
-
-/*
- * tcache pointers close to NULL are used to encode state information that is
- * used for two purposes: preventing thread caching on a per thread basis and
- * cleaning up during thread shutdown.
- */
-#define TCACHE_STATE_DISABLED ((tcache_t *)(uintptr_t)1)
-#define TCACHE_STATE_REINCARNATED ((tcache_t *)(uintptr_t)2)
-#define TCACHE_STATE_PURGATORY ((tcache_t *)(uintptr_t)3)
-#define TCACHE_STATE_MAX TCACHE_STATE_PURGATORY
-
-/*
- * Absolute maximum number of cache slots for each small bin in the thread
- * cache. This is an additional constraint beyond that imposed as: twice the
- * number of regions per run for this size class.
- *
- * This constant must be an even number.
- */
-#define TCACHE_NSLOTS_SMALL_MAX 200
-
-/* Number of cache slots for large size classes. */
-#define TCACHE_NSLOTS_LARGE 20
-
-/* (1U << opt_lg_tcache_max) is used to compute tcache_maxclass. */
-#define LG_TCACHE_MAXCLASS_DEFAULT 15
-
-/*
- * TCACHE_GC_SWEEP is the approximate number of allocation events between
- * full GC sweeps. Integer rounding may cause the actual number to be
- * slightly higher, since GC is performed incrementally.
- */
-#define TCACHE_GC_SWEEP 8192
-
-/* Number of tcache allocation/deallocation events between incremental GCs. */
-#define TCACHE_GC_INCR \
- ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1))
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-typedef enum {
- tcache_enabled_false = 0, /* Enable cast to/from bool. */
- tcache_enabled_true = 1,
- tcache_enabled_default = 2
-} tcache_enabled_t;
-
-/*
- * Read-only information associated with each element of tcache_t's tbins array
- * is stored separately, mainly to reduce memory usage.
- */
-struct tcache_bin_info_s {
- unsigned ncached_max; /* Upper limit on ncached. */
-};
-
-struct tcache_bin_s {
- tcache_bin_stats_t tstats;
- int low_water; /* Min # cached since last GC. */
- unsigned lg_fill_div; /* Fill (ncached_max >> lg_fill_div). */
- unsigned ncached; /* # of cached objects. */
- void **avail; /* Stack of available objects. */
-};
-
-struct tcache_s {
- ql_elm(tcache_t) link; /* Used for aggregating stats. */
- uint64_t prof_accumbytes;/* Cleared after arena_prof_accum() */
- arena_t *arena; /* This thread's arena. */
- unsigned ev_cnt; /* Event count since incremental GC. */
- unsigned next_gc_bin; /* Next bin to GC. */
- tcache_bin_t tbins[1]; /* Dynamically sized. */
- /*
- * The pointer stacks associated with tbins follow as a contiguous
- * array. During tcache initialization, the avail pointer in each
- * element of tbins is initialized to point to the proper offset within
- * this array.
- */
-};
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-extern bool opt_tcache;
-extern ssize_t opt_lg_tcache_max;
-
-extern tcache_bin_info_t *tcache_bin_info;
-
-/*
- * Number of tcache bins. There are NBINS small-object bins, plus 0 or more
- * large-object bins.
- */
-extern size_t nhbins;
-
-/* Maximum cached size class. */
-extern size_t tcache_maxclass;
-
-size_t tcache_salloc(const void *ptr);
-void tcache_event_hard(tcache_t *tcache);
-void *tcache_alloc_small_hard(tcache_t *tcache, tcache_bin_t *tbin,
- size_t binind);
-void tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem,
- tcache_t *tcache);
-void tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem,
- tcache_t *tcache);
-void tcache_arena_associate(tcache_t *tcache, arena_t *arena);
-void tcache_arena_dissociate(tcache_t *tcache);
-tcache_t *tcache_create(arena_t *arena);
-void tcache_destroy(tcache_t *tcache);
-void tcache_thread_cleanup(void *arg);
-void tcache_stats_merge(tcache_t *tcache, arena_t *arena);
-bool tcache_boot0(void);
-bool tcache_boot1(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache, tcache_t *)
-malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache_enabled, tcache_enabled_t)
-
-void tcache_event(tcache_t *tcache);
-void tcache_flush(void);
-bool tcache_enabled_get(void);
-tcache_t *tcache_get(bool create);
-void tcache_enabled_set(bool enabled);
-void *tcache_alloc_easy(tcache_bin_t *tbin);
-void *tcache_alloc_small(tcache_t *tcache, size_t size, bool zero);
-void *tcache_alloc_large(tcache_t *tcache, size_t size, bool zero);
-void tcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind);
-void tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TCACHE_C_))
-/* Map of thread-specific caches. */
-malloc_tsd_externs(tcache, tcache_t *)
-malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache, tcache_t *, NULL,
- tcache_thread_cleanup)
-/* Per thread flag that allows thread caches to be disabled. */
-malloc_tsd_externs(tcache_enabled, tcache_enabled_t)
-malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache_enabled, tcache_enabled_t,
- tcache_enabled_default, malloc_tsd_no_cleanup)
-
-JEMALLOC_INLINE void
-tcache_flush(void)
-{
- tcache_t *tcache;
-
- cassert(config_tcache);
-
- tcache = *tcache_tsd_get();
- if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX)
- return;
- tcache_destroy(tcache);
- tcache = NULL;
- tcache_tsd_set(&tcache);
-}
-
-JEMALLOC_INLINE bool
-tcache_enabled_get(void)
-{
- tcache_enabled_t tcache_enabled;
-
- cassert(config_tcache);
-
- tcache_enabled = *tcache_enabled_tsd_get();
- if (tcache_enabled == tcache_enabled_default) {
- tcache_enabled = (tcache_enabled_t)opt_tcache;
- tcache_enabled_tsd_set(&tcache_enabled);
- }
-
- return ((bool)tcache_enabled);
-}
-
-JEMALLOC_INLINE void
-tcache_enabled_set(bool enabled)
-{
- tcache_enabled_t tcache_enabled;
- tcache_t *tcache;
-
- cassert(config_tcache);
-
- tcache_enabled = (tcache_enabled_t)enabled;
- tcache_enabled_tsd_set(&tcache_enabled);
- tcache = *tcache_tsd_get();
- if (enabled) {
- if (tcache == TCACHE_STATE_DISABLED) {
- tcache = NULL;
- tcache_tsd_set(&tcache);
- }
- } else /* disabled */ {
- if (tcache > TCACHE_STATE_MAX) {
- tcache_destroy(tcache);
- tcache = NULL;
- }
- if (tcache == NULL) {
- tcache = TCACHE_STATE_DISABLED;
- tcache_tsd_set(&tcache);
- }
- }
-}
-
-JEMALLOC_ALWAYS_INLINE tcache_t *
-tcache_get(bool create)
-{
- tcache_t *tcache;
-
- if (config_tcache == false)
- return (NULL);
- if (config_lazy_lock && isthreaded == false)
- return (NULL);
-
- tcache = *tcache_tsd_get();
- if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX) {
- if (tcache == TCACHE_STATE_DISABLED)
- return (NULL);
- if (tcache == NULL) {
- if (create == false) {
- /*
- * Creating a tcache here would cause
- * allocation as a side effect of free().
- * Ordinarily that would be okay since
- * tcache_create() failure is a soft failure
- * that doesn't propagate. However, if TLS
- * data are freed via free() as in glibc,
- * subtle corruption could result from setting
- * a TLS variable after its backing memory is
- * freed.
- */
- return (NULL);
- }
- if (tcache_enabled_get() == false) {
- tcache_enabled_set(false); /* Memoize. */
- return (NULL);
- }
- return (tcache_create(choose_arena(NULL)));
- }
- if (tcache == TCACHE_STATE_PURGATORY) {
- /*
- * Make a note that an allocator function was called
- * after tcache_thread_cleanup() was called.
- */
- tcache = TCACHE_STATE_REINCARNATED;
- tcache_tsd_set(&tcache);
- return (NULL);
- }
- if (tcache == TCACHE_STATE_REINCARNATED)
- return (NULL);
- not_reached();
- }
-
- return (tcache);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-tcache_event(tcache_t *tcache)
-{
-
- if (TCACHE_GC_INCR == 0)
- return;
-
- tcache->ev_cnt++;
- assert(tcache->ev_cnt <= TCACHE_GC_INCR);
- if (tcache->ev_cnt == TCACHE_GC_INCR)
- tcache_event_hard(tcache);
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-tcache_alloc_easy(tcache_bin_t *tbin)
-{
- void *ret;
-
- if (tbin->ncached == 0) {
- tbin->low_water = -1;
- return (NULL);
- }
- tbin->ncached--;
- if ((int)tbin->ncached < tbin->low_water)
- tbin->low_water = tbin->ncached;
- ret = tbin->avail[tbin->ncached];
- return (ret);
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-tcache_alloc_small(tcache_t *tcache, size_t size, bool zero)
-{
- void *ret;
- size_t binind;
- tcache_bin_t *tbin;
-
- binind = SMALL_SIZE2BIN(size);
- assert(binind < NBINS);
- tbin = &tcache->tbins[binind];
- ret = tcache_alloc_easy(tbin);
- if (ret == NULL) {
- ret = tcache_alloc_small_hard(tcache, tbin, binind);
- if (ret == NULL)
- return (NULL);
- }
- assert(tcache_salloc(ret) == arena_bin_info[binind].reg_size);
-
- if (zero == false) {
- if (config_fill) {
- if (opt_junk) {
- arena_alloc_junk_small(ret,
- &arena_bin_info[binind], false);
- } else if (opt_zero)
- memset(ret, 0, size);
- }
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- } else {
- if (config_fill && opt_junk) {
- arena_alloc_junk_small(ret, &arena_bin_info[binind],
- true);
- }
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- memset(ret, 0, size);
- }
-
- if (config_stats)
- tbin->tstats.nrequests++;
- if (config_prof)
- tcache->prof_accumbytes += arena_bin_info[binind].reg_size;
- tcache_event(tcache);
- return (ret);
-}
-
-JEMALLOC_ALWAYS_INLINE void *
-tcache_alloc_large(tcache_t *tcache, size_t size, bool zero)
-{
- void *ret;
- size_t binind;
- tcache_bin_t *tbin;
-
- size = PAGE_CEILING(size);
- assert(size <= tcache_maxclass);
- binind = NBINS + (size >> LG_PAGE) - 1;
- assert(binind < nhbins);
- tbin = &tcache->tbins[binind];
- ret = tcache_alloc_easy(tbin);
- if (ret == NULL) {
- /*
- * Only allocate one large object at a time, because it's quite
- * expensive to create one and not use it.
- */
- ret = arena_malloc_large(tcache->arena, size, zero);
- if (ret == NULL)
- return (NULL);
- } else {
- if (config_prof && prof_promote && size == PAGE) {
- arena_chunk_t *chunk =
- (arena_chunk_t *)CHUNK_ADDR2BASE(ret);
- size_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >>
- LG_PAGE);
- arena_mapbits_large_binind_set(chunk, pageind,
- BININD_INVALID);
- }
- if (zero == false) {
- if (config_fill) {
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
- }
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- } else {
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- memset(ret, 0, size);
- }
-
- if (config_stats)
- tbin->tstats.nrequests++;
- if (config_prof)
- tcache->prof_accumbytes += size;
- }
-
- tcache_event(tcache);
- return (ret);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-tcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind)
-{
- tcache_bin_t *tbin;
- tcache_bin_info_t *tbin_info;
-
- assert(tcache_salloc(ptr) <= SMALL_MAXCLASS);
-
- if (config_fill && opt_junk)
- arena_dalloc_junk_small(ptr, &arena_bin_info[binind]);
-
- tbin = &tcache->tbins[binind];
- tbin_info = &tcache_bin_info[binind];
- if (tbin->ncached == tbin_info->ncached_max) {
- tcache_bin_flush_small(tbin, binind, (tbin_info->ncached_max >>
- 1), tcache);
- }
- assert(tbin->ncached < tbin_info->ncached_max);
- tbin->avail[tbin->ncached] = ptr;
- tbin->ncached++;
-
- tcache_event(tcache);
-}
-
-JEMALLOC_ALWAYS_INLINE void
-tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size)
-{
- size_t binind;
- tcache_bin_t *tbin;
- tcache_bin_info_t *tbin_info;
-
- assert((size & PAGE_MASK) == 0);
- assert(tcache_salloc(ptr) > SMALL_MAXCLASS);
- assert(tcache_salloc(ptr) <= tcache_maxclass);
-
- binind = NBINS + (size >> LG_PAGE) - 1;
-
- if (config_fill && opt_junk)
- memset(ptr, 0x5a, size);
-
- tbin = &tcache->tbins[binind];
- tbin_info = &tcache_bin_info[binind];
- if (tbin->ncached == tbin_info->ncached_max) {
- tcache_bin_flush_large(tbin, binind, (tbin_info->ncached_max >>
- 1), tcache);
- }
- assert(tbin->ncached < tbin_info->ncached_max);
- tbin->avail[tbin->ncached] = ptr;
- tbin->ncached++;
-
- tcache_event(tcache);
-}
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/tsd.h b/extra/jemalloc/include/jemalloc/internal/tsd.h
deleted file mode 100644
index 0037cf35e70..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/tsd.h
+++ /dev/null
@@ -1,397 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-/* Maximum number of malloc_tsd users with cleanup functions. */
-#define MALLOC_TSD_CLEANUPS_MAX 8
-
-typedef bool (*malloc_tsd_cleanup_t)(void);
-
-/*
- * TLS/TSD-agnostic macro-based implementation of thread-specific data. There
- * are four macros that support (at least) three use cases: file-private,
- * library-private, and library-private inlined. Following is an example
- * library-private tsd variable:
- *
- * In example.h:
- * typedef struct {
- * int x;
- * int y;
- * } example_t;
- * #define EX_INITIALIZER JEMALLOC_CONCAT({0, 0})
- * malloc_tsd_protos(, example, example_t *)
- * malloc_tsd_externs(example, example_t *)
- * In example.c:
- * malloc_tsd_data(, example, example_t *, EX_INITIALIZER)
- * malloc_tsd_funcs(, example, example_t *, EX_INITIALIZER,
- * example_tsd_cleanup)
- *
- * The result is a set of generated functions, e.g.:
- *
- * bool example_tsd_boot(void) {...}
- * example_t **example_tsd_get() {...}
- * void example_tsd_set(example_t **val) {...}
- *
- * Note that all of the functions deal in terms of (a_type *) rather than
- * (a_type) so that it is possible to support non-pointer types (unlike
- * pthreads TSD). example_tsd_cleanup() is passed an (a_type *) pointer that is
- * cast to (void *). This means that the cleanup function needs to cast *and*
- * dereference the function argument, e.g.:
- *
- * void
- * example_tsd_cleanup(void *arg)
- * {
- * example_t *example = *(example_t **)arg;
- *
- * [...]
- * if ([want the cleanup function to be called again]) {
- * example_tsd_set(&example);
- * }
- * }
- *
- * If example_tsd_set() is called within example_tsd_cleanup(), it will be
- * called again. This is similar to how pthreads TSD destruction works, except
- * that pthreads only calls the cleanup function again if the value was set to
- * non-NULL.
- */
-
-/* malloc_tsd_protos(). */
-#define malloc_tsd_protos(a_attr, a_name, a_type) \
-a_attr bool \
-a_name##_tsd_boot(void); \
-a_attr a_type * \
-a_name##_tsd_get(void); \
-a_attr void \
-a_name##_tsd_set(a_type *val);
-
-/* malloc_tsd_externs(). */
-#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP
-#define malloc_tsd_externs(a_name, a_type) \
-extern __thread a_type a_name##_tls; \
-extern __thread bool a_name##_initialized; \
-extern bool a_name##_booted;
-#elif (defined(JEMALLOC_TLS))
-#define malloc_tsd_externs(a_name, a_type) \
-extern __thread a_type a_name##_tls; \
-extern pthread_key_t a_name##_tsd; \
-extern bool a_name##_booted;
-#elif (defined(_WIN32))
-#define malloc_tsd_externs(a_name, a_type) \
-extern DWORD a_name##_tsd; \
-extern bool a_name##_booted;
-#else
-#define malloc_tsd_externs(a_name, a_type) \
-extern pthread_key_t a_name##_tsd; \
-extern bool a_name##_booted;
-#endif
-
-/* malloc_tsd_data(). */
-#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP
-#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
-a_attr __thread a_type JEMALLOC_TLS_MODEL \
- a_name##_tls = a_initializer; \
-a_attr __thread bool JEMALLOC_TLS_MODEL \
- a_name##_initialized = false; \
-a_attr bool a_name##_booted = false;
-#elif (defined(JEMALLOC_TLS))
-#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
-a_attr __thread a_type JEMALLOC_TLS_MODEL \
- a_name##_tls = a_initializer; \
-a_attr pthread_key_t a_name##_tsd; \
-a_attr bool a_name##_booted = false;
-#elif (defined(_WIN32))
-#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
-a_attr DWORD a_name##_tsd; \
-a_attr bool a_name##_booted = false;
-#else
-#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
-a_attr pthread_key_t a_name##_tsd; \
-a_attr bool a_name##_booted = false;
-#endif
-
-/* malloc_tsd_funcs(). */
-#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP
-#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
- a_cleanup) \
-/* Initialization/cleanup. */ \
-a_attr bool \
-a_name##_tsd_cleanup_wrapper(void) \
-{ \
- \
- if (a_name##_initialized) { \
- a_name##_initialized = false; \
- a_cleanup(&a_name##_tls); \
- } \
- return (a_name##_initialized); \
-} \
-a_attr bool \
-a_name##_tsd_boot(void) \
-{ \
- \
- if (a_cleanup != malloc_tsd_no_cleanup) { \
- malloc_tsd_cleanup_register( \
- &a_name##_tsd_cleanup_wrapper); \
- } \
- a_name##_booted = true; \
- return (false); \
-} \
-/* Get/set. */ \
-a_attr a_type * \
-a_name##_tsd_get(void) \
-{ \
- \
- assert(a_name##_booted); \
- return (&a_name##_tls); \
-} \
-a_attr void \
-a_name##_tsd_set(a_type *val) \
-{ \
- \
- assert(a_name##_booted); \
- a_name##_tls = (*val); \
- if (a_cleanup != malloc_tsd_no_cleanup) \
- a_name##_initialized = true; \
-}
-#elif (defined(JEMALLOC_TLS))
-#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
- a_cleanup) \
-/* Initialization/cleanup. */ \
-a_attr bool \
-a_name##_tsd_boot(void) \
-{ \
- \
- if (a_cleanup != malloc_tsd_no_cleanup) { \
- if (pthread_key_create(&a_name##_tsd, a_cleanup) != 0) \
- return (true); \
- } \
- a_name##_booted = true; \
- return (false); \
-} \
-/* Get/set. */ \
-a_attr a_type * \
-a_name##_tsd_get(void) \
-{ \
- \
- assert(a_name##_booted); \
- return (&a_name##_tls); \
-} \
-a_attr void \
-a_name##_tsd_set(a_type *val) \
-{ \
- \
- assert(a_name##_booted); \
- a_name##_tls = (*val); \
- if (a_cleanup != malloc_tsd_no_cleanup) { \
- if (pthread_setspecific(a_name##_tsd, \
- (void *)(&a_name##_tls))) { \
- malloc_write("<jemalloc>: Error" \
- " setting TSD for "#a_name"\n"); \
- if (opt_abort) \
- abort(); \
- } \
- } \
-}
-#elif (defined(_WIN32))
-#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
- a_cleanup) \
-/* Data structure. */ \
-typedef struct { \
- bool initialized; \
- a_type val; \
-} a_name##_tsd_wrapper_t; \
-/* Initialization/cleanup. */ \
-a_attr bool \
-a_name##_tsd_cleanup_wrapper(void) \
-{ \
- a_name##_tsd_wrapper_t *wrapper; \
- \
- wrapper = (a_name##_tsd_wrapper_t *) TlsGetValue(a_name##_tsd); \
- if (wrapper == NULL) \
- return (false); \
- if (a_cleanup != malloc_tsd_no_cleanup && \
- wrapper->initialized) { \
- a_type val = wrapper->val; \
- a_type tsd_static_data = a_initializer; \
- wrapper->initialized = false; \
- wrapper->val = tsd_static_data; \
- a_cleanup(&val); \
- if (wrapper->initialized) { \
- /* Trigger another cleanup round. */ \
- return (true); \
- } \
- } \
- malloc_tsd_dalloc(wrapper); \
- return (false); \
-} \
-a_attr bool \
-a_name##_tsd_boot(void) \
-{ \
- \
- a_name##_tsd = TlsAlloc(); \
- if (a_name##_tsd == TLS_OUT_OF_INDEXES) \
- return (true); \
- if (a_cleanup != malloc_tsd_no_cleanup) { \
- malloc_tsd_cleanup_register( \
- &a_name##_tsd_cleanup_wrapper); \
- } \
- a_name##_booted = true; \
- return (false); \
-} \
-/* Get/set. */ \
-a_attr a_name##_tsd_wrapper_t * \
-a_name##_tsd_get_wrapper(void) \
-{ \
- a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \
- TlsGetValue(a_name##_tsd); \
- \
- if (wrapper == NULL) { \
- wrapper = (a_name##_tsd_wrapper_t *) \
- malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \
- if (wrapper == NULL) { \
- malloc_write("<jemalloc>: Error allocating" \
- " TSD for "#a_name"\n"); \
- abort(); \
- } else { \
- static a_type tsd_static_data = a_initializer; \
- wrapper->initialized = false; \
- wrapper->val = tsd_static_data; \
- } \
- if (!TlsSetValue(a_name##_tsd, (void *)wrapper)) { \
- malloc_write("<jemalloc>: Error setting" \
- " TSD for "#a_name"\n"); \
- abort(); \
- } \
- } \
- return (wrapper); \
-} \
-a_attr a_type * \
-a_name##_tsd_get(void) \
-{ \
- a_name##_tsd_wrapper_t *wrapper; \
- \
- assert(a_name##_booted); \
- wrapper = a_name##_tsd_get_wrapper(); \
- return (&wrapper->val); \
-} \
-a_attr void \
-a_name##_tsd_set(a_type *val) \
-{ \
- a_name##_tsd_wrapper_t *wrapper; \
- \
- assert(a_name##_booted); \
- wrapper = a_name##_tsd_get_wrapper(); \
- wrapper->val = *(val); \
- if (a_cleanup != malloc_tsd_no_cleanup) \
- wrapper->initialized = true; \
-}
-#else
-#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
- a_cleanup) \
-/* Data structure. */ \
-typedef struct { \
- bool initialized; \
- a_type val; \
-} a_name##_tsd_wrapper_t; \
-/* Initialization/cleanup. */ \
-a_attr void \
-a_name##_tsd_cleanup_wrapper(void *arg) \
-{ \
- a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *)arg;\
- \
- if (a_cleanup != malloc_tsd_no_cleanup && \
- wrapper->initialized) { \
- wrapper->initialized = false; \
- a_cleanup(&wrapper->val); \
- if (wrapper->initialized) { \
- /* Trigger another cleanup round. */ \
- if (pthread_setspecific(a_name##_tsd, \
- (void *)wrapper)) { \
- malloc_write("<jemalloc>: Error" \
- " setting TSD for "#a_name"\n"); \
- if (opt_abort) \
- abort(); \
- } \
- return; \
- } \
- } \
- malloc_tsd_dalloc(wrapper); \
-} \
-a_attr bool \
-a_name##_tsd_boot(void) \
-{ \
- \
- if (pthread_key_create(&a_name##_tsd, \
- a_name##_tsd_cleanup_wrapper) != 0) \
- return (true); \
- a_name##_booted = true; \
- return (false); \
-} \
-/* Get/set. */ \
-a_attr a_name##_tsd_wrapper_t * \
-a_name##_tsd_get_wrapper(void) \
-{ \
- a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \
- pthread_getspecific(a_name##_tsd); \
- \
- if (wrapper == NULL) { \
- wrapper = (a_name##_tsd_wrapper_t *) \
- malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \
- if (wrapper == NULL) { \
- malloc_write("<jemalloc>: Error allocating" \
- " TSD for "#a_name"\n"); \
- abort(); \
- } else { \
- static a_type tsd_static_data = a_initializer; \
- wrapper->initialized = false; \
- wrapper->val = tsd_static_data; \
- } \
- if (pthread_setspecific(a_name##_tsd, \
- (void *)wrapper)) { \
- malloc_write("<jemalloc>: Error setting" \
- " TSD for "#a_name"\n"); \
- abort(); \
- } \
- } \
- return (wrapper); \
-} \
-a_attr a_type * \
-a_name##_tsd_get(void) \
-{ \
- a_name##_tsd_wrapper_t *wrapper; \
- \
- assert(a_name##_booted); \
- wrapper = a_name##_tsd_get_wrapper(); \
- return (&wrapper->val); \
-} \
-a_attr void \
-a_name##_tsd_set(a_type *val) \
-{ \
- a_name##_tsd_wrapper_t *wrapper; \
- \
- assert(a_name##_booted); \
- wrapper = a_name##_tsd_get_wrapper(); \
- wrapper->val = *(val); \
- if (a_cleanup != malloc_tsd_no_cleanup) \
- wrapper->initialized = true; \
-}
-#endif
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-void *malloc_tsd_malloc(size_t size);
-void malloc_tsd_dalloc(void *wrapper);
-void malloc_tsd_no_cleanup(void *);
-void malloc_tsd_cleanup_register(bool (*f)(void));
-void malloc_tsd_boot(void);
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/internal/util.h b/extra/jemalloc/include/jemalloc/internal/util.h
deleted file mode 100644
index 8479693631a..00000000000
--- a/extra/jemalloc/include/jemalloc/internal/util.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/******************************************************************************/
-#ifdef JEMALLOC_H_TYPES
-
-/* Size of stack-allocated buffer passed to buferror(). */
-#define BUFERROR_BUF 64
-
-/*
- * Size of stack-allocated buffer used by malloc_{,v,vc}printf(). This must be
- * large enough for all possible uses within jemalloc.
- */
-#define MALLOC_PRINTF_BUFSIZE 4096
-
-/*
- * Wrap a cpp argument that contains commas such that it isn't broken up into
- * multiple arguments.
- */
-#define JEMALLOC_CONCAT(...) __VA_ARGS__
-
-/*
- * Silence compiler warnings due to uninitialized values. This is used
- * wherever the compiler fails to recognize that the variable is never used
- * uninitialized.
- */
-#ifdef JEMALLOC_CC_SILENCE
-# define JEMALLOC_CC_SILENCE_INIT(v) = v
-#else
-# define JEMALLOC_CC_SILENCE_INIT(v)
-#endif
-
-/*
- * Define a custom assert() in order to reduce the chances of deadlock during
- * assertion failure.
- */
-#ifndef assert
-#define assert(e) do { \
- if (config_debug && !(e)) { \
- malloc_printf( \
- "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n", \
- __FILE__, __LINE__, #e); \
- abort(); \
- } \
-} while (0)
-#endif
-
-/* Use to assert a particular configuration, e.g., cassert(config_debug). */
-#define cassert(c) do { \
- if ((c) == false) \
- assert(false); \
-} while (0)
-
-#ifndef not_reached
-#define not_reached() do { \
- if (config_debug) { \
- malloc_printf( \
- "<jemalloc>: %s:%d: Unreachable code reached\n", \
- __FILE__, __LINE__); \
- abort(); \
- } \
-} while (0)
-#endif
-
-#ifndef not_implemented
-#define not_implemented() do { \
- if (config_debug) { \
- malloc_printf("<jemalloc>: %s:%d: Not implemented\n", \
- __FILE__, __LINE__); \
- abort(); \
- } \
-} while (0)
-#endif
-
-#define assert_not_implemented(e) do { \
- if (config_debug && !(e)) \
- not_implemented(); \
-} while (0)
-
-#endif /* JEMALLOC_H_TYPES */
-/******************************************************************************/
-#ifdef JEMALLOC_H_STRUCTS
-
-#endif /* JEMALLOC_H_STRUCTS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_EXTERNS
-
-int buferror(char *buf, size_t buflen);
-uintmax_t malloc_strtoumax(const char *nptr, char **endptr, int base);
-void malloc_write(const char *s);
-
-/*
- * malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating
- * point math.
- */
-int malloc_vsnprintf(char *str, size_t size, const char *format,
- va_list ap);
-int malloc_snprintf(char *str, size_t size, const char *format, ...)
- JEMALLOC_ATTR(format(printf, 3, 4));
-void malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,
- const char *format, va_list ap);
-void malloc_cprintf(void (*write)(void *, const char *), void *cbopaque,
- const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4));
-void malloc_printf(const char *format, ...)
- JEMALLOC_ATTR(format(printf, 1, 2));
-
-#endif /* JEMALLOC_H_EXTERNS */
-/******************************************************************************/
-#ifdef JEMALLOC_H_INLINES
-
-#ifndef JEMALLOC_ENABLE_INLINE
-size_t pow2_ceil(size_t x);
-void malloc_write(const char *s);
-void set_errno(int errnum);
-int get_errno(void);
-#endif
-
-#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_))
-/* Compute the smallest power of 2 that is >= x. */
-JEMALLOC_INLINE size_t
-pow2_ceil(size_t x)
-{
-
- x--;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
-#if (LG_SIZEOF_PTR == 3)
- x |= x >> 32;
-#endif
- x++;
- return (x);
-}
-
-/* Sets error code */
-JEMALLOC_INLINE void
-set_errno(int errnum)
-{
-
-#ifdef _WIN32
- SetLastError(errnum);
-#else
- errno = errnum;
-#endif
-}
-
-/* Get last error code */
-JEMALLOC_INLINE int
-get_errno(void)
-{
-
-#ifdef _WIN32
- return (GetLastError());
-#else
- return (errno);
-#endif
-}
-#endif
-
-#endif /* JEMALLOC_H_INLINES */
-/******************************************************************************/
diff --git a/extra/jemalloc/include/jemalloc/jemalloc.h.in b/extra/jemalloc/include/jemalloc/jemalloc.h.in
deleted file mode 100644
index 31b1304a20a..00000000000
--- a/extra/jemalloc/include/jemalloc/jemalloc.h.in
+++ /dev/null
@@ -1,157 +0,0 @@
-#ifndef JEMALLOC_H_
-#define JEMALLOC_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <limits.h>
-#include <strings.h>
-
-#define JEMALLOC_VERSION "@jemalloc_version@"
-#define JEMALLOC_VERSION_MAJOR @jemalloc_version_major@
-#define JEMALLOC_VERSION_MINOR @jemalloc_version_minor@
-#define JEMALLOC_VERSION_BUGFIX @jemalloc_version_bugfix@
-#define JEMALLOC_VERSION_NREV @jemalloc_version_nrev@
-#define JEMALLOC_VERSION_GID "@jemalloc_version_gid@"
-
-#include "jemalloc_defs@install_suffix@.h"
-
-#ifdef JEMALLOC_EXPERIMENTAL
-#define ALLOCM_LG_ALIGN(la) (la)
-#if LG_SIZEOF_PTR == 2
-#define ALLOCM_ALIGN(a) (ffs(a)-1)
-#else
-#define ALLOCM_ALIGN(a) ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31)
-#endif
-#define ALLOCM_ZERO ((int)0x40)
-#define ALLOCM_NO_MOVE ((int)0x80)
-/* Bias arena index bits so that 0 encodes "ALLOCM_ARENA() unspecified". */
-#define ALLOCM_ARENA(a) ((int)(((a)+1) << 8))
-
-#define ALLOCM_SUCCESS 0
-#define ALLOCM_ERR_OOM 1
-#define ALLOCM_ERR_NOT_MOVED 2
-#endif
-
-/*
- * The je_ prefix on the following public symbol declarations is an artifact of
- * namespace management, and should be omitted in application code unless
- * JEMALLOC_NO_DEMANGLE is defined (see below).
- */
-extern JEMALLOC_EXPORT const char *je_malloc_conf;
-extern JEMALLOC_EXPORT void (*je_malloc_message)(void *cbopaque,
- const char *s);
-
-JEMALLOC_EXPORT void *je_malloc(size_t size) JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void *je_calloc(size_t num, size_t size)
- JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT int je_posix_memalign(void **memptr, size_t alignment,
- size_t size) JEMALLOC_ATTR(nonnull(1));
-JEMALLOC_EXPORT void *je_aligned_alloc(size_t alignment, size_t size)
- JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void *je_realloc(void *ptr, size_t size);
-JEMALLOC_EXPORT void je_free(void *ptr);
-
-#ifdef JEMALLOC_OVERRIDE_MEMALIGN
-JEMALLOC_EXPORT void * je_memalign(size_t alignment, size_t size)
- JEMALLOC_ATTR(malloc);
-#endif
-
-#ifdef JEMALLOC_OVERRIDE_VALLOC
-JEMALLOC_EXPORT void * je_valloc(size_t size) JEMALLOC_ATTR(malloc);
-#endif
-
-JEMALLOC_EXPORT size_t je_malloc_usable_size(
- JEMALLOC_USABLE_SIZE_CONST void *ptr);
-JEMALLOC_EXPORT void je_malloc_stats_print(void (*write_cb)(void *,
- const char *), void *je_cbopaque, const char *opts);
-JEMALLOC_EXPORT int je_mallctl(const char *name, void *oldp,
- size_t *oldlenp, void *newp, size_t newlen);
-JEMALLOC_EXPORT int je_mallctlnametomib(const char *name, size_t *mibp,
- size_t *miblenp);
-JEMALLOC_EXPORT int je_mallctlbymib(const size_t *mib, size_t miblen,
- void *oldp, size_t *oldlenp, void *newp, size_t newlen);
-
-#ifdef JEMALLOC_EXPERIMENTAL
-JEMALLOC_EXPORT int je_allocm(void **ptr, size_t *rsize, size_t size,
- int flags) JEMALLOC_ATTR(nonnull(1));
-JEMALLOC_EXPORT int je_rallocm(void **ptr, size_t *rsize, size_t size,
- size_t extra, int flags) JEMALLOC_ATTR(nonnull(1));
-JEMALLOC_EXPORT int je_sallocm(const void *ptr, size_t *rsize, int flags)
- JEMALLOC_ATTR(nonnull(1));
-JEMALLOC_EXPORT int je_dallocm(void *ptr, int flags)
- JEMALLOC_ATTR(nonnull(1));
-JEMALLOC_EXPORT int je_nallocm(size_t *rsize, size_t size, int flags);
-#endif
-
-/*
- * By default application code must explicitly refer to mangled symbol names,
- * so that it is possible to use jemalloc in conjunction with another allocator
- * in the same application. Define JEMALLOC_MANGLE in order to cause automatic
- * name mangling that matches the API prefixing that happened as a result of
- * --with-mangling and/or --with-jemalloc-prefix configuration settings.
- */
-#ifdef JEMALLOC_MANGLE
-#ifndef JEMALLOC_NO_DEMANGLE
-#define JEMALLOC_NO_DEMANGLE
-#endif
-#define malloc_conf je_malloc_conf
-#define malloc_message je_malloc_message
-#define malloc je_malloc
-#define calloc je_calloc
-#define posix_memalign je_posix_memalign
-#define aligned_alloc je_aligned_alloc
-#define realloc je_realloc
-#define free je_free
-#define malloc_usable_size je_malloc_usable_size
-#define malloc_stats_print je_malloc_stats_print
-#define mallctl je_mallctl
-#define mallctlnametomib je_mallctlnametomib
-#define mallctlbymib je_mallctlbymib
-#define memalign je_memalign
-#define valloc je_valloc
-#ifdef JEMALLOC_EXPERIMENTAL
-#define allocm je_allocm
-#define rallocm je_rallocm
-#define sallocm je_sallocm
-#define dallocm je_dallocm
-#define nallocm je_nallocm
-#endif
-#endif
-
-/*
- * The je_* macros can be used as stable alternative names for the public
- * jemalloc API if JEMALLOC_NO_DEMANGLE is defined. This is primarily meant
- * for use in jemalloc itself, but it can be used by application code to
- * provide isolation from the name mangling specified via --with-mangling
- * and/or --with-jemalloc-prefix.
- */
-#ifndef JEMALLOC_NO_DEMANGLE
-#undef je_malloc_conf
-#undef je_malloc_message
-#undef je_malloc
-#undef je_calloc
-#undef je_posix_memalign
-#undef je_aligned_alloc
-#undef je_realloc
-#undef je_free
-#undef je_malloc_usable_size
-#undef je_malloc_stats_print
-#undef je_mallctl
-#undef je_mallctlnametomib
-#undef je_mallctlbymib
-#undef je_memalign
-#undef je_valloc
-#ifdef JEMALLOC_EXPERIMENTAL
-#undef je_allocm
-#undef je_rallocm
-#undef je_sallocm
-#undef je_dallocm
-#undef je_nallocm
-#endif
-#endif
-
-#ifdef __cplusplus
-};
-#endif
-#endif /* JEMALLOC_H_ */
diff --git a/extra/jemalloc/include/jemalloc/jemalloc_defs.h.in b/extra/jemalloc/include/jemalloc/jemalloc_defs.h.in
deleted file mode 100644
index 3fcf93ce5d2..00000000000
--- a/extra/jemalloc/include/jemalloc/jemalloc_defs.h.in
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all
- * public APIs to be prefixed. This makes it possible, with some care, to use
- * multiple allocators simultaneously.
- */
-#undef JEMALLOC_PREFIX
-#undef JEMALLOC_CPREFIX
-
-/*
- * Name mangling for public symbols is controlled by --with-mangling and
- * --with-jemalloc-prefix. With default settings the je_ prefix is stripped by
- * these macro definitions.
- */
-#undef je_malloc_conf
-#undef je_malloc_message
-#undef je_malloc
-#undef je_calloc
-#undef je_posix_memalign
-#undef je_aligned_alloc
-#undef je_realloc
-#undef je_free
-#undef je_malloc_usable_size
-#undef je_malloc_stats_print
-#undef je_mallctl
-#undef je_mallctlnametomib
-#undef je_mallctlbymib
-#undef je_memalign
-#undef je_valloc
-#undef je_allocm
-#undef je_rallocm
-#undef je_sallocm
-#undef je_dallocm
-#undef je_nallocm
-
-/*
- * JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs.
- * For shared libraries, symbol visibility mechanisms prevent these symbols
- * from being exported, but for static libraries, naming collisions are a real
- * possibility.
- */
-#undef JEMALLOC_PRIVATE_NAMESPACE
-#undef JEMALLOC_N
-
-/*
- * Hyper-threaded CPUs may need a special instruction inside spin loops in
- * order to yield to another virtual CPU.
- */
-#undef CPU_SPINWAIT
-
-/* Defined if the equivalent of FreeBSD's atomic(9) functions are available. */
-#undef JEMALLOC_ATOMIC9
-
-/*
- * Defined if OSAtomic*() functions are available, as provided by Darwin, and
- * documented in the atomic(3) manual page.
- */
-#undef JEMALLOC_OSATOMIC
-
-/*
- * Defined if __sync_add_and_fetch(uint32_t *, uint32_t) and
- * __sync_sub_and_fetch(uint32_t *, uint32_t) are available, despite
- * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 not being defined (which means the
- * functions are defined in libgcc instead of being inlines)
- */
-#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_4
-
-/*
- * Defined if __sync_add_and_fetch(uint64_t *, uint64_t) and
- * __sync_sub_and_fetch(uint64_t *, uint64_t) are available, despite
- * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 not being defined (which means the
- * functions are defined in libgcc instead of being inlines)
- */
-#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8
-
-/*
- * Defined if OSSpin*() functions are available, as provided by Darwin, and
- * documented in the spinlock(3) manual page.
- */
-#undef JEMALLOC_OSSPIN
-
-/*
- * Defined if _malloc_thread_cleanup() exists. At least in the case of
- * FreeBSD, pthread_key_create() allocates, which if used during malloc
- * bootstrapping will cause recursion into the pthreads library. Therefore, if
- * _malloc_thread_cleanup() exists, use it as the basis for thread cleanup in
- * malloc_tsd.
- */
-#undef JEMALLOC_MALLOC_THREAD_CLEANUP
-
-/*
- * Defined if threaded initialization is known to be safe on this platform.
- * Among other things, it must be possible to initialize a mutex without
- * triggering allocation in order for threaded allocation to be safe.
- */
-#undef JEMALLOC_THREADED_INIT
-
-/*
- * Defined if the pthreads implementation defines
- * _pthread_mutex_init_calloc_cb(), in which case the function is used in order
- * to avoid recursive allocation during mutex initialization.
- */
-#undef JEMALLOC_MUTEX_INIT_CB
-
-/* Defined if __attribute__((...)) syntax is supported. */
-#undef JEMALLOC_HAVE_ATTR
-#ifdef JEMALLOC_HAVE_ATTR
-# define JEMALLOC_ATTR(s) __attribute__((s))
-# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default"))
-# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
-# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
-# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)
-#elif _MSC_VER
-# define JEMALLOC_ATTR(s)
-# ifdef DLLEXPORT
-# define JEMALLOC_EXPORT __declspec(dllexport)
-# else
-# define JEMALLOC_EXPORT __declspec(dllimport)
-# endif
-# define JEMALLOC_ALIGNED(s) __declspec(align(s))
-# define JEMALLOC_SECTION(s) __declspec(allocate(s))
-# define JEMALLOC_NOINLINE __declspec(noinline)
-#else
-# define JEMALLOC_ATTR(s)
-# define JEMALLOC_EXPORT
-# define JEMALLOC_ALIGNED(s)
-# define JEMALLOC_SECTION(s)
-# define JEMALLOC_NOINLINE
-#endif
-
-/* Defined if sbrk() is supported. */
-#undef JEMALLOC_HAVE_SBRK
-
-/* Non-empty if the tls_model attribute is supported. */
-#undef JEMALLOC_TLS_MODEL
-
-/* JEMALLOC_CC_SILENCE enables code that silences unuseful compiler warnings. */
-#undef JEMALLOC_CC_SILENCE
-
-/*
- * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables
- * inline functions.
- */
-#undef JEMALLOC_DEBUG
-
-/* JEMALLOC_STATS enables statistics calculation. */
-#undef JEMALLOC_STATS
-
-/* JEMALLOC_PROF enables allocation profiling. */
-#undef JEMALLOC_PROF
-
-/* Use libunwind for profile backtracing if defined. */
-#undef JEMALLOC_PROF_LIBUNWIND
-
-/* Use libgcc for profile backtracing if defined. */
-#undef JEMALLOC_PROF_LIBGCC
-
-/* Use gcc intrinsics for profile backtracing if defined. */
-#undef JEMALLOC_PROF_GCC
-
-/*
- * JEMALLOC_TCACHE enables a thread-specific caching layer for small objects.
- * This makes it possible to allocate/deallocate objects without any locking
- * when the cache is in the steady state.
- */
-#undef JEMALLOC_TCACHE
-
-/*
- * JEMALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage
- * segment (DSS).
- */
-#undef JEMALLOC_DSS
-
-/* Support memory filling (junk/zero/quarantine/redzone). */
-#undef JEMALLOC_FILL
-
-/* Support the experimental API. */
-#undef JEMALLOC_EXPERIMENTAL
-
-/* Support utrace(2)-based tracing. */
-#undef JEMALLOC_UTRACE
-
-/* Support Valgrind. */
-#undef JEMALLOC_VALGRIND
-
-/* Support optional abort() on OOM. */
-#undef JEMALLOC_XMALLOC
-
-/* Support lazy locking (avoid locking unless a second thread is launched). */
-#undef JEMALLOC_LAZY_LOCK
-
-/* One page is 2^STATIC_PAGE_SHIFT bytes. */
-#undef STATIC_PAGE_SHIFT
-
-/*
- * If defined, use munmap() to unmap freed chunks, rather than storing them for
- * later reuse. This is disabled by default on Linux because common sequences
- * of mmap()/munmap() calls will cause virtual memory map holes.
- */
-#undef JEMALLOC_MUNMAP
-
-/*
- * If defined, use mremap(...MREMAP_FIXED...) for huge realloc(). This is
- * disabled by default because it is Linux-specific and it will cause virtual
- * memory map holes, much like munmap(2) does.
- */
-#undef JEMALLOC_MREMAP
-
-/* TLS is used to map arenas and magazine caches to threads. */
-#undef JEMALLOC_TLS
-
-/*
- * JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside
- * within jemalloc-owned chunks before dereferencing them.
- */
-#undef JEMALLOC_IVSALLOC
-
-/*
- * Define overrides for non-standard allocator-related functions if they
- * are present on the system.
- */
-#undef JEMALLOC_OVERRIDE_MEMALIGN
-#undef JEMALLOC_OVERRIDE_VALLOC
-
-/*
- * At least Linux omits the "const" in:
- *
- * size_t malloc_usable_size(const void *ptr);
- *
- * Match the operating system's prototype.
- */
-#undef JEMALLOC_USABLE_SIZE_CONST
-
-/*
- * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings.
- */
-#undef JEMALLOC_ZONE
-#undef JEMALLOC_ZONE_VERSION
-
-/*
- * Methods for purging unused pages differ between operating systems.
- *
- * madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages,
- * such that new pages will be demand-zeroed if
- * the address region is later touched.
- * madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being
- * unused, such that they will be discarded rather
- * than swapped out.
- */
-#undef JEMALLOC_PURGE_MADVISE_DONTNEED
-#undef JEMALLOC_PURGE_MADVISE_FREE
-
-/*
- * Define if operating system has alloca.h header.
- */
-#undef JEMALLOC_HAS_ALLOCA_H
-
-/* sizeof(void *) == 2^LG_SIZEOF_PTR. */
-#undef LG_SIZEOF_PTR
-
-/* sizeof(int) == 2^LG_SIZEOF_INT. */
-#undef LG_SIZEOF_INT
-
-/* sizeof(long) == 2^LG_SIZEOF_LONG. */
-#undef LG_SIZEOF_LONG
-
-/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */
-#undef LG_SIZEOF_INTMAX_T
diff --git a/extra/jemalloc/include/msvc_compat/inttypes.h b/extra/jemalloc/include/msvc_compat/inttypes.h
deleted file mode 100644
index a4e6b75cb91..00000000000
--- a/extra/jemalloc/include/msvc_compat/inttypes.h
+++ /dev/null
@@ -1,313 +0,0 @@
-// ISO C9x compliant inttypes.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. The name of the author may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_INTTYPES_H_ // [
-#define _MSC_INTTYPES_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#include "stdint.h"
-
-// 7.8 Format conversion of integer types
-
-typedef struct {
- intmax_t quot;
- intmax_t rem;
-} imaxdiv_t;
-
-// 7.8.1 Macros for format specifiers
-
-#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
-
-#ifdef _WIN64
-# define __PRI64_PREFIX "l"
-# define __PRIPTR_PREFIX "l"
-#else
-# define __PRI64_PREFIX "ll"
-# define __PRIPTR_PREFIX
-#endif
-
-// The fprintf macros for signed integers are:
-#define PRId8 "d"
-#define PRIi8 "i"
-#define PRIdLEAST8 "d"
-#define PRIiLEAST8 "i"
-#define PRIdFAST8 "d"
-#define PRIiFAST8 "i"
-
-#define PRId16 "hd"
-#define PRIi16 "hi"
-#define PRIdLEAST16 "hd"
-#define PRIiLEAST16 "hi"
-#define PRIdFAST16 "hd"
-#define PRIiFAST16 "hi"
-
-#define PRId32 "d"
-#define PRIi32 "i"
-#define PRIdLEAST32 "d"
-#define PRIiLEAST32 "i"
-#define PRIdFAST32 "d"
-#define PRIiFAST32 "i"
-
-#define PRId64 __PRI64_PREFIX "d"
-#define PRIi64 __PRI64_PREFIX "i"
-#define PRIdLEAST64 __PRI64_PREFIX "d"
-#define PRIiLEAST64 __PRI64_PREFIX "i"
-#define PRIdFAST64 __PRI64_PREFIX "d"
-#define PRIiFAST64 __PRI64_PREFIX "i"
-
-#define PRIdMAX __PRI64_PREFIX "d"
-#define PRIiMAX __PRI64_PREFIX "i"
-
-#define PRIdPTR __PRIPTR_PREFIX "d"
-#define PRIiPTR __PRIPTR_PREFIX "i"
-
-// The fprintf macros for unsigned integers are:
-#define PRIo8 "o"
-#define PRIu8 "u"
-#define PRIx8 "x"
-#define PRIX8 "X"
-#define PRIoLEAST8 "o"
-#define PRIuLEAST8 "u"
-#define PRIxLEAST8 "x"
-#define PRIXLEAST8 "X"
-#define PRIoFAST8 "o"
-#define PRIuFAST8 "u"
-#define PRIxFAST8 "x"
-#define PRIXFAST8 "X"
-
-#define PRIo16 "ho"
-#define PRIu16 "hu"
-#define PRIx16 "hx"
-#define PRIX16 "hX"
-#define PRIoLEAST16 "ho"
-#define PRIuLEAST16 "hu"
-#define PRIxLEAST16 "hx"
-#define PRIXLEAST16 "hX"
-#define PRIoFAST16 "ho"
-#define PRIuFAST16 "hu"
-#define PRIxFAST16 "hx"
-#define PRIXFAST16 "hX"
-
-#define PRIo32 "o"
-#define PRIu32 "u"
-#define PRIx32 "x"
-#define PRIX32 "X"
-#define PRIoLEAST32 "o"
-#define PRIuLEAST32 "u"
-#define PRIxLEAST32 "x"
-#define PRIXLEAST32 "X"
-#define PRIoFAST32 "o"
-#define PRIuFAST32 "u"
-#define PRIxFAST32 "x"
-#define PRIXFAST32 "X"
-
-#define PRIo64 __PRI64_PREFIX "o"
-#define PRIu64 __PRI64_PREFIX "u"
-#define PRIx64 __PRI64_PREFIX "x"
-#define PRIX64 __PRI64_PREFIX "X"
-#define PRIoLEAST64 __PRI64_PREFIX "o"
-#define PRIuLEAST64 __PRI64_PREFIX "u"
-#define PRIxLEAST64 __PRI64_PREFIX "x"
-#define PRIXLEAST64 __PRI64_PREFIX "X"
-#define PRIoFAST64 __PRI64_PREFIX "o"
-#define PRIuFAST64 __PRI64_PREFIX "u"
-#define PRIxFAST64 __PRI64_PREFIX "x"
-#define PRIXFAST64 __PRI64_PREFIX "X"
-
-#define PRIoMAX __PRI64_PREFIX "o"
-#define PRIuMAX __PRI64_PREFIX "u"
-#define PRIxMAX __PRI64_PREFIX "x"
-#define PRIXMAX __PRI64_PREFIX "X"
-
-#define PRIoPTR __PRIPTR_PREFIX "o"
-#define PRIuPTR __PRIPTR_PREFIX "u"
-#define PRIxPTR __PRIPTR_PREFIX "x"
-#define PRIXPTR __PRIPTR_PREFIX "X"
-
-// The fscanf macros for signed integers are:
-#define SCNd8 "d"
-#define SCNi8 "i"
-#define SCNdLEAST8 "d"
-#define SCNiLEAST8 "i"
-#define SCNdFAST8 "d"
-#define SCNiFAST8 "i"
-
-#define SCNd16 "hd"
-#define SCNi16 "hi"
-#define SCNdLEAST16 "hd"
-#define SCNiLEAST16 "hi"
-#define SCNdFAST16 "hd"
-#define SCNiFAST16 "hi"
-
-#define SCNd32 "ld"
-#define SCNi32 "li"
-#define SCNdLEAST32 "ld"
-#define SCNiLEAST32 "li"
-#define SCNdFAST32 "ld"
-#define SCNiFAST32 "li"
-
-#define SCNd64 "I64d"
-#define SCNi64 "I64i"
-#define SCNdLEAST64 "I64d"
-#define SCNiLEAST64 "I64i"
-#define SCNdFAST64 "I64d"
-#define SCNiFAST64 "I64i"
-
-#define SCNdMAX "I64d"
-#define SCNiMAX "I64i"
-
-#ifdef _WIN64 // [
-# define SCNdPTR "I64d"
-# define SCNiPTR "I64i"
-#else // _WIN64 ][
-# define SCNdPTR "ld"
-# define SCNiPTR "li"
-#endif // _WIN64 ]
-
-// The fscanf macros for unsigned integers are:
-#define SCNo8 "o"
-#define SCNu8 "u"
-#define SCNx8 "x"
-#define SCNX8 "X"
-#define SCNoLEAST8 "o"
-#define SCNuLEAST8 "u"
-#define SCNxLEAST8 "x"
-#define SCNXLEAST8 "X"
-#define SCNoFAST8 "o"
-#define SCNuFAST8 "u"
-#define SCNxFAST8 "x"
-#define SCNXFAST8 "X"
-
-#define SCNo16 "ho"
-#define SCNu16 "hu"
-#define SCNx16 "hx"
-#define SCNX16 "hX"
-#define SCNoLEAST16 "ho"
-#define SCNuLEAST16 "hu"
-#define SCNxLEAST16 "hx"
-#define SCNXLEAST16 "hX"
-#define SCNoFAST16 "ho"
-#define SCNuFAST16 "hu"
-#define SCNxFAST16 "hx"
-#define SCNXFAST16 "hX"
-
-#define SCNo32 "lo"
-#define SCNu32 "lu"
-#define SCNx32 "lx"
-#define SCNX32 "lX"
-#define SCNoLEAST32 "lo"
-#define SCNuLEAST32 "lu"
-#define SCNxLEAST32 "lx"
-#define SCNXLEAST32 "lX"
-#define SCNoFAST32 "lo"
-#define SCNuFAST32 "lu"
-#define SCNxFAST32 "lx"
-#define SCNXFAST32 "lX"
-
-#define SCNo64 "I64o"
-#define SCNu64 "I64u"
-#define SCNx64 "I64x"
-#define SCNX64 "I64X"
-#define SCNoLEAST64 "I64o"
-#define SCNuLEAST64 "I64u"
-#define SCNxLEAST64 "I64x"
-#define SCNXLEAST64 "I64X"
-#define SCNoFAST64 "I64o"
-#define SCNuFAST64 "I64u"
-#define SCNxFAST64 "I64x"
-#define SCNXFAST64 "I64X"
-
-#define SCNoMAX "I64o"
-#define SCNuMAX "I64u"
-#define SCNxMAX "I64x"
-#define SCNXMAX "I64X"
-
-#ifdef _WIN64 // [
-# define SCNoPTR "I64o"
-# define SCNuPTR "I64u"
-# define SCNxPTR "I64x"
-# define SCNXPTR "I64X"
-#else // _WIN64 ][
-# define SCNoPTR "lo"
-# define SCNuPTR "lu"
-# define SCNxPTR "lx"
-# define SCNXPTR "lX"
-#endif // _WIN64 ]
-
-#endif // __STDC_FORMAT_MACROS ]
-
-// 7.8.2 Functions for greatest-width integer types
-
-// 7.8.2.1 The imaxabs function
-#define imaxabs _abs64
-
-// 7.8.2.2 The imaxdiv function
-
-// This is modified version of div() function from Microsoft's div.c found
-// in %MSVC.NET%\crt\src\div.c
-#ifdef STATIC_IMAXDIV // [
-static
-#else // STATIC_IMAXDIV ][
-_inline
-#endif // STATIC_IMAXDIV ]
-imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
-{
- imaxdiv_t result;
-
- result.quot = numer / denom;
- result.rem = numer % denom;
-
- if (numer < 0 && result.rem > 0) {
- // did division wrong; must fix up
- ++result.quot;
- result.rem -= denom;
- }
-
- return result;
-}
-
-// 7.8.2.3 The strtoimax and strtoumax functions
-#define strtoimax _strtoi64
-#define strtoumax _strtoui64
-
-// 7.8.2.4 The wcstoimax and wcstoumax functions
-#define wcstoimax _wcstoi64
-#define wcstoumax _wcstoui64
-
-
-#endif // _MSC_INTTYPES_H_ ]
diff --git a/extra/jemalloc/include/msvc_compat/stdbool.h b/extra/jemalloc/include/msvc_compat/stdbool.h
deleted file mode 100644
index da9ee8b809b..00000000000
--- a/extra/jemalloc/include/msvc_compat/stdbool.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef stdbool_h
-#define stdbool_h
-
-#include <wtypes.h>
-
-/* MSVC doesn't define _Bool or bool in C, but does have BOOL */
-/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */
-typedef BOOL _Bool;
-
-#define bool _Bool
-#define true 1
-#define false 0
-
-#define __bool_true_false_are_defined 1
-
-#endif /* stdbool_h */
diff --git a/extra/jemalloc/include/msvc_compat/stdint.h b/extra/jemalloc/include/msvc_compat/stdint.h
deleted file mode 100644
index d02608a5972..00000000000
--- a/extra/jemalloc/include/msvc_compat/stdint.h
+++ /dev/null
@@ -1,247 +0,0 @@
-// ISO C9x compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2008 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. The name of the author may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_STDINT_H_ // [
-#define _MSC_STDINT_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#include <limits.h>
-
-// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
-// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
-// or compiler give many errors like this:
-// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
-#ifdef __cplusplus
-extern "C" {
-#endif
-# include <wchar.h>
-#ifdef __cplusplus
-}
-#endif
-
-// Define _W64 macros to mark types changing their size, like intptr_t.
-#ifndef _W64
-# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
-# define _W64 __w64
-# else
-# define _W64
-# endif
-#endif
-
-
-// 7.18.1 Integer types
-
-// 7.18.1.1 Exact-width integer types
-
-// Visual Studio 6 and Embedded Visual C++ 4 doesn't
-// realize that, e.g. char has the same size as __int8
-// so we give up on __intX for them.
-#if (_MSC_VER < 1300)
- typedef signed char int8_t;
- typedef signed short int16_t;
- typedef signed int int32_t;
- typedef unsigned char uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned int uint32_t;
-#else
- typedef signed __int8 int8_t;
- typedef signed __int16 int16_t;
- typedef signed __int32 int32_t;
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int16 uint16_t;
- typedef unsigned __int32 uint32_t;
-#endif
-typedef signed __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-
-// 7.18.1.2 Minimum-width integer types
-typedef int8_t int_least8_t;
-typedef int16_t int_least16_t;
-typedef int32_t int_least32_t;
-typedef int64_t int_least64_t;
-typedef uint8_t uint_least8_t;
-typedef uint16_t uint_least16_t;
-typedef uint32_t uint_least32_t;
-typedef uint64_t uint_least64_t;
-
-// 7.18.1.3 Fastest minimum-width integer types
-typedef int8_t int_fast8_t;
-typedef int16_t int_fast16_t;
-typedef int32_t int_fast32_t;
-typedef int64_t int_fast64_t;
-typedef uint8_t uint_fast8_t;
-typedef uint16_t uint_fast16_t;
-typedef uint32_t uint_fast32_t;
-typedef uint64_t uint_fast64_t;
-
-// 7.18.1.4 Integer types capable of holding object pointers
-#ifdef _WIN64 // [
- typedef signed __int64 intptr_t;
- typedef unsigned __int64 uintptr_t;
-#else // _WIN64 ][
- typedef _W64 signed int intptr_t;
- typedef _W64 unsigned int uintptr_t;
-#endif // _WIN64 ]
-
-// 7.18.1.5 Greatest-width integer types
-typedef int64_t intmax_t;
-typedef uint64_t uintmax_t;
-
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN ((int8_t)_I8_MIN)
-#define INT8_MAX _I8_MAX
-#define INT16_MIN ((int16_t)_I16_MIN)
-#define INT16_MAX _I16_MAX
-#define INT32_MIN ((int32_t)_I32_MIN)
-#define INT32_MAX _I32_MAX
-#define INT64_MIN ((int64_t)_I64_MIN)
-#define INT64_MAX _I64_MAX
-#define UINT8_MAX _UI8_MAX
-#define UINT16_MAX _UI16_MAX
-#define UINT32_MAX _UI32_MAX
-#define UINT64_MAX _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-# define INTPTR_MIN INT64_MIN
-# define INTPTR_MAX INT64_MAX
-# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
-# define INTPTR_MIN INT32_MIN
-# define INTPTR_MAX INT32_MAX
-# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-#define UINTMAX_MAX UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-# define PTRDIFF_MIN _I64_MIN
-# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
-# define PTRDIFF_MIN _I32_MIN
-# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
-
-#define SIG_ATOMIC_MIN INT_MIN
-#define SIG_ATOMIC_MAX INT_MAX
-
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
-# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
-# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
-#ifndef WCHAR_MIN // [
-# define WCHAR_MIN 0
-#endif // WCHAR_MIN ]
-#ifndef WCHAR_MAX // [
-# define WCHAR_MAX _UI16_MAX
-#endif // WCHAR_MAX ]
-
-#define WINT_MIN 0
-#define WINT_MAX _UI16_MAX
-
-#endif // __STDC_LIMIT_MACROS ]
-
-
-// 7.18.4 Limits of other integer types
-
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
-
-// 7.18.4.1 Macros for minimum-width integer constants
-
-#define INT8_C(val) val##i8
-#define INT16_C(val) val##i16
-#define INT32_C(val) val##i32
-#define INT64_C(val) val##i64
-
-#define UINT8_C(val) val##ui8
-#define UINT16_C(val) val##ui16
-#define UINT32_C(val) val##ui32
-#define UINT64_C(val) val##ui64
-
-// 7.18.4.2 Macros for greatest-width integer constants
-#define INTMAX_C INT64_C
-#define UINTMAX_C UINT64_C
-
-#endif // __STDC_CONSTANT_MACROS ]
-
-
-#endif // _MSC_STDINT_H_ ]
diff --git a/extra/jemalloc/include/msvc_compat/strings.h b/extra/jemalloc/include/msvc_compat/strings.h
deleted file mode 100644
index c84975b6b8e..00000000000
--- a/extra/jemalloc/include/msvc_compat/strings.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef strings_h
-#define strings_h
-
-/* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided
- * for both */
-#include <intrin.h>
-#pragma intrinsic(_BitScanForward)
-static __forceinline int ffsl(long x)
-{
- unsigned long i;
-
- if (_BitScanForward(&i, x))
- return (i + 1);
- return (0);
-}
-
-static __forceinline int ffs(int x)
-{
-
- return (ffsl(x));
-}
-
-#endif
diff --git a/extra/jemalloc/install-sh b/extra/jemalloc/install-sh
deleted file mode 100755
index ebc66913e94..00000000000
--- a/extra/jemalloc/install-sh
+++ /dev/null
@@ -1,250 +0,0 @@
-#! /bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
-#
-# Copyright 1991 by the Massachusetts Institute of Technology
-#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission. M.I.T. makes no representations about the
-# suitability of this software for any purpose. It is provided "as is"
-# without express or implied warranty.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch. It can only install one file at a time, a restriction
-# shared with many OS's install programs.
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
-
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
-else
- true
-fi
-
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
-
- if [ -d $dst ]; then
- instcmd=:
- else
- instcmd=mkdir
- fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
-
- if [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
-
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-'
-IFS="${IFS-${defaultIFS}}"
-
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
-
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
-
- pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
-
-# don't allow the sed command to completely eliminate the filename
-
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
-
-# Make a temp file name in the proper directory.
-
- dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
- $doit $instcmd $src $dsttmp &&
-
- trap "rm -f ${dsttmp}" 0 &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing. If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
-
-fi &&
-
-
-exit 0
diff --git a/extra/jemalloc/src/arena.c b/extra/jemalloc/src/arena.c
deleted file mode 100644
index d28b629a1e1..00000000000
--- a/extra/jemalloc/src/arena.c
+++ /dev/null
@@ -1,2385 +0,0 @@
-#define JEMALLOC_ARENA_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Data. */
-
-ssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;
-arena_bin_info_t arena_bin_info[NBINS];
-
-JEMALLOC_ALIGNED(CACHELINE)
-const uint8_t small_size2bin[] = {
-#define S2B_8(i) i,
-#define S2B_16(i) S2B_8(i) S2B_8(i)
-#define S2B_32(i) S2B_16(i) S2B_16(i)
-#define S2B_64(i) S2B_32(i) S2B_32(i)
-#define S2B_128(i) S2B_64(i) S2B_64(i)
-#define S2B_256(i) S2B_128(i) S2B_128(i)
-#define S2B_512(i) S2B_256(i) S2B_256(i)
-#define S2B_1024(i) S2B_512(i) S2B_512(i)
-#define S2B_2048(i) S2B_1024(i) S2B_1024(i)
-#define S2B_4096(i) S2B_2048(i) S2B_2048(i)
-#define S2B_8192(i) S2B_4096(i) S2B_4096(i)
-#define SIZE_CLASS(bin, delta, size) \
- S2B_##delta(bin)
- SIZE_CLASSES
-#undef S2B_8
-#undef S2B_16
-#undef S2B_32
-#undef S2B_64
-#undef S2B_128
-#undef S2B_256
-#undef S2B_512
-#undef S2B_1024
-#undef S2B_2048
-#undef S2B_4096
-#undef S2B_8192
-#undef SIZE_CLASS
-};
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static void arena_avail_insert(arena_t *arena, arena_chunk_t *chunk,
- size_t pageind, size_t npages, bool maybe_adjac_pred,
- bool maybe_adjac_succ);
-static void arena_avail_remove(arena_t *arena, arena_chunk_t *chunk,
- size_t pageind, size_t npages, bool maybe_adjac_pred,
- bool maybe_adjac_succ);
-static void arena_run_split(arena_t *arena, arena_run_t *run, size_t size,
- bool large, size_t binind, bool zero);
-static arena_chunk_t *arena_chunk_alloc(arena_t *arena);
-static void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
-static arena_run_t *arena_run_alloc_helper(arena_t *arena, size_t size,
- bool large, size_t binind, bool zero);
-static arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool large,
- size_t binind, bool zero);
-static arena_chunk_t *chunks_dirty_iter_cb(arena_chunk_tree_t *tree,
- arena_chunk_t *chunk, void *arg);
-static void arena_purge(arena_t *arena, bool all);
-static void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty,
- bool cleaned);
-static void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk,
- arena_run_t *run, size_t oldsize, size_t newsize);
-static void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk,
- arena_run_t *run, size_t oldsize, size_t newsize, bool dirty);
-static arena_run_t *arena_bin_runs_first(arena_bin_t *bin);
-static void arena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run);
-static void arena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run);
-static arena_run_t *arena_bin_nonfull_run_tryget(arena_bin_t *bin);
-static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
-static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin);
-static void arena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run,
- arena_bin_t *bin);
-static void arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk,
- arena_run_t *run, arena_bin_t *bin);
-static void arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk,
- arena_run_t *run, arena_bin_t *bin);
-static void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk,
- void *ptr, size_t oldsize, size_t size);
-static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk,
- void *ptr, size_t oldsize, size_t size, size_t extra, bool zero);
-static bool arena_ralloc_large(void *ptr, size_t oldsize, size_t size,
- size_t extra, bool zero);
-static size_t bin_info_run_size_calc(arena_bin_info_t *bin_info,
- size_t min_run_size);
-static void bin_info_init(void);
-
-/******************************************************************************/
-
-static inline int
-arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
-{
- uintptr_t a_mapelm = (uintptr_t)a;
- uintptr_t b_mapelm = (uintptr_t)b;
-
- assert(a != NULL);
- assert(b != NULL);
-
- return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));
-}
-
-/* Generate red-black tree functions. */
-rb_gen(static UNUSED, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t,
- u.rb_link, arena_run_comp)
-
-static inline int
-arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
-{
- int ret;
- size_t a_size = a->bits & ~PAGE_MASK;
- size_t b_size = b->bits & ~PAGE_MASK;
-
- ret = (a_size > b_size) - (a_size < b_size);
- if (ret == 0) {
- uintptr_t a_mapelm, b_mapelm;
-
- if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY)
- a_mapelm = (uintptr_t)a;
- else {
- /*
- * Treat keys as though they are lower than anything
- * else.
- */
- a_mapelm = 0;
- }
- b_mapelm = (uintptr_t)b;
-
- ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
- }
-
- return (ret);
-}
-
-/* Generate red-black tree functions. */
-rb_gen(static UNUSED, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t,
- u.rb_link, arena_avail_comp)
-
-static inline int
-arena_chunk_dirty_comp(arena_chunk_t *a, arena_chunk_t *b)
-{
-
- assert(a != NULL);
- assert(b != NULL);
-
- /*
- * Short-circuit for self comparison. The following comparison code
- * would come to the same result, but at the cost of executing the slow
- * path.
- */
- if (a == b)
- return (0);
-
- /*
- * Order such that chunks with higher fragmentation are "less than"
- * those with lower fragmentation -- purging order is from "least" to
- * "greatest". Fragmentation is measured as:
- *
- * mean current avail run size
- * --------------------------------
- * mean defragmented avail run size
- *
- * navail
- * -----------
- * nruns_avail nruns_avail-nruns_adjac
- * = ========================= = -----------------------
- * navail nruns_avail
- * -----------------------
- * nruns_avail-nruns_adjac
- *
- * The following code multiplies away the denominator prior to
- * comparison, in order to avoid division.
- *
- */
- {
- size_t a_val = (a->nruns_avail - a->nruns_adjac) *
- b->nruns_avail;
- size_t b_val = (b->nruns_avail - b->nruns_adjac) *
- a->nruns_avail;
-
- if (a_val < b_val)
- return (1);
- if (a_val > b_val)
- return (-1);
- }
- /*
- * Break ties by chunk address. For fragmented chunks, report lower
- * addresses as "lower", so that fragmentation reduction happens first
- * at lower addresses. However, use the opposite ordering for
- * unfragmented chunks, in order to increase the chances of
- * re-allocating dirty runs.
- */
- {
- uintptr_t a_chunk = (uintptr_t)a;
- uintptr_t b_chunk = (uintptr_t)b;
- int ret = ((a_chunk > b_chunk) - (a_chunk < b_chunk));
- if (a->nruns_adjac == 0) {
- assert(b->nruns_adjac == 0);
- ret = -ret;
- }
- return (ret);
- }
-}
-
-/* Generate red-black tree functions. */
-rb_gen(static UNUSED, arena_chunk_dirty_, arena_chunk_tree_t, arena_chunk_t,
- dirty_link, arena_chunk_dirty_comp)
-
-static inline bool
-arena_avail_adjac_pred(arena_chunk_t *chunk, size_t pageind)
-{
- bool ret;
-
- if (pageind-1 < map_bias)
- ret = false;
- else {
- ret = (arena_mapbits_allocated_get(chunk, pageind-1) == 0);
- assert(ret == false || arena_mapbits_dirty_get(chunk,
- pageind-1) != arena_mapbits_dirty_get(chunk, pageind));
- }
- return (ret);
-}
-
-static inline bool
-arena_avail_adjac_succ(arena_chunk_t *chunk, size_t pageind, size_t npages)
-{
- bool ret;
-
- if (pageind+npages == chunk_npages)
- ret = false;
- else {
- assert(pageind+npages < chunk_npages);
- ret = (arena_mapbits_allocated_get(chunk, pageind+npages) == 0);
- assert(ret == false || arena_mapbits_dirty_get(chunk, pageind)
- != arena_mapbits_dirty_get(chunk, pageind+npages));
- }
- return (ret);
-}
-
-static inline bool
-arena_avail_adjac(arena_chunk_t *chunk, size_t pageind, size_t npages)
-{
-
- return (arena_avail_adjac_pred(chunk, pageind) ||
- arena_avail_adjac_succ(chunk, pageind, npages));
-}
-
-static void
-arena_avail_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind,
- size_t npages, bool maybe_adjac_pred, bool maybe_adjac_succ)
-{
-
- assert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>
- LG_PAGE));
-
- /*
- * chunks_dirty is keyed by nruns_{avail,adjac}, so the chunk must be
- * removed and reinserted even if the run to be inserted is clean.
- */
- if (chunk->ndirty != 0)
- arena_chunk_dirty_remove(&arena->chunks_dirty, chunk);
-
- if (maybe_adjac_pred && arena_avail_adjac_pred(chunk, pageind))
- chunk->nruns_adjac++;
- if (maybe_adjac_succ && arena_avail_adjac_succ(chunk, pageind, npages))
- chunk->nruns_adjac++;
- chunk->nruns_avail++;
- assert(chunk->nruns_avail > chunk->nruns_adjac);
-
- if (arena_mapbits_dirty_get(chunk, pageind) != 0) {
- arena->ndirty += npages;
- chunk->ndirty += npages;
- }
- if (chunk->ndirty != 0)
- arena_chunk_dirty_insert(&arena->chunks_dirty, chunk);
-
- arena_avail_tree_insert(&arena->runs_avail, arena_mapp_get(chunk,
- pageind));
-}
-
-static void
-arena_avail_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind,
- size_t npages, bool maybe_adjac_pred, bool maybe_adjac_succ)
-{
-
- assert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >>
- LG_PAGE));
-
- /*
- * chunks_dirty is keyed by nruns_{avail,adjac}, so the chunk must be
- * removed and reinserted even if the run to be removed is clean.
- */
- if (chunk->ndirty != 0)
- arena_chunk_dirty_remove(&arena->chunks_dirty, chunk);
-
- if (maybe_adjac_pred && arena_avail_adjac_pred(chunk, pageind))
- chunk->nruns_adjac--;
- if (maybe_adjac_succ && arena_avail_adjac_succ(chunk, pageind, npages))
- chunk->nruns_adjac--;
- chunk->nruns_avail--;
- assert(chunk->nruns_avail > chunk->nruns_adjac || (chunk->nruns_avail
- == 0 && chunk->nruns_adjac == 0));
-
- if (arena_mapbits_dirty_get(chunk, pageind) != 0) {
- arena->ndirty -= npages;
- chunk->ndirty -= npages;
- }
- if (chunk->ndirty != 0)
- arena_chunk_dirty_insert(&arena->chunks_dirty, chunk);
-
- arena_avail_tree_remove(&arena->runs_avail, arena_mapp_get(chunk,
- pageind));
-}
-
-static inline void *
-arena_run_reg_alloc(arena_run_t *run, arena_bin_info_t *bin_info)
-{
- void *ret;
- unsigned regind;
- bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +
- (uintptr_t)bin_info->bitmap_offset);
-
- assert(run->nfree > 0);
- assert(bitmap_full(bitmap, &bin_info->bitmap_info) == false);
-
- regind = bitmap_sfu(bitmap, &bin_info->bitmap_info);
- ret = (void *)((uintptr_t)run + (uintptr_t)bin_info->reg0_offset +
- (uintptr_t)(bin_info->reg_interval * regind));
- run->nfree--;
- if (regind == run->nextind)
- run->nextind++;
- assert(regind < run->nextind);
- return (ret);
-}
-
-static inline void
-arena_run_reg_dalloc(arena_run_t *run, void *ptr)
-{
- arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- size_t mapbits = arena_mapbits_get(chunk, pageind);
- size_t binind = arena_ptr_small_binind_get(ptr, mapbits);
- arena_bin_info_t *bin_info = &arena_bin_info[binind];
- unsigned regind = arena_run_regind(run, bin_info, ptr);
- bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +
- (uintptr_t)bin_info->bitmap_offset);
-
- assert(run->nfree < bin_info->nregs);
- /* Freeing an interior pointer can cause assertion failure. */
- assert(((uintptr_t)ptr - ((uintptr_t)run +
- (uintptr_t)bin_info->reg0_offset)) %
- (uintptr_t)bin_info->reg_interval == 0);
- assert((uintptr_t)ptr >= (uintptr_t)run +
- (uintptr_t)bin_info->reg0_offset);
- /* Freeing an unallocated pointer can cause assertion failure. */
- assert(bitmap_get(bitmap, &bin_info->bitmap_info, regind));
-
- bitmap_unset(bitmap, &bin_info->bitmap_info, regind);
- run->nfree++;
-}
-
-static inline void
-arena_run_zero(arena_chunk_t *chunk, size_t run_ind, size_t npages)
-{
-
- VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind <<
- LG_PAGE)), (npages << LG_PAGE));
- memset((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), 0,
- (npages << LG_PAGE));
-}
-
-static inline void
-arena_run_page_mark_zeroed(arena_chunk_t *chunk, size_t run_ind)
-{
-
- VALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind <<
- LG_PAGE)), PAGE);
-}
-
-static inline void
-arena_run_page_validate_zeroed(arena_chunk_t *chunk, size_t run_ind)
-{
- size_t i;
- UNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE));
-
- arena_run_page_mark_zeroed(chunk, run_ind);
- for (i = 0; i < PAGE / sizeof(size_t); i++)
- assert(p[i] == 0);
-}
-
-static void
-arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
- size_t binind, bool zero)
-{
- arena_chunk_t *chunk;
- size_t run_ind, total_pages, need_pages, rem_pages, i;
- size_t flag_dirty;
-
- assert((large && binind == BININD_INVALID) || (large == false && binind
- != BININD_INVALID));
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);
- flag_dirty = arena_mapbits_dirty_get(chunk, run_ind);
- total_pages = arena_mapbits_unallocated_size_get(chunk, run_ind) >>
- LG_PAGE;
- assert(arena_mapbits_dirty_get(chunk, run_ind+total_pages-1) ==
- flag_dirty);
- need_pages = (size >> LG_PAGE);
- assert(need_pages > 0);
- assert(need_pages <= total_pages);
- rem_pages = total_pages - need_pages;
-
- arena_avail_remove(arena, chunk, run_ind, total_pages, true, true);
- if (config_stats) {
- /*
- * Update stats_cactive if nactive is crossing a chunk
- * multiple.
- */
- size_t cactive_diff = CHUNK_CEILING((arena->nactive +
- need_pages) << LG_PAGE) - CHUNK_CEILING(arena->nactive <<
- LG_PAGE);
- if (cactive_diff != 0)
- stats_cactive_add(cactive_diff);
- }
- arena->nactive += need_pages;
-
- /* Keep track of trailing unused pages for later use. */
- if (rem_pages > 0) {
- if (flag_dirty != 0) {
- arena_mapbits_unallocated_set(chunk, run_ind+need_pages,
- (rem_pages << LG_PAGE), CHUNK_MAP_DIRTY);
- arena_mapbits_unallocated_set(chunk,
- run_ind+total_pages-1, (rem_pages << LG_PAGE),
- CHUNK_MAP_DIRTY);
- } else {
- arena_mapbits_unallocated_set(chunk, run_ind+need_pages,
- (rem_pages << LG_PAGE),
- arena_mapbits_unzeroed_get(chunk,
- run_ind+need_pages));
- arena_mapbits_unallocated_set(chunk,
- run_ind+total_pages-1, (rem_pages << LG_PAGE),
- arena_mapbits_unzeroed_get(chunk,
- run_ind+total_pages-1));
- }
- arena_avail_insert(arena, chunk, run_ind+need_pages, rem_pages,
- false, true);
- }
-
- /*
- * Update the page map separately for large vs. small runs, since it is
- * possible to avoid iteration for large mallocs.
- */
- if (large) {
- if (zero) {
- if (flag_dirty == 0) {
- /*
- * The run is clean, so some pages may be
- * zeroed (i.e. never before touched).
- */
- for (i = 0; i < need_pages; i++) {
- if (arena_mapbits_unzeroed_get(chunk,
- run_ind+i) != 0) {
- arena_run_zero(chunk, run_ind+i,
- 1);
- } else if (config_debug) {
- arena_run_page_validate_zeroed(
- chunk, run_ind+i);
- } else {
- arena_run_page_mark_zeroed(
- chunk, run_ind+i);
- }
- }
- } else {
- /*
- * The run is dirty, so all pages must be
- * zeroed.
- */
- arena_run_zero(chunk, run_ind, need_pages);
- }
- } else {
- VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +
- (run_ind << LG_PAGE)), (need_pages << LG_PAGE));
- }
-
- /*
- * Set the last element first, in case the run only contains one
- * page (i.e. both statements set the same element).
- */
- arena_mapbits_large_set(chunk, run_ind+need_pages-1, 0,
- flag_dirty);
- arena_mapbits_large_set(chunk, run_ind, size, flag_dirty);
- } else {
- assert(zero == false);
- /*
- * Propagate the dirty and unzeroed flags to the allocated
- * small run, so that arena_dalloc_bin_run() has the ability to
- * conditionally trim clean pages.
- */
- arena_mapbits_small_set(chunk, run_ind, 0, binind, flag_dirty);
- /*
- * The first page will always be dirtied during small run
- * initialization, so a validation failure here would not
- * actually cause an observable failure.
- */
- if (config_debug && flag_dirty == 0 &&
- arena_mapbits_unzeroed_get(chunk, run_ind) == 0)
- arena_run_page_validate_zeroed(chunk, run_ind);
- for (i = 1; i < need_pages - 1; i++) {
- arena_mapbits_small_set(chunk, run_ind+i, i, binind, 0);
- if (config_debug && flag_dirty == 0 &&
- arena_mapbits_unzeroed_get(chunk, run_ind+i) == 0) {
- arena_run_page_validate_zeroed(chunk,
- run_ind+i);
- }
- }
- arena_mapbits_small_set(chunk, run_ind+need_pages-1,
- need_pages-1, binind, flag_dirty);
- if (config_debug && flag_dirty == 0 &&
- arena_mapbits_unzeroed_get(chunk, run_ind+need_pages-1) ==
- 0) {
- arena_run_page_validate_zeroed(chunk,
- run_ind+need_pages-1);
- }
- VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk +
- (run_ind << LG_PAGE)), (need_pages << LG_PAGE));
- }
-}
-
-static arena_chunk_t *
-arena_chunk_alloc(arena_t *arena)
-{
- arena_chunk_t *chunk;
- size_t i;
-
- if (arena->spare != NULL) {
- chunk = arena->spare;
- arena->spare = NULL;
-
- assert(arena_mapbits_allocated_get(chunk, map_bias) == 0);
- assert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0);
- assert(arena_mapbits_unallocated_size_get(chunk, map_bias) ==
- arena_maxclass);
- assert(arena_mapbits_unallocated_size_get(chunk,
- chunk_npages-1) == arena_maxclass);
- assert(arena_mapbits_dirty_get(chunk, map_bias) ==
- arena_mapbits_dirty_get(chunk, chunk_npages-1));
- } else {
- bool zero;
- size_t unzeroed;
-
- zero = false;
- malloc_mutex_unlock(&arena->lock);
- chunk = (arena_chunk_t *)chunk_alloc(chunksize, chunksize,
- false, &zero, arena->dss_prec);
- malloc_mutex_lock(&arena->lock);
- if (chunk == NULL)
- return (NULL);
- if (config_stats)
- arena->stats.mapped += chunksize;
-
- chunk->arena = arena;
-
- /*
- * Claim that no pages are in use, since the header is merely
- * overhead.
- */
- chunk->ndirty = 0;
-
- chunk->nruns_avail = 0;
- chunk->nruns_adjac = 0;
-
- /*
- * Initialize the map to contain one maximal free untouched run.
- * Mark the pages as zeroed iff chunk_alloc() returned a zeroed
- * chunk.
- */
- unzeroed = zero ? 0 : CHUNK_MAP_UNZEROED;
- arena_mapbits_unallocated_set(chunk, map_bias, arena_maxclass,
- unzeroed);
- /*
- * There is no need to initialize the internal page map entries
- * unless the chunk is not zeroed.
- */
- if (zero == false) {
- VALGRIND_MAKE_MEM_UNDEFINED(
- (void *)arena_mapp_get(chunk, map_bias+1),
- (size_t)((uintptr_t) arena_mapp_get(chunk,
- chunk_npages-1) - (uintptr_t)arena_mapp_get(chunk,
- map_bias+1)));
- for (i = map_bias+1; i < chunk_npages-1; i++)
- arena_mapbits_unzeroed_set(chunk, i, unzeroed);
- } else {
- VALGRIND_MAKE_MEM_DEFINED(
- (void *)arena_mapp_get(chunk, map_bias+1),
- (size_t)((uintptr_t) arena_mapp_get(chunk,
- chunk_npages-1) - (uintptr_t)arena_mapp_get(chunk,
- map_bias+1)));
- if (config_debug) {
- for (i = map_bias+1; i < chunk_npages-1; i++) {
- assert(arena_mapbits_unzeroed_get(chunk,
- i) == unzeroed);
- }
- }
- }
- arena_mapbits_unallocated_set(chunk, chunk_npages-1,
- arena_maxclass, unzeroed);
- }
-
- /* Insert the run into the runs_avail tree. */
- arena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias,
- false, false);
-
- return (chunk);
-}
-
-static void
-arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
-{
- assert(arena_mapbits_allocated_get(chunk, map_bias) == 0);
- assert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0);
- assert(arena_mapbits_unallocated_size_get(chunk, map_bias) ==
- arena_maxclass);
- assert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) ==
- arena_maxclass);
- assert(arena_mapbits_dirty_get(chunk, map_bias) ==
- arena_mapbits_dirty_get(chunk, chunk_npages-1));
-
- /*
- * Remove run from the runs_avail tree, so that the arena does not use
- * it.
- */
- arena_avail_remove(arena, chunk, map_bias, chunk_npages-map_bias,
- false, false);
-
- if (arena->spare != NULL) {
- arena_chunk_t *spare = arena->spare;
-
- arena->spare = chunk;
- malloc_mutex_unlock(&arena->lock);
- chunk_dealloc((void *)spare, chunksize, true);
- malloc_mutex_lock(&arena->lock);
- if (config_stats)
- arena->stats.mapped -= chunksize;
- } else
- arena->spare = chunk;
-}
-
-static arena_run_t *
-arena_run_alloc_helper(arena_t *arena, size_t size, bool large, size_t binind,
- bool zero)
-{
- arena_run_t *run;
- arena_chunk_map_t *mapelm, key;
-
- key.bits = size | CHUNK_MAP_KEY;
- mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key);
- if (mapelm != NULL) {
- arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);
- size_t pageind = (((uintptr_t)mapelm -
- (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t))
- + map_bias;
-
- run = (arena_run_t *)((uintptr_t)run_chunk + (pageind <<
- LG_PAGE));
- arena_run_split(arena, run, size, large, binind, zero);
- return (run);
- }
-
- return (NULL);
-}
-
-static arena_run_t *
-arena_run_alloc(arena_t *arena, size_t size, bool large, size_t binind,
- bool zero)
-{
- arena_chunk_t *chunk;
- arena_run_t *run;
-
- assert(size <= arena_maxclass);
- assert((size & PAGE_MASK) == 0);
- assert((large && binind == BININD_INVALID) || (large == false && binind
- != BININD_INVALID));
-
- /* Search the arena's chunks for the lowest best fit. */
- run = arena_run_alloc_helper(arena, size, large, binind, zero);
- if (run != NULL)
- return (run);
-
- /*
- * No usable runs. Create a new chunk from which to allocate the run.
- */
- chunk = arena_chunk_alloc(arena);
- if (chunk != NULL) {
- run = (arena_run_t *)((uintptr_t)chunk + (map_bias << LG_PAGE));
- arena_run_split(arena, run, size, large, binind, zero);
- return (run);
- }
-
- /*
- * arena_chunk_alloc() failed, but another thread may have made
- * sufficient memory available while this one dropped arena->lock in
- * arena_chunk_alloc(), so search one more time.
- */
- return (arena_run_alloc_helper(arena, size, large, binind, zero));
-}
-
-static inline void
-arena_maybe_purge(arena_t *arena)
-{
- size_t npurgeable, threshold;
-
- /* Don't purge if the option is disabled. */
- if (opt_lg_dirty_mult < 0)
- return;
- /* Don't purge if all dirty pages are already being purged. */
- if (arena->ndirty <= arena->npurgatory)
- return;
- npurgeable = arena->ndirty - arena->npurgatory;
- threshold = (arena->nactive >> opt_lg_dirty_mult);
- /*
- * Don't purge unless the number of purgeable pages exceeds the
- * threshold.
- */
- if (npurgeable <= threshold)
- return;
-
- arena_purge(arena, false);
-}
-
-static inline size_t
-arena_chunk_purge(arena_t *arena, arena_chunk_t *chunk, bool all)
-{
- size_t npurged;
- ql_head(arena_chunk_map_t) mapelms;
- arena_chunk_map_t *mapelm;
- size_t pageind, npages;
- size_t nmadvise;
-
- ql_new(&mapelms);
-
- /*
- * If chunk is the spare, temporarily re-allocate it, 1) so that its
- * run is reinserted into runs_avail, and 2) so that it cannot be
- * completely discarded by another thread while arena->lock is dropped
- * by this thread. Note that the arena_run_dalloc() call will
- * implicitly deallocate the chunk, so no explicit action is required
- * in this function to deallocate the chunk.
- *
- * Note that once a chunk contains dirty pages, it cannot again contain
- * a single run unless 1) it is a dirty run, or 2) this function purges
- * dirty pages and causes the transition to a single clean run. Thus
- * (chunk == arena->spare) is possible, but it is not possible for
- * this function to be called on the spare unless it contains a dirty
- * run.
- */
- if (chunk == arena->spare) {
- assert(arena_mapbits_dirty_get(chunk, map_bias) != 0);
- assert(arena_mapbits_dirty_get(chunk, chunk_npages-1) != 0);
-
- arena_chunk_alloc(arena);
- }
-
- if (config_stats)
- arena->stats.purged += chunk->ndirty;
-
- /*
- * Operate on all dirty runs if there is no clean/dirty run
- * fragmentation.
- */
- if (chunk->nruns_adjac == 0)
- all = true;
-
- /*
- * Temporarily allocate free dirty runs within chunk. If all is false,
- * only operate on dirty runs that are fragments; otherwise operate on
- * all dirty runs.
- */
- for (pageind = map_bias; pageind < chunk_npages; pageind += npages) {
- mapelm = arena_mapp_get(chunk, pageind);
- if (arena_mapbits_allocated_get(chunk, pageind) == 0) {
- size_t run_size =
- arena_mapbits_unallocated_size_get(chunk, pageind);
-
- npages = run_size >> LG_PAGE;
- assert(pageind + npages <= chunk_npages);
- assert(arena_mapbits_dirty_get(chunk, pageind) ==
- arena_mapbits_dirty_get(chunk, pageind+npages-1));
-
- if (arena_mapbits_dirty_get(chunk, pageind) != 0 &&
- (all || arena_avail_adjac(chunk, pageind,
- npages))) {
- arena_run_t *run = (arena_run_t *)((uintptr_t)
- chunk + (uintptr_t)(pageind << LG_PAGE));
-
- arena_run_split(arena, run, run_size, true,
- BININD_INVALID, false);
- /* Append to list for later processing. */
- ql_elm_new(mapelm, u.ql_link);
- ql_tail_insert(&mapelms, mapelm, u.ql_link);
- }
- } else {
- /* Skip run. */
- if (arena_mapbits_large_get(chunk, pageind) != 0) {
- npages = arena_mapbits_large_size_get(chunk,
- pageind) >> LG_PAGE;
- } else {
- size_t binind;
- arena_bin_info_t *bin_info;
- arena_run_t *run = (arena_run_t *)((uintptr_t)
- chunk + (uintptr_t)(pageind << LG_PAGE));
-
- assert(arena_mapbits_small_runind_get(chunk,
- pageind) == 0);
- binind = arena_bin_index(arena, run->bin);
- bin_info = &arena_bin_info[binind];
- npages = bin_info->run_size >> LG_PAGE;
- }
- }
- }
- assert(pageind == chunk_npages);
- assert(chunk->ndirty == 0 || all == false);
- assert(chunk->nruns_adjac == 0);
-
- malloc_mutex_unlock(&arena->lock);
- if (config_stats)
- nmadvise = 0;
- npurged = 0;
- ql_foreach(mapelm, &mapelms, u.ql_link) {
- bool unzeroed;
- size_t flag_unzeroed, i;
-
- pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) /
- sizeof(arena_chunk_map_t)) + map_bias;
- npages = arena_mapbits_large_size_get(chunk, pageind) >>
- LG_PAGE;
- assert(pageind + npages <= chunk_npages);
- unzeroed = pages_purge((void *)((uintptr_t)chunk + (pageind <<
- LG_PAGE)), (npages << LG_PAGE));
- flag_unzeroed = unzeroed ? CHUNK_MAP_UNZEROED : 0;
- /*
- * Set the unzeroed flag for all pages, now that pages_purge()
- * has returned whether the pages were zeroed as a side effect
- * of purging. This chunk map modification is safe even though
- * the arena mutex isn't currently owned by this thread,
- * because the run is marked as allocated, thus protecting it
- * from being modified by any other thread. As long as these
- * writes don't perturb the first and last elements'
- * CHUNK_MAP_ALLOCATED bits, behavior is well defined.
- */
- for (i = 0; i < npages; i++) {
- arena_mapbits_unzeroed_set(chunk, pageind+i,
- flag_unzeroed);
- }
- npurged += npages;
- if (config_stats)
- nmadvise++;
- }
- malloc_mutex_lock(&arena->lock);
- if (config_stats)
- arena->stats.nmadvise += nmadvise;
-
- /* Deallocate runs. */
- for (mapelm = ql_first(&mapelms); mapelm != NULL;
- mapelm = ql_first(&mapelms)) {
- arena_run_t *run;
-
- pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) /
- sizeof(arena_chunk_map_t)) + map_bias;
- run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)(pageind <<
- LG_PAGE));
- ql_remove(&mapelms, mapelm, u.ql_link);
- arena_run_dalloc(arena, run, false, true);
- }
-
- return (npurged);
-}
-
-static arena_chunk_t *
-chunks_dirty_iter_cb(arena_chunk_tree_t *tree, arena_chunk_t *chunk, void *arg)
-{
- size_t *ndirty = (size_t *)arg;
-
- assert(chunk->ndirty != 0);
- *ndirty += chunk->ndirty;
- return (NULL);
-}
-
-static void
-arena_purge(arena_t *arena, bool all)
-{
- arena_chunk_t *chunk;
- size_t npurgatory;
- if (config_debug) {
- size_t ndirty = 0;
-
- arena_chunk_dirty_iter(&arena->chunks_dirty, NULL,
- chunks_dirty_iter_cb, (void *)&ndirty);
- assert(ndirty == arena->ndirty);
- }
- assert(arena->ndirty > arena->npurgatory || all);
- assert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty -
- arena->npurgatory) || all);
-
- if (config_stats)
- arena->stats.npurge++;
-
- /*
- * Compute the minimum number of pages that this thread should try to
- * purge, and add the result to arena->npurgatory. This will keep
- * multiple threads from racing to reduce ndirty below the threshold.
- */
- {
- size_t npurgeable = arena->ndirty - arena->npurgatory;
-
- if (all == false) {
- size_t threshold = (arena->nactive >>
- opt_lg_dirty_mult);
-
- npurgatory = npurgeable - threshold;
- } else
- npurgatory = npurgeable;
- }
- arena->npurgatory += npurgatory;
-
- while (npurgatory > 0) {
- size_t npurgeable, npurged, nunpurged;
-
- /* Get next chunk with dirty pages. */
- chunk = arena_chunk_dirty_first(&arena->chunks_dirty);
- if (chunk == NULL) {
- /*
- * This thread was unable to purge as many pages as
- * originally intended, due to races with other threads
- * that either did some of the purging work, or re-used
- * dirty pages.
- */
- arena->npurgatory -= npurgatory;
- return;
- }
- npurgeable = chunk->ndirty;
- assert(npurgeable != 0);
-
- if (npurgeable > npurgatory && chunk->nruns_adjac == 0) {
- /*
- * This thread will purge all the dirty pages in chunk,
- * so set npurgatory to reflect this thread's intent to
- * purge the pages. This tends to reduce the chances
- * of the following scenario:
- *
- * 1) This thread sets arena->npurgatory such that
- * (arena->ndirty - arena->npurgatory) is at the
- * threshold.
- * 2) This thread drops arena->lock.
- * 3) Another thread causes one or more pages to be
- * dirtied, and immediately determines that it must
- * purge dirty pages.
- *
- * If this scenario *does* play out, that's okay,
- * because all of the purging work being done really
- * needs to happen.
- */
- arena->npurgatory += npurgeable - npurgatory;
- npurgatory = npurgeable;
- }
-
- /*
- * Keep track of how many pages are purgeable, versus how many
- * actually get purged, and adjust counters accordingly.
- */
- arena->npurgatory -= npurgeable;
- npurgatory -= npurgeable;
- npurged = arena_chunk_purge(arena, chunk, all);
- nunpurged = npurgeable - npurged;
- arena->npurgatory += nunpurged;
- npurgatory += nunpurged;
- }
-}
-
-void
-arena_purge_all(arena_t *arena)
-{
-
- malloc_mutex_lock(&arena->lock);
- arena_purge(arena, true);
- malloc_mutex_unlock(&arena->lock);
-}
-
-static void
-arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty, bool cleaned)
-{
- arena_chunk_t *chunk;
- size_t size, run_ind, run_pages, flag_dirty;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);
- assert(run_ind >= map_bias);
- assert(run_ind < chunk_npages);
- if (arena_mapbits_large_get(chunk, run_ind) != 0) {
- size = arena_mapbits_large_size_get(chunk, run_ind);
- assert(size == PAGE ||
- arena_mapbits_large_size_get(chunk,
- run_ind+(size>>LG_PAGE)-1) == 0);
- } else {
- size_t binind = arena_bin_index(arena, run->bin);
- arena_bin_info_t *bin_info = &arena_bin_info[binind];
- size = bin_info->run_size;
- }
- run_pages = (size >> LG_PAGE);
- if (config_stats) {
- /*
- * Update stats_cactive if nactive is crossing a chunk
- * multiple.
- */
- size_t cactive_diff = CHUNK_CEILING(arena->nactive << LG_PAGE) -
- CHUNK_CEILING((arena->nactive - run_pages) << LG_PAGE);
- if (cactive_diff != 0)
- stats_cactive_sub(cactive_diff);
- }
- arena->nactive -= run_pages;
-
- /*
- * The run is dirty if the caller claims to have dirtied it, as well as
- * if it was already dirty before being allocated and the caller
- * doesn't claim to have cleaned it.
- */
- assert(arena_mapbits_dirty_get(chunk, run_ind) ==
- arena_mapbits_dirty_get(chunk, run_ind+run_pages-1));
- if (cleaned == false && arena_mapbits_dirty_get(chunk, run_ind) != 0)
- dirty = true;
- flag_dirty = dirty ? CHUNK_MAP_DIRTY : 0;
-
- /* Mark pages as unallocated in the chunk map. */
- if (dirty) {
- arena_mapbits_unallocated_set(chunk, run_ind, size,
- CHUNK_MAP_DIRTY);
- arena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size,
- CHUNK_MAP_DIRTY);
- } else {
- arena_mapbits_unallocated_set(chunk, run_ind, size,
- arena_mapbits_unzeroed_get(chunk, run_ind));
- arena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size,
- arena_mapbits_unzeroed_get(chunk, run_ind+run_pages-1));
- }
-
- /* Try to coalesce forward. */
- if (run_ind + run_pages < chunk_npages &&
- arena_mapbits_allocated_get(chunk, run_ind+run_pages) == 0 &&
- arena_mapbits_dirty_get(chunk, run_ind+run_pages) == flag_dirty) {
- size_t nrun_size = arena_mapbits_unallocated_size_get(chunk,
- run_ind+run_pages);
- size_t nrun_pages = nrun_size >> LG_PAGE;
-
- /*
- * Remove successor from runs_avail; the coalesced run is
- * inserted later.
- */
- assert(arena_mapbits_unallocated_size_get(chunk,
- run_ind+run_pages+nrun_pages-1) == nrun_size);
- assert(arena_mapbits_dirty_get(chunk,
- run_ind+run_pages+nrun_pages-1) == flag_dirty);
- arena_avail_remove(arena, chunk, run_ind+run_pages, nrun_pages,
- false, true);
-
- size += nrun_size;
- run_pages += nrun_pages;
-
- arena_mapbits_unallocated_size_set(chunk, run_ind, size);
- arena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1,
- size);
- }
-
- /* Try to coalesce backward. */
- if (run_ind > map_bias && arena_mapbits_allocated_get(chunk, run_ind-1)
- == 0 && arena_mapbits_dirty_get(chunk, run_ind-1) == flag_dirty) {
- size_t prun_size = arena_mapbits_unallocated_size_get(chunk,
- run_ind-1);
- size_t prun_pages = prun_size >> LG_PAGE;
-
- run_ind -= prun_pages;
-
- /*
- * Remove predecessor from runs_avail; the coalesced run is
- * inserted later.
- */
- assert(arena_mapbits_unallocated_size_get(chunk, run_ind) ==
- prun_size);
- assert(arena_mapbits_dirty_get(chunk, run_ind) == flag_dirty);
- arena_avail_remove(arena, chunk, run_ind, prun_pages, true,
- false);
-
- size += prun_size;
- run_pages += prun_pages;
-
- arena_mapbits_unallocated_size_set(chunk, run_ind, size);
- arena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1,
- size);
- }
-
- /* Insert into runs_avail, now that coalescing is complete. */
- assert(arena_mapbits_unallocated_size_get(chunk, run_ind) ==
- arena_mapbits_unallocated_size_get(chunk, run_ind+run_pages-1));
- assert(arena_mapbits_dirty_get(chunk, run_ind) ==
- arena_mapbits_dirty_get(chunk, run_ind+run_pages-1));
- arena_avail_insert(arena, chunk, run_ind, run_pages, true, true);
-
- /* Deallocate chunk if it is now completely unused. */
- if (size == arena_maxclass) {
- assert(run_ind == map_bias);
- assert(run_pages == (arena_maxclass >> LG_PAGE));
- arena_chunk_dealloc(arena, chunk);
- }
-
- /*
- * It is okay to do dirty page processing here even if the chunk was
- * deallocated above, since in that case it is the spare. Waiting
- * until after possible chunk deallocation to do dirty processing
- * allows for an old spare to be fully deallocated, thus decreasing the
- * chances of spuriously crossing the dirty page purging threshold.
- */
- if (dirty)
- arena_maybe_purge(arena);
-}
-
-static void
-arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- size_t oldsize, size_t newsize)
-{
- size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;
- size_t head_npages = (oldsize - newsize) >> LG_PAGE;
- size_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind);
-
- assert(oldsize > newsize);
-
- /*
- * Update the chunk map so that arena_run_dalloc() can treat the
- * leading run as separately allocated. Set the last element of each
- * run first, in case of single-page runs.
- */
- assert(arena_mapbits_large_size_get(chunk, pageind) == oldsize);
- arena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty);
- arena_mapbits_large_set(chunk, pageind, oldsize-newsize, flag_dirty);
-
- if (config_debug) {
- UNUSED size_t tail_npages = newsize >> LG_PAGE;
- assert(arena_mapbits_large_size_get(chunk,
- pageind+head_npages+tail_npages-1) == 0);
- assert(arena_mapbits_dirty_get(chunk,
- pageind+head_npages+tail_npages-1) == flag_dirty);
- }
- arena_mapbits_large_set(chunk, pageind+head_npages, newsize,
- flag_dirty);
-
- arena_run_dalloc(arena, run, false, false);
-}
-
-static void
-arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- size_t oldsize, size_t newsize, bool dirty)
-{
- size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;
- size_t head_npages = newsize >> LG_PAGE;
- size_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind);
-
- assert(oldsize > newsize);
-
- /*
- * Update the chunk map so that arena_run_dalloc() can treat the
- * trailing run as separately allocated. Set the last element of each
- * run first, in case of single-page runs.
- */
- assert(arena_mapbits_large_size_get(chunk, pageind) == oldsize);
- arena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty);
- arena_mapbits_large_set(chunk, pageind, newsize, flag_dirty);
-
- if (config_debug) {
- UNUSED size_t tail_npages = (oldsize - newsize) >> LG_PAGE;
- assert(arena_mapbits_large_size_get(chunk,
- pageind+head_npages+tail_npages-1) == 0);
- assert(arena_mapbits_dirty_get(chunk,
- pageind+head_npages+tail_npages-1) == flag_dirty);
- }
- arena_mapbits_large_set(chunk, pageind+head_npages, oldsize-newsize,
- flag_dirty);
-
- arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),
- dirty, false);
-}
-
-static arena_run_t *
-arena_bin_runs_first(arena_bin_t *bin)
-{
- arena_chunk_map_t *mapelm = arena_run_tree_first(&bin->runs);
- if (mapelm != NULL) {
- arena_chunk_t *chunk;
- size_t pageind;
- arena_run_t *run;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm);
- pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) /
- sizeof(arena_chunk_map_t))) + map_bias;
- run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
- arena_mapbits_small_runind_get(chunk, pageind)) <<
- LG_PAGE));
- return (run);
- }
-
- return (NULL);
-}
-
-static void
-arena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run)
-{
- arena_chunk_t *chunk = CHUNK_ADDR2BASE(run);
- size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;
- arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind);
-
- assert(arena_run_tree_search(&bin->runs, mapelm) == NULL);
-
- arena_run_tree_insert(&bin->runs, mapelm);
-}
-
-static void
-arena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run)
-{
- arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE;
- arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind);
-
- assert(arena_run_tree_search(&bin->runs, mapelm) != NULL);
-
- arena_run_tree_remove(&bin->runs, mapelm);
-}
-
-static arena_run_t *
-arena_bin_nonfull_run_tryget(arena_bin_t *bin)
-{
- arena_run_t *run = arena_bin_runs_first(bin);
- if (run != NULL) {
- arena_bin_runs_remove(bin, run);
- if (config_stats)
- bin->stats.reruns++;
- }
- return (run);
-}
-
-static arena_run_t *
-arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
-{
- arena_run_t *run;
- size_t binind;
- arena_bin_info_t *bin_info;
-
- /* Look for a usable run. */
- run = arena_bin_nonfull_run_tryget(bin);
- if (run != NULL)
- return (run);
- /* No existing runs have any space available. */
-
- binind = arena_bin_index(arena, bin);
- bin_info = &arena_bin_info[binind];
-
- /* Allocate a new run. */
- malloc_mutex_unlock(&bin->lock);
- /******************************/
- malloc_mutex_lock(&arena->lock);
- run = arena_run_alloc(arena, bin_info->run_size, false, binind, false);
- if (run != NULL) {
- bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run +
- (uintptr_t)bin_info->bitmap_offset);
-
- /* Initialize run internals. */
- run->bin = bin;
- run->nextind = 0;
- run->nfree = bin_info->nregs;
- bitmap_init(bitmap, &bin_info->bitmap_info);
- }
- malloc_mutex_unlock(&arena->lock);
- /********************************/
- malloc_mutex_lock(&bin->lock);
- if (run != NULL) {
- if (config_stats) {
- bin->stats.nruns++;
- bin->stats.curruns++;
- }
- return (run);
- }
-
- /*
- * arena_run_alloc() failed, but another thread may have made
- * sufficient memory available while this one dropped bin->lock above,
- * so search one more time.
- */
- run = arena_bin_nonfull_run_tryget(bin);
- if (run != NULL)
- return (run);
-
- return (NULL);
-}
-
-/* Re-fill bin->runcur, then call arena_run_reg_alloc(). */
-static void *
-arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
-{
- void *ret;
- size_t binind;
- arena_bin_info_t *bin_info;
- arena_run_t *run;
-
- binind = arena_bin_index(arena, bin);
- bin_info = &arena_bin_info[binind];
- bin->runcur = NULL;
- run = arena_bin_nonfull_run_get(arena, bin);
- if (bin->runcur != NULL && bin->runcur->nfree > 0) {
- /*
- * Another thread updated runcur while this one ran without the
- * bin lock in arena_bin_nonfull_run_get().
- */
- assert(bin->runcur->nfree > 0);
- ret = arena_run_reg_alloc(bin->runcur, bin_info);
- if (run != NULL) {
- arena_chunk_t *chunk;
-
- /*
- * arena_run_alloc() may have allocated run, or it may
- * have pulled run from the bin's run tree. Therefore
- * it is unsafe to make any assumptions about how run
- * has previously been used, and arena_bin_lower_run()
- * must be called, as if a region were just deallocated
- * from the run.
- */
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- if (run->nfree == bin_info->nregs)
- arena_dalloc_bin_run(arena, chunk, run, bin);
- else
- arena_bin_lower_run(arena, chunk, run, bin);
- }
- return (ret);
- }
-
- if (run == NULL)
- return (NULL);
-
- bin->runcur = run;
-
- assert(bin->runcur->nfree > 0);
-
- return (arena_run_reg_alloc(bin->runcur, bin_info));
-}
-
-void
-arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind,
- uint64_t prof_accumbytes)
-{
- unsigned i, nfill;
- arena_bin_t *bin;
- arena_run_t *run;
- void *ptr;
-
- assert(tbin->ncached == 0);
-
- if (config_prof && arena_prof_accum(arena, prof_accumbytes))
- prof_idump();
- bin = &arena->bins[binind];
- malloc_mutex_lock(&bin->lock);
- for (i = 0, nfill = (tcache_bin_info[binind].ncached_max >>
- tbin->lg_fill_div); i < nfill; i++) {
- if ((run = bin->runcur) != NULL && run->nfree > 0)
- ptr = arena_run_reg_alloc(run, &arena_bin_info[binind]);
- else
- ptr = arena_bin_malloc_hard(arena, bin);
- if (ptr == NULL)
- break;
- if (config_fill && opt_junk) {
- arena_alloc_junk_small(ptr, &arena_bin_info[binind],
- true);
- }
- /* Insert such that low regions get used first. */
- tbin->avail[nfill - 1 - i] = ptr;
- }
- if (config_stats) {
- bin->stats.allocated += i * arena_bin_info[binind].reg_size;
- bin->stats.nmalloc += i;
- bin->stats.nrequests += tbin->tstats.nrequests;
- bin->stats.nfills++;
- tbin->tstats.nrequests = 0;
- }
- malloc_mutex_unlock(&bin->lock);
- tbin->ncached = i;
-}
-
-void
-arena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, bool zero)
-{
-
- if (zero) {
- size_t redzone_size = bin_info->redzone_size;
- memset((void *)((uintptr_t)ptr - redzone_size), 0xa5,
- redzone_size);
- memset((void *)((uintptr_t)ptr + bin_info->reg_size), 0xa5,
- redzone_size);
- } else {
- memset((void *)((uintptr_t)ptr - bin_info->redzone_size), 0xa5,
- bin_info->reg_interval);
- }
-}
-
-void
-arena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info)
-{
- size_t size = bin_info->reg_size;
- size_t redzone_size = bin_info->redzone_size;
- size_t i;
- bool error = false;
-
- for (i = 1; i <= redzone_size; i++) {
- unsigned byte;
- if ((byte = *(uint8_t *)((uintptr_t)ptr - i)) != 0xa5) {
- error = true;
- malloc_printf("<jemalloc>: Corrupt redzone "
- "%zu byte%s before %p (size %zu), byte=%#x\n", i,
- (i == 1) ? "" : "s", ptr, size, byte);
- }
- }
- for (i = 0; i < redzone_size; i++) {
- unsigned byte;
- if ((byte = *(uint8_t *)((uintptr_t)ptr + size + i)) != 0xa5) {
- error = true;
- malloc_printf("<jemalloc>: Corrupt redzone "
- "%zu byte%s after end of %p (size %zu), byte=%#x\n",
- i, (i == 1) ? "" : "s", ptr, size, byte);
- }
- }
- if (opt_abort && error)
- abort();
-
- memset((void *)((uintptr_t)ptr - redzone_size), 0x5a,
- bin_info->reg_interval);
-}
-
-void *
-arena_malloc_small(arena_t *arena, size_t size, bool zero)
-{
- void *ret;
- arena_bin_t *bin;
- arena_run_t *run;
- size_t binind;
-
- binind = SMALL_SIZE2BIN(size);
- assert(binind < NBINS);
- bin = &arena->bins[binind];
- size = arena_bin_info[binind].reg_size;
-
- malloc_mutex_lock(&bin->lock);
- if ((run = bin->runcur) != NULL && run->nfree > 0)
- ret = arena_run_reg_alloc(run, &arena_bin_info[binind]);
- else
- ret = arena_bin_malloc_hard(arena, bin);
-
- if (ret == NULL) {
- malloc_mutex_unlock(&bin->lock);
- return (NULL);
- }
-
- if (config_stats) {
- bin->stats.allocated += size;
- bin->stats.nmalloc++;
- bin->stats.nrequests++;
- }
- malloc_mutex_unlock(&bin->lock);
- if (config_prof && isthreaded == false && arena_prof_accum(arena, size))
- prof_idump();
-
- if (zero == false) {
- if (config_fill) {
- if (opt_junk) {
- arena_alloc_junk_small(ret,
- &arena_bin_info[binind], false);
- } else if (opt_zero)
- memset(ret, 0, size);
- }
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- } else {
- if (config_fill && opt_junk) {
- arena_alloc_junk_small(ret, &arena_bin_info[binind],
- true);
- }
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- memset(ret, 0, size);
- }
-
- return (ret);
-}
-
-void *
-arena_malloc_large(arena_t *arena, size_t size, bool zero)
-{
- void *ret;
- UNUSED bool idump;
-
- /* Large allocation. */
- size = PAGE_CEILING(size);
- malloc_mutex_lock(&arena->lock);
- ret = (void *)arena_run_alloc(arena, size, true, BININD_INVALID, zero);
- if (ret == NULL) {
- malloc_mutex_unlock(&arena->lock);
- return (NULL);
- }
- if (config_stats) {
- arena->stats.nmalloc_large++;
- arena->stats.nrequests_large++;
- arena->stats.allocated_large += size;
- arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
- }
- if (config_prof)
- idump = arena_prof_accum_locked(arena, size);
- malloc_mutex_unlock(&arena->lock);
- if (config_prof && idump)
- prof_idump();
-
- if (zero == false) {
- if (config_fill) {
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
- }
- }
-
- return (ret);
-}
-
-/* Only handles large allocations that require more than page alignment. */
-void *
-arena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero)
-{
- void *ret;
- size_t alloc_size, leadsize, trailsize;
- arena_run_t *run;
- arena_chunk_t *chunk;
-
- assert((size & PAGE_MASK) == 0);
-
- alignment = PAGE_CEILING(alignment);
- alloc_size = size + alignment - PAGE;
-
- malloc_mutex_lock(&arena->lock);
- run = arena_run_alloc(arena, alloc_size, true, BININD_INVALID, zero);
- if (run == NULL) {
- malloc_mutex_unlock(&arena->lock);
- return (NULL);
- }
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
-
- leadsize = ALIGNMENT_CEILING((uintptr_t)run, alignment) -
- (uintptr_t)run;
- assert(alloc_size >= leadsize + size);
- trailsize = alloc_size - leadsize - size;
- ret = (void *)((uintptr_t)run + leadsize);
- if (leadsize != 0) {
- arena_run_trim_head(arena, chunk, run, alloc_size, alloc_size -
- leadsize);
- }
- if (trailsize != 0) {
- arena_run_trim_tail(arena, chunk, ret, size + trailsize, size,
- false);
- }
-
- if (config_stats) {
- arena->stats.nmalloc_large++;
- arena->stats.nrequests_large++;
- arena->stats.allocated_large += size;
- arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
- }
- malloc_mutex_unlock(&arena->lock);
-
- if (config_fill && zero == false) {
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
- }
- return (ret);
-}
-
-void
-arena_prof_promoted(const void *ptr, size_t size)
-{
- arena_chunk_t *chunk;
- size_t pageind, binind;
-
- cassert(config_prof);
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
- assert(isalloc(ptr, false) == PAGE);
- assert(isalloc(ptr, true) == PAGE);
- assert(size <= SMALL_MAXCLASS);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- binind = SMALL_SIZE2BIN(size);
- assert(binind < NBINS);
- arena_mapbits_large_binind_set(chunk, pageind, binind);
-
- assert(isalloc(ptr, false) == PAGE);
- assert(isalloc(ptr, true) == size);
-}
-
-static void
-arena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run,
- arena_bin_t *bin)
-{
-
- /* Dissociate run from bin. */
- if (run == bin->runcur)
- bin->runcur = NULL;
- else {
- size_t binind = arena_bin_index(chunk->arena, bin);
- arena_bin_info_t *bin_info = &arena_bin_info[binind];
-
- if (bin_info->nregs != 1) {
- /*
- * This block's conditional is necessary because if the
- * run only contains one region, then it never gets
- * inserted into the non-full runs tree.
- */
- arena_bin_runs_remove(bin, run);
- }
- }
-}
-
-static void
-arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- arena_bin_t *bin)
-{
- size_t binind;
- arena_bin_info_t *bin_info;
- size_t npages, run_ind, past;
-
- assert(run != bin->runcur);
- assert(arena_run_tree_search(&bin->runs,
- arena_mapp_get(chunk, ((uintptr_t)run-(uintptr_t)chunk)>>LG_PAGE))
- == NULL);
-
- binind = arena_bin_index(chunk->arena, run->bin);
- bin_info = &arena_bin_info[binind];
-
- malloc_mutex_unlock(&bin->lock);
- /******************************/
- npages = bin_info->run_size >> LG_PAGE;
- run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE);
- past = (size_t)(PAGE_CEILING((uintptr_t)run +
- (uintptr_t)bin_info->reg0_offset + (uintptr_t)(run->nextind *
- bin_info->reg_interval - bin_info->redzone_size) -
- (uintptr_t)chunk) >> LG_PAGE);
- malloc_mutex_lock(&arena->lock);
-
- /*
- * If the run was originally clean, and some pages were never touched,
- * trim the clean pages before deallocating the dirty portion of the
- * run.
- */
- assert(arena_mapbits_dirty_get(chunk, run_ind) ==
- arena_mapbits_dirty_get(chunk, run_ind+npages-1));
- if (arena_mapbits_dirty_get(chunk, run_ind) == 0 && past - run_ind <
- npages) {
- /* Trim clean pages. Convert to large run beforehand. */
- assert(npages > 0);
- arena_mapbits_large_set(chunk, run_ind, bin_info->run_size, 0);
- arena_mapbits_large_set(chunk, run_ind+npages-1, 0, 0);
- arena_run_trim_tail(arena, chunk, run, (npages << LG_PAGE),
- ((past - run_ind) << LG_PAGE), false);
- /* npages = past - run_ind; */
- }
- arena_run_dalloc(arena, run, true, false);
- malloc_mutex_unlock(&arena->lock);
- /****************************/
- malloc_mutex_lock(&bin->lock);
- if (config_stats)
- bin->stats.curruns--;
-}
-
-static void
-arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- arena_bin_t *bin)
-{
-
- /*
- * Make sure that if bin->runcur is non-NULL, it refers to the lowest
- * non-full run. It is okay to NULL runcur out rather than proactively
- * keeping it pointing at the lowest non-full run.
- */
- if ((uintptr_t)run < (uintptr_t)bin->runcur) {
- /* Switch runcur. */
- if (bin->runcur->nfree > 0)
- arena_bin_runs_insert(bin, bin->runcur);
- bin->runcur = run;
- if (config_stats)
- bin->stats.reruns++;
- } else
- arena_bin_runs_insert(bin, run);
-}
-
-void
-arena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- arena_chunk_map_t *mapelm)
-{
- size_t pageind;
- arena_run_t *run;
- arena_bin_t *bin;
- arena_bin_info_t *bin_info;
- size_t size, binind;
-
- pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
- arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE));
- bin = run->bin;
- binind = arena_ptr_small_binind_get(ptr, mapelm->bits);
- bin_info = &arena_bin_info[binind];
- if (config_fill || config_stats)
- size = bin_info->reg_size;
-
- if (config_fill && opt_junk)
- arena_dalloc_junk_small(ptr, bin_info);
-
- arena_run_reg_dalloc(run, ptr);
- if (run->nfree == bin_info->nregs) {
- arena_dissociate_bin_run(chunk, run, bin);
- arena_dalloc_bin_run(arena, chunk, run, bin);
- } else if (run->nfree == 1 && run != bin->runcur)
- arena_bin_lower_run(arena, chunk, run, bin);
-
- if (config_stats) {
- bin->stats.allocated -= size;
- bin->stats.ndalloc++;
- }
-}
-
-void
-arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t pageind, arena_chunk_map_t *mapelm)
-{
- arena_run_t *run;
- arena_bin_t *bin;
-
- run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
- arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE));
- bin = run->bin;
- malloc_mutex_lock(&bin->lock);
- arena_dalloc_bin_locked(arena, chunk, ptr, mapelm);
- malloc_mutex_unlock(&bin->lock);
-}
-
-void
-arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t pageind)
-{
- arena_chunk_map_t *mapelm;
-
- if (config_debug) {
- /* arena_ptr_small_binind_get() does extra sanity checking. */
- assert(arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk,
- pageind)) != BININD_INVALID);
- }
- mapelm = arena_mapp_get(chunk, pageind);
- arena_dalloc_bin(arena, chunk, ptr, pageind, mapelm);
-}
-
-void
-arena_dalloc_large_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr)
-{
-
- if (config_fill || config_stats) {
- size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- size_t size = arena_mapbits_large_size_get(chunk, pageind);
-
- if (config_fill && config_stats && opt_junk)
- memset(ptr, 0x5a, size);
- if (config_stats) {
- arena->stats.ndalloc_large++;
- arena->stats.allocated_large -= size;
- arena->stats.lstats[(size >> LG_PAGE) - 1].ndalloc++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].curruns--;
- }
- }
-
- arena_run_dalloc(arena, (arena_run_t *)ptr, true, false);
-}
-
-void
-arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
-{
-
- malloc_mutex_lock(&arena->lock);
- arena_dalloc_large_locked(arena, chunk, ptr);
- malloc_mutex_unlock(&arena->lock);
-}
-
-static void
-arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t oldsize, size_t size)
-{
-
- assert(size < oldsize);
-
- /*
- * Shrink the run, and make trailing pages available for other
- * allocations.
- */
- malloc_mutex_lock(&arena->lock);
- arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,
- true);
- if (config_stats) {
- arena->stats.ndalloc_large++;
- arena->stats.allocated_large -= oldsize;
- arena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++;
- arena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--;
-
- arena->stats.nmalloc_large++;
- arena->stats.nrequests_large++;
- arena->stats.allocated_large += size;
- arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
- }
- malloc_mutex_unlock(&arena->lock);
-}
-
-static bool
-arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t oldsize, size_t size, size_t extra, bool zero)
-{
- size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
- size_t npages = oldsize >> LG_PAGE;
- size_t followsize;
-
- assert(oldsize == arena_mapbits_large_size_get(chunk, pageind));
-
- /* Try to extend the run. */
- assert(size + extra > oldsize);
- malloc_mutex_lock(&arena->lock);
- if (pageind + npages < chunk_npages &&
- arena_mapbits_allocated_get(chunk, pageind+npages) == 0 &&
- (followsize = arena_mapbits_unallocated_size_get(chunk,
- pageind+npages)) >= size - oldsize) {
- /*
- * The next run is available and sufficiently large. Split the
- * following run, then merge the first part with the existing
- * allocation.
- */
- size_t flag_dirty;
- size_t splitsize = (oldsize + followsize <= size + extra)
- ? followsize : size + extra - oldsize;
- arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk +
- ((pageind+npages) << LG_PAGE)), splitsize, true,
- BININD_INVALID, zero);
-
- size = oldsize + splitsize;
- npages = size >> LG_PAGE;
-
- /*
- * Mark the extended run as dirty if either portion of the run
- * was dirty before allocation. This is rather pedantic,
- * because there's not actually any sequence of events that
- * could cause the resulting run to be passed to
- * arena_run_dalloc() with the dirty argument set to false
- * (which is when dirty flag consistency would really matter).
- */
- flag_dirty = arena_mapbits_dirty_get(chunk, pageind) |
- arena_mapbits_dirty_get(chunk, pageind+npages-1);
- arena_mapbits_large_set(chunk, pageind, size, flag_dirty);
- arena_mapbits_large_set(chunk, pageind+npages-1, 0, flag_dirty);
-
- if (config_stats) {
- arena->stats.ndalloc_large++;
- arena->stats.allocated_large -= oldsize;
- arena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++;
- arena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--;
-
- arena->stats.nmalloc_large++;
- arena->stats.nrequests_large++;
- arena->stats.allocated_large += size;
- arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++;
- arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
- }
- malloc_mutex_unlock(&arena->lock);
- return (false);
- }
- malloc_mutex_unlock(&arena->lock);
-
- return (true);
-}
-
-/*
- * Try to resize a large allocation, in order to avoid copying. This will
- * always fail if growing an object, and the following run is already in use.
- */
-static bool
-arena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra,
- bool zero)
-{
- size_t psize;
-
- psize = PAGE_CEILING(size + extra);
- if (psize == oldsize) {
- /* Same size class. */
- if (config_fill && opt_junk && size < oldsize) {
- memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
- size);
- }
- return (false);
- } else {
- arena_chunk_t *chunk;
- arena_t *arena;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- arena = chunk->arena;
-
- if (psize < oldsize) {
- /* Fill before shrinking in order avoid a race. */
- if (config_fill && opt_junk) {
- memset((void *)((uintptr_t)ptr + size), 0x5a,
- oldsize - size);
- }
- arena_ralloc_large_shrink(arena, chunk, ptr, oldsize,
- psize);
- return (false);
- } else {
- bool ret = arena_ralloc_large_grow(arena, chunk, ptr,
- oldsize, PAGE_CEILING(size),
- psize - PAGE_CEILING(size), zero);
- if (config_fill && ret == false && zero == false &&
- opt_zero) {
- memset((void *)((uintptr_t)ptr + oldsize), 0,
- size - oldsize);
- }
- return (ret);
- }
- }
-}
-
-void *
-arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra,
- bool zero)
-{
-
- /*
- * Avoid moving the allocation if the size class can be left the same.
- */
- if (oldsize <= arena_maxclass) {
- if (oldsize <= SMALL_MAXCLASS) {
- assert(arena_bin_info[SMALL_SIZE2BIN(oldsize)].reg_size
- == oldsize);
- if ((size + extra <= SMALL_MAXCLASS &&
- SMALL_SIZE2BIN(size + extra) ==
- SMALL_SIZE2BIN(oldsize)) || (size <= oldsize &&
- size + extra >= oldsize)) {
- if (config_fill && opt_junk && size < oldsize) {
- memset((void *)((uintptr_t)ptr + size),
- 0x5a, oldsize - size);
- }
- return (ptr);
- }
- } else {
- assert(size <= arena_maxclass);
- if (size + extra > SMALL_MAXCLASS) {
- if (arena_ralloc_large(ptr, oldsize, size,
- extra, zero) == false)
- return (ptr);
- }
- }
- }
-
- /* Reallocation would require a move. */
- return (NULL);
-}
-
-void *
-arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size,
- size_t extra, size_t alignment, bool zero, bool try_tcache_alloc,
- bool try_tcache_dalloc)
-{
- void *ret;
- size_t copysize;
-
- /* Try to avoid moving the allocation. */
- ret = arena_ralloc_no_move(ptr, oldsize, size, extra, zero);
- if (ret != NULL)
- return (ret);
-
- /*
- * size and oldsize are different enough that we need to move the
- * object. In that case, fall back to allocating new space and
- * copying.
- */
- if (alignment != 0) {
- size_t usize = sa2u(size + extra, alignment);
- if (usize == 0)
- return (NULL);
- ret = ipallocx(usize, alignment, zero, try_tcache_alloc, arena);
- } else
- ret = arena_malloc(arena, size + extra, zero, try_tcache_alloc);
-
- if (ret == NULL) {
- if (extra == 0)
- return (NULL);
- /* Try again, this time without extra. */
- if (alignment != 0) {
- size_t usize = sa2u(size, alignment);
- if (usize == 0)
- return (NULL);
- ret = ipallocx(usize, alignment, zero, try_tcache_alloc,
- arena);
- } else
- ret = arena_malloc(arena, size, zero, try_tcache_alloc);
-
- if (ret == NULL)
- return (NULL);
- }
-
- /* Junk/zero-filling were already done by ipalloc()/arena_malloc(). */
-
- /*
- * Copy at most size bytes (not size+extra), since the caller has no
- * expectation that the extra bytes will be reliably preserved.
- */
- copysize = (size < oldsize) ? size : oldsize;
- VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize);
- memcpy(ret, ptr, copysize);
- iqallocx(ptr, try_tcache_dalloc);
- return (ret);
-}
-
-dss_prec_t
-arena_dss_prec_get(arena_t *arena)
-{
- dss_prec_t ret;
-
- malloc_mutex_lock(&arena->lock);
- ret = arena->dss_prec;
- malloc_mutex_unlock(&arena->lock);
- return (ret);
-}
-
-void
-arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec)
-{
-
- malloc_mutex_lock(&arena->lock);
- arena->dss_prec = dss_prec;
- malloc_mutex_unlock(&arena->lock);
-}
-
-void
-arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive,
- size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats,
- malloc_large_stats_t *lstats)
-{
- unsigned i;
-
- malloc_mutex_lock(&arena->lock);
- *dss = dss_prec_names[arena->dss_prec];
- *nactive += arena->nactive;
- *ndirty += arena->ndirty;
-
- astats->mapped += arena->stats.mapped;
- astats->npurge += arena->stats.npurge;
- astats->nmadvise += arena->stats.nmadvise;
- astats->purged += arena->stats.purged;
- astats->allocated_large += arena->stats.allocated_large;
- astats->nmalloc_large += arena->stats.nmalloc_large;
- astats->ndalloc_large += arena->stats.ndalloc_large;
- astats->nrequests_large += arena->stats.nrequests_large;
-
- for (i = 0; i < nlclasses; i++) {
- lstats[i].nmalloc += arena->stats.lstats[i].nmalloc;
- lstats[i].ndalloc += arena->stats.lstats[i].ndalloc;
- lstats[i].nrequests += arena->stats.lstats[i].nrequests;
- lstats[i].curruns += arena->stats.lstats[i].curruns;
- }
- malloc_mutex_unlock(&arena->lock);
-
- for (i = 0; i < NBINS; i++) {
- arena_bin_t *bin = &arena->bins[i];
-
- malloc_mutex_lock(&bin->lock);
- bstats[i].allocated += bin->stats.allocated;
- bstats[i].nmalloc += bin->stats.nmalloc;
- bstats[i].ndalloc += bin->stats.ndalloc;
- bstats[i].nrequests += bin->stats.nrequests;
- if (config_tcache) {
- bstats[i].nfills += bin->stats.nfills;
- bstats[i].nflushes += bin->stats.nflushes;
- }
- bstats[i].nruns += bin->stats.nruns;
- bstats[i].reruns += bin->stats.reruns;
- bstats[i].curruns += bin->stats.curruns;
- malloc_mutex_unlock(&bin->lock);
- }
-}
-
-bool
-arena_new(arena_t *arena, unsigned ind)
-{
- unsigned i;
- arena_bin_t *bin;
-
- arena->ind = ind;
- arena->nthreads = 0;
-
- if (malloc_mutex_init(&arena->lock))
- return (true);
-
- if (config_stats) {
- memset(&arena->stats, 0, sizeof(arena_stats_t));
- arena->stats.lstats =
- (malloc_large_stats_t *)base_alloc(nlclasses *
- sizeof(malloc_large_stats_t));
- if (arena->stats.lstats == NULL)
- return (true);
- memset(arena->stats.lstats, 0, nlclasses *
- sizeof(malloc_large_stats_t));
- if (config_tcache)
- ql_new(&arena->tcache_ql);
- }
-
- if (config_prof)
- arena->prof_accumbytes = 0;
-
- arena->dss_prec = chunk_dss_prec_get();
-
- /* Initialize chunks. */
- arena_chunk_dirty_new(&arena->chunks_dirty);
- arena->spare = NULL;
-
- arena->nactive = 0;
- arena->ndirty = 0;
- arena->npurgatory = 0;
-
- arena_avail_tree_new(&arena->runs_avail);
-
- /* Initialize bins. */
- for (i = 0; i < NBINS; i++) {
- bin = &arena->bins[i];
- if (malloc_mutex_init(&bin->lock))
- return (true);
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
- if (config_stats)
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
- }
-
- return (false);
-}
-
-/*
- * Calculate bin_info->run_size such that it meets the following constraints:
- *
- * *) bin_info->run_size >= min_run_size
- * *) bin_info->run_size <= arena_maxclass
- * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
- * *) bin_info->nregs <= RUN_MAXREGS
- *
- * bin_info->nregs, bin_info->bitmap_offset, and bin_info->reg0_offset are also
- * calculated here, since these settings are all interdependent.
- */
-static size_t
-bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size)
-{
- size_t pad_size;
- size_t try_run_size, good_run_size;
- uint32_t try_nregs, good_nregs;
- uint32_t try_hdr_size, good_hdr_size;
- uint32_t try_bitmap_offset, good_bitmap_offset;
- uint32_t try_ctx0_offset, good_ctx0_offset;
- uint32_t try_redzone0_offset, good_redzone0_offset;
-
- assert(min_run_size >= PAGE);
- assert(min_run_size <= arena_maxclass);
-
- /*
- * Determine redzone size based on minimum alignment and minimum
- * redzone size. Add padding to the end of the run if it is needed to
- * align the regions. The padding allows each redzone to be half the
- * minimum alignment; without the padding, each redzone would have to
- * be twice as large in order to maintain alignment.
- */
- if (config_fill && opt_redzone) {
- size_t align_min = ZU(1) << (ffs(bin_info->reg_size) - 1);
- if (align_min <= REDZONE_MINSIZE) {
- bin_info->redzone_size = REDZONE_MINSIZE;
- pad_size = 0;
- } else {
- bin_info->redzone_size = align_min >> 1;
- pad_size = bin_info->redzone_size;
- }
- } else {
- bin_info->redzone_size = 0;
- pad_size = 0;
- }
- bin_info->reg_interval = bin_info->reg_size +
- (bin_info->redzone_size << 1);
-
- /*
- * Calculate known-valid settings before entering the run_size
- * expansion loop, so that the first part of the loop always copies
- * valid settings.
- *
- * The do..while loop iteratively reduces the number of regions until
- * the run header and the regions no longer overlap. A closed formula
- * would be quite messy, since there is an interdependency between the
- * header's mask length and the number of regions.
- */
- try_run_size = min_run_size;
- try_nregs = ((try_run_size - sizeof(arena_run_t)) /
- bin_info->reg_interval)
- + 1; /* Counter-act try_nregs-- in loop. */
- if (try_nregs > RUN_MAXREGS) {
- try_nregs = RUN_MAXREGS
- + 1; /* Counter-act try_nregs-- in loop. */
- }
- do {
- try_nregs--;
- try_hdr_size = sizeof(arena_run_t);
- /* Pad to a long boundary. */
- try_hdr_size = LONG_CEILING(try_hdr_size);
- try_bitmap_offset = try_hdr_size;
- /* Add space for bitmap. */
- try_hdr_size += bitmap_size(try_nregs);
- if (config_prof && opt_prof && prof_promote == false) {
- /* Pad to a quantum boundary. */
- try_hdr_size = QUANTUM_CEILING(try_hdr_size);
- try_ctx0_offset = try_hdr_size;
- /* Add space for one (prof_ctx_t *) per region. */
- try_hdr_size += try_nregs * sizeof(prof_ctx_t *);
- } else
- try_ctx0_offset = 0;
- try_redzone0_offset = try_run_size - (try_nregs *
- bin_info->reg_interval) - pad_size;
- } while (try_hdr_size > try_redzone0_offset);
-
- /* run_size expansion loop. */
- do {
- /*
- * Copy valid settings before trying more aggressive settings.
- */
- good_run_size = try_run_size;
- good_nregs = try_nregs;
- good_hdr_size = try_hdr_size;
- good_bitmap_offset = try_bitmap_offset;
- good_ctx0_offset = try_ctx0_offset;
- good_redzone0_offset = try_redzone0_offset;
-
- /* Try more aggressive settings. */
- try_run_size += PAGE;
- try_nregs = ((try_run_size - sizeof(arena_run_t) - pad_size) /
- bin_info->reg_interval)
- + 1; /* Counter-act try_nregs-- in loop. */
- if (try_nregs > RUN_MAXREGS) {
- try_nregs = RUN_MAXREGS
- + 1; /* Counter-act try_nregs-- in loop. */
- }
- do {
- try_nregs--;
- try_hdr_size = sizeof(arena_run_t);
- /* Pad to a long boundary. */
- try_hdr_size = LONG_CEILING(try_hdr_size);
- try_bitmap_offset = try_hdr_size;
- /* Add space for bitmap. */
- try_hdr_size += bitmap_size(try_nregs);
- if (config_prof && opt_prof && prof_promote == false) {
- /* Pad to a quantum boundary. */
- try_hdr_size = QUANTUM_CEILING(try_hdr_size);
- try_ctx0_offset = try_hdr_size;
- /*
- * Add space for one (prof_ctx_t *) per region.
- */
- try_hdr_size += try_nregs *
- sizeof(prof_ctx_t *);
- }
- try_redzone0_offset = try_run_size - (try_nregs *
- bin_info->reg_interval) - pad_size;
- } while (try_hdr_size > try_redzone0_offset);
- } while (try_run_size <= arena_maxclass
- && try_run_size <= arena_maxclass
- && RUN_MAX_OVRHD * (bin_info->reg_interval << 3) >
- RUN_MAX_OVRHD_RELAX
- && (try_redzone0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size
- && try_nregs < RUN_MAXREGS);
-
- assert(good_hdr_size <= good_redzone0_offset);
-
- /* Copy final settings. */
- bin_info->run_size = good_run_size;
- bin_info->nregs = good_nregs;
- bin_info->bitmap_offset = good_bitmap_offset;
- bin_info->ctx0_offset = good_ctx0_offset;
- bin_info->reg0_offset = good_redzone0_offset + bin_info->redzone_size;
-
- assert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs
- * bin_info->reg_interval) + pad_size == bin_info->run_size);
-
- return (good_run_size);
-}
-
-static void
-bin_info_init(void)
-{
- arena_bin_info_t *bin_info;
- size_t prev_run_size = PAGE;
-
-#define SIZE_CLASS(bin, delta, size) \
- bin_info = &arena_bin_info[bin]; \
- bin_info->reg_size = size; \
- prev_run_size = bin_info_run_size_calc(bin_info, prev_run_size);\
- bitmap_info_init(&bin_info->bitmap_info, bin_info->nregs);
- SIZE_CLASSES
-#undef SIZE_CLASS
-}
-
-void
-arena_boot(void)
-{
- size_t header_size;
- unsigned i;
-
- /*
- * Compute the header size such that it is large enough to contain the
- * page map. The page map is biased to omit entries for the header
- * itself, so some iteration is necessary to compute the map bias.
- *
- * 1) Compute safe header_size and map_bias values that include enough
- * space for an unbiased page map.
- * 2) Refine map_bias based on (1) to omit the header pages in the page
- * map. The resulting map_bias may be one too small.
- * 3) Refine map_bias based on (2). The result will be >= the result
- * from (2), and will always be correct.
- */
- map_bias = 0;
- for (i = 0; i < 3; i++) {
- header_size = offsetof(arena_chunk_t, map) +
- (sizeof(arena_chunk_map_t) * (chunk_npages-map_bias));
- map_bias = (header_size >> LG_PAGE) + ((header_size & PAGE_MASK)
- != 0);
- }
- assert(map_bias > 0);
-
- arena_maxclass = chunksize - (map_bias << LG_PAGE);
-
- bin_info_init();
-}
-
-void
-arena_prefork(arena_t *arena)
-{
- unsigned i;
-
- malloc_mutex_prefork(&arena->lock);
- for (i = 0; i < NBINS; i++)
- malloc_mutex_prefork(&arena->bins[i].lock);
-}
-
-void
-arena_postfork_parent(arena_t *arena)
-{
- unsigned i;
-
- for (i = 0; i < NBINS; i++)
- malloc_mutex_postfork_parent(&arena->bins[i].lock);
- malloc_mutex_postfork_parent(&arena->lock);
-}
-
-void
-arena_postfork_child(arena_t *arena)
-{
- unsigned i;
-
- for (i = 0; i < NBINS; i++)
- malloc_mutex_postfork_child(&arena->bins[i].lock);
- malloc_mutex_postfork_child(&arena->lock);
-}
diff --git a/extra/jemalloc/src/atomic.c b/extra/jemalloc/src/atomic.c
deleted file mode 100644
index 77ee313113b..00000000000
--- a/extra/jemalloc/src/atomic.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define JEMALLOC_ATOMIC_C_
-#include "jemalloc/internal/jemalloc_internal.h"
diff --git a/extra/jemalloc/src/base.c b/extra/jemalloc/src/base.c
deleted file mode 100644
index 4e62e8fa918..00000000000
--- a/extra/jemalloc/src/base.c
+++ /dev/null
@@ -1,142 +0,0 @@
-#define JEMALLOC_BASE_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Data. */
-
-static malloc_mutex_t base_mtx;
-
-/*
- * Current pages that are being used for internal memory allocations. These
- * pages are carved up in cacheline-size quanta, so that there is no chance of
- * false cache line sharing.
- */
-static void *base_pages;
-static void *base_next_addr;
-static void *base_past_addr; /* Addr immediately past base_pages. */
-static extent_node_t *base_nodes;
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static bool base_pages_alloc(size_t minsize);
-
-/******************************************************************************/
-
-static bool
-base_pages_alloc(size_t minsize)
-{
- size_t csize;
- bool zero;
-
- assert(minsize != 0);
- csize = CHUNK_CEILING(minsize);
- zero = false;
- base_pages = chunk_alloc(csize, chunksize, true, &zero,
- chunk_dss_prec_get());
- if (base_pages == NULL)
- return (true);
- base_next_addr = base_pages;
- base_past_addr = (void *)((uintptr_t)base_pages + csize);
-
- return (false);
-}
-
-void *
-base_alloc(size_t size)
-{
- void *ret;
- size_t csize;
-
- /* Round size up to nearest multiple of the cacheline size. */
- csize = CACHELINE_CEILING(size);
-
- malloc_mutex_lock(&base_mtx);
- /* Make sure there's enough space for the allocation. */
- if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {
- if (base_pages_alloc(csize)) {
- malloc_mutex_unlock(&base_mtx);
- return (NULL);
- }
- }
- /* Allocate. */
- ret = base_next_addr;
- base_next_addr = (void *)((uintptr_t)base_next_addr + csize);
- malloc_mutex_unlock(&base_mtx);
- VALGRIND_MAKE_MEM_UNDEFINED(ret, csize);
-
- return (ret);
-}
-
-void *
-base_calloc(size_t number, size_t size)
-{
- void *ret = base_alloc(number * size);
-
- if (ret != NULL)
- memset(ret, 0, number * size);
-
- return (ret);
-}
-
-extent_node_t *
-base_node_alloc(void)
-{
- extent_node_t *ret;
-
- malloc_mutex_lock(&base_mtx);
- if (base_nodes != NULL) {
- ret = base_nodes;
- base_nodes = *(extent_node_t **)ret;
- malloc_mutex_unlock(&base_mtx);
- VALGRIND_MAKE_MEM_UNDEFINED(ret, sizeof(extent_node_t));
- } else {
- malloc_mutex_unlock(&base_mtx);
- ret = (extent_node_t *)base_alloc(sizeof(extent_node_t));
- }
-
- return (ret);
-}
-
-void
-base_node_dealloc(extent_node_t *node)
-{
-
- VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));
- malloc_mutex_lock(&base_mtx);
- *(extent_node_t **)node = base_nodes;
- base_nodes = node;
- malloc_mutex_unlock(&base_mtx);
-}
-
-bool
-base_boot(void)
-{
-
- base_nodes = NULL;
- if (malloc_mutex_init(&base_mtx))
- return (true);
-
- return (false);
-}
-
-void
-base_prefork(void)
-{
-
- malloc_mutex_prefork(&base_mtx);
-}
-
-void
-base_postfork_parent(void)
-{
-
- malloc_mutex_postfork_parent(&base_mtx);
-}
-
-void
-base_postfork_child(void)
-{
-
- malloc_mutex_postfork_child(&base_mtx);
-}
diff --git a/extra/jemalloc/src/bitmap.c b/extra/jemalloc/src/bitmap.c
deleted file mode 100644
index b47e2629093..00000000000
--- a/extra/jemalloc/src/bitmap.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#define JEMALLOC_BITMAP_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static size_t bits2groups(size_t nbits);
-
-/******************************************************************************/
-
-static size_t
-bits2groups(size_t nbits)
-{
-
- return ((nbits >> LG_BITMAP_GROUP_NBITS) +
- !!(nbits & BITMAP_GROUP_NBITS_MASK));
-}
-
-void
-bitmap_info_init(bitmap_info_t *binfo, size_t nbits)
-{
- unsigned i;
- size_t group_count;
-
- assert(nbits > 0);
- assert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS));
-
- /*
- * Compute the number of groups necessary to store nbits bits, and
- * progressively work upward through the levels until reaching a level
- * that requires only one group.
- */
- binfo->levels[0].group_offset = 0;
- group_count = bits2groups(nbits);
- for (i = 1; group_count > 1; i++) {
- assert(i < BITMAP_MAX_LEVELS);
- binfo->levels[i].group_offset = binfo->levels[i-1].group_offset
- + group_count;
- group_count = bits2groups(group_count);
- }
- binfo->levels[i].group_offset = binfo->levels[i-1].group_offset
- + group_count;
- binfo->nlevels = i;
- binfo->nbits = nbits;
-}
-
-size_t
-bitmap_info_ngroups(const bitmap_info_t *binfo)
-{
-
- return (binfo->levels[binfo->nlevels].group_offset << LG_SIZEOF_BITMAP);
-}
-
-size_t
-bitmap_size(size_t nbits)
-{
- bitmap_info_t binfo;
-
- bitmap_info_init(&binfo, nbits);
- return (bitmap_info_ngroups(&binfo));
-}
-
-void
-bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo)
-{
- size_t extra;
- unsigned i;
-
- /*
- * Bits are actually inverted with regard to the external bitmap
- * interface, so the bitmap starts out with all 1 bits, except for
- * trailing unused bits (if any). Note that each group uses bit 0 to
- * correspond to the first logical bit in the group, so extra bits
- * are the most significant bits of the last group.
- */
- memset(bitmap, 0xffU, binfo->levels[binfo->nlevels].group_offset <<
- LG_SIZEOF_BITMAP);
- extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK))
- & BITMAP_GROUP_NBITS_MASK;
- if (extra != 0)
- bitmap[binfo->levels[1].group_offset - 1] >>= extra;
- for (i = 1; i < binfo->nlevels; i++) {
- size_t group_count = binfo->levels[i].group_offset -
- binfo->levels[i-1].group_offset;
- extra = (BITMAP_GROUP_NBITS - (group_count &
- BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK;
- if (extra != 0)
- bitmap[binfo->levels[i+1].group_offset - 1] >>= extra;
- }
-}
diff --git a/extra/jemalloc/src/chunk.c b/extra/jemalloc/src/chunk.c
deleted file mode 100644
index 044f76be96c..00000000000
--- a/extra/jemalloc/src/chunk.c
+++ /dev/null
@@ -1,385 +0,0 @@
-#define JEMALLOC_CHUNK_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Data. */
-
-const char *opt_dss = DSS_DEFAULT;
-size_t opt_lg_chunk = LG_CHUNK_DEFAULT;
-
-malloc_mutex_t chunks_mtx;
-chunk_stats_t stats_chunks;
-
-/*
- * Trees of chunks that were previously allocated (trees differ only in node
- * ordering). These are used when allocating chunks, in an attempt to re-use
- * address space. Depending on function, different tree orderings are needed,
- * which is why there are two trees with the same contents.
- */
-static extent_tree_t chunks_szad_mmap;
-static extent_tree_t chunks_ad_mmap;
-static extent_tree_t chunks_szad_dss;
-static extent_tree_t chunks_ad_dss;
-
-rtree_t *chunks_rtree;
-
-/* Various chunk-related settings. */
-size_t chunksize;
-size_t chunksize_mask; /* (chunksize - 1). */
-size_t chunk_npages;
-size_t map_bias;
-size_t arena_maxclass; /* Max size class for arenas. */
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static void *chunk_recycle(extent_tree_t *chunks_szad,
- extent_tree_t *chunks_ad, size_t size, size_t alignment, bool base,
- bool *zero);
-static void chunk_record(extent_tree_t *chunks_szad,
- extent_tree_t *chunks_ad, void *chunk, size_t size);
-
-/******************************************************************************/
-
-static void *
-chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size,
- size_t alignment, bool base, bool *zero)
-{
- void *ret;
- extent_node_t *node;
- extent_node_t key;
- size_t alloc_size, leadsize, trailsize;
- bool zeroed;
-
- if (base) {
- /*
- * This function may need to call base_node_{,de}alloc(), but
- * the current chunk allocation request is on behalf of the
- * base allocator. Avoid deadlock (and if that weren't an
- * issue, potential for infinite recursion) by returning NULL.
- */
- return (NULL);
- }
-
- alloc_size = size + alignment - chunksize;
- /* Beware size_t wrap-around. */
- if (alloc_size < size)
- return (NULL);
- key.addr = NULL;
- key.size = alloc_size;
- malloc_mutex_lock(&chunks_mtx);
- node = extent_tree_szad_nsearch(chunks_szad, &key);
- if (node == NULL) {
- malloc_mutex_unlock(&chunks_mtx);
- return (NULL);
- }
- leadsize = ALIGNMENT_CEILING((uintptr_t)node->addr, alignment) -
- (uintptr_t)node->addr;
- assert(node->size >= leadsize + size);
- trailsize = node->size - leadsize - size;
- ret = (void *)((uintptr_t)node->addr + leadsize);
- zeroed = node->zeroed;
- if (zeroed)
- *zero = true;
- /* Remove node from the tree. */
- extent_tree_szad_remove(chunks_szad, node);
- extent_tree_ad_remove(chunks_ad, node);
- if (leadsize != 0) {
- /* Insert the leading space as a smaller chunk. */
- node->size = leadsize;
- extent_tree_szad_insert(chunks_szad, node);
- extent_tree_ad_insert(chunks_ad, node);
- node = NULL;
- }
- if (trailsize != 0) {
- /* Insert the trailing space as a smaller chunk. */
- if (node == NULL) {
- /*
- * An additional node is required, but
- * base_node_alloc() can cause a new base chunk to be
- * allocated. Drop chunks_mtx in order to avoid
- * deadlock, and if node allocation fails, deallocate
- * the result before returning an error.
- */
- malloc_mutex_unlock(&chunks_mtx);
- node = base_node_alloc();
- if (node == NULL) {
- chunk_dealloc(ret, size, true);
- return (NULL);
- }
- malloc_mutex_lock(&chunks_mtx);
- }
- node->addr = (void *)((uintptr_t)(ret) + size);
- node->size = trailsize;
- node->zeroed = zeroed;
- extent_tree_szad_insert(chunks_szad, node);
- extent_tree_ad_insert(chunks_ad, node);
- node = NULL;
- }
- malloc_mutex_unlock(&chunks_mtx);
-
- if (node != NULL)
- base_node_dealloc(node);
- if (*zero) {
- if (zeroed == false)
- memset(ret, 0, size);
- else if (config_debug) {
- size_t i;
- size_t *p = (size_t *)(uintptr_t)ret;
-
- VALGRIND_MAKE_MEM_DEFINED(ret, size);
- for (i = 0; i < size / sizeof(size_t); i++)
- assert(p[i] == 0);
- }
- }
- return (ret);
-}
-
-/*
- * If the caller specifies (*zero == false), it is still possible to receive
- * zeroed memory, in which case *zero is toggled to true. arena_chunk_alloc()
- * takes advantage of this to avoid demanding zeroed chunks, but taking
- * advantage of them if they are returned.
- */
-void *
-chunk_alloc(size_t size, size_t alignment, bool base, bool *zero,
- dss_prec_t dss_prec)
-{
- void *ret;
-
- assert(size != 0);
- assert((size & chunksize_mask) == 0);
- assert(alignment != 0);
- assert((alignment & chunksize_mask) == 0);
-
- /* "primary" dss. */
- if (config_dss && dss_prec == dss_prec_primary) {
- if ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size,
- alignment, base, zero)) != NULL)
- goto label_return;
- if ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL)
- goto label_return;
- }
- /* mmap. */
- if ((ret = chunk_recycle(&chunks_szad_mmap, &chunks_ad_mmap, size,
- alignment, base, zero)) != NULL)
- goto label_return;
- if ((ret = chunk_alloc_mmap(size, alignment, zero)) != NULL)
- goto label_return;
- /* "secondary" dss. */
- if (config_dss && dss_prec == dss_prec_secondary) {
- if ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size,
- alignment, base, zero)) != NULL)
- goto label_return;
- if ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL)
- goto label_return;
- }
-
- /* All strategies for allocation failed. */
- ret = NULL;
-label_return:
- if (ret != NULL) {
- if (config_ivsalloc && base == false) {
- if (rtree_set(chunks_rtree, (uintptr_t)ret, ret)) {
- chunk_dealloc(ret, size, true);
- return (NULL);
- }
- }
- if (config_stats || config_prof) {
- bool gdump;
- malloc_mutex_lock(&chunks_mtx);
- if (config_stats)
- stats_chunks.nchunks += (size / chunksize);
- stats_chunks.curchunks += (size / chunksize);
- if (stats_chunks.curchunks > stats_chunks.highchunks) {
- stats_chunks.highchunks =
- stats_chunks.curchunks;
- if (config_prof)
- gdump = true;
- } else if (config_prof)
- gdump = false;
- malloc_mutex_unlock(&chunks_mtx);
- if (config_prof && opt_prof && opt_prof_gdump && gdump)
- prof_gdump();
- }
- if (config_valgrind)
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- }
- assert(CHUNK_ADDR2BASE(ret) == ret);
- return (ret);
-}
-
-static void
-chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk,
- size_t size)
-{
- bool unzeroed;
- extent_node_t *xnode, *node, *prev, key;
-
- unzeroed = pages_purge(chunk, size);
- VALGRIND_MAKE_MEM_NOACCESS(chunk, size);
-
- /*
- * Allocate a node before acquiring chunks_mtx even though it might not
- * be needed, because base_node_alloc() may cause a new base chunk to
- * be allocated, which could cause deadlock if chunks_mtx were already
- * held.
- */
- xnode = base_node_alloc();
-
- malloc_mutex_lock(&chunks_mtx);
- key.addr = (void *)((uintptr_t)chunk + size);
- node = extent_tree_ad_nsearch(chunks_ad, &key);
- /* Try to coalesce forward. */
- if (node != NULL && node->addr == key.addr) {
- /*
- * Coalesce chunk with the following address range. This does
- * not change the position within chunks_ad, so only
- * remove/insert from/into chunks_szad.
- */
- extent_tree_szad_remove(chunks_szad, node);
- node->addr = chunk;
- node->size += size;
- node->zeroed = (node->zeroed && (unzeroed == false));
- extent_tree_szad_insert(chunks_szad, node);
- if (xnode != NULL)
- base_node_dealloc(xnode);
- } else {
- /* Coalescing forward failed, so insert a new node. */
- if (xnode == NULL) {
- /*
- * base_node_alloc() failed, which is an exceedingly
- * unlikely failure. Leak chunk; its pages have
- * already been purged, so this is only a virtual
- * memory leak.
- */
- malloc_mutex_unlock(&chunks_mtx);
- return;
- }
- node = xnode;
- node->addr = chunk;
- node->size = size;
- node->zeroed = (unzeroed == false);
- extent_tree_ad_insert(chunks_ad, node);
- extent_tree_szad_insert(chunks_szad, node);
- }
-
- /* Try to coalesce backward. */
- prev = extent_tree_ad_prev(chunks_ad, node);
- if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) ==
- chunk) {
- /*
- * Coalesce chunk with the previous address range. This does
- * not change the position within chunks_ad, so only
- * remove/insert node from/into chunks_szad.
- */
- extent_tree_szad_remove(chunks_szad, prev);
- extent_tree_ad_remove(chunks_ad, prev);
-
- extent_tree_szad_remove(chunks_szad, node);
- node->addr = prev->addr;
- node->size += prev->size;
- node->zeroed = (node->zeroed && prev->zeroed);
- extent_tree_szad_insert(chunks_szad, node);
-
- base_node_dealloc(prev);
- }
- malloc_mutex_unlock(&chunks_mtx);
-}
-
-void
-chunk_unmap(void *chunk, size_t size)
-{
- assert(chunk != NULL);
- assert(CHUNK_ADDR2BASE(chunk) == chunk);
- assert(size != 0);
- assert((size & chunksize_mask) == 0);
-
- if (config_dss && chunk_in_dss(chunk))
- chunk_record(&chunks_szad_dss, &chunks_ad_dss, chunk, size);
- else if (chunk_dealloc_mmap(chunk, size))
- chunk_record(&chunks_szad_mmap, &chunks_ad_mmap, chunk, size);
-}
-
-void
-chunk_dealloc(void *chunk, size_t size, bool unmap)
-{
-
- assert(chunk != NULL);
- assert(CHUNK_ADDR2BASE(chunk) == chunk);
- assert(size != 0);
- assert((size & chunksize_mask) == 0);
-
- if (config_ivsalloc)
- rtree_set(chunks_rtree, (uintptr_t)chunk, NULL);
- if (config_stats || config_prof) {
- malloc_mutex_lock(&chunks_mtx);
- assert(stats_chunks.curchunks >= (size / chunksize));
- stats_chunks.curchunks -= (size / chunksize);
- malloc_mutex_unlock(&chunks_mtx);
- }
-
- if (unmap)
- chunk_unmap(chunk, size);
-}
-
-bool
-chunk_boot(void)
-{
-
- /* Set variables according to the value of opt_lg_chunk. */
- chunksize = (ZU(1) << opt_lg_chunk);
- assert(chunksize >= PAGE);
- chunksize_mask = chunksize - 1;
- chunk_npages = (chunksize >> LG_PAGE);
-
- if (config_stats || config_prof) {
- if (malloc_mutex_init(&chunks_mtx))
- return (true);
- memset(&stats_chunks, 0, sizeof(chunk_stats_t));
- }
- if (config_dss && chunk_dss_boot())
- return (true);
- extent_tree_szad_new(&chunks_szad_mmap);
- extent_tree_ad_new(&chunks_ad_mmap);
- extent_tree_szad_new(&chunks_szad_dss);
- extent_tree_ad_new(&chunks_ad_dss);
- if (config_ivsalloc) {
- chunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) -
- opt_lg_chunk);
- if (chunks_rtree == NULL)
- return (true);
- }
-
- return (false);
-}
-
-void
-chunk_prefork(void)
-{
-
- malloc_mutex_lock(&chunks_mtx);
- if (config_ivsalloc)
- rtree_prefork(chunks_rtree);
- chunk_dss_prefork();
-}
-
-void
-chunk_postfork_parent(void)
-{
-
- chunk_dss_postfork_parent();
- if (config_ivsalloc)
- rtree_postfork_parent(chunks_rtree);
- malloc_mutex_postfork_parent(&chunks_mtx);
-}
-
-void
-chunk_postfork_child(void)
-{
-
- chunk_dss_postfork_child();
- if (config_ivsalloc)
- rtree_postfork_child(chunks_rtree);
- malloc_mutex_postfork_child(&chunks_mtx);
-}
diff --git a/extra/jemalloc/src/chunk_dss.c b/extra/jemalloc/src/chunk_dss.c
deleted file mode 100644
index 24781cc52dc..00000000000
--- a/extra/jemalloc/src/chunk_dss.c
+++ /dev/null
@@ -1,197 +0,0 @@
-#define JEMALLOC_CHUNK_DSS_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-/******************************************************************************/
-/* Data. */
-
-const char *dss_prec_names[] = {
- "disabled",
- "primary",
- "secondary",
- "N/A"
-};
-
-/* Current dss precedence default, used when creating new arenas. */
-static dss_prec_t dss_prec_default = DSS_PREC_DEFAULT;
-
-/*
- * Protects sbrk() calls. This avoids malloc races among threads, though it
- * does not protect against races with threads that call sbrk() directly.
- */
-static malloc_mutex_t dss_mtx;
-
-/* Base address of the DSS. */
-static void *dss_base;
-/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */
-static void *dss_prev;
-/* Current upper limit on DSS addresses. */
-static void *dss_max;
-
-/******************************************************************************/
-
-#ifndef JEMALLOC_HAVE_SBRK
-static void *
-sbrk(intptr_t increment)
-{
-
- not_implemented();
-
- return (NULL);
-}
-#endif
-
-dss_prec_t
-chunk_dss_prec_get(void)
-{
- dss_prec_t ret;
-
- if (config_dss == false)
- return (dss_prec_disabled);
- malloc_mutex_lock(&dss_mtx);
- ret = dss_prec_default;
- malloc_mutex_unlock(&dss_mtx);
- return (ret);
-}
-
-bool
-chunk_dss_prec_set(dss_prec_t dss_prec)
-{
-
- if (config_dss == false)
- return (true);
- malloc_mutex_lock(&dss_mtx);
- dss_prec_default = dss_prec;
- malloc_mutex_unlock(&dss_mtx);
- return (false);
-}
-
-void *
-chunk_alloc_dss(size_t size, size_t alignment, bool *zero)
-{
- void *ret;
-
- cassert(config_dss);
- assert(size > 0 && (size & chunksize_mask) == 0);
- assert(alignment > 0 && (alignment & chunksize_mask) == 0);
-
- /*
- * sbrk() uses a signed increment argument, so take care not to
- * interpret a huge allocation request as a negative increment.
- */
- if ((intptr_t)size < 0)
- return (NULL);
-
- malloc_mutex_lock(&dss_mtx);
- if (dss_prev != (void *)-1) {
- size_t gap_size, cpad_size;
- void *cpad, *dss_next;
- intptr_t incr;
-
- /*
- * The loop is necessary to recover from races with other
- * threads that are using the DSS for something other than
- * malloc.
- */
- do {
- /* Get the current end of the DSS. */
- dss_max = sbrk(0);
- /*
- * Calculate how much padding is necessary to
- * chunk-align the end of the DSS.
- */
- gap_size = (chunksize - CHUNK_ADDR2OFFSET(dss_max)) &
- chunksize_mask;
- /*
- * Compute how much chunk-aligned pad space (if any) is
- * necessary to satisfy alignment. This space can be
- * recycled for later use.
- */
- cpad = (void *)((uintptr_t)dss_max + gap_size);
- ret = (void *)ALIGNMENT_CEILING((uintptr_t)dss_max,
- alignment);
- cpad_size = (uintptr_t)ret - (uintptr_t)cpad;
- dss_next = (void *)((uintptr_t)ret + size);
- if ((uintptr_t)ret < (uintptr_t)dss_max ||
- (uintptr_t)dss_next < (uintptr_t)dss_max) {
- /* Wrap-around. */
- malloc_mutex_unlock(&dss_mtx);
- return (NULL);
- }
- incr = gap_size + cpad_size + size;
- dss_prev = sbrk(incr);
- if (dss_prev == dss_max) {
- /* Success. */
- dss_max = dss_next;
- malloc_mutex_unlock(&dss_mtx);
- if (cpad_size != 0)
- chunk_unmap(cpad, cpad_size);
- if (*zero) {
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- memset(ret, 0, size);
- }
- return (ret);
- }
- } while (dss_prev != (void *)-1);
- }
- malloc_mutex_unlock(&dss_mtx);
-
- return (NULL);
-}
-
-bool
-chunk_in_dss(void *chunk)
-{
- bool ret;
-
- cassert(config_dss);
-
- malloc_mutex_lock(&dss_mtx);
- if ((uintptr_t)chunk >= (uintptr_t)dss_base
- && (uintptr_t)chunk < (uintptr_t)dss_max)
- ret = true;
- else
- ret = false;
- malloc_mutex_unlock(&dss_mtx);
-
- return (ret);
-}
-
-bool
-chunk_dss_boot(void)
-{
-
- cassert(config_dss);
-
- if (malloc_mutex_init(&dss_mtx))
- return (true);
- dss_base = sbrk(0);
- dss_prev = dss_base;
- dss_max = dss_base;
-
- return (false);
-}
-
-void
-chunk_dss_prefork(void)
-{
-
- if (config_dss)
- malloc_mutex_prefork(&dss_mtx);
-}
-
-void
-chunk_dss_postfork_parent(void)
-{
-
- if (config_dss)
- malloc_mutex_postfork_parent(&dss_mtx);
-}
-
-void
-chunk_dss_postfork_child(void)
-{
-
- if (config_dss)
- malloc_mutex_postfork_child(&dss_mtx);
-}
-
-/******************************************************************************/
diff --git a/extra/jemalloc/src/chunk_mmap.c b/extra/jemalloc/src/chunk_mmap.c
deleted file mode 100644
index 8a42e75915f..00000000000
--- a/extra/jemalloc/src/chunk_mmap.c
+++ /dev/null
@@ -1,210 +0,0 @@
-#define JEMALLOC_CHUNK_MMAP_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static void *pages_map(void *addr, size_t size);
-static void pages_unmap(void *addr, size_t size);
-static void *chunk_alloc_mmap_slow(size_t size, size_t alignment,
- bool *zero);
-
-/******************************************************************************/
-
-static void *
-pages_map(void *addr, size_t size)
-{
- void *ret;
-
- assert(size != 0);
-
-#ifdef _WIN32
- /*
- * If VirtualAlloc can't allocate at the given address when one is
- * given, it fails and returns NULL.
- */
- ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,
- PAGE_READWRITE);
-#else
- /*
- * We don't use MAP_FIXED here, because it can cause the *replacement*
- * of existing mappings, and we only want to create new mappings.
- */
- ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
- -1, 0);
- assert(ret != NULL);
-
- if (ret == MAP_FAILED)
- ret = NULL;
- else if (addr != NULL && ret != addr) {
- /*
- * We succeeded in mapping memory, but not in the right place.
- */
- if (munmap(ret, size) == -1) {
- char buf[BUFERROR_BUF];
-
- buferror(buf, sizeof(buf));
- malloc_printf("<jemalloc: Error in munmap(): %s\n",
- buf);
- if (opt_abort)
- abort();
- }
- ret = NULL;
- }
-#endif
- assert(ret == NULL || (addr == NULL && ret != addr)
- || (addr != NULL && ret == addr));
- return (ret);
-}
-
-static void
-pages_unmap(void *addr, size_t size)
-{
-
-#ifdef _WIN32
- if (VirtualFree(addr, 0, MEM_RELEASE) == 0)
-#else
- if (munmap(addr, size) == -1)
-#endif
- {
- char buf[BUFERROR_BUF];
-
- buferror(buf, sizeof(buf));
- malloc_printf("<jemalloc>: Error in "
-#ifdef _WIN32
- "VirtualFree"
-#else
- "munmap"
-#endif
- "(): %s\n", buf);
- if (opt_abort)
- abort();
- }
-}
-
-static void *
-pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size)
-{
- void *ret = (void *)((uintptr_t)addr + leadsize);
-
- assert(alloc_size >= leadsize + size);
-#ifdef _WIN32
- {
- void *new_addr;
-
- pages_unmap(addr, alloc_size);
- new_addr = pages_map(ret, size);
- if (new_addr == ret)
- return (ret);
- if (new_addr)
- pages_unmap(new_addr, size);
- return (NULL);
- }
-#else
- {
- size_t trailsize = alloc_size - leadsize - size;
-
- if (leadsize != 0)
- pages_unmap(addr, leadsize);
- if (trailsize != 0)
- pages_unmap((void *)((uintptr_t)ret + size), trailsize);
- return (ret);
- }
-#endif
-}
-
-bool
-pages_purge(void *addr, size_t length)
-{
- bool unzeroed;
-
-#ifdef _WIN32
- VirtualAlloc(addr, length, MEM_RESET, PAGE_READWRITE);
- unzeroed = true;
-#else
-# ifdef JEMALLOC_PURGE_MADVISE_DONTNEED
-# define JEMALLOC_MADV_PURGE MADV_DONTNEED
-# define JEMALLOC_MADV_ZEROS true
-# elif defined(JEMALLOC_PURGE_MADVISE_FREE)
-# define JEMALLOC_MADV_PURGE MADV_FREE
-# define JEMALLOC_MADV_ZEROS false
-# else
-# error "No method defined for purging unused dirty pages."
-# endif
- int err = madvise(addr, length, JEMALLOC_MADV_PURGE);
- unzeroed = (JEMALLOC_MADV_ZEROS == false || err != 0);
-# undef JEMALLOC_MADV_PURGE
-# undef JEMALLOC_MADV_ZEROS
-#endif
- return (unzeroed);
-}
-
-static void *
-chunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero)
-{
- void *ret, *pages;
- size_t alloc_size, leadsize;
-
- alloc_size = size + alignment - PAGE;
- /* Beware size_t wrap-around. */
- if (alloc_size < size)
- return (NULL);
- do {
- pages = pages_map(NULL, alloc_size);
- if (pages == NULL)
- return (NULL);
- leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -
- (uintptr_t)pages;
- ret = pages_trim(pages, alloc_size, leadsize, size);
- } while (ret == NULL);
-
- assert(ret != NULL);
- *zero = true;
- return (ret);
-}
-
-void *
-chunk_alloc_mmap(size_t size, size_t alignment, bool *zero)
-{
- void *ret;
- size_t offset;
-
- /*
- * Ideally, there would be a way to specify alignment to mmap() (like
- * NetBSD has), but in the absence of such a feature, we have to work
- * hard to efficiently create aligned mappings. The reliable, but
- * slow method is to create a mapping that is over-sized, then trim the
- * excess. However, that always results in one or two calls to
- * pages_unmap().
- *
- * Optimistically try mapping precisely the right amount before falling
- * back to the slow method, with the expectation that the optimistic
- * approach works most of the time.
- */
-
- assert(alignment != 0);
- assert((alignment & chunksize_mask) == 0);
-
- ret = pages_map(NULL, size);
- if (ret == NULL)
- return (NULL);
- offset = ALIGNMENT_ADDR2OFFSET(ret, alignment);
- if (offset != 0) {
- pages_unmap(ret, size);
- return (chunk_alloc_mmap_slow(size, alignment, zero));
- }
-
- assert(ret != NULL);
- *zero = true;
- return (ret);
-}
-
-bool
-chunk_dealloc_mmap(void *chunk, size_t size)
-{
-
- if (config_munmap)
- pages_unmap(chunk, size);
-
- return (config_munmap == false);
-}
diff --git a/extra/jemalloc/src/ckh.c b/extra/jemalloc/src/ckh.c
deleted file mode 100644
index 2f38348bb85..00000000000
--- a/extra/jemalloc/src/ckh.c
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- *******************************************************************************
- * Implementation of (2^1+,2) cuckoo hashing, where 2^1+ indicates that each
- * hash bucket contains 2^n cells, for n >= 1, and 2 indicates that two hash
- * functions are employed. The original cuckoo hashing algorithm was described
- * in:
- *
- * Pagh, R., F.F. Rodler (2004) Cuckoo Hashing. Journal of Algorithms
- * 51(2):122-144.
- *
- * Generalization of cuckoo hashing was discussed in:
- *
- * Erlingsson, U., M. Manasse, F. McSherry (2006) A cool and practical
- * alternative to traditional hash tables. In Proceedings of the 7th
- * Workshop on Distributed Data and Structures (WDAS'06), Santa Clara, CA,
- * January 2006.
- *
- * This implementation uses precisely two hash functions because that is the
- * fewest that can work, and supporting multiple hashes is an implementation
- * burden. Here is a reproduction of Figure 1 from Erlingsson et al. (2006)
- * that shows approximate expected maximum load factors for various
- * configurations:
- *
- * | #cells/bucket |
- * #hashes | 1 | 2 | 4 | 8 |
- * --------+-------+-------+-------+-------+
- * 1 | 0.006 | 0.006 | 0.03 | 0.12 |
- * 2 | 0.49 | 0.86 |>0.93< |>0.96< |
- * 3 | 0.91 | 0.97 | 0.98 | 0.999 |
- * 4 | 0.97 | 0.99 | 0.999 | |
- *
- * The number of cells per bucket is chosen such that a bucket fits in one cache
- * line. So, on 32- and 64-bit systems, we use (8,2) and (4,2) cuckoo hashing,
- * respectively.
- *
- ******************************************************************************/
-#define JEMALLOC_CKH_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static bool ckh_grow(ckh_t *ckh);
-static void ckh_shrink(ckh_t *ckh);
-
-/******************************************************************************/
-
-/*
- * Search bucket for key and return the cell number if found; SIZE_T_MAX
- * otherwise.
- */
-JEMALLOC_INLINE size_t
-ckh_bucket_search(ckh_t *ckh, size_t bucket, const void *key)
-{
- ckhc_t *cell;
- unsigned i;
-
- for (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {
- cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];
- if (cell->key != NULL && ckh->keycomp(key, cell->key))
- return ((bucket << LG_CKH_BUCKET_CELLS) + i);
- }
-
- return (SIZE_T_MAX);
-}
-
-/*
- * Search table for key and return cell number if found; SIZE_T_MAX otherwise.
- */
-JEMALLOC_INLINE size_t
-ckh_isearch(ckh_t *ckh, const void *key)
-{
- size_t hashes[2], bucket, cell;
-
- assert(ckh != NULL);
-
- ckh->hash(key, hashes);
-
- /* Search primary bucket. */
- bucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);
- cell = ckh_bucket_search(ckh, bucket, key);
- if (cell != SIZE_T_MAX)
- return (cell);
-
- /* Search secondary bucket. */
- bucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);
- cell = ckh_bucket_search(ckh, bucket, key);
- return (cell);
-}
-
-JEMALLOC_INLINE bool
-ckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key,
- const void *data)
-{
- ckhc_t *cell;
- unsigned offset, i;
-
- /*
- * Cycle through the cells in the bucket, starting at a random position.
- * The randomness avoids worst-case search overhead as buckets fill up.
- */
- prng32(offset, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C);
- for (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) {
- cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) +
- ((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))];
- if (cell->key == NULL) {
- cell->key = key;
- cell->data = data;
- ckh->count++;
- return (false);
- }
- }
-
- return (true);
-}
-
-/*
- * No space is available in bucket. Randomly evict an item, then try to find an
- * alternate location for that item. Iteratively repeat this
- * eviction/relocation procedure until either success or detection of an
- * eviction/relocation bucket cycle.
- */
-JEMALLOC_INLINE bool
-ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,
- void const **argdata)
-{
- const void *key, *data, *tkey, *tdata;
- ckhc_t *cell;
- size_t hashes[2], bucket, tbucket;
- unsigned i;
-
- bucket = argbucket;
- key = *argkey;
- data = *argdata;
- while (true) {
- /*
- * Choose a random item within the bucket to evict. This is
- * critical to correct function, because without (eventually)
- * evicting all items within a bucket during iteration, it
- * would be possible to get stuck in an infinite loop if there
- * were an item for which both hashes indicated the same
- * bucket.
- */
- prng32(i, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C);
- cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i];
- assert(cell->key != NULL);
-
- /* Swap cell->{key,data} and {key,data} (evict). */
- tkey = cell->key; tdata = cell->data;
- cell->key = key; cell->data = data;
- key = tkey; data = tdata;
-
-#ifdef CKH_COUNT
- ckh->nrelocs++;
-#endif
-
- /* Find the alternate bucket for the evicted item. */
- ckh->hash(key, hashes);
- tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);
- if (tbucket == bucket) {
- tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets)
- - 1);
- /*
- * It may be that (tbucket == bucket) still, if the
- * item's hashes both indicate this bucket. However,
- * we are guaranteed to eventually escape this bucket
- * during iteration, assuming pseudo-random item
- * selection (true randomness would make infinite
- * looping a remote possibility). The reason we can
- * never get trapped forever is that there are two
- * cases:
- *
- * 1) This bucket == argbucket, so we will quickly
- * detect an eviction cycle and terminate.
- * 2) An item was evicted to this bucket from another,
- * which means that at least one item in this bucket
- * has hashes that indicate distinct buckets.
- */
- }
- /* Check for a cycle. */
- if (tbucket == argbucket) {
- *argkey = key;
- *argdata = data;
- return (true);
- }
-
- bucket = tbucket;
- if (ckh_try_bucket_insert(ckh, bucket, key, data) == false)
- return (false);
- }
-}
-
-JEMALLOC_INLINE bool
-ckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata)
-{
- size_t hashes[2], bucket;
- const void *key = *argkey;
- const void *data = *argdata;
-
- ckh->hash(key, hashes);
-
- /* Try to insert in primary bucket. */
- bucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);
- if (ckh_try_bucket_insert(ckh, bucket, key, data) == false)
- return (false);
-
- /* Try to insert in secondary bucket. */
- bucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);
- if (ckh_try_bucket_insert(ckh, bucket, key, data) == false)
- return (false);
-
- /*
- * Try to find a place for this item via iterative eviction/relocation.
- */
- return (ckh_evict_reloc_insert(ckh, bucket, argkey, argdata));
-}
-
-/*
- * Try to rebuild the hash table from scratch by inserting all items from the
- * old table into the new.
- */
-JEMALLOC_INLINE bool
-ckh_rebuild(ckh_t *ckh, ckhc_t *aTab)
-{
- size_t count, i, nins;
- const void *key, *data;
-
- count = ckh->count;
- ckh->count = 0;
- for (i = nins = 0; nins < count; i++) {
- if (aTab[i].key != NULL) {
- key = aTab[i].key;
- data = aTab[i].data;
- if (ckh_try_insert(ckh, &key, &data)) {
- ckh->count = count;
- return (true);
- }
- nins++;
- }
- }
-
- return (false);
-}
-
-static bool
-ckh_grow(ckh_t *ckh)
-{
- bool ret;
- ckhc_t *tab, *ttab;
- size_t lg_curcells;
- unsigned lg_prevbuckets;
-
-#ifdef CKH_COUNT
- ckh->ngrows++;
-#endif
-
- /*
- * It is possible (though unlikely, given well behaved hashes) that the
- * table will have to be doubled more than once in order to create a
- * usable table.
- */
- lg_prevbuckets = ckh->lg_curbuckets;
- lg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS;
- while (true) {
- size_t usize;
-
- lg_curcells++;
- usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);
- if (usize == 0) {
- ret = true;
- goto label_return;
- }
- tab = (ckhc_t *)ipalloc(usize, CACHELINE, true);
- if (tab == NULL) {
- ret = true;
- goto label_return;
- }
- /* Swap in new table. */
- ttab = ckh->tab;
- ckh->tab = tab;
- tab = ttab;
- ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;
-
- if (ckh_rebuild(ckh, tab) == false) {
- idalloc(tab);
- break;
- }
-
- /* Rebuilding failed, so back out partially rebuilt table. */
- idalloc(ckh->tab);
- ckh->tab = tab;
- ckh->lg_curbuckets = lg_prevbuckets;
- }
-
- ret = false;
-label_return:
- return (ret);
-}
-
-static void
-ckh_shrink(ckh_t *ckh)
-{
- ckhc_t *tab, *ttab;
- size_t lg_curcells, usize;
- unsigned lg_prevbuckets;
-
- /*
- * It is possible (though unlikely, given well behaved hashes) that the
- * table rebuild will fail.
- */
- lg_prevbuckets = ckh->lg_curbuckets;
- lg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS - 1;
- usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE);
- if (usize == 0)
- return;
- tab = (ckhc_t *)ipalloc(usize, CACHELINE, true);
- if (tab == NULL) {
- /*
- * An OOM error isn't worth propagating, since it doesn't
- * prevent this or future operations from proceeding.
- */
- return;
- }
- /* Swap in new table. */
- ttab = ckh->tab;
- ckh->tab = tab;
- tab = ttab;
- ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS;
-
- if (ckh_rebuild(ckh, tab) == false) {
- idalloc(tab);
-#ifdef CKH_COUNT
- ckh->nshrinks++;
-#endif
- return;
- }
-
- /* Rebuilding failed, so back out partially rebuilt table. */
- idalloc(ckh->tab);
- ckh->tab = tab;
- ckh->lg_curbuckets = lg_prevbuckets;
-#ifdef CKH_COUNT
- ckh->nshrinkfails++;
-#endif
-}
-
-bool
-ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp)
-{
- bool ret;
- size_t mincells, usize;
- unsigned lg_mincells;
-
- assert(minitems > 0);
- assert(hash != NULL);
- assert(keycomp != NULL);
-
-#ifdef CKH_COUNT
- ckh->ngrows = 0;
- ckh->nshrinks = 0;
- ckh->nshrinkfails = 0;
- ckh->ninserts = 0;
- ckh->nrelocs = 0;
-#endif
- ckh->prng_state = 42; /* Value doesn't really matter. */
- ckh->count = 0;
-
- /*
- * Find the minimum power of 2 that is large enough to fit aBaseCount
- * entries. We are using (2+,2) cuckoo hashing, which has an expected
- * maximum load factor of at least ~0.86, so 0.75 is a conservative load
- * factor that will typically allow 2^aLgMinItems to fit without ever
- * growing the table.
- */
- assert(LG_CKH_BUCKET_CELLS > 0);
- mincells = ((minitems + (3 - (minitems % 3))) / 3) << 2;
- for (lg_mincells = LG_CKH_BUCKET_CELLS;
- (ZU(1) << lg_mincells) < mincells;
- lg_mincells++)
- ; /* Do nothing. */
- ckh->lg_minbuckets = lg_mincells - LG_CKH_BUCKET_CELLS;
- ckh->lg_curbuckets = lg_mincells - LG_CKH_BUCKET_CELLS;
- ckh->hash = hash;
- ckh->keycomp = keycomp;
-
- usize = sa2u(sizeof(ckhc_t) << lg_mincells, CACHELINE);
- if (usize == 0) {
- ret = true;
- goto label_return;
- }
- ckh->tab = (ckhc_t *)ipalloc(usize, CACHELINE, true);
- if (ckh->tab == NULL) {
- ret = true;
- goto label_return;
- }
-
- ret = false;
-label_return:
- return (ret);
-}
-
-void
-ckh_delete(ckh_t *ckh)
-{
-
- assert(ckh != NULL);
-
-#ifdef CKH_VERBOSE
- malloc_printf(
- "%s(%p): ngrows: %"PRIu64", nshrinks: %"PRIu64","
- " nshrinkfails: %"PRIu64", ninserts: %"PRIu64","
- " nrelocs: %"PRIu64"\n", __func__, ckh,
- (unsigned long long)ckh->ngrows,
- (unsigned long long)ckh->nshrinks,
- (unsigned long long)ckh->nshrinkfails,
- (unsigned long long)ckh->ninserts,
- (unsigned long long)ckh->nrelocs);
-#endif
-
- idalloc(ckh->tab);
- if (config_debug)
- memset(ckh, 0x5a, sizeof(ckh_t));
-}
-
-size_t
-ckh_count(ckh_t *ckh)
-{
-
- assert(ckh != NULL);
-
- return (ckh->count);
-}
-
-bool
-ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data)
-{
- size_t i, ncells;
-
- for (i = *tabind, ncells = (ZU(1) << (ckh->lg_curbuckets +
- LG_CKH_BUCKET_CELLS)); i < ncells; i++) {
- if (ckh->tab[i].key != NULL) {
- if (key != NULL)
- *key = (void *)ckh->tab[i].key;
- if (data != NULL)
- *data = (void *)ckh->tab[i].data;
- *tabind = i + 1;
- return (false);
- }
- }
-
- return (true);
-}
-
-bool
-ckh_insert(ckh_t *ckh, const void *key, const void *data)
-{
- bool ret;
-
- assert(ckh != NULL);
- assert(ckh_search(ckh, key, NULL, NULL));
-
-#ifdef CKH_COUNT
- ckh->ninserts++;
-#endif
-
- while (ckh_try_insert(ckh, &key, &data)) {
- if (ckh_grow(ckh)) {
- ret = true;
- goto label_return;
- }
- }
-
- ret = false;
-label_return:
- return (ret);
-}
-
-bool
-ckh_remove(ckh_t *ckh, const void *searchkey, void **key, void **data)
-{
- size_t cell;
-
- assert(ckh != NULL);
-
- cell = ckh_isearch(ckh, searchkey);
- if (cell != SIZE_T_MAX) {
- if (key != NULL)
- *key = (void *)ckh->tab[cell].key;
- if (data != NULL)
- *data = (void *)ckh->tab[cell].data;
- ckh->tab[cell].key = NULL;
- ckh->tab[cell].data = NULL; /* Not necessary. */
-
- ckh->count--;
- /* Try to halve the table if it is less than 1/4 full. */
- if (ckh->count < (ZU(1) << (ckh->lg_curbuckets
- + LG_CKH_BUCKET_CELLS - 2)) && ckh->lg_curbuckets
- > ckh->lg_minbuckets) {
- /* Ignore error due to OOM. */
- ckh_shrink(ckh);
- }
-
- return (false);
- }
-
- return (true);
-}
-
-bool
-ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data)
-{
- size_t cell;
-
- assert(ckh != NULL);
-
- cell = ckh_isearch(ckh, searchkey);
- if (cell != SIZE_T_MAX) {
- if (key != NULL)
- *key = (void *)ckh->tab[cell].key;
- if (data != NULL)
- *data = (void *)ckh->tab[cell].data;
- return (false);
- }
-
- return (true);
-}
-
-void
-ckh_string_hash(const void *key, size_t r_hash[2])
-{
-
- hash(key, strlen((const char *)key), 0x94122f33U, r_hash);
-}
-
-bool
-ckh_string_keycomp(const void *k1, const void *k2)
-{
-
- assert(k1 != NULL);
- assert(k2 != NULL);
-
- return (strcmp((char *)k1, (char *)k2) ? false : true);
-}
-
-void
-ckh_pointer_hash(const void *key, size_t r_hash[2])
-{
- union {
- const void *v;
- size_t i;
- } u;
-
- assert(sizeof(u.v) == sizeof(u.i));
- u.v = key;
- hash(&u.i, sizeof(u.i), 0xd983396eU, r_hash);
-}
-
-bool
-ckh_pointer_keycomp(const void *k1, const void *k2)
-{
-
- return ((k1 == k2) ? true : false);
-}
diff --git a/extra/jemalloc/src/ctl.c b/extra/jemalloc/src/ctl.c
deleted file mode 100644
index 7ce4fc4d573..00000000000
--- a/extra/jemalloc/src/ctl.c
+++ /dev/null
@@ -1,1673 +0,0 @@
-#define JEMALLOC_CTL_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Data. */
-
-/*
- * ctl_mtx protects the following:
- * - ctl_stats.*
- * - opt_prof_active
- */
-static malloc_mutex_t ctl_mtx;
-static bool ctl_initialized;
-static uint64_t ctl_epoch;
-static ctl_stats_t ctl_stats;
-
-/******************************************************************************/
-/* Helpers for named and indexed nodes. */
-
-static inline const ctl_named_node_t *
-ctl_named_node(const ctl_node_t *node)
-{
-
- return ((node->named) ? (const ctl_named_node_t *)node : NULL);
-}
-
-static inline const ctl_named_node_t *
-ctl_named_children(const ctl_named_node_t *node, int index)
-{
- const ctl_named_node_t *children = ctl_named_node(node->children);
-
- return (children ? &children[index] : NULL);
-}
-
-static inline const ctl_indexed_node_t *
-ctl_indexed_node(const ctl_node_t *node)
-{
-
- return ((node->named == false) ? (const ctl_indexed_node_t *)node :
- NULL);
-}
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-#define CTL_PROTO(n) \
-static int n##_ctl(const size_t *mib, size_t miblen, void *oldp, \
- size_t *oldlenp, void *newp, size_t newlen);
-
-#define INDEX_PROTO(n) \
-static const ctl_named_node_t *n##_index(const size_t *mib, \
- size_t miblen, size_t i);
-
-static bool ctl_arena_init(ctl_arena_stats_t *astats);
-static void ctl_arena_clear(ctl_arena_stats_t *astats);
-static void ctl_arena_stats_amerge(ctl_arena_stats_t *cstats,
- arena_t *arena);
-static void ctl_arena_stats_smerge(ctl_arena_stats_t *sstats,
- ctl_arena_stats_t *astats);
-static void ctl_arena_refresh(arena_t *arena, unsigned i);
-static bool ctl_grow(void);
-static void ctl_refresh(void);
-static bool ctl_init(void);
-static int ctl_lookup(const char *name, ctl_node_t const **nodesp,
- size_t *mibp, size_t *depthp);
-
-CTL_PROTO(version)
-CTL_PROTO(epoch)
-CTL_PROTO(thread_tcache_enabled)
-CTL_PROTO(thread_tcache_flush)
-CTL_PROTO(thread_arena)
-CTL_PROTO(thread_allocated)
-CTL_PROTO(thread_allocatedp)
-CTL_PROTO(thread_deallocated)
-CTL_PROTO(thread_deallocatedp)
-CTL_PROTO(config_debug)
-CTL_PROTO(config_dss)
-CTL_PROTO(config_fill)
-CTL_PROTO(config_lazy_lock)
-CTL_PROTO(config_mremap)
-CTL_PROTO(config_munmap)
-CTL_PROTO(config_prof)
-CTL_PROTO(config_prof_libgcc)
-CTL_PROTO(config_prof_libunwind)
-CTL_PROTO(config_stats)
-CTL_PROTO(config_tcache)
-CTL_PROTO(config_tls)
-CTL_PROTO(config_utrace)
-CTL_PROTO(config_valgrind)
-CTL_PROTO(config_xmalloc)
-CTL_PROTO(opt_abort)
-CTL_PROTO(opt_dss)
-CTL_PROTO(opt_lg_chunk)
-CTL_PROTO(opt_narenas)
-CTL_PROTO(opt_lg_dirty_mult)
-CTL_PROTO(opt_stats_print)
-CTL_PROTO(opt_junk)
-CTL_PROTO(opt_zero)
-CTL_PROTO(opt_quarantine)
-CTL_PROTO(opt_redzone)
-CTL_PROTO(opt_utrace)
-CTL_PROTO(opt_valgrind)
-CTL_PROTO(opt_xmalloc)
-CTL_PROTO(opt_tcache)
-CTL_PROTO(opt_lg_tcache_max)
-CTL_PROTO(opt_prof)
-CTL_PROTO(opt_prof_prefix)
-CTL_PROTO(opt_prof_active)
-CTL_PROTO(opt_lg_prof_sample)
-CTL_PROTO(opt_lg_prof_interval)
-CTL_PROTO(opt_prof_gdump)
-CTL_PROTO(opt_prof_final)
-CTL_PROTO(opt_prof_leak)
-CTL_PROTO(opt_prof_accum)
-CTL_PROTO(arena_i_purge)
-static void arena_purge(unsigned arena_ind);
-CTL_PROTO(arena_i_dss)
-INDEX_PROTO(arena_i)
-CTL_PROTO(arenas_bin_i_size)
-CTL_PROTO(arenas_bin_i_nregs)
-CTL_PROTO(arenas_bin_i_run_size)
-INDEX_PROTO(arenas_bin_i)
-CTL_PROTO(arenas_lrun_i_size)
-INDEX_PROTO(arenas_lrun_i)
-CTL_PROTO(arenas_narenas)
-CTL_PROTO(arenas_initialized)
-CTL_PROTO(arenas_quantum)
-CTL_PROTO(arenas_page)
-CTL_PROTO(arenas_tcache_max)
-CTL_PROTO(arenas_nbins)
-CTL_PROTO(arenas_nhbins)
-CTL_PROTO(arenas_nlruns)
-CTL_PROTO(arenas_purge)
-CTL_PROTO(arenas_extend)
-CTL_PROTO(prof_active)
-CTL_PROTO(prof_dump)
-CTL_PROTO(prof_interval)
-CTL_PROTO(stats_chunks_current)
-CTL_PROTO(stats_chunks_total)
-CTL_PROTO(stats_chunks_high)
-CTL_PROTO(stats_huge_allocated)
-CTL_PROTO(stats_huge_nmalloc)
-CTL_PROTO(stats_huge_ndalloc)
-CTL_PROTO(stats_arenas_i_small_allocated)
-CTL_PROTO(stats_arenas_i_small_nmalloc)
-CTL_PROTO(stats_arenas_i_small_ndalloc)
-CTL_PROTO(stats_arenas_i_small_nrequests)
-CTL_PROTO(stats_arenas_i_large_allocated)
-CTL_PROTO(stats_arenas_i_large_nmalloc)
-CTL_PROTO(stats_arenas_i_large_ndalloc)
-CTL_PROTO(stats_arenas_i_large_nrequests)
-CTL_PROTO(stats_arenas_i_bins_j_allocated)
-CTL_PROTO(stats_arenas_i_bins_j_nmalloc)
-CTL_PROTO(stats_arenas_i_bins_j_ndalloc)
-CTL_PROTO(stats_arenas_i_bins_j_nrequests)
-CTL_PROTO(stats_arenas_i_bins_j_nfills)
-CTL_PROTO(stats_arenas_i_bins_j_nflushes)
-CTL_PROTO(stats_arenas_i_bins_j_nruns)
-CTL_PROTO(stats_arenas_i_bins_j_nreruns)
-CTL_PROTO(stats_arenas_i_bins_j_curruns)
-INDEX_PROTO(stats_arenas_i_bins_j)
-CTL_PROTO(stats_arenas_i_lruns_j_nmalloc)
-CTL_PROTO(stats_arenas_i_lruns_j_ndalloc)
-CTL_PROTO(stats_arenas_i_lruns_j_nrequests)
-CTL_PROTO(stats_arenas_i_lruns_j_curruns)
-INDEX_PROTO(stats_arenas_i_lruns_j)
-CTL_PROTO(stats_arenas_i_nthreads)
-CTL_PROTO(stats_arenas_i_dss)
-CTL_PROTO(stats_arenas_i_pactive)
-CTL_PROTO(stats_arenas_i_pdirty)
-CTL_PROTO(stats_arenas_i_mapped)
-CTL_PROTO(stats_arenas_i_npurge)
-CTL_PROTO(stats_arenas_i_nmadvise)
-CTL_PROTO(stats_arenas_i_purged)
-INDEX_PROTO(stats_arenas_i)
-CTL_PROTO(stats_cactive)
-CTL_PROTO(stats_allocated)
-CTL_PROTO(stats_active)
-CTL_PROTO(stats_mapped)
-
-/******************************************************************************/
-/* mallctl tree. */
-
-/* Maximum tree depth. */
-#define CTL_MAX_DEPTH 6
-
-#define NAME(n) {true}, n
-#define CHILD(t, c) \
- sizeof(c##_node) / sizeof(ctl_##t##_node_t), \
- (ctl_node_t *)c##_node, \
- NULL
-#define CTL(c) 0, NULL, c##_ctl
-
-/*
- * Only handles internal indexed nodes, since there are currently no external
- * ones.
- */
-#define INDEX(i) {false}, i##_index
-
-static const ctl_named_node_t tcache_node[] = {
- {NAME("enabled"), CTL(thread_tcache_enabled)},
- {NAME("flush"), CTL(thread_tcache_flush)}
-};
-
-static const ctl_named_node_t thread_node[] = {
- {NAME("arena"), CTL(thread_arena)},
- {NAME("allocated"), CTL(thread_allocated)},
- {NAME("allocatedp"), CTL(thread_allocatedp)},
- {NAME("deallocated"), CTL(thread_deallocated)},
- {NAME("deallocatedp"), CTL(thread_deallocatedp)},
- {NAME("tcache"), CHILD(named, tcache)}
-};
-
-static const ctl_named_node_t config_node[] = {
- {NAME("debug"), CTL(config_debug)},
- {NAME("dss"), CTL(config_dss)},
- {NAME("fill"), CTL(config_fill)},
- {NAME("lazy_lock"), CTL(config_lazy_lock)},
- {NAME("mremap"), CTL(config_mremap)},
- {NAME("munmap"), CTL(config_munmap)},
- {NAME("prof"), CTL(config_prof)},
- {NAME("prof_libgcc"), CTL(config_prof_libgcc)},
- {NAME("prof_libunwind"), CTL(config_prof_libunwind)},
- {NAME("stats"), CTL(config_stats)},
- {NAME("tcache"), CTL(config_tcache)},
- {NAME("tls"), CTL(config_tls)},
- {NAME("utrace"), CTL(config_utrace)},
- {NAME("valgrind"), CTL(config_valgrind)},
- {NAME("xmalloc"), CTL(config_xmalloc)}
-};
-
-static const ctl_named_node_t opt_node[] = {
- {NAME("abort"), CTL(opt_abort)},
- {NAME("dss"), CTL(opt_dss)},
- {NAME("lg_chunk"), CTL(opt_lg_chunk)},
- {NAME("narenas"), CTL(opt_narenas)},
- {NAME("lg_dirty_mult"), CTL(opt_lg_dirty_mult)},
- {NAME("stats_print"), CTL(opt_stats_print)},
- {NAME("junk"), CTL(opt_junk)},
- {NAME("zero"), CTL(opt_zero)},
- {NAME("quarantine"), CTL(opt_quarantine)},
- {NAME("redzone"), CTL(opt_redzone)},
- {NAME("utrace"), CTL(opt_utrace)},
- {NAME("valgrind"), CTL(opt_valgrind)},
- {NAME("xmalloc"), CTL(opt_xmalloc)},
- {NAME("tcache"), CTL(opt_tcache)},
- {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)},
- {NAME("prof"), CTL(opt_prof)},
- {NAME("prof_prefix"), CTL(opt_prof_prefix)},
- {NAME("prof_active"), CTL(opt_prof_active)},
- {NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
- {NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
- {NAME("prof_gdump"), CTL(opt_prof_gdump)},
- {NAME("prof_final"), CTL(opt_prof_final)},
- {NAME("prof_leak"), CTL(opt_prof_leak)},
- {NAME("prof_accum"), CTL(opt_prof_accum)}
-};
-
-static const ctl_named_node_t arena_i_node[] = {
- {NAME("purge"), CTL(arena_i_purge)},
- {NAME("dss"), CTL(arena_i_dss)}
-};
-static const ctl_named_node_t super_arena_i_node[] = {
- {NAME(""), CHILD(named, arena_i)}
-};
-
-static const ctl_indexed_node_t arena_node[] = {
- {INDEX(arena_i)}
-};
-
-static const ctl_named_node_t arenas_bin_i_node[] = {
- {NAME("size"), CTL(arenas_bin_i_size)},
- {NAME("nregs"), CTL(arenas_bin_i_nregs)},
- {NAME("run_size"), CTL(arenas_bin_i_run_size)}
-};
-static const ctl_named_node_t super_arenas_bin_i_node[] = {
- {NAME(""), CHILD(named, arenas_bin_i)}
-};
-
-static const ctl_indexed_node_t arenas_bin_node[] = {
- {INDEX(arenas_bin_i)}
-};
-
-static const ctl_named_node_t arenas_lrun_i_node[] = {
- {NAME("size"), CTL(arenas_lrun_i_size)}
-};
-static const ctl_named_node_t super_arenas_lrun_i_node[] = {
- {NAME(""), CHILD(named, arenas_lrun_i)}
-};
-
-static const ctl_indexed_node_t arenas_lrun_node[] = {
- {INDEX(arenas_lrun_i)}
-};
-
-static const ctl_named_node_t arenas_node[] = {
- {NAME("narenas"), CTL(arenas_narenas)},
- {NAME("initialized"), CTL(arenas_initialized)},
- {NAME("quantum"), CTL(arenas_quantum)},
- {NAME("page"), CTL(arenas_page)},
- {NAME("tcache_max"), CTL(arenas_tcache_max)},
- {NAME("nbins"), CTL(arenas_nbins)},
- {NAME("nhbins"), CTL(arenas_nhbins)},
- {NAME("bin"), CHILD(indexed, arenas_bin)},
- {NAME("nlruns"), CTL(arenas_nlruns)},
- {NAME("lrun"), CHILD(indexed, arenas_lrun)},
- {NAME("purge"), CTL(arenas_purge)},
- {NAME("extend"), CTL(arenas_extend)}
-};
-
-static const ctl_named_node_t prof_node[] = {
- {NAME("active"), CTL(prof_active)},
- {NAME("dump"), CTL(prof_dump)},
- {NAME("interval"), CTL(prof_interval)}
-};
-
-static const ctl_named_node_t stats_chunks_node[] = {
- {NAME("current"), CTL(stats_chunks_current)},
- {NAME("total"), CTL(stats_chunks_total)},
- {NAME("high"), CTL(stats_chunks_high)}
-};
-
-static const ctl_named_node_t stats_huge_node[] = {
- {NAME("allocated"), CTL(stats_huge_allocated)},
- {NAME("nmalloc"), CTL(stats_huge_nmalloc)},
- {NAME("ndalloc"), CTL(stats_huge_ndalloc)}
-};
-
-static const ctl_named_node_t stats_arenas_i_small_node[] = {
- {NAME("allocated"), CTL(stats_arenas_i_small_allocated)},
- {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)},
- {NAME("ndalloc"), CTL(stats_arenas_i_small_ndalloc)},
- {NAME("nrequests"), CTL(stats_arenas_i_small_nrequests)}
-};
-
-static const ctl_named_node_t stats_arenas_i_large_node[] = {
- {NAME("allocated"), CTL(stats_arenas_i_large_allocated)},
- {NAME("nmalloc"), CTL(stats_arenas_i_large_nmalloc)},
- {NAME("ndalloc"), CTL(stats_arenas_i_large_ndalloc)},
- {NAME("nrequests"), CTL(stats_arenas_i_large_nrequests)}
-};
-
-static const ctl_named_node_t stats_arenas_i_bins_j_node[] = {
- {NAME("allocated"), CTL(stats_arenas_i_bins_j_allocated)},
- {NAME("nmalloc"), CTL(stats_arenas_i_bins_j_nmalloc)},
- {NAME("ndalloc"), CTL(stats_arenas_i_bins_j_ndalloc)},
- {NAME("nrequests"), CTL(stats_arenas_i_bins_j_nrequests)},
- {NAME("nfills"), CTL(stats_arenas_i_bins_j_nfills)},
- {NAME("nflushes"), CTL(stats_arenas_i_bins_j_nflushes)},
- {NAME("nruns"), CTL(stats_arenas_i_bins_j_nruns)},
- {NAME("nreruns"), CTL(stats_arenas_i_bins_j_nreruns)},
- {NAME("curruns"), CTL(stats_arenas_i_bins_j_curruns)}
-};
-static const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {
- {NAME(""), CHILD(named, stats_arenas_i_bins_j)}
-};
-
-static const ctl_indexed_node_t stats_arenas_i_bins_node[] = {
- {INDEX(stats_arenas_i_bins_j)}
-};
-
-static const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {
- {NAME("nmalloc"), CTL(stats_arenas_i_lruns_j_nmalloc)},
- {NAME("ndalloc"), CTL(stats_arenas_i_lruns_j_ndalloc)},
- {NAME("nrequests"), CTL(stats_arenas_i_lruns_j_nrequests)},
- {NAME("curruns"), CTL(stats_arenas_i_lruns_j_curruns)}
-};
-static const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {
- {NAME(""), CHILD(named, stats_arenas_i_lruns_j)}
-};
-
-static const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {
- {INDEX(stats_arenas_i_lruns_j)}
-};
-
-static const ctl_named_node_t stats_arenas_i_node[] = {
- {NAME("nthreads"), CTL(stats_arenas_i_nthreads)},
- {NAME("dss"), CTL(stats_arenas_i_dss)},
- {NAME("pactive"), CTL(stats_arenas_i_pactive)},
- {NAME("pdirty"), CTL(stats_arenas_i_pdirty)},
- {NAME("mapped"), CTL(stats_arenas_i_mapped)},
- {NAME("npurge"), CTL(stats_arenas_i_npurge)},
- {NAME("nmadvise"), CTL(stats_arenas_i_nmadvise)},
- {NAME("purged"), CTL(stats_arenas_i_purged)},
- {NAME("small"), CHILD(named, stats_arenas_i_small)},
- {NAME("large"), CHILD(named, stats_arenas_i_large)},
- {NAME("bins"), CHILD(indexed, stats_arenas_i_bins)},
- {NAME("lruns"), CHILD(indexed, stats_arenas_i_lruns)}
-};
-static const ctl_named_node_t super_stats_arenas_i_node[] = {
- {NAME(""), CHILD(named, stats_arenas_i)}
-};
-
-static const ctl_indexed_node_t stats_arenas_node[] = {
- {INDEX(stats_arenas_i)}
-};
-
-static const ctl_named_node_t stats_node[] = {
- {NAME("cactive"), CTL(stats_cactive)},
- {NAME("allocated"), CTL(stats_allocated)},
- {NAME("active"), CTL(stats_active)},
- {NAME("mapped"), CTL(stats_mapped)},
- {NAME("chunks"), CHILD(named, stats_chunks)},
- {NAME("huge"), CHILD(named, stats_huge)},
- {NAME("arenas"), CHILD(indexed, stats_arenas)}
-};
-
-static const ctl_named_node_t root_node[] = {
- {NAME("version"), CTL(version)},
- {NAME("epoch"), CTL(epoch)},
- {NAME("thread"), CHILD(named, thread)},
- {NAME("config"), CHILD(named, config)},
- {NAME("opt"), CHILD(named, opt)},
- {NAME("arena"), CHILD(indexed, arena)},
- {NAME("arenas"), CHILD(named, arenas)},
- {NAME("prof"), CHILD(named, prof)},
- {NAME("stats"), CHILD(named, stats)}
-};
-static const ctl_named_node_t super_root_node[] = {
- {NAME(""), CHILD(named, root)}
-};
-
-#undef NAME
-#undef CHILD
-#undef CTL
-#undef INDEX
-
-/******************************************************************************/
-
-static bool
-ctl_arena_init(ctl_arena_stats_t *astats)
-{
-
- if (astats->lstats == NULL) {
- astats->lstats = (malloc_large_stats_t *)base_alloc(nlclasses *
- sizeof(malloc_large_stats_t));
- if (astats->lstats == NULL)
- return (true);
- }
-
- return (false);
-}
-
-static void
-ctl_arena_clear(ctl_arena_stats_t *astats)
-{
-
- astats->dss = dss_prec_names[dss_prec_limit];
- astats->pactive = 0;
- astats->pdirty = 0;
- if (config_stats) {
- memset(&astats->astats, 0, sizeof(arena_stats_t));
- astats->allocated_small = 0;
- astats->nmalloc_small = 0;
- astats->ndalloc_small = 0;
- astats->nrequests_small = 0;
- memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));
- memset(astats->lstats, 0, nlclasses *
- sizeof(malloc_large_stats_t));
- }
-}
-
-static void
-ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena)
-{
- unsigned i;
-
- arena_stats_merge(arena, &cstats->dss, &cstats->pactive,
- &cstats->pdirty, &cstats->astats, cstats->bstats, cstats->lstats);
-
- for (i = 0; i < NBINS; i++) {
- cstats->allocated_small += cstats->bstats[i].allocated;
- cstats->nmalloc_small += cstats->bstats[i].nmalloc;
- cstats->ndalloc_small += cstats->bstats[i].ndalloc;
- cstats->nrequests_small += cstats->bstats[i].nrequests;
- }
-}
-
-static void
-ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)
-{
- unsigned i;
-
- sstats->pactive += astats->pactive;
- sstats->pdirty += astats->pdirty;
-
- sstats->astats.mapped += astats->astats.mapped;
- sstats->astats.npurge += astats->astats.npurge;
- sstats->astats.nmadvise += astats->astats.nmadvise;
- sstats->astats.purged += astats->astats.purged;
-
- sstats->allocated_small += astats->allocated_small;
- sstats->nmalloc_small += astats->nmalloc_small;
- sstats->ndalloc_small += astats->ndalloc_small;
- sstats->nrequests_small += astats->nrequests_small;
-
- sstats->astats.allocated_large += astats->astats.allocated_large;
- sstats->astats.nmalloc_large += astats->astats.nmalloc_large;
- sstats->astats.ndalloc_large += astats->astats.ndalloc_large;
- sstats->astats.nrequests_large += astats->astats.nrequests_large;
-
- for (i = 0; i < nlclasses; i++) {
- sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;
- sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;
- sstats->lstats[i].nrequests += astats->lstats[i].nrequests;
- sstats->lstats[i].curruns += astats->lstats[i].curruns;
- }
-
- for (i = 0; i < NBINS; i++) {
- sstats->bstats[i].allocated += astats->bstats[i].allocated;
- sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
- sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
- sstats->bstats[i].nrequests += astats->bstats[i].nrequests;
- if (config_tcache) {
- sstats->bstats[i].nfills += astats->bstats[i].nfills;
- sstats->bstats[i].nflushes +=
- astats->bstats[i].nflushes;
- }
- sstats->bstats[i].nruns += astats->bstats[i].nruns;
- sstats->bstats[i].reruns += astats->bstats[i].reruns;
- sstats->bstats[i].curruns += astats->bstats[i].curruns;
- }
-}
-
-static void
-ctl_arena_refresh(arena_t *arena, unsigned i)
-{
- ctl_arena_stats_t *astats = &ctl_stats.arenas[i];
- ctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas];
-
- ctl_arena_clear(astats);
-
- sstats->nthreads += astats->nthreads;
- if (config_stats) {
- ctl_arena_stats_amerge(astats, arena);
- /* Merge into sum stats as well. */
- ctl_arena_stats_smerge(sstats, astats);
- } else {
- astats->pactive += arena->nactive;
- astats->pdirty += arena->ndirty;
- /* Merge into sum stats as well. */
- sstats->pactive += arena->nactive;
- sstats->pdirty += arena->ndirty;
- }
-}
-
-static bool
-ctl_grow(void)
-{
- size_t astats_size;
- ctl_arena_stats_t *astats;
- arena_t **tarenas;
-
- /* Extend arena stats and arenas arrays. */
- astats_size = (ctl_stats.narenas + 2) * sizeof(ctl_arena_stats_t);
- if (ctl_stats.narenas == narenas_auto) {
- /* ctl_stats.arenas and arenas came from base_alloc(). */
- astats = (ctl_arena_stats_t *)imalloc(astats_size);
- if (astats == NULL)
- return (true);
- memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) *
- sizeof(ctl_arena_stats_t));
-
- tarenas = (arena_t **)imalloc((ctl_stats.narenas + 1) *
- sizeof(arena_t *));
- if (tarenas == NULL) {
- idalloc(astats);
- return (true);
- }
- memcpy(tarenas, arenas, ctl_stats.narenas * sizeof(arena_t *));
- } else {
- astats = (ctl_arena_stats_t *)iralloc(ctl_stats.arenas,
- astats_size, 0, 0, false, false);
- if (astats == NULL)
- return (true);
-
- tarenas = (arena_t **)iralloc(arenas, (ctl_stats.narenas + 1) *
- sizeof(arena_t *), 0, 0, false, false);
- if (tarenas == NULL)
- return (true);
- }
- /* Initialize the new astats and arenas elements. */
- memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t));
- if (ctl_arena_init(&astats[ctl_stats.narenas + 1]))
- return (true);
- tarenas[ctl_stats.narenas] = NULL;
- /* Swap merged stats to their new location. */
- {
- ctl_arena_stats_t tstats;
- memcpy(&tstats, &astats[ctl_stats.narenas],
- sizeof(ctl_arena_stats_t));
- memcpy(&astats[ctl_stats.narenas],
- &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t));
- memcpy(&astats[ctl_stats.narenas + 1], &tstats,
- sizeof(ctl_arena_stats_t));
- }
- ctl_stats.arenas = astats;
- ctl_stats.narenas++;
- malloc_mutex_lock(&arenas_lock);
- arenas = tarenas;
- narenas_total++;
- arenas_extend(narenas_total - 1);
- malloc_mutex_unlock(&arenas_lock);
-
- return (false);
-}
-
-static void
-ctl_refresh(void)
-{
- unsigned i;
- VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);
-
- if (config_stats) {
- malloc_mutex_lock(&chunks_mtx);
- ctl_stats.chunks.current = stats_chunks.curchunks;
- ctl_stats.chunks.total = stats_chunks.nchunks;
- ctl_stats.chunks.high = stats_chunks.highchunks;
- malloc_mutex_unlock(&chunks_mtx);
-
- malloc_mutex_lock(&huge_mtx);
- ctl_stats.huge.allocated = huge_allocated;
- ctl_stats.huge.nmalloc = huge_nmalloc;
- ctl_stats.huge.ndalloc = huge_ndalloc;
- malloc_mutex_unlock(&huge_mtx);
- }
-
- /*
- * Clear sum stats, since they will be merged into by
- * ctl_arena_refresh().
- */
- ctl_stats.arenas[ctl_stats.narenas].nthreads = 0;
- ctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]);
-
- malloc_mutex_lock(&arenas_lock);
- memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas);
- for (i = 0; i < ctl_stats.narenas; i++) {
- if (arenas[i] != NULL)
- ctl_stats.arenas[i].nthreads = arenas[i]->nthreads;
- else
- ctl_stats.arenas[i].nthreads = 0;
- }
- malloc_mutex_unlock(&arenas_lock);
- for (i = 0; i < ctl_stats.narenas; i++) {
- bool initialized = (tarenas[i] != NULL);
-
- ctl_stats.arenas[i].initialized = initialized;
- if (initialized)
- ctl_arena_refresh(tarenas[i], i);
- }
-
- if (config_stats) {
- ctl_stats.allocated =
- ctl_stats.arenas[ctl_stats.narenas].allocated_small
- + ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large
- + ctl_stats.huge.allocated;
- ctl_stats.active =
- (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE)
- + ctl_stats.huge.allocated;
- ctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk);
- }
-
- ctl_epoch++;
-}
-
-static bool
-ctl_init(void)
-{
- bool ret;
-
- malloc_mutex_lock(&ctl_mtx);
- if (ctl_initialized == false) {
- /*
- * Allocate space for one extra arena stats element, which
- * contains summed stats across all arenas.
- */
- assert(narenas_auto == narenas_total_get());
- ctl_stats.narenas = narenas_auto;
- ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc(
- (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t));
- if (ctl_stats.arenas == NULL) {
- ret = true;
- goto label_return;
- }
- memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) *
- sizeof(ctl_arena_stats_t));
-
- /*
- * Initialize all stats structures, regardless of whether they
- * ever get used. Lazy initialization would allow errors to
- * cause inconsistent state to be viewable by the application.
- */
- if (config_stats) {
- unsigned i;
- for (i = 0; i <= ctl_stats.narenas; i++) {
- if (ctl_arena_init(&ctl_stats.arenas[i])) {
- ret = true;
- goto label_return;
- }
- }
- }
- ctl_stats.arenas[ctl_stats.narenas].initialized = true;
-
- ctl_epoch = 0;
- ctl_refresh();
- ctl_initialized = true;
- }
-
- ret = false;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-static int
-ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp,
- size_t *depthp)
-{
- int ret;
- const char *elm, *tdot, *dot;
- size_t elen, i, j;
- const ctl_named_node_t *node;
-
- elm = name;
- /* Equivalent to strchrnul(). */
- dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
- elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
- if (elen == 0) {
- ret = ENOENT;
- goto label_return;
- }
- node = super_root_node;
- for (i = 0; i < *depthp; i++) {
- assert(node);
- assert(node->nchildren > 0);
- if (ctl_named_node(node->children) != NULL) {
- const ctl_named_node_t *pnode = node;
-
- /* Children are named. */
- for (j = 0; j < node->nchildren; j++) {
- const ctl_named_node_t *child =
- ctl_named_children(node, j);
- if (strlen(child->name) == elen &&
- strncmp(elm, child->name, elen) == 0) {
- node = child;
- if (nodesp != NULL)
- nodesp[i] =
- (const ctl_node_t *)node;
- mibp[i] = j;
- break;
- }
- }
- if (node == pnode) {
- ret = ENOENT;
- goto label_return;
- }
- } else {
- uintmax_t index;
- const ctl_indexed_node_t *inode;
-
- /* Children are indexed. */
- index = malloc_strtoumax(elm, NULL, 10);
- if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
- ret = ENOENT;
- goto label_return;
- }
-
- inode = ctl_indexed_node(node->children);
- node = inode->index(mibp, *depthp, (size_t)index);
- if (node == NULL) {
- ret = ENOENT;
- goto label_return;
- }
-
- if (nodesp != NULL)
- nodesp[i] = (const ctl_node_t *)node;
- mibp[i] = (size_t)index;
- }
-
- if (node->ctl != NULL) {
- /* Terminal node. */
- if (*dot != '\0') {
- /*
- * The name contains more elements than are
- * in this path through the tree.
- */
- ret = ENOENT;
- goto label_return;
- }
- /* Complete lookup successful. */
- *depthp = i + 1;
- break;
- }
-
- /* Update elm. */
- if (*dot == '\0') {
- /* No more elements. */
- ret = ENOENT;
- goto label_return;
- }
- elm = &dot[1];
- dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
- strchr(elm, '\0');
- elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
- }
-
- ret = 0;
-label_return:
- return (ret);
-}
-
-int
-ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,
- size_t newlen)
-{
- int ret;
- size_t depth;
- ctl_node_t const *nodes[CTL_MAX_DEPTH];
- size_t mib[CTL_MAX_DEPTH];
- const ctl_named_node_t *node;
-
- if (ctl_initialized == false && ctl_init()) {
- ret = EAGAIN;
- goto label_return;
- }
-
- depth = CTL_MAX_DEPTH;
- ret = ctl_lookup(name, nodes, mib, &depth);
- if (ret != 0)
- goto label_return;
-
- node = ctl_named_node(nodes[depth-1]);
- if (node != NULL && node->ctl)
- ret = node->ctl(mib, depth, oldp, oldlenp, newp, newlen);
- else {
- /* The name refers to a partial path through the ctl tree. */
- ret = ENOENT;
- }
-
-label_return:
- return(ret);
-}
-
-int
-ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp)
-{
- int ret;
-
- if (ctl_initialized == false && ctl_init()) {
- ret = EAGAIN;
- goto label_return;
- }
-
- ret = ctl_lookup(name, NULL, mibp, miblenp);
-label_return:
- return(ret);
-}
-
-int
-ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret;
- const ctl_named_node_t *node;
- size_t i;
-
- if (ctl_initialized == false && ctl_init()) {
- ret = EAGAIN;
- goto label_return;
- }
-
- /* Iterate down the tree. */
- node = super_root_node;
- for (i = 0; i < miblen; i++) {
- assert(node);
- assert(node->nchildren > 0);
- if (ctl_named_node(node->children) != NULL) {
- /* Children are named. */
- if (node->nchildren <= mib[i]) {
- ret = ENOENT;
- goto label_return;
- }
- node = ctl_named_children(node, mib[i]);
- } else {
- const ctl_indexed_node_t *inode;
-
- /* Indexed element. */
- inode = ctl_indexed_node(node->children);
- node = inode->index(mib, miblen, mib[i]);
- if (node == NULL) {
- ret = ENOENT;
- goto label_return;
- }
- }
- }
-
- /* Call the ctl function. */
- if (node && node->ctl)
- ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen);
- else {
- /* Partial MIB. */
- ret = ENOENT;
- }
-
-label_return:
- return(ret);
-}
-
-bool
-ctl_boot(void)
-{
-
- if (malloc_mutex_init(&ctl_mtx))
- return (true);
-
- ctl_initialized = false;
-
- return (false);
-}
-
-void
-ctl_prefork(void)
-{
-
- malloc_mutex_lock(&ctl_mtx);
-}
-
-void
-ctl_postfork_parent(void)
-{
-
- malloc_mutex_postfork_parent(&ctl_mtx);
-}
-
-void
-ctl_postfork_child(void)
-{
-
- malloc_mutex_postfork_child(&ctl_mtx);
-}
-
-/******************************************************************************/
-/* *_ctl() functions. */
-
-#define READONLY() do { \
- if (newp != NULL || newlen != 0) { \
- ret = EPERM; \
- goto label_return; \
- } \
-} while (0)
-
-#define WRITEONLY() do { \
- if (oldp != NULL || oldlenp != NULL) { \
- ret = EPERM; \
- goto label_return; \
- } \
-} while (0)
-
-#define READ(v, t) do { \
- if (oldp != NULL && oldlenp != NULL) { \
- if (*oldlenp != sizeof(t)) { \
- size_t copylen = (sizeof(t) <= *oldlenp) \
- ? sizeof(t) : *oldlenp; \
- memcpy(oldp, (void *)&(v), copylen); \
- ret = EINVAL; \
- goto label_return; \
- } else \
- *(t *)oldp = (v); \
- } \
-} while (0)
-
-#define WRITE(v, t) do { \
- if (newp != NULL) { \
- if (newlen != sizeof(t)) { \
- ret = EINVAL; \
- goto label_return; \
- } \
- (v) = *(t *)newp; \
- } \
-} while (0)
-
-/*
- * There's a lot of code duplication in the following macros due to limitations
- * in how nested cpp macros are expanded.
- */
-#define CTL_RO_CLGEN(c, l, n, v, t) \
-static int \
-n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
- void *newp, size_t newlen) \
-{ \
- int ret; \
- t oldval; \
- \
- if ((c) == false) \
- return (ENOENT); \
- if (l) \
- malloc_mutex_lock(&ctl_mtx); \
- READONLY(); \
- oldval = (v); \
- READ(oldval, t); \
- \
- ret = 0; \
-label_return: \
- if (l) \
- malloc_mutex_unlock(&ctl_mtx); \
- return (ret); \
-}
-
-#define CTL_RO_CGEN(c, n, v, t) \
-static int \
-n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
- void *newp, size_t newlen) \
-{ \
- int ret; \
- t oldval; \
- \
- if ((c) == false) \
- return (ENOENT); \
- malloc_mutex_lock(&ctl_mtx); \
- READONLY(); \
- oldval = (v); \
- READ(oldval, t); \
- \
- ret = 0; \
-label_return: \
- malloc_mutex_unlock(&ctl_mtx); \
- return (ret); \
-}
-
-#define CTL_RO_GEN(n, v, t) \
-static int \
-n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
- void *newp, size_t newlen) \
-{ \
- int ret; \
- t oldval; \
- \
- malloc_mutex_lock(&ctl_mtx); \
- READONLY(); \
- oldval = (v); \
- READ(oldval, t); \
- \
- ret = 0; \
-label_return: \
- malloc_mutex_unlock(&ctl_mtx); \
- return (ret); \
-}
-
-/*
- * ctl_mtx is not acquired, under the assumption that no pertinent data will
- * mutate during the call.
- */
-#define CTL_RO_NL_CGEN(c, n, v, t) \
-static int \
-n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
- void *newp, size_t newlen) \
-{ \
- int ret; \
- t oldval; \
- \
- if ((c) == false) \
- return (ENOENT); \
- READONLY(); \
- oldval = (v); \
- READ(oldval, t); \
- \
- ret = 0; \
-label_return: \
- return (ret); \
-}
-
-#define CTL_RO_NL_GEN(n, v, t) \
-static int \
-n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
- void *newp, size_t newlen) \
-{ \
- int ret; \
- t oldval; \
- \
- READONLY(); \
- oldval = (v); \
- READ(oldval, t); \
- \
- ret = 0; \
-label_return: \
- return (ret); \
-}
-
-#define CTL_RO_BOOL_CONFIG_GEN(n) \
-static int \
-n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
- void *newp, size_t newlen) \
-{ \
- int ret; \
- bool oldval; \
- \
- READONLY(); \
- oldval = n; \
- READ(oldval, bool); \
- \
- ret = 0; \
-label_return: \
- return (ret); \
-}
-
-CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
-
-static int
-epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret;
- uint64_t newval __attribute__((unused));
-
- malloc_mutex_lock(&ctl_mtx);
- WRITE(newval, uint64_t);
- if (newp != NULL)
- ctl_refresh();
- READ(ctl_epoch, uint64_t);
-
- ret = 0;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-static int
-thread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp,
- size_t *oldlenp, void *newp, size_t newlen)
-{
- int ret;
- bool oldval;
-
- if (config_tcache == false)
- return (ENOENT);
-
- oldval = tcache_enabled_get();
- if (newp != NULL) {
- if (newlen != sizeof(bool)) {
- ret = EINVAL;
- goto label_return;
- }
- tcache_enabled_set(*(bool *)newp);
- }
- READ(oldval, bool);
-
- ret = 0;
-label_return:
- return (ret);
-}
-
-static int
-thread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp,
- size_t *oldlenp, void *newp, size_t newlen)
-{
- int ret;
-
- if (config_tcache == false)
- return (ENOENT);
-
- READONLY();
- WRITEONLY();
-
- tcache_flush();
-
- ret = 0;
-label_return:
- return (ret);
-}
-
-static int
-thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret;
- unsigned newind, oldind;
-
- malloc_mutex_lock(&ctl_mtx);
- newind = oldind = choose_arena(NULL)->ind;
- WRITE(newind, unsigned);
- READ(oldind, unsigned);
- if (newind != oldind) {
- arena_t *arena;
-
- if (newind >= ctl_stats.narenas) {
- /* New arena index is out of range. */
- ret = EFAULT;
- goto label_return;
- }
-
- /* Initialize arena if necessary. */
- malloc_mutex_lock(&arenas_lock);
- if ((arena = arenas[newind]) == NULL && (arena =
- arenas_extend(newind)) == NULL) {
- malloc_mutex_unlock(&arenas_lock);
- ret = EAGAIN;
- goto label_return;
- }
- assert(arena == arenas[newind]);
- arenas[oldind]->nthreads--;
- arenas[newind]->nthreads++;
- malloc_mutex_unlock(&arenas_lock);
-
- /* Set new arena association. */
- if (config_tcache) {
- tcache_t *tcache;
- if ((uintptr_t)(tcache = *tcache_tsd_get()) >
- (uintptr_t)TCACHE_STATE_MAX) {
- tcache_arena_dissociate(tcache);
- tcache_arena_associate(tcache, arena);
- }
- }
- arenas_tsd_set(&arena);
- }
-
- ret = 0;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-CTL_RO_NL_CGEN(config_stats, thread_allocated,
- thread_allocated_tsd_get()->allocated, uint64_t)
-CTL_RO_NL_CGEN(config_stats, thread_allocatedp,
- &thread_allocated_tsd_get()->allocated, uint64_t *)
-CTL_RO_NL_CGEN(config_stats, thread_deallocated,
- thread_allocated_tsd_get()->deallocated, uint64_t)
-CTL_RO_NL_CGEN(config_stats, thread_deallocatedp,
- &thread_allocated_tsd_get()->deallocated, uint64_t *)
-
-/******************************************************************************/
-
-CTL_RO_BOOL_CONFIG_GEN(config_debug)
-CTL_RO_BOOL_CONFIG_GEN(config_dss)
-CTL_RO_BOOL_CONFIG_GEN(config_fill)
-CTL_RO_BOOL_CONFIG_GEN(config_lazy_lock)
-CTL_RO_BOOL_CONFIG_GEN(config_mremap)
-CTL_RO_BOOL_CONFIG_GEN(config_munmap)
-CTL_RO_BOOL_CONFIG_GEN(config_prof)
-CTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc)
-CTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind)
-CTL_RO_BOOL_CONFIG_GEN(config_stats)
-CTL_RO_BOOL_CONFIG_GEN(config_tcache)
-CTL_RO_BOOL_CONFIG_GEN(config_tls)
-CTL_RO_BOOL_CONFIG_GEN(config_utrace)
-CTL_RO_BOOL_CONFIG_GEN(config_valgrind)
-CTL_RO_BOOL_CONFIG_GEN(config_xmalloc)
-
-/******************************************************************************/
-
-CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
-CTL_RO_NL_GEN(opt_dss, opt_dss, const char *)
-CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
-CTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t)
-CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
-CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
-CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool)
-CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
-CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
-CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
-CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
-CTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool)
-CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
-CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
-CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
-CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
-CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
-CTL_RO_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) /* Mutable. */
-CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
-CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
-CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
-CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
-CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
-CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
-
-/******************************************************************************/
-
-/* ctl_mutex must be held during execution of this function. */
-static void
-arena_purge(unsigned arena_ind)
-{
- VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);
-
- malloc_mutex_lock(&arenas_lock);
- memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas);
- malloc_mutex_unlock(&arenas_lock);
-
- if (arena_ind == ctl_stats.narenas) {
- unsigned i;
- for (i = 0; i < ctl_stats.narenas; i++) {
- if (tarenas[i] != NULL)
- arena_purge_all(tarenas[i]);
- }
- } else {
- assert(arena_ind < ctl_stats.narenas);
- if (tarenas[arena_ind] != NULL)
- arena_purge_all(tarenas[arena_ind]);
- }
-}
-
-static int
-arena_i_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret;
-
- READONLY();
- WRITEONLY();
- malloc_mutex_lock(&ctl_mtx);
- arena_purge(mib[1]);
- malloc_mutex_unlock(&ctl_mtx);
-
- ret = 0;
-label_return:
- return (ret);
-}
-
-static int
-arena_i_dss_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret, i;
- bool match, err;
- const char *dss;
- unsigned arena_ind = mib[1];
- dss_prec_t dss_prec_old = dss_prec_limit;
- dss_prec_t dss_prec = dss_prec_limit;
-
- malloc_mutex_lock(&ctl_mtx);
- WRITE(dss, const char *);
- match = false;
- for (i = 0; i < dss_prec_limit; i++) {
- if (strcmp(dss_prec_names[i], dss) == 0) {
- dss_prec = i;
- match = true;
- break;
- }
- }
- if (match == false) {
- ret = EINVAL;
- goto label_return;
- }
-
- if (arena_ind < ctl_stats.narenas) {
- arena_t *arena = arenas[arena_ind];
- if (arena != NULL) {
- dss_prec_old = arena_dss_prec_get(arena);
- arena_dss_prec_set(arena, dss_prec);
- err = false;
- } else
- err = true;
- } else {
- dss_prec_old = chunk_dss_prec_get();
- err = chunk_dss_prec_set(dss_prec);
- }
- dss = dss_prec_names[dss_prec_old];
- READ(dss, const char *);
- if (err) {
- ret = EFAULT;
- goto label_return;
- }
-
- ret = 0;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-static const ctl_named_node_t *
-arena_i_index(const size_t *mib, size_t miblen, size_t i)
-{
- const ctl_named_node_t * ret;
-
- malloc_mutex_lock(&ctl_mtx);
- if (i > ctl_stats.narenas) {
- ret = NULL;
- goto label_return;
- }
-
- ret = super_arena_i_node;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-
-/******************************************************************************/
-
-CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)
-CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)
-CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)
-static const ctl_named_node_t *
-arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)
-{
-
- if (i > NBINS)
- return (NULL);
- return (super_arenas_bin_i_node);
-}
-
-CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t)
-static const ctl_named_node_t *
-arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)
-{
-
- if (i > nlclasses)
- return (NULL);
- return (super_arenas_lrun_i_node);
-}
-
-static int
-arenas_narenas_ctl(const size_t *mib, size_t miblen, void *oldp,
- size_t *oldlenp, void *newp, size_t newlen)
-{
- int ret;
- unsigned narenas;
-
- malloc_mutex_lock(&ctl_mtx);
- READONLY();
- if (*oldlenp != sizeof(unsigned)) {
- ret = EINVAL;
- goto label_return;
- }
- narenas = ctl_stats.narenas;
- READ(narenas, unsigned);
-
- ret = 0;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-static int
-arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,
- size_t *oldlenp, void *newp, size_t newlen)
-{
- int ret;
- unsigned nread, i;
-
- malloc_mutex_lock(&ctl_mtx);
- READONLY();
- if (*oldlenp != ctl_stats.narenas * sizeof(bool)) {
- ret = EINVAL;
- nread = (*oldlenp < ctl_stats.narenas * sizeof(bool))
- ? (*oldlenp / sizeof(bool)) : ctl_stats.narenas;
- } else {
- ret = 0;
- nread = ctl_stats.narenas;
- }
-
- for (i = 0; i < nread; i++)
- ((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
-
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
-CTL_RO_NL_GEN(arenas_page, PAGE, size_t)
-CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)
-CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)
-CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)
-CTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t)
-
-static int
-arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret;
- unsigned arena_ind;
-
- malloc_mutex_lock(&ctl_mtx);
- WRITEONLY();
- arena_ind = UINT_MAX;
- WRITE(arena_ind, unsigned);
- if (newp != NULL && arena_ind >= ctl_stats.narenas)
- ret = EFAULT;
- else {
- if (arena_ind == UINT_MAX)
- arena_ind = ctl_stats.narenas;
- arena_purge(arena_ind);
- ret = 0;
- }
-
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-static int
-arenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret;
- unsigned narenas;
-
- malloc_mutex_lock(&ctl_mtx);
- READONLY();
- if (ctl_grow()) {
- ret = EAGAIN;
- goto label_return;
- }
- narenas = ctl_stats.narenas - 1;
- READ(narenas, unsigned);
-
- ret = 0;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-/******************************************************************************/
-
-static int
-prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret;
- bool oldval;
-
- if (config_prof == false)
- return (ENOENT);
-
- malloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */
- oldval = opt_prof_active;
- if (newp != NULL) {
- /*
- * The memory barriers will tend to make opt_prof_active
- * propagate faster on systems with weak memory ordering.
- */
- mb_write();
- WRITE(opt_prof_active, bool);
- mb_write();
- }
- READ(oldval, bool);
-
- ret = 0;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-static int
-prof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
- int ret;
- const char *filename = NULL;
-
- if (config_prof == false)
- return (ENOENT);
-
- WRITEONLY();
- WRITE(filename, const char *);
-
- if (prof_mdump(filename)) {
- ret = EFAULT;
- goto label_return;
- }
-
- ret = 0;
-label_return:
- return (ret);
-}
-
-CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
-
-/******************************************************************************/
-
-CTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current,
- size_t)
-CTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t)
-CTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t)
-CTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t)
-CTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t)
-CTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
- ctl_stats.arenas[mib[2]].allocated_small, size_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
- ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
- ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
- ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
- ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
- ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
- ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
- ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)
-
-CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)
-CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)
-CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,
- ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)
-
-static const ctl_named_node_t *
-stats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j)
-{
-
- if (j > NBINS)
- return (NULL);
- return (super_stats_arenas_i_bins_j_node);
-}
-
-CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,
- ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,
- ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,
- ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,
- ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)
-
-static const ctl_named_node_t *
-stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j)
-{
-
- if (j > nlclasses)
- return (NULL);
- return (super_stats_arenas_i_lruns_j_node);
-}
-
-CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)
-CTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)
-CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
-CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
- ctl_stats.arenas[mib[2]].astats.mapped, size_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
- ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
- ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)
-CTL_RO_CGEN(config_stats, stats_arenas_i_purged,
- ctl_stats.arenas[mib[2]].astats.purged, uint64_t)
-
-static const ctl_named_node_t *
-stats_arenas_i_index(const size_t *mib, size_t miblen, size_t i)
-{
- const ctl_named_node_t * ret;
-
- malloc_mutex_lock(&ctl_mtx);
- if (i > ctl_stats.narenas || ctl_stats.arenas[i].initialized == false) {
- ret = NULL;
- goto label_return;
- }
-
- ret = super_stats_arenas_i_node;
-label_return:
- malloc_mutex_unlock(&ctl_mtx);
- return (ret);
-}
-
-CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)
-CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)
-CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
-CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)
diff --git a/extra/jemalloc/src/extent.c b/extra/jemalloc/src/extent.c
deleted file mode 100644
index 8c09b486ed8..00000000000
--- a/extra/jemalloc/src/extent.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#define JEMALLOC_EXTENT_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-
-static inline int
-extent_szad_comp(extent_node_t *a, extent_node_t *b)
-{
- int ret;
- size_t a_size = a->size;
- size_t b_size = b->size;
-
- ret = (a_size > b_size) - (a_size < b_size);
- if (ret == 0) {
- uintptr_t a_addr = (uintptr_t)a->addr;
- uintptr_t b_addr = (uintptr_t)b->addr;
-
- ret = (a_addr > b_addr) - (a_addr < b_addr);
- }
-
- return (ret);
-}
-
-/* Generate red-black tree functions. */
-rb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, link_szad,
- extent_szad_comp)
-
-static inline int
-extent_ad_comp(extent_node_t *a, extent_node_t *b)
-{
- uintptr_t a_addr = (uintptr_t)a->addr;
- uintptr_t b_addr = (uintptr_t)b->addr;
-
- return ((a_addr > b_addr) - (a_addr < b_addr));
-}
-
-/* Generate red-black tree functions. */
-rb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad,
- extent_ad_comp)
diff --git a/extra/jemalloc/src/hash.c b/extra/jemalloc/src/hash.c
deleted file mode 100644
index cfa4da0275c..00000000000
--- a/extra/jemalloc/src/hash.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define JEMALLOC_HASH_C_
-#include "jemalloc/internal/jemalloc_internal.h"
diff --git a/extra/jemalloc/src/huge.c b/extra/jemalloc/src/huge.c
deleted file mode 100644
index aa08d43d362..00000000000
--- a/extra/jemalloc/src/huge.c
+++ /dev/null
@@ -1,313 +0,0 @@
-#define JEMALLOC_HUGE_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Data. */
-
-uint64_t huge_nmalloc;
-uint64_t huge_ndalloc;
-size_t huge_allocated;
-
-malloc_mutex_t huge_mtx;
-
-/******************************************************************************/
-
-/* Tree of chunks that are stand-alone huge allocations. */
-static extent_tree_t huge;
-
-void *
-huge_malloc(size_t size, bool zero)
-{
-
- return (huge_palloc(size, chunksize, zero));
-}
-
-void *
-huge_palloc(size_t size, size_t alignment, bool zero)
-{
- void *ret;
- size_t csize;
- extent_node_t *node;
- bool is_zeroed;
-
- /* Allocate one or more contiguous chunks for this request. */
-
- csize = CHUNK_CEILING(size);
- if (csize == 0) {
- /* size is large enough to cause size_t wrap-around. */
- return (NULL);
- }
-
- /* Allocate an extent node with which to track the chunk. */
- node = base_node_alloc();
- if (node == NULL)
- return (NULL);
-
- /*
- * Copy zero into is_zeroed and pass the copy to chunk_alloc(), so that
- * it is possible to make correct junk/zero fill decisions below.
- */
- is_zeroed = zero;
- ret = chunk_alloc(csize, alignment, false, &is_zeroed,
- chunk_dss_prec_get());
- if (ret == NULL) {
- base_node_dealloc(node);
- return (NULL);
- }
-
- /* Insert node into huge. */
- node->addr = ret;
- node->size = csize;
-
- malloc_mutex_lock(&huge_mtx);
- extent_tree_ad_insert(&huge, node);
- if (config_stats) {
- stats_cactive_add(csize);
- huge_nmalloc++;
- huge_allocated += csize;
- }
- malloc_mutex_unlock(&huge_mtx);
-
- if (config_fill && zero == false) {
- if (opt_junk)
- memset(ret, 0xa5, csize);
- else if (opt_zero && is_zeroed == false)
- memset(ret, 0, csize);
- }
-
- return (ret);
-}
-
-void *
-huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra)
-{
-
- /*
- * Avoid moving the allocation if the size class can be left the same.
- */
- if (oldsize > arena_maxclass
- && CHUNK_CEILING(oldsize) >= CHUNK_CEILING(size)
- && CHUNK_CEILING(oldsize) <= CHUNK_CEILING(size+extra)) {
- assert(CHUNK_CEILING(oldsize) == oldsize);
- if (config_fill && opt_junk && size < oldsize) {
- memset((void *)((uintptr_t)ptr + size), 0x5a,
- oldsize - size);
- }
- return (ptr);
- }
-
- /* Reallocation would require a move. */
- return (NULL);
-}
-
-void *
-huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
- size_t alignment, bool zero, bool try_tcache_dalloc)
-{
- void *ret;
- size_t copysize;
-
- /* Try to avoid moving the allocation. */
- ret = huge_ralloc_no_move(ptr, oldsize, size, extra);
- if (ret != NULL)
- return (ret);
-
- /*
- * size and oldsize are different enough that we need to use a
- * different size class. In that case, fall back to allocating new
- * space and copying.
- */
- if (alignment > chunksize)
- ret = huge_palloc(size + extra, alignment, zero);
- else
- ret = huge_malloc(size + extra, zero);
-
- if (ret == NULL) {
- if (extra == 0)
- return (NULL);
- /* Try again, this time without extra. */
- if (alignment > chunksize)
- ret = huge_palloc(size, alignment, zero);
- else
- ret = huge_malloc(size, zero);
-
- if (ret == NULL)
- return (NULL);
- }
-
- /*
- * Copy at most size bytes (not size+extra), since the caller has no
- * expectation that the extra bytes will be reliably preserved.
- */
- copysize = (size < oldsize) ? size : oldsize;
-
-#ifdef JEMALLOC_MREMAP
- /*
- * Use mremap(2) if this is a huge-->huge reallocation, and neither the
- * source nor the destination are in dss.
- */
- if (oldsize >= chunksize && (config_dss == false || (chunk_in_dss(ptr)
- == false && chunk_in_dss(ret) == false))) {
- size_t newsize = huge_salloc(ret);
-
- /*
- * Remove ptr from the tree of huge allocations before
- * performing the remap operation, in order to avoid the
- * possibility of another thread acquiring that mapping before
- * this one removes it from the tree.
- */
- huge_dalloc(ptr, false);
- if (mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE|MREMAP_FIXED,
- ret) == MAP_FAILED) {
- /*
- * Assuming no chunk management bugs in the allocator,
- * the only documented way an error can occur here is
- * if the application changed the map type for a
- * portion of the old allocation. This is firmly in
- * undefined behavior territory, so write a diagnostic
- * message, and optionally abort.
- */
- char buf[BUFERROR_BUF];
-
- buferror(buf, sizeof(buf));
- malloc_printf("<jemalloc>: Error in mremap(): %s\n",
- buf);
- if (opt_abort)
- abort();
- memcpy(ret, ptr, copysize);
- chunk_dealloc_mmap(ptr, oldsize);
- }
- } else
-#endif
- {
- memcpy(ret, ptr, copysize);
- iqallocx(ptr, try_tcache_dalloc);
- }
- return (ret);
-}
-
-void
-huge_dalloc(void *ptr, bool unmap)
-{
- extent_node_t *node, key;
-
- malloc_mutex_lock(&huge_mtx);
-
- /* Extract from tree of huge allocations. */
- key.addr = ptr;
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
- assert(node->addr == ptr);
- extent_tree_ad_remove(&huge, node);
-
- if (config_stats) {
- stats_cactive_sub(node->size);
- huge_ndalloc++;
- huge_allocated -= node->size;
- }
-
- malloc_mutex_unlock(&huge_mtx);
-
- if (unmap && config_fill && config_dss && opt_junk)
- memset(node->addr, 0x5a, node->size);
-
- chunk_dealloc(node->addr, node->size, unmap);
-
- base_node_dealloc(node);
-}
-
-size_t
-huge_salloc(const void *ptr)
-{
- size_t ret;
- extent_node_t *node, key;
-
- malloc_mutex_lock(&huge_mtx);
-
- /* Extract from tree of huge allocations. */
- key.addr = __DECONST(void *, ptr);
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
-
- ret = node->size;
-
- malloc_mutex_unlock(&huge_mtx);
-
- return (ret);
-}
-
-prof_ctx_t *
-huge_prof_ctx_get(const void *ptr)
-{
- prof_ctx_t *ret;
- extent_node_t *node, key;
-
- malloc_mutex_lock(&huge_mtx);
-
- /* Extract from tree of huge allocations. */
- key.addr = __DECONST(void *, ptr);
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
-
- ret = node->prof_ctx;
-
- malloc_mutex_unlock(&huge_mtx);
-
- return (ret);
-}
-
-void
-huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx)
-{
- extent_node_t *node, key;
-
- malloc_mutex_lock(&huge_mtx);
-
- /* Extract from tree of huge allocations. */
- key.addr = __DECONST(void *, ptr);
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
-
- node->prof_ctx = ctx;
-
- malloc_mutex_unlock(&huge_mtx);
-}
-
-bool
-huge_boot(void)
-{
-
- /* Initialize chunks data. */
- if (malloc_mutex_init(&huge_mtx))
- return (true);
- extent_tree_ad_new(&huge);
-
- if (config_stats) {
- huge_nmalloc = 0;
- huge_ndalloc = 0;
- huge_allocated = 0;
- }
-
- return (false);
-}
-
-void
-huge_prefork(void)
-{
-
- malloc_mutex_prefork(&huge_mtx);
-}
-
-void
-huge_postfork_parent(void)
-{
-
- malloc_mutex_postfork_parent(&huge_mtx);
-}
-
-void
-huge_postfork_child(void)
-{
-
- malloc_mutex_postfork_child(&huge_mtx);
-}
diff --git a/extra/jemalloc/src/jemalloc.c b/extra/jemalloc/src/jemalloc.c
deleted file mode 100644
index bc350ed953b..00000000000
--- a/extra/jemalloc/src/jemalloc.c
+++ /dev/null
@@ -1,1868 +0,0 @@
-#define JEMALLOC_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Data. */
-
-malloc_tsd_data(, arenas, arena_t *, NULL)
-malloc_tsd_data(, thread_allocated, thread_allocated_t,
- THREAD_ALLOCATED_INITIALIZER)
-
-/* Runtime configuration options. */
-const char *je_malloc_conf;
-bool opt_abort =
-#ifdef JEMALLOC_DEBUG
- true
-#else
- false
-#endif
- ;
-bool opt_junk =
-#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
- true
-#else
- false
-#endif
- ;
-size_t opt_quarantine = ZU(0);
-bool opt_redzone = false;
-bool opt_utrace = false;
-bool opt_valgrind = false;
-bool opt_xmalloc = false;
-bool opt_zero = false;
-size_t opt_narenas = 0;
-
-unsigned ncpus;
-
-malloc_mutex_t arenas_lock;
-arena_t **arenas;
-unsigned narenas_total;
-unsigned narenas_auto;
-
-/* Set to true once the allocator has been initialized. */
-static bool malloc_initialized = false;
-
-#ifdef JEMALLOC_THREADED_INIT
-/* Used to let the initializing thread recursively allocate. */
-# define NO_INITIALIZER ((unsigned long)0)
-# define INITIALIZER pthread_self()
-# define IS_INITIALIZER (malloc_initializer == pthread_self())
-static pthread_t malloc_initializer = NO_INITIALIZER;
-#else
-# define NO_INITIALIZER false
-# define INITIALIZER true
-# define IS_INITIALIZER malloc_initializer
-static bool malloc_initializer = NO_INITIALIZER;
-#endif
-
-/* Used to avoid initialization races. */
-#ifdef _WIN32
-static malloc_mutex_t init_lock;
-
-JEMALLOC_ATTR(constructor)
-static void WINAPI
-_init_init_lock(void)
-{
-
- malloc_mutex_init(&init_lock);
-}
-
-#ifdef _MSC_VER
-# pragma section(".CRT$XCU", read)
-JEMALLOC_SECTION(".CRT$XCU") JEMALLOC_ATTR(used)
-static const void (WINAPI *init_init_lock)(void) = _init_init_lock;
-#endif
-
-#else
-static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER;
-#endif
-
-typedef struct {
- void *p; /* Input pointer (as in realloc(p, s)). */
- size_t s; /* Request size. */
- void *r; /* Result pointer. */
-} malloc_utrace_t;
-
-#ifdef JEMALLOC_UTRACE
-# define UTRACE(a, b, c) do { \
- if (opt_utrace) { \
- int utrace_serrno = errno; \
- malloc_utrace_t ut; \
- ut.p = (a); \
- ut.s = (b); \
- ut.r = (c); \
- utrace(&ut, sizeof(ut)); \
- errno = utrace_serrno; \
- } \
-} while (0)
-#else
-# define UTRACE(a, b, c)
-#endif
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static void stats_print_atexit(void);
-static unsigned malloc_ncpus(void);
-static bool malloc_conf_next(char const **opts_p, char const **k_p,
- size_t *klen_p, char const **v_p, size_t *vlen_p);
-static void malloc_conf_error(const char *msg, const char *k, size_t klen,
- const char *v, size_t vlen);
-static void malloc_conf_init(void);
-static bool malloc_init_hard(void);
-static int imemalign(void **memptr, size_t alignment, size_t size,
- size_t min_alignment);
-
-/******************************************************************************/
-/*
- * Begin miscellaneous support functions.
- */
-
-/* Create a new arena and insert it into the arenas array at index ind. */
-arena_t *
-arenas_extend(unsigned ind)
-{
- arena_t *ret;
-
- ret = (arena_t *)base_alloc(sizeof(arena_t));
- if (ret != NULL && arena_new(ret, ind) == false) {
- arenas[ind] = ret;
- return (ret);
- }
- /* Only reached if there is an OOM error. */
-
- /*
- * OOM here is quite inconvenient to propagate, since dealing with it
- * would require a check for failure in the fast path. Instead, punt
- * by using arenas[0]. In practice, this is an extremely unlikely
- * failure.
- */
- malloc_write("<jemalloc>: Error initializing arena\n");
- if (opt_abort)
- abort();
-
- return (arenas[0]);
-}
-
-/* Slow path, called only by choose_arena(). */
-arena_t *
-choose_arena_hard(void)
-{
- arena_t *ret;
-
- if (narenas_auto > 1) {
- unsigned i, choose, first_null;
-
- choose = 0;
- first_null = narenas_auto;
- malloc_mutex_lock(&arenas_lock);
- assert(arenas[0] != NULL);
- for (i = 1; i < narenas_auto; i++) {
- if (arenas[i] != NULL) {
- /*
- * Choose the first arena that has the lowest
- * number of threads assigned to it.
- */
- if (arenas[i]->nthreads <
- arenas[choose]->nthreads)
- choose = i;
- } else if (first_null == narenas_auto) {
- /*
- * Record the index of the first uninitialized
- * arena, in case all extant arenas are in use.
- *
- * NB: It is possible for there to be
- * discontinuities in terms of initialized
- * versus uninitialized arenas, due to the
- * "thread.arena" mallctl.
- */
- first_null = i;
- }
- }
-
- if (arenas[choose]->nthreads == 0
- || first_null == narenas_auto) {
- /*
- * Use an unloaded arena, or the least loaded arena if
- * all arenas are already initialized.
- */
- ret = arenas[choose];
- } else {
- /* Initialize a new arena. */
- ret = arenas_extend(first_null);
- }
- ret->nthreads++;
- malloc_mutex_unlock(&arenas_lock);
- } else {
- ret = arenas[0];
- malloc_mutex_lock(&arenas_lock);
- ret->nthreads++;
- malloc_mutex_unlock(&arenas_lock);
- }
-
- arenas_tsd_set(&ret);
-
- return (ret);
-}
-
-static void
-stats_print_atexit(void)
-{
-
- if (config_tcache && config_stats) {
- unsigned narenas, i;
-
- /*
- * Merge stats from extant threads. This is racy, since
- * individual threads do not lock when recording tcache stats
- * events. As a consequence, the final stats may be slightly
- * out of date by the time they are reported, if other threads
- * continue to allocate.
- */
- for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
- arena_t *arena = arenas[i];
- if (arena != NULL) {
- tcache_t *tcache;
-
- /*
- * tcache_stats_merge() locks bins, so if any
- * code is introduced that acquires both arena
- * and bin locks in the opposite order,
- * deadlocks may result.
- */
- malloc_mutex_lock(&arena->lock);
- ql_foreach(tcache, &arena->tcache_ql, link) {
- tcache_stats_merge(tcache, arena);
- }
- malloc_mutex_unlock(&arena->lock);
- }
- }
- }
- je_malloc_stats_print(NULL, NULL, NULL);
-}
-
-/*
- * End miscellaneous support functions.
- */
-/******************************************************************************/
-/*
- * Begin initialization functions.
- */
-
-static unsigned
-malloc_ncpus(void)
-{
- unsigned ret;
- long result;
-
-#ifdef _WIN32
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- result = si.dwNumberOfProcessors;
-#else
- result = sysconf(_SC_NPROCESSORS_ONLN);
-#endif
- if (result == -1) {
- /* Error. */
- ret = 1;
- } else {
- ret = (unsigned)result;
- }
-
- return (ret);
-}
-
-void
-arenas_cleanup(void *arg)
-{
- arena_t *arena = *(arena_t **)arg;
-
- malloc_mutex_lock(&arenas_lock);
- arena->nthreads--;
- malloc_mutex_unlock(&arenas_lock);
-}
-
-static JEMALLOC_ATTR(always_inline) void
-malloc_thread_init(void)
-{
-
- /*
- * TSD initialization can't be safely done as a side effect of
- * deallocation, because it is possible for a thread to do nothing but
- * deallocate its TLS data via free(), in which case writing to TLS
- * would cause write-after-free memory corruption. The quarantine
- * facility *only* gets used as a side effect of deallocation, so make
- * a best effort attempt at initializing its TSD by hooking all
- * allocation events.
- */
- if (config_fill && opt_quarantine)
- quarantine_alloc_hook();
-}
-
-static JEMALLOC_ATTR(always_inline) bool
-malloc_init(void)
-{
-
- if (malloc_initialized == false && malloc_init_hard())
- return (true);
- malloc_thread_init();
-
- return (false);
-}
-
-static bool
-malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p,
- char const **v_p, size_t *vlen_p)
-{
- bool accept;
- const char *opts = *opts_p;
-
- *k_p = opts;
-
- for (accept = false; accept == false;) {
- switch (*opts) {
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
- case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
- case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
- case 'Y': case 'Z':
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
- case 's': case 't': case 'u': case 'v': case 'w': case 'x':
- case 'y': case 'z':
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- case '_':
- opts++;
- break;
- case ':':
- opts++;
- *klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p;
- *v_p = opts;
- accept = true;
- break;
- case '\0':
- if (opts != *opts_p) {
- malloc_write("<jemalloc>: Conf string ends "
- "with key\n");
- }
- return (true);
- default:
- malloc_write("<jemalloc>: Malformed conf string\n");
- return (true);
- }
- }
-
- for (accept = false; accept == false;) {
- switch (*opts) {
- case ',':
- opts++;
- /*
- * Look ahead one character here, because the next time
- * this function is called, it will assume that end of
- * input has been cleanly reached if no input remains,
- * but we have optimistically already consumed the
- * comma if one exists.
- */
- if (*opts == '\0') {
- malloc_write("<jemalloc>: Conf string ends "
- "with comma\n");
- }
- *vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p;
- accept = true;
- break;
- case '\0':
- *vlen_p = (uintptr_t)opts - (uintptr_t)*v_p;
- accept = true;
- break;
- default:
- opts++;
- break;
- }
- }
-
- *opts_p = opts;
- return (false);
-}
-
-static void
-malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v,
- size_t vlen)
-{
-
- malloc_printf("<jemalloc>: %s: %.*s:%.*s\n", msg, (int)klen, k,
- (int)vlen, v);
-}
-
-static void
-malloc_conf_init(void)
-{
- unsigned i;
- char buf[PATH_MAX + 1];
- const char *opts, *k, *v;
- size_t klen, vlen;
-
- /*
- * Automatically configure valgrind before processing options. The
- * valgrind option remains in jemalloc 3.x for compatibility reasons.
- */
- if (config_valgrind) {
- opt_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false;
- if (config_fill && opt_valgrind) {
- opt_junk = false;
- assert(opt_zero == false);
- opt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT;
- opt_redzone = true;
- }
- if (config_tcache && opt_valgrind)
- opt_tcache = false;
- }
-
- for (i = 0; i < 3; i++) {
- /* Get runtime configuration. */
- switch (i) {
- case 0:
- if (je_malloc_conf != NULL) {
- /*
- * Use options that were compiled into the
- * program.
- */
- opts = je_malloc_conf;
- } else {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- case 1: {
-#ifndef _WIN32
- int linklen;
- const char *linkname =
-# ifdef JEMALLOC_PREFIX
- "/etc/"JEMALLOC_PREFIX"malloc.conf"
-# else
- "/etc/malloc.conf"
-# endif
- ;
-
- if ((linklen = readlink(linkname, buf,
- sizeof(buf) - 1)) != -1) {
- /*
- * Use the contents of the "/etc/malloc.conf"
- * symbolic link's name.
- */
- buf[linklen] = '\0';
- opts = buf;
- } else
-#endif
- {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- } case 2: {
- const char *envname =
-#ifdef JEMALLOC_PREFIX
- JEMALLOC_CPREFIX"MALLOC_CONF"
-#else
- "MALLOC_CONF"
-#endif
- ;
-
- if ((opts = getenv(envname)) != NULL) {
- /*
- * Do nothing; opts is already initialized to
- * the value of the MALLOC_CONF environment
- * variable.
- */
- } else {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- } default:
- /* NOTREACHED */
- assert(false);
- buf[0] = '\0';
- opts = buf;
- }
-
- while (*opts != '\0' && malloc_conf_next(&opts, &k, &klen, &v,
- &vlen) == false) {
-#define CONF_HANDLE_BOOL(o, n) \
- if (sizeof(n)-1 == klen && strncmp(n, k, \
- klen) == 0) { \
- if (strncmp("true", v, vlen) == 0 && \
- vlen == sizeof("true")-1) \
- o = true; \
- else if (strncmp("false", v, vlen) == \
- 0 && vlen == sizeof("false")-1) \
- o = false; \
- else { \
- malloc_conf_error( \
- "Invalid conf value", \
- k, klen, v, vlen); \
- } \
- continue; \
- }
-#define CONF_HANDLE_SIZE_T(o, n, min, max, clip) \
- if (sizeof(n)-1 == klen && strncmp(n, k, \
- klen) == 0) { \
- uintmax_t um; \
- char *end; \
- \
- set_errno(0); \
- um = malloc_strtoumax(v, &end, 0); \
- if (get_errno() != 0 || (uintptr_t)end -\
- (uintptr_t)v != vlen) { \
- malloc_conf_error( \
- "Invalid conf value", \
- k, klen, v, vlen); \
- } else if (clip) { \
- if (um < min) \
- o = min; \
- else if (um > max) \
- o = max; \
- else \
- o = um; \
- } else { \
- if (um < min || um > max) { \
- malloc_conf_error( \
- "Out-of-range " \
- "conf value", \
- k, klen, v, vlen); \
- } else \
- o = um; \
- } \
- continue; \
- }
-#define CONF_HANDLE_SSIZE_T(o, n, min, max) \
- if (sizeof(n)-1 == klen && strncmp(n, k, \
- klen) == 0) { \
- long l; \
- char *end; \
- \
- set_errno(0); \
- l = strtol(v, &end, 0); \
- if (get_errno() != 0 || (uintptr_t)end -\
- (uintptr_t)v != vlen) { \
- malloc_conf_error( \
- "Invalid conf value", \
- k, klen, v, vlen); \
- } else if (l < (ssize_t)min || l > \
- (ssize_t)max) { \
- malloc_conf_error( \
- "Out-of-range conf value", \
- k, klen, v, vlen); \
- } else \
- o = l; \
- continue; \
- }
-#define CONF_HANDLE_CHAR_P(o, n, d) \
- if (sizeof(n)-1 == klen && strncmp(n, k, \
- klen) == 0) { \
- size_t cpylen = (vlen <= \
- sizeof(o)-1) ? vlen : \
- sizeof(o)-1; \
- strncpy(o, v, cpylen); \
- o[cpylen] = '\0'; \
- continue; \
- }
-
- CONF_HANDLE_BOOL(opt_abort, "abort")
- /*
- * Chunks always require at least one header page, plus
- * one data page in the absence of redzones, or three
- * pages in the presence of redzones. In order to
- * simplify options processing, fix the limit based on
- * config_fill.
- */
- CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE +
- (config_fill ? 2 : 1), (sizeof(size_t) << 3) - 1,
- true)
- if (strncmp("dss", k, klen) == 0) {
- int i;
- bool match = false;
- for (i = 0; i < dss_prec_limit; i++) {
- if (strncmp(dss_prec_names[i], v, vlen)
- == 0) {
- if (chunk_dss_prec_set(i)) {
- malloc_conf_error(
- "Error setting dss",
- k, klen, v, vlen);
- } else {
- opt_dss =
- dss_prec_names[i];
- match = true;
- break;
- }
- }
- }
- if (match == false) {
- malloc_conf_error("Invalid conf value",
- k, klen, v, vlen);
- }
- continue;
- }
- CONF_HANDLE_SIZE_T(opt_narenas, "narenas", 1,
- SIZE_T_MAX, false)
- CONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, "lg_dirty_mult",
- -1, (sizeof(size_t) << 3) - 1)
- CONF_HANDLE_BOOL(opt_stats_print, "stats_print")
- if (config_fill) {
- CONF_HANDLE_BOOL(opt_junk, "junk")
- CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine",
- 0, SIZE_T_MAX, false)
- CONF_HANDLE_BOOL(opt_redzone, "redzone")
- CONF_HANDLE_BOOL(opt_zero, "zero")
- }
- if (config_utrace) {
- CONF_HANDLE_BOOL(opt_utrace, "utrace")
- }
- if (config_valgrind) {
- CONF_HANDLE_BOOL(opt_valgrind, "valgrind")
- }
- if (config_xmalloc) {
- CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc")
- }
- if (config_tcache) {
- CONF_HANDLE_BOOL(opt_tcache, "tcache")
- CONF_HANDLE_SSIZE_T(opt_lg_tcache_max,
- "lg_tcache_max", -1,
- (sizeof(size_t) << 3) - 1)
- }
- if (config_prof) {
- CONF_HANDLE_BOOL(opt_prof, "prof")
- CONF_HANDLE_CHAR_P(opt_prof_prefix,
- "prof_prefix", "jeprof")
- CONF_HANDLE_BOOL(opt_prof_active, "prof_active")
- CONF_HANDLE_SSIZE_T(opt_lg_prof_sample,
- "lg_prof_sample", 0,
- (sizeof(uint64_t) << 3) - 1)
- CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum")
- CONF_HANDLE_SSIZE_T(opt_lg_prof_interval,
- "lg_prof_interval", -1,
- (sizeof(uint64_t) << 3) - 1)
- CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump")
- CONF_HANDLE_BOOL(opt_prof_final, "prof_final")
- CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak")
- }
- malloc_conf_error("Invalid conf pair", k, klen, v,
- vlen);
-#undef CONF_HANDLE_BOOL
-#undef CONF_HANDLE_SIZE_T
-#undef CONF_HANDLE_SSIZE_T
-#undef CONF_HANDLE_CHAR_P
- }
- }
-}
-
-static bool
-malloc_init_hard(void)
-{
- arena_t *init_arenas[1];
-
- malloc_mutex_lock(&init_lock);
- if (malloc_initialized || IS_INITIALIZER) {
- /*
- * Another thread initialized the allocator before this one
- * acquired init_lock, or this thread is the initializing
- * thread, and it is recursively allocating.
- */
- malloc_mutex_unlock(&init_lock);
- return (false);
- }
-#ifdef JEMALLOC_THREADED_INIT
- if (malloc_initializer != NO_INITIALIZER && IS_INITIALIZER == false) {
- /* Busy-wait until the initializing thread completes. */
- do {
- malloc_mutex_unlock(&init_lock);
- CPU_SPINWAIT;
- malloc_mutex_lock(&init_lock);
- } while (malloc_initialized == false);
- malloc_mutex_unlock(&init_lock);
- return (false);
- }
-#endif
- malloc_initializer = INITIALIZER;
-
- malloc_tsd_boot();
- if (config_prof)
- prof_boot0();
-
- malloc_conf_init();
-
-#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \
- && !defined(_WIN32))
- /* Register fork handlers. */
- if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,
- jemalloc_postfork_child) != 0) {
- malloc_write("<jemalloc>: Error in pthread_atfork()\n");
- if (opt_abort)
- abort();
- }
-#endif
-
- if (opt_stats_print) {
- /* Print statistics at exit. */
- if (atexit(stats_print_atexit) != 0) {
- malloc_write("<jemalloc>: Error in atexit()\n");
- if (opt_abort)
- abort();
- }
- }
-
- if (base_boot()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (chunk_boot()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (ctl_boot()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (config_prof)
- prof_boot1();
-
- arena_boot();
-
- if (config_tcache && tcache_boot0()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (huge_boot()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (malloc_mutex_init(&arenas_lock))
- return (true);
-
- /*
- * Create enough scaffolding to allow recursive allocation in
- * malloc_ncpus().
- */
- narenas_total = narenas_auto = 1;
- arenas = init_arenas;
- memset(arenas, 0, sizeof(arena_t *) * narenas_auto);
-
- /*
- * Initialize one arena here. The rest are lazily created in
- * choose_arena_hard().
- */
- arenas_extend(0);
- if (arenas[0] == NULL) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- /* Initialize allocation counters before any allocations can occur. */
- if (config_stats && thread_allocated_tsd_boot()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (arenas_tsd_boot()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (config_tcache && tcache_boot1()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (config_fill && quarantine_boot()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (config_prof && prof_boot2()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- /* Get number of CPUs. */
- malloc_mutex_unlock(&init_lock);
- ncpus = malloc_ncpus();
- malloc_mutex_lock(&init_lock);
-
- if (mutex_boot()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
- if (opt_narenas == 0) {
- /*
- * For SMP systems, create more than one arena per CPU by
- * default.
- */
- if (ncpus > 1)
- opt_narenas = ncpus << 2;
- else
- opt_narenas = 1;
- }
- narenas_auto = opt_narenas;
- /*
- * Make sure that the arenas array can be allocated. In practice, this
- * limit is enough to allow the allocator to function, but the ctl
- * machinery will fail to allocate memory at far lower limits.
- */
- if (narenas_auto > chunksize / sizeof(arena_t *)) {
- narenas_auto = chunksize / sizeof(arena_t *);
- malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n",
- narenas_auto);
- }
- narenas_total = narenas_auto;
-
- /* Allocate and initialize arenas. */
- arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas_total);
- if (arenas == NULL) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
- /*
- * Zero the array. In practice, this should always be pre-zeroed,
- * since it was just mmap()ed, but let's be sure.
- */
- memset(arenas, 0, sizeof(arena_t *) * narenas_total);
- /* Copy the pointer to the one arena that was already initialized. */
- arenas[0] = init_arenas[0];
-
- malloc_initialized = true;
- malloc_mutex_unlock(&init_lock);
- return (false);
-}
-
-/*
- * End initialization functions.
- */
-/******************************************************************************/
-/*
- * Begin malloc(3)-compatible functions.
- */
-
-void *
-je_malloc(size_t size)
-{
- void *ret;
- size_t usize JEMALLOC_CC_SILENCE_INIT(0);
- prof_thr_cnt_t *cnt JEMALLOC_CC_SILENCE_INIT(NULL);
-
- if (malloc_init()) {
- ret = NULL;
- goto label_oom;
- }
-
- if (size == 0)
- size = 1;
-
- if (config_prof && opt_prof) {
- usize = s2u(size);
- PROF_ALLOC_PREP(1, usize, cnt);
- if (cnt == NULL) {
- ret = NULL;
- goto label_oom;
- }
- if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
- SMALL_MAXCLASS) {
- ret = imalloc(SMALL_MAXCLASS+1);
- if (ret != NULL)
- arena_prof_promoted(ret, usize);
- } else
- ret = imalloc(size);
- } else {
- if (config_stats || (config_valgrind && opt_valgrind))
- usize = s2u(size);
- ret = imalloc(size);
- }
-
-label_oom:
- if (ret == NULL) {
- if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error in malloc(): "
- "out of memory\n");
- abort();
- }
- set_errno(ENOMEM);
- }
- if (config_prof && opt_prof && ret != NULL)
- prof_malloc(ret, usize, cnt);
- if (config_stats && ret != NULL) {
- assert(usize == isalloc(ret, config_prof));
- thread_allocated_tsd_get()->allocated += usize;
- }
- UTRACE(0, size, ret);
- JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, false);
- return (ret);
-}
-
-JEMALLOC_ATTR(nonnull(1))
-#ifdef JEMALLOC_PROF
-/*
- * Avoid any uncertainty as to how many backtrace frames to ignore in
- * PROF_ALLOC_PREP().
- */
-JEMALLOC_NOINLINE
-#endif
-static int
-imemalign(void **memptr, size_t alignment, size_t size,
- size_t min_alignment)
-{
- int ret;
- size_t usize;
- void *result;
- prof_thr_cnt_t *cnt JEMALLOC_CC_SILENCE_INIT(NULL);
-
- assert(min_alignment != 0);
-
- if (malloc_init())
- result = NULL;
- else {
- if (size == 0)
- size = 1;
-
- /* Make sure that alignment is a large enough power of 2. */
- if (((alignment - 1) & alignment) != 0
- || (alignment < min_alignment)) {
- if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error allocating "
- "aligned memory: invalid alignment\n");
- abort();
- }
- result = NULL;
- ret = EINVAL;
- goto label_return;
- }
-
- usize = sa2u(size, alignment);
- if (usize == 0) {
- result = NULL;
- ret = ENOMEM;
- goto label_return;
- }
-
- if (config_prof && opt_prof) {
- PROF_ALLOC_PREP(2, usize, cnt);
- if (cnt == NULL) {
- result = NULL;
- ret = EINVAL;
- } else {
- if (prof_promote && (uintptr_t)cnt !=
- (uintptr_t)1U && usize <= SMALL_MAXCLASS) {
- assert(sa2u(SMALL_MAXCLASS+1,
- alignment) != 0);
- result = ipalloc(sa2u(SMALL_MAXCLASS+1,
- alignment), alignment, false);
- if (result != NULL) {
- arena_prof_promoted(result,
- usize);
- }
- } else {
- result = ipalloc(usize, alignment,
- false);
- }
- }
- } else
- result = ipalloc(usize, alignment, false);
- }
-
- if (result == NULL) {
- if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error allocating aligned "
- "memory: out of memory\n");
- abort();
- }
- ret = ENOMEM;
- goto label_return;
- }
-
- *memptr = result;
- ret = 0;
-
-label_return:
- if (config_stats && result != NULL) {
- assert(usize == isalloc(result, config_prof));
- thread_allocated_tsd_get()->allocated += usize;
- }
- if (config_prof && opt_prof && result != NULL)
- prof_malloc(result, usize, cnt);
- UTRACE(0, size, result);
- return (ret);
-}
-
-int
-je_posix_memalign(void **memptr, size_t alignment, size_t size)
-{
- int ret = imemalign(memptr, alignment, size, sizeof(void *));
- JEMALLOC_VALGRIND_MALLOC(ret == 0, *memptr, isalloc(*memptr,
- config_prof), false);
- return (ret);
-}
-
-void *
-je_aligned_alloc(size_t alignment, size_t size)
-{
- void *ret;
- int err;
-
- if ((err = imemalign(&ret, alignment, size, 1)) != 0) {
- ret = NULL;
- set_errno(err);
- }
- JEMALLOC_VALGRIND_MALLOC(err == 0, ret, isalloc(ret, config_prof),
- false);
- return (ret);
-}
-
-void *
-je_calloc(size_t num, size_t size)
-{
- void *ret;
- size_t num_size;
- size_t usize JEMALLOC_CC_SILENCE_INIT(0);
- prof_thr_cnt_t *cnt JEMALLOC_CC_SILENCE_INIT(NULL);
-
- if (malloc_init()) {
- num_size = 0;
- ret = NULL;
- goto label_return;
- }
-
- num_size = num * size;
- if (num_size == 0) {
- if (num == 0 || size == 0)
- num_size = 1;
- else {
- ret = NULL;
- goto label_return;
- }
- /*
- * Try to avoid division here. We know that it isn't possible to
- * overflow during multiplication if neither operand uses any of the
- * most significant half of the bits in a size_t.
- */
- } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
- && (num_size / size != num)) {
- /* size_t overflow. */
- ret = NULL;
- goto label_return;
- }
-
- if (config_prof && opt_prof) {
- usize = s2u(num_size);
- PROF_ALLOC_PREP(1, usize, cnt);
- if (cnt == NULL) {
- ret = NULL;
- goto label_return;
- }
- if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize
- <= SMALL_MAXCLASS) {
- ret = icalloc(SMALL_MAXCLASS+1);
- if (ret != NULL)
- arena_prof_promoted(ret, usize);
- } else
- ret = icalloc(num_size);
- } else {
- if (config_stats || (config_valgrind && opt_valgrind))
- usize = s2u(num_size);
- ret = icalloc(num_size);
- }
-
-label_return:
- if (ret == NULL) {
- if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error in calloc(): out of "
- "memory\n");
- abort();
- }
- set_errno(ENOMEM);
- }
-
- if (config_prof && opt_prof && ret != NULL)
- prof_malloc(ret, usize, cnt);
- if (config_stats && ret != NULL) {
- assert(usize == isalloc(ret, config_prof));
- thread_allocated_tsd_get()->allocated += usize;
- }
- UTRACE(0, num_size, ret);
- JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, true);
- return (ret);
-}
-
-void *
-je_realloc(void *ptr, size_t size)
-{
- void *ret;
- size_t usize JEMALLOC_CC_SILENCE_INIT(0);
- size_t old_size = 0;
- size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
- prof_thr_cnt_t *cnt JEMALLOC_CC_SILENCE_INIT(NULL);
- prof_ctx_t *old_ctx JEMALLOC_CC_SILENCE_INIT(NULL);
-
- if (size == 0) {
- if (ptr != NULL) {
- /* realloc(ptr, 0) is equivalent to free(p). */
- assert(malloc_initialized || IS_INITIALIZER);
- if (config_prof) {
- old_size = isalloc(ptr, true);
- if (config_valgrind && opt_valgrind)
- old_rzsize = p2rz(ptr);
- } else if (config_stats) {
- old_size = isalloc(ptr, false);
- if (config_valgrind && opt_valgrind)
- old_rzsize = u2rz(old_size);
- } else if (config_valgrind && opt_valgrind) {
- old_size = isalloc(ptr, false);
- old_rzsize = u2rz(old_size);
- }
- if (config_prof && opt_prof) {
- old_ctx = prof_ctx_get(ptr);
- cnt = NULL;
- }
- iqalloc(ptr);
- ret = NULL;
- goto label_return;
- } else
- size = 1;
- }
-
- if (ptr != NULL) {
- assert(malloc_initialized || IS_INITIALIZER);
- malloc_thread_init();
-
- if (config_prof) {
- old_size = isalloc(ptr, true);
- if (config_valgrind && opt_valgrind)
- old_rzsize = p2rz(ptr);
- } else if (config_stats) {
- old_size = isalloc(ptr, false);
- if (config_valgrind && opt_valgrind)
- old_rzsize = u2rz(old_size);
- } else if (config_valgrind && opt_valgrind) {
- old_size = isalloc(ptr, false);
- old_rzsize = u2rz(old_size);
- }
- if (config_prof && opt_prof) {
- usize = s2u(size);
- old_ctx = prof_ctx_get(ptr);
- PROF_ALLOC_PREP(1, usize, cnt);
- if (cnt == NULL) {
- old_ctx = NULL;
- ret = NULL;
- goto label_oom;
- }
- if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U &&
- usize <= SMALL_MAXCLASS) {
- ret = iralloc(ptr, SMALL_MAXCLASS+1, 0, 0,
- false, false);
- if (ret != NULL)
- arena_prof_promoted(ret, usize);
- else
- old_ctx = NULL;
- } else {
- ret = iralloc(ptr, size, 0, 0, false, false);
- if (ret == NULL)
- old_ctx = NULL;
- }
- } else {
- if (config_stats || (config_valgrind && opt_valgrind))
- usize = s2u(size);
- ret = iralloc(ptr, size, 0, 0, false, false);
- }
-
-label_oom:
- if (ret == NULL) {
- if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error in realloc(): "
- "out of memory\n");
- abort();
- }
- set_errno(ENOMEM);
- }
- } else {
- /* realloc(NULL, size) is equivalent to malloc(size). */
- if (config_prof && opt_prof)
- old_ctx = NULL;
- if (malloc_init()) {
- if (config_prof && opt_prof)
- cnt = NULL;
- ret = NULL;
- } else {
- if (config_prof && opt_prof) {
- usize = s2u(size);
- PROF_ALLOC_PREP(1, usize, cnt);
- if (cnt == NULL)
- ret = NULL;
- else {
- if (prof_promote && (uintptr_t)cnt !=
- (uintptr_t)1U && usize <=
- SMALL_MAXCLASS) {
- ret = imalloc(SMALL_MAXCLASS+1);
- if (ret != NULL) {
- arena_prof_promoted(ret,
- usize);
- }
- } else
- ret = imalloc(size);
- }
- } else {
- if (config_stats || (config_valgrind &&
- opt_valgrind))
- usize = s2u(size);
- ret = imalloc(size);
- }
- }
-
- if (ret == NULL) {
- if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error in realloc(): "
- "out of memory\n");
- abort();
- }
- set_errno(ENOMEM);
- }
- }
-
-label_return:
- if (config_prof && opt_prof)
- prof_realloc(ret, usize, cnt, old_size, old_ctx);
- if (config_stats && ret != NULL) {
- thread_allocated_t *ta;
- assert(usize == isalloc(ret, config_prof));
- ta = thread_allocated_tsd_get();
- ta->allocated += usize;
- ta->deallocated += old_size;
- }
- UTRACE(ptr, size, ret);
- JEMALLOC_VALGRIND_REALLOC(ret, usize, ptr, old_size, old_rzsize, false);
- return (ret);
-}
-
-void
-je_free(void *ptr)
-{
-
- UTRACE(ptr, 0, 0);
- if (ptr != NULL) {
- size_t usize;
- size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);
-
- assert(malloc_initialized || IS_INITIALIZER);
-
- if (config_prof && opt_prof) {
- usize = isalloc(ptr, config_prof);
- prof_free(ptr, usize);
- } else if (config_stats || config_valgrind)
- usize = isalloc(ptr, config_prof);
- if (config_stats)
- thread_allocated_tsd_get()->deallocated += usize;
- if (config_valgrind && opt_valgrind)
- rzsize = p2rz(ptr);
- iqalloc(ptr);
- JEMALLOC_VALGRIND_FREE(ptr, rzsize);
- }
-}
-
-/*
- * End malloc(3)-compatible functions.
- */
-/******************************************************************************/
-/*
- * Begin non-standard override functions.
- */
-
-#ifdef JEMALLOC_OVERRIDE_MEMALIGN
-void *
-je_memalign(size_t alignment, size_t size)
-{
- void *ret JEMALLOC_CC_SILENCE_INIT(NULL);
- imemalign(&ret, alignment, size, 1);
- JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false);
- return (ret);
-}
-#endif
-
-#ifdef JEMALLOC_OVERRIDE_VALLOC
-void *
-je_valloc(size_t size)
-{
- void *ret JEMALLOC_CC_SILENCE_INIT(NULL);
- imemalign(&ret, PAGE, size, 1);
- JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false);
- return (ret);
-}
-#endif
-
-/*
- * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has
- * #define je_malloc malloc
- */
-#define malloc_is_malloc 1
-#define is_malloc_(a) malloc_is_ ## a
-#define is_malloc(a) is_malloc_(a)
-
-#if ((is_malloc(je_malloc) == 1) && defined(__GLIBC__) && !defined(__UCLIBC__))
-/*
- * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
- * to inconsistently reference libc's malloc(3)-compatible functions
- * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).
- *
- * These definitions interpose hooks in glibc. The functions are actually
- * passed an extra argument for the caller return address, which will be
- * ignored.
- */
-JEMALLOC_EXPORT void (* __free_hook)(void *ptr) = je_free;
-JEMALLOC_EXPORT void *(* __malloc_hook)(size_t size) = je_malloc;
-JEMALLOC_EXPORT void *(* __realloc_hook)(void *ptr, size_t size) = je_realloc;
-JEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) =
- je_memalign;
-#endif
-
-/*
- * End non-standard override functions.
- */
-/******************************************************************************/
-/*
- * Begin non-standard functions.
- */
-
-size_t
-je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
-{
- size_t ret;
-
- assert(malloc_initialized || IS_INITIALIZER);
- malloc_thread_init();
-
- if (config_ivsalloc)
- ret = ivsalloc(ptr, config_prof);
- else
- ret = (ptr != NULL) ? isalloc(ptr, config_prof) : 0;
-
- return (ret);
-}
-
-void
-je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
- const char *opts)
-{
-
- stats_print(write_cb, cbopaque, opts);
-}
-
-int
-je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,
- size_t newlen)
-{
-
- if (malloc_init())
- return (EAGAIN);
-
- return (ctl_byname(name, oldp, oldlenp, newp, newlen));
-}
-
-int
-je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp)
-{
-
- if (malloc_init())
- return (EAGAIN);
-
- return (ctl_nametomib(name, mibp, miblenp));
-}
-
-int
-je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen)
-{
-
- if (malloc_init())
- return (EAGAIN);
-
- return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen));
-}
-
-/*
- * End non-standard functions.
- */
-/******************************************************************************/
-/*
- * Begin experimental functions.
- */
-#ifdef JEMALLOC_EXPERIMENTAL
-
-static JEMALLOC_ATTR(always_inline) void *
-iallocm(size_t usize, size_t alignment, bool zero, bool try_tcache,
- arena_t *arena)
-{
-
- assert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize,
- alignment)));
-
- if (alignment != 0)
- return (ipallocx(usize, alignment, zero, try_tcache, arena));
- else if (zero)
- return (icallocx(usize, try_tcache, arena));
- else
- return (imallocx(usize, try_tcache, arena));
-}
-
-int
-je_allocm(void **ptr, size_t *rsize, size_t size, int flags)
-{
- void *p;
- size_t usize;
- size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
- & (SIZE_T_MAX-1));
- bool zero = flags & ALLOCM_ZERO;
- unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
- arena_t *arena;
- bool try_tcache;
-
- assert(ptr != NULL);
- assert(size != 0);
-
- if (malloc_init())
- goto label_oom;
-
- if (arena_ind != UINT_MAX) {
- arena = arenas[arena_ind];
- try_tcache = false;
- } else {
- arena = NULL;
- try_tcache = true;
- }
-
- usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
- if (usize == 0)
- goto label_oom;
-
- if (config_prof && opt_prof) {
- prof_thr_cnt_t *cnt;
-
- PROF_ALLOC_PREP(1, usize, cnt);
- if (cnt == NULL)
- goto label_oom;
- if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
- SMALL_MAXCLASS) {
- size_t usize_promoted = (alignment == 0) ?
- s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1,
- alignment);
- assert(usize_promoted != 0);
- p = iallocm(usize_promoted, alignment, zero,
- try_tcache, arena);
- if (p == NULL)
- goto label_oom;
- arena_prof_promoted(p, usize);
- } else {
- p = iallocm(usize, alignment, zero, try_tcache, arena);
- if (p == NULL)
- goto label_oom;
- }
- prof_malloc(p, usize, cnt);
- } else {
- p = iallocm(usize, alignment, zero, try_tcache, arena);
- if (p == NULL)
- goto label_oom;
- }
- if (rsize != NULL)
- *rsize = usize;
-
- *ptr = p;
- if (config_stats) {
- assert(usize == isalloc(p, config_prof));
- thread_allocated_tsd_get()->allocated += usize;
- }
- UTRACE(0, size, p);
- JEMALLOC_VALGRIND_MALLOC(true, p, usize, zero);
- return (ALLOCM_SUCCESS);
-label_oom:
- if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error in allocm(): "
- "out of memory\n");
- abort();
- }
- *ptr = NULL;
- UTRACE(0, size, 0);
- return (ALLOCM_ERR_OOM);
-}
-
-int
-je_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags)
-{
- void *p, *q;
- size_t usize;
- size_t old_size;
- size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0);
- size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
- & (SIZE_T_MAX-1));
- bool zero = flags & ALLOCM_ZERO;
- bool no_move = flags & ALLOCM_NO_MOVE;
- unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
- bool try_tcache_alloc, try_tcache_dalloc;
- arena_t *arena;
-
- assert(ptr != NULL);
- assert(*ptr != NULL);
- assert(size != 0);
- assert(SIZE_T_MAX - size >= extra);
- assert(malloc_initialized || IS_INITIALIZER);
- malloc_thread_init();
-
- if (arena_ind != UINT_MAX) {
- arena_chunk_t *chunk;
- try_tcache_alloc = true;
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(*ptr);
- try_tcache_dalloc = (chunk == *ptr || chunk->arena !=
- arenas[arena_ind]);
- arena = arenas[arena_ind];
- } else {
- try_tcache_alloc = true;
- try_tcache_dalloc = true;
- arena = NULL;
- }
-
- p = *ptr;
- if (config_prof && opt_prof) {
- prof_thr_cnt_t *cnt;
-
- /*
- * usize isn't knowable before iralloc() returns when extra is
- * non-zero. Therefore, compute its maximum possible value and
- * use that in PROF_ALLOC_PREP() to decide whether to capture a
- * backtrace. prof_realloc() will use the actual usize to
- * decide whether to sample.
- */
- size_t max_usize = (alignment == 0) ? s2u(size+extra) :
- sa2u(size+extra, alignment);
- prof_ctx_t *old_ctx = prof_ctx_get(p);
- old_size = isalloc(p, true);
- if (config_valgrind && opt_valgrind)
- old_rzsize = p2rz(p);
- PROF_ALLOC_PREP(1, max_usize, cnt);
- if (cnt == NULL)
- goto label_oom;
- /*
- * Use minimum usize to determine whether promotion may happen.
- */
- if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U
- && ((alignment == 0) ? s2u(size) : sa2u(size, alignment))
- <= SMALL_MAXCLASS) {
- q = irallocx(p, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >=
- size+extra) ? 0 : size+extra - (SMALL_MAXCLASS+1),
- alignment, zero, no_move, try_tcache_alloc,
- try_tcache_dalloc, arena);
- if (q == NULL)
- goto label_err;
- if (max_usize < PAGE) {
- usize = max_usize;
- arena_prof_promoted(q, usize);
- } else
- usize = isalloc(q, config_prof);
- } else {
- q = irallocx(p, size, extra, alignment, zero, no_move,
- try_tcache_alloc, try_tcache_dalloc, arena);
- if (q == NULL)
- goto label_err;
- usize = isalloc(q, config_prof);
- }
- prof_realloc(q, usize, cnt, old_size, old_ctx);
- if (rsize != NULL)
- *rsize = usize;
- } else {
- if (config_stats) {
- old_size = isalloc(p, false);
- if (config_valgrind && opt_valgrind)
- old_rzsize = u2rz(old_size);
- } else if (config_valgrind && opt_valgrind) {
- old_size = isalloc(p, false);
- old_rzsize = u2rz(old_size);
- }
- q = irallocx(p, size, extra, alignment, zero, no_move,
- try_tcache_alloc, try_tcache_dalloc, arena);
- if (q == NULL)
- goto label_err;
- if (config_stats)
- usize = isalloc(q, config_prof);
- if (rsize != NULL) {
- if (config_stats == false)
- usize = isalloc(q, config_prof);
- *rsize = usize;
- }
- }
-
- *ptr = q;
- if (config_stats) {
- thread_allocated_t *ta;
- ta = thread_allocated_tsd_get();
- ta->allocated += usize;
- ta->deallocated += old_size;
- }
- UTRACE(p, size, q);
- JEMALLOC_VALGRIND_REALLOC(q, usize, p, old_size, old_rzsize, zero);
- return (ALLOCM_SUCCESS);
-label_err:
- if (no_move) {
- UTRACE(p, size, q);
- return (ALLOCM_ERR_NOT_MOVED);
- }
-label_oom:
- if (config_xmalloc && opt_xmalloc) {
- malloc_write("<jemalloc>: Error in rallocm(): "
- "out of memory\n");
- abort();
- }
- UTRACE(p, size, 0);
- return (ALLOCM_ERR_OOM);
-}
-
-int
-je_sallocm(const void *ptr, size_t *rsize, int flags)
-{
- size_t sz;
-
- assert(malloc_initialized || IS_INITIALIZER);
- malloc_thread_init();
-
- if (config_ivsalloc)
- sz = ivsalloc(ptr, config_prof);
- else {
- assert(ptr != NULL);
- sz = isalloc(ptr, config_prof);
- }
- assert(rsize != NULL);
- *rsize = sz;
-
- return (ALLOCM_SUCCESS);
-}
-
-int
-je_dallocm(void *ptr, int flags)
-{
- size_t usize;
- size_t rzsize JEMALLOC_CC_SILENCE_INIT(0);
- unsigned arena_ind = ((unsigned)(flags >> 8)) - 1;
- bool try_tcache;
-
- assert(ptr != NULL);
- assert(malloc_initialized || IS_INITIALIZER);
-
- if (arena_ind != UINT_MAX) {
- arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- try_tcache = (chunk == ptr || chunk->arena !=
- arenas[arena_ind]);
- } else
- try_tcache = true;
-
- UTRACE(ptr, 0, 0);
- if (config_stats || config_valgrind)
- usize = isalloc(ptr, config_prof);
- if (config_prof && opt_prof) {
- if (config_stats == false && config_valgrind == false)
- usize = isalloc(ptr, config_prof);
- prof_free(ptr, usize);
- }
- if (config_stats)
- thread_allocated_tsd_get()->deallocated += usize;
- if (config_valgrind && opt_valgrind)
- rzsize = p2rz(ptr);
- iqallocx(ptr, try_tcache);
- JEMALLOC_VALGRIND_FREE(ptr, rzsize);
-
- return (ALLOCM_SUCCESS);
-}
-
-int
-je_nallocm(size_t *rsize, size_t size, int flags)
-{
- size_t usize;
- size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK)
- & (SIZE_T_MAX-1));
-
- assert(size != 0);
-
- if (malloc_init())
- return (ALLOCM_ERR_OOM);
-
- usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment);
- if (usize == 0)
- return (ALLOCM_ERR_OOM);
-
- if (rsize != NULL)
- *rsize = usize;
- return (ALLOCM_SUCCESS);
-}
-
-#endif
-/*
- * End experimental functions.
- */
-/******************************************************************************/
-/*
- * The following functions are used by threading libraries for protection of
- * malloc during fork().
- */
-
-/*
- * If an application creates a thread before doing any allocation in the main
- * thread, then calls fork(2) in the main thread followed by memory allocation
- * in the child process, a race can occur that results in deadlock within the
- * child: the main thread may have forked while the created thread had
- * partially initialized the allocator. Ordinarily jemalloc prevents
- * fork/malloc races via the following functions it registers during
- * initialization using pthread_atfork(), but of course that does no good if
- * the allocator isn't fully initialized at fork time. The following library
- * constructor is a partial solution to this problem. It may still possible to
- * trigger the deadlock described above, but doing so would involve forking via
- * a library constructor that runs before jemalloc's runs.
- */
-JEMALLOC_ATTR(constructor)
-static void
-jemalloc_constructor(void)
-{
-
- malloc_init();
-}
-
-#ifndef JEMALLOC_MUTEX_INIT_CB
-void
-jemalloc_prefork(void)
-#else
-JEMALLOC_EXPORT void
-_malloc_prefork(void)
-#endif
-{
- unsigned i;
-
-#ifdef JEMALLOC_MUTEX_INIT_CB
- if (malloc_initialized == false)
- return;
-#endif
- assert(malloc_initialized);
-
- /* Acquire all mutexes in a safe order. */
- ctl_prefork();
- prof_prefork();
- malloc_mutex_prefork(&arenas_lock);
- for (i = 0; i < narenas_total; i++) {
- if (arenas[i] != NULL)
- arena_prefork(arenas[i]);
- }
- chunk_prefork();
- base_prefork();
- huge_prefork();
-}
-
-#ifndef JEMALLOC_MUTEX_INIT_CB
-void
-jemalloc_postfork_parent(void)
-#else
-JEMALLOC_EXPORT void
-_malloc_postfork(void)
-#endif
-{
- unsigned i;
-
-#ifdef JEMALLOC_MUTEX_INIT_CB
- if (malloc_initialized == false)
- return;
-#endif
- assert(malloc_initialized);
-
- /* Release all mutexes, now that fork() has completed. */
- huge_postfork_parent();
- base_postfork_parent();
- chunk_postfork_parent();
- for (i = 0; i < narenas_total; i++) {
- if (arenas[i] != NULL)
- arena_postfork_parent(arenas[i]);
- }
- malloc_mutex_postfork_parent(&arenas_lock);
- prof_postfork_parent();
- ctl_postfork_parent();
-}
-
-void
-jemalloc_postfork_child(void)
-{
- unsigned i;
-
- assert(malloc_initialized);
-
- /* Release all mutexes, now that fork() has completed. */
- huge_postfork_child();
- base_postfork_child();
- chunk_postfork_child();
- for (i = 0; i < narenas_total; i++) {
- if (arenas[i] != NULL)
- arena_postfork_child(arenas[i]);
- }
- malloc_mutex_postfork_child(&arenas_lock);
- prof_postfork_child();
- ctl_postfork_child();
-}
-
-/******************************************************************************/
-/*
- * The following functions are used for TLS allocation/deallocation in static
- * binaries on FreeBSD. The primary difference between these and i[mcd]alloc()
- * is that these avoid accessing TLS variables.
- */
-
-static void *
-a0alloc(size_t size, bool zero)
-{
-
- if (malloc_init())
- return (NULL);
-
- if (size == 0)
- size = 1;
-
- if (size <= arena_maxclass)
- return (arena_malloc(arenas[0], size, zero, false));
- else
- return (huge_malloc(size, zero));
-}
-
-void *
-a0malloc(size_t size)
-{
-
- return (a0alloc(size, false));
-}
-
-void *
-a0calloc(size_t num, size_t size)
-{
-
- return (a0alloc(num * size, true));
-}
-
-void
-a0free(void *ptr)
-{
- arena_chunk_t *chunk;
-
- if (ptr == NULL)
- return;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk != ptr)
- arena_dalloc(chunk->arena, chunk, ptr, false);
- else
- huge_dalloc(ptr, true);
-}
-
-/******************************************************************************/
diff --git a/extra/jemalloc/src/mb.c b/extra/jemalloc/src/mb.c
deleted file mode 100644
index dc2c0a256fd..00000000000
--- a/extra/jemalloc/src/mb.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define JEMALLOC_MB_C_
-#include "jemalloc/internal/jemalloc_internal.h"
diff --git a/extra/jemalloc/src/mutex.c b/extra/jemalloc/src/mutex.c
deleted file mode 100644
index 55e18c23713..00000000000
--- a/extra/jemalloc/src/mutex.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#define JEMALLOC_MUTEX_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
-#include <dlfcn.h>
-#endif
-
-#ifndef _CRT_SPINCOUNT
-#define _CRT_SPINCOUNT 4000
-#endif
-
-/******************************************************************************/
-/* Data. */
-
-#ifdef JEMALLOC_LAZY_LOCK
-bool isthreaded = false;
-#endif
-#ifdef JEMALLOC_MUTEX_INIT_CB
-static bool postpone_init = true;
-static malloc_mutex_t *postponed_mutexes = NULL;
-#endif
-
-#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
-static void pthread_create_once(void);
-#endif
-
-/******************************************************************************/
-/*
- * We intercept pthread_create() calls in order to toggle isthreaded if the
- * process goes multi-threaded.
- */
-
-#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
-static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *,
- void *(*)(void *), void *__restrict);
-
-static void
-pthread_create_once(void)
-{
-
- pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create");
- if (pthread_create_fptr == NULL) {
- malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, "
- "\"pthread_create\")\n");
- abort();
- }
-
- isthreaded = true;
-}
-
-JEMALLOC_EXPORT int
-pthread_create(pthread_t *__restrict thread,
- const pthread_attr_t *__restrict attr, void *(*start_routine)(void *),
- void *__restrict arg)
-{
- static pthread_once_t once_control = PTHREAD_ONCE_INIT;
-
- pthread_once(&once_control, pthread_create_once);
-
- return (pthread_create_fptr(thread, attr, start_routine, arg));
-}
-#endif
-
-/******************************************************************************/
-
-#ifdef JEMALLOC_MUTEX_INIT_CB
-JEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
- void *(calloc_cb)(size_t, size_t));
-#endif
-
-bool
-malloc_mutex_init(malloc_mutex_t *mutex)
-{
-
-#ifdef _WIN32
- if (!InitializeCriticalSectionAndSpinCount(&mutex->lock,
- _CRT_SPINCOUNT))
- return (true);
-#elif (defined(JEMALLOC_OSSPIN))
- mutex->lock = 0;
-#elif (defined(JEMALLOC_MUTEX_INIT_CB))
- if (postpone_init) {
- mutex->postponed_next = postponed_mutexes;
- postponed_mutexes = mutex;
- } else {
- if (_pthread_mutex_init_calloc_cb(&mutex->lock, base_calloc) !=
- 0)
- return (true);
- }
-#else
- pthread_mutexattr_t attr;
-
- if (pthread_mutexattr_init(&attr) != 0)
- return (true);
- pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE);
- if (pthread_mutex_init(&mutex->lock, &attr) != 0) {
- pthread_mutexattr_destroy(&attr);
- return (true);
- }
- pthread_mutexattr_destroy(&attr);
-#endif
- return (false);
-}
-
-void
-malloc_mutex_prefork(malloc_mutex_t *mutex)
-{
-
- malloc_mutex_lock(mutex);
-}
-
-void
-malloc_mutex_postfork_parent(malloc_mutex_t *mutex)
-{
-
- malloc_mutex_unlock(mutex);
-}
-
-void
-malloc_mutex_postfork_child(malloc_mutex_t *mutex)
-{
-
-#ifdef JEMALLOC_MUTEX_INIT_CB
- malloc_mutex_unlock(mutex);
-#else
- if (malloc_mutex_init(mutex)) {
- malloc_printf("<jemalloc>: Error re-initializing mutex in "
- "child\n");
- if (opt_abort)
- abort();
- }
-#endif
-}
-
-bool
-mutex_boot(void)
-{
-
-#ifdef JEMALLOC_MUTEX_INIT_CB
- postpone_init = false;
- while (postponed_mutexes != NULL) {
- if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock,
- base_calloc) != 0)
- return (true);
- postponed_mutexes = postponed_mutexes->postponed_next;
- }
-#endif
- return (false);
-}
diff --git a/extra/jemalloc/src/prof.c b/extra/jemalloc/src/prof.c
deleted file mode 100644
index c133b95c2c6..00000000000
--- a/extra/jemalloc/src/prof.c
+++ /dev/null
@@ -1,1283 +0,0 @@
-#define JEMALLOC_PROF_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-/******************************************************************************/
-
-#ifdef JEMALLOC_PROF_LIBUNWIND
-#define UNW_LOCAL_ONLY
-#include <libunwind.h>
-#endif
-
-#ifdef JEMALLOC_PROF_LIBGCC
-#include <unwind.h>
-#endif
-
-/******************************************************************************/
-/* Data. */
-
-malloc_tsd_data(, prof_tdata, prof_tdata_t *, NULL)
-
-bool opt_prof = false;
-bool opt_prof_active = true;
-size_t opt_lg_prof_sample = LG_PROF_SAMPLE_DEFAULT;
-ssize_t opt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT;
-bool opt_prof_gdump = false;
-bool opt_prof_final = true;
-bool opt_prof_leak = false;
-bool opt_prof_accum = false;
-char opt_prof_prefix[PATH_MAX + 1];
-
-uint64_t prof_interval = 0;
-bool prof_promote;
-
-/*
- * Table of mutexes that are shared among ctx's. These are leaf locks, so
- * there is no problem with using them for more than one ctx at the same time.
- * The primary motivation for this sharing though is that ctx's are ephemeral,
- * and destroying mutexes causes complications for systems that allocate when
- * creating/destroying mutexes.
- */
-static malloc_mutex_t *ctx_locks;
-static unsigned cum_ctxs; /* Atomic counter. */
-
-/*
- * Global hash of (prof_bt_t *)-->(prof_ctx_t *). This is the master data
- * structure that knows about all backtraces currently captured.
- */
-static ckh_t bt2ctx;
-static malloc_mutex_t bt2ctx_mtx;
-
-static malloc_mutex_t prof_dump_seq_mtx;
-static uint64_t prof_dump_seq;
-static uint64_t prof_dump_iseq;
-static uint64_t prof_dump_mseq;
-static uint64_t prof_dump_useq;
-
-/*
- * This buffer is rather large for stack allocation, so use a single buffer for
- * all profile dumps. The buffer is implicitly protected by bt2ctx_mtx, since
- * it must be locked anyway during dumping.
- */
-static char prof_dump_buf[PROF_DUMP_BUFSIZE];
-static unsigned prof_dump_buf_end;
-static int prof_dump_fd;
-
-/* Do not dump any profiles until bootstrapping is complete. */
-static bool prof_booted = false;
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static prof_bt_t *bt_dup(prof_bt_t *bt);
-static void bt_destroy(prof_bt_t *bt);
-#ifdef JEMALLOC_PROF_LIBGCC
-static _Unwind_Reason_Code prof_unwind_init_callback(
- struct _Unwind_Context *context, void *arg);
-static _Unwind_Reason_Code prof_unwind_callback(
- struct _Unwind_Context *context, void *arg);
-#endif
-static bool prof_flush(bool propagate_err);
-static bool prof_write(bool propagate_err, const char *s);
-static bool prof_printf(bool propagate_err, const char *format, ...)
- JEMALLOC_ATTR(format(printf, 2, 3));
-static void prof_ctx_sum(prof_ctx_t *ctx, prof_cnt_t *cnt_all,
- size_t *leak_nctx);
-static void prof_ctx_destroy(prof_ctx_t *ctx);
-static void prof_ctx_merge(prof_ctx_t *ctx, prof_thr_cnt_t *cnt);
-static bool prof_dump_ctx(bool propagate_err, prof_ctx_t *ctx,
- prof_bt_t *bt);
-static bool prof_dump_maps(bool propagate_err);
-static bool prof_dump(bool propagate_err, const char *filename,
- bool leakcheck);
-static void prof_dump_filename(char *filename, char v, int64_t vseq);
-static void prof_fdump(void);
-static void prof_bt_hash(const void *key, size_t r_hash[2]);
-static bool prof_bt_keycomp(const void *k1, const void *k2);
-static malloc_mutex_t *prof_ctx_mutex_choose(void);
-
-/******************************************************************************/
-
-void
-bt_init(prof_bt_t *bt, void **vec)
-{
-
- cassert(config_prof);
-
- bt->vec = vec;
- bt->len = 0;
-}
-
-static void
-bt_destroy(prof_bt_t *bt)
-{
-
- cassert(config_prof);
-
- idalloc(bt);
-}
-
-static prof_bt_t *
-bt_dup(prof_bt_t *bt)
-{
- prof_bt_t *ret;
-
- cassert(config_prof);
-
- /*
- * Create a single allocation that has space for vec immediately
- * following the prof_bt_t structure. The backtraces that get
- * stored in the backtrace caches are copied from stack-allocated
- * temporary variables, so size is known at creation time. Making this
- * a contiguous object improves cache locality.
- */
- ret = (prof_bt_t *)imalloc(QUANTUM_CEILING(sizeof(prof_bt_t)) +
- (bt->len * sizeof(void *)));
- if (ret == NULL)
- return (NULL);
- ret->vec = (void **)((uintptr_t)ret +
- QUANTUM_CEILING(sizeof(prof_bt_t)));
- memcpy(ret->vec, bt->vec, bt->len * sizeof(void *));
- ret->len = bt->len;
-
- return (ret);
-}
-
-static inline void
-prof_enter(prof_tdata_t *prof_tdata)
-{
-
- cassert(config_prof);
-
- assert(prof_tdata->enq == false);
- prof_tdata->enq = true;
-
- malloc_mutex_lock(&bt2ctx_mtx);
-}
-
-static inline void
-prof_leave(prof_tdata_t *prof_tdata)
-{
- bool idump, gdump;
-
- cassert(config_prof);
-
- malloc_mutex_unlock(&bt2ctx_mtx);
-
- assert(prof_tdata->enq);
- prof_tdata->enq = false;
- idump = prof_tdata->enq_idump;
- prof_tdata->enq_idump = false;
- gdump = prof_tdata->enq_gdump;
- prof_tdata->enq_gdump = false;
-
- if (idump)
- prof_idump();
- if (gdump)
- prof_gdump();
-}
-
-#ifdef JEMALLOC_PROF_LIBUNWIND
-void
-prof_backtrace(prof_bt_t *bt, unsigned nignore)
-{
- unw_context_t uc;
- unw_cursor_t cursor;
- unsigned i;
- int err;
-
- cassert(config_prof);
- assert(bt->len == 0);
- assert(bt->vec != NULL);
-
- unw_getcontext(&uc);
- unw_init_local(&cursor, &uc);
-
- /* Throw away (nignore+1) stack frames, if that many exist. */
- for (i = 0; i < nignore + 1; i++) {
- err = unw_step(&cursor);
- if (err <= 0)
- return;
- }
-
- /*
- * Iterate over stack frames until there are no more, or until no space
- * remains in bt.
- */
- for (i = 0; i < PROF_BT_MAX; i++) {
- unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *)&bt->vec[i]);
- bt->len++;
- err = unw_step(&cursor);
- if (err <= 0)
- break;
- }
-}
-#elif (defined(JEMALLOC_PROF_LIBGCC))
-static _Unwind_Reason_Code
-prof_unwind_init_callback(struct _Unwind_Context *context, void *arg)
-{
-
- cassert(config_prof);
-
- return (_URC_NO_REASON);
-}
-
-static _Unwind_Reason_Code
-prof_unwind_callback(struct _Unwind_Context *context, void *arg)
-{
- prof_unwind_data_t *data = (prof_unwind_data_t *)arg;
-
- cassert(config_prof);
-
- if (data->nignore > 0)
- data->nignore--;
- else {
- data->bt->vec[data->bt->len] = (void *)_Unwind_GetIP(context);
- data->bt->len++;
- if (data->bt->len == data->max)
- return (_URC_END_OF_STACK);
- }
-
- return (_URC_NO_REASON);
-}
-
-void
-prof_backtrace(prof_bt_t *bt, unsigned nignore)
-{
- prof_unwind_data_t data = {bt, nignore, PROF_BT_MAX};
-
- cassert(config_prof);
-
- _Unwind_Backtrace(prof_unwind_callback, &data);
-}
-#elif (defined(JEMALLOC_PROF_GCC))
-void
-prof_backtrace(prof_bt_t *bt, unsigned nignore)
-{
-#define BT_FRAME(i) \
- if ((i) < nignore + PROF_BT_MAX) { \
- void *p; \
- if (__builtin_frame_address(i) == 0) \
- return; \
- p = __builtin_return_address(i); \
- if (p == NULL) \
- return; \
- if (i >= nignore) { \
- bt->vec[(i) - nignore] = p; \
- bt->len = (i) - nignore + 1; \
- } \
- } else \
- return;
-
- cassert(config_prof);
- assert(nignore <= 3);
-
- BT_FRAME(0)
- BT_FRAME(1)
- BT_FRAME(2)
- BT_FRAME(3)
- BT_FRAME(4)
- BT_FRAME(5)
- BT_FRAME(6)
- BT_FRAME(7)
- BT_FRAME(8)
- BT_FRAME(9)
-
- BT_FRAME(10)
- BT_FRAME(11)
- BT_FRAME(12)
- BT_FRAME(13)
- BT_FRAME(14)
- BT_FRAME(15)
- BT_FRAME(16)
- BT_FRAME(17)
- BT_FRAME(18)
- BT_FRAME(19)
-
- BT_FRAME(20)
- BT_FRAME(21)
- BT_FRAME(22)
- BT_FRAME(23)
- BT_FRAME(24)
- BT_FRAME(25)
- BT_FRAME(26)
- BT_FRAME(27)
- BT_FRAME(28)
- BT_FRAME(29)
-
- BT_FRAME(30)
- BT_FRAME(31)
- BT_FRAME(32)
- BT_FRAME(33)
- BT_FRAME(34)
- BT_FRAME(35)
- BT_FRAME(36)
- BT_FRAME(37)
- BT_FRAME(38)
- BT_FRAME(39)
-
- BT_FRAME(40)
- BT_FRAME(41)
- BT_FRAME(42)
- BT_FRAME(43)
- BT_FRAME(44)
- BT_FRAME(45)
- BT_FRAME(46)
- BT_FRAME(47)
- BT_FRAME(48)
- BT_FRAME(49)
-
- BT_FRAME(50)
- BT_FRAME(51)
- BT_FRAME(52)
- BT_FRAME(53)
- BT_FRAME(54)
- BT_FRAME(55)
- BT_FRAME(56)
- BT_FRAME(57)
- BT_FRAME(58)
- BT_FRAME(59)
-
- BT_FRAME(60)
- BT_FRAME(61)
- BT_FRAME(62)
- BT_FRAME(63)
- BT_FRAME(64)
- BT_FRAME(65)
- BT_FRAME(66)
- BT_FRAME(67)
- BT_FRAME(68)
- BT_FRAME(69)
-
- BT_FRAME(70)
- BT_FRAME(71)
- BT_FRAME(72)
- BT_FRAME(73)
- BT_FRAME(74)
- BT_FRAME(75)
- BT_FRAME(76)
- BT_FRAME(77)
- BT_FRAME(78)
- BT_FRAME(79)
-
- BT_FRAME(80)
- BT_FRAME(81)
- BT_FRAME(82)
- BT_FRAME(83)
- BT_FRAME(84)
- BT_FRAME(85)
- BT_FRAME(86)
- BT_FRAME(87)
- BT_FRAME(88)
- BT_FRAME(89)
-
- BT_FRAME(90)
- BT_FRAME(91)
- BT_FRAME(92)
- BT_FRAME(93)
- BT_FRAME(94)
- BT_FRAME(95)
- BT_FRAME(96)
- BT_FRAME(97)
- BT_FRAME(98)
- BT_FRAME(99)
-
- BT_FRAME(100)
- BT_FRAME(101)
- BT_FRAME(102)
- BT_FRAME(103)
- BT_FRAME(104)
- BT_FRAME(105)
- BT_FRAME(106)
- BT_FRAME(107)
- BT_FRAME(108)
- BT_FRAME(109)
-
- BT_FRAME(110)
- BT_FRAME(111)
- BT_FRAME(112)
- BT_FRAME(113)
- BT_FRAME(114)
- BT_FRAME(115)
- BT_FRAME(116)
- BT_FRAME(117)
- BT_FRAME(118)
- BT_FRAME(119)
-
- BT_FRAME(120)
- BT_FRAME(121)
- BT_FRAME(122)
- BT_FRAME(123)
- BT_FRAME(124)
- BT_FRAME(125)
- BT_FRAME(126)
- BT_FRAME(127)
-
- /* Extras to compensate for nignore. */
- BT_FRAME(128)
- BT_FRAME(129)
- BT_FRAME(130)
-#undef BT_FRAME
-}
-#else
-void
-prof_backtrace(prof_bt_t *bt, unsigned nignore)
-{
-
- cassert(config_prof);
- assert(false);
-}
-#endif
-
-prof_thr_cnt_t *
-prof_lookup(prof_bt_t *bt)
-{
- union {
- prof_thr_cnt_t *p;
- void *v;
- } ret;
- prof_tdata_t *prof_tdata;
-
- cassert(config_prof);
-
- prof_tdata = prof_tdata_get(false);
- if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
- return (NULL);
-
- if (ckh_search(&prof_tdata->bt2cnt, bt, NULL, &ret.v)) {
- union {
- prof_bt_t *p;
- void *v;
- } btkey;
- union {
- prof_ctx_t *p;
- void *v;
- } ctx;
- bool new_ctx;
-
- /*
- * This thread's cache lacks bt. Look for it in the global
- * cache.
- */
- prof_enter(prof_tdata);
- if (ckh_search(&bt2ctx, bt, &btkey.v, &ctx.v)) {
- /* bt has never been seen before. Insert it. */
- ctx.v = imalloc(sizeof(prof_ctx_t));
- if (ctx.v == NULL) {
- prof_leave(prof_tdata);
- return (NULL);
- }
- btkey.p = bt_dup(bt);
- if (btkey.v == NULL) {
- prof_leave(prof_tdata);
- idalloc(ctx.v);
- return (NULL);
- }
- ctx.p->bt = btkey.p;
- ctx.p->lock = prof_ctx_mutex_choose();
- /*
- * Set nlimbo to 1, in order to avoid a race condition
- * with prof_ctx_merge()/prof_ctx_destroy().
- */
- ctx.p->nlimbo = 1;
- memset(&ctx.p->cnt_merged, 0, sizeof(prof_cnt_t));
- ql_new(&ctx.p->cnts_ql);
- if (ckh_insert(&bt2ctx, btkey.v, ctx.v)) {
- /* OOM. */
- prof_leave(prof_tdata);
- idalloc(btkey.v);
- idalloc(ctx.v);
- return (NULL);
- }
- new_ctx = true;
- } else {
- /*
- * Increment nlimbo, in order to avoid a race condition
- * with prof_ctx_merge()/prof_ctx_destroy().
- */
- malloc_mutex_lock(ctx.p->lock);
- ctx.p->nlimbo++;
- malloc_mutex_unlock(ctx.p->lock);
- new_ctx = false;
- }
- prof_leave(prof_tdata);
-
- /* Link a prof_thd_cnt_t into ctx for this thread. */
- if (ckh_count(&prof_tdata->bt2cnt) == PROF_TCMAX) {
- assert(ckh_count(&prof_tdata->bt2cnt) > 0);
- /*
- * Flush the least recently used cnt in order to keep
- * bt2cnt from becoming too large.
- */
- ret.p = ql_last(&prof_tdata->lru_ql, lru_link);
- assert(ret.v != NULL);
- if (ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt,
- NULL, NULL))
- assert(false);
- ql_remove(&prof_tdata->lru_ql, ret.p, lru_link);
- prof_ctx_merge(ret.p->ctx, ret.p);
- /* ret can now be re-used. */
- } else {
- assert(ckh_count(&prof_tdata->bt2cnt) < PROF_TCMAX);
- /* Allocate and partially initialize a new cnt. */
- ret.v = imalloc(sizeof(prof_thr_cnt_t));
- if (ret.p == NULL) {
- if (new_ctx)
- prof_ctx_destroy(ctx.p);
- return (NULL);
- }
- ql_elm_new(ret.p, cnts_link);
- ql_elm_new(ret.p, lru_link);
- }
- /* Finish initializing ret. */
- ret.p->ctx = ctx.p;
- ret.p->epoch = 0;
- memset(&ret.p->cnts, 0, sizeof(prof_cnt_t));
- if (ckh_insert(&prof_tdata->bt2cnt, btkey.v, ret.v)) {
- if (new_ctx)
- prof_ctx_destroy(ctx.p);
- idalloc(ret.v);
- return (NULL);
- }
- ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);
- malloc_mutex_lock(ctx.p->lock);
- ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link);
- ctx.p->nlimbo--;
- malloc_mutex_unlock(ctx.p->lock);
- } else {
- /* Move ret to the front of the LRU. */
- ql_remove(&prof_tdata->lru_ql, ret.p, lru_link);
- ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);
- }
-
- return (ret.p);
-}
-
-static bool
-prof_flush(bool propagate_err)
-{
- bool ret = false;
- ssize_t err;
-
- cassert(config_prof);
-
- err = write(prof_dump_fd, prof_dump_buf, prof_dump_buf_end);
- if (err == -1) {
- if (propagate_err == false) {
- malloc_write("<jemalloc>: write() failed during heap "
- "profile flush\n");
- if (opt_abort)
- abort();
- }
- ret = true;
- }
- prof_dump_buf_end = 0;
-
- return (ret);
-}
-
-static bool
-prof_write(bool propagate_err, const char *s)
-{
- unsigned i, slen, n;
-
- cassert(config_prof);
-
- i = 0;
- slen = strlen(s);
- while (i < slen) {
- /* Flush the buffer if it is full. */
- if (prof_dump_buf_end == PROF_DUMP_BUFSIZE)
- if (prof_flush(propagate_err) && propagate_err)
- return (true);
-
- if (prof_dump_buf_end + slen <= PROF_DUMP_BUFSIZE) {
- /* Finish writing. */
- n = slen - i;
- } else {
- /* Write as much of s as will fit. */
- n = PROF_DUMP_BUFSIZE - prof_dump_buf_end;
- }
- memcpy(&prof_dump_buf[prof_dump_buf_end], &s[i], n);
- prof_dump_buf_end += n;
- i += n;
- }
-
- return (false);
-}
-
-JEMALLOC_ATTR(format(printf, 2, 3))
-static bool
-prof_printf(bool propagate_err, const char *format, ...)
-{
- bool ret;
- va_list ap;
- char buf[PROF_PRINTF_BUFSIZE];
-
- va_start(ap, format);
- malloc_vsnprintf(buf, sizeof(buf), format, ap);
- va_end(ap);
- ret = prof_write(propagate_err, buf);
-
- return (ret);
-}
-
-static void
-prof_ctx_sum(prof_ctx_t *ctx, prof_cnt_t *cnt_all, size_t *leak_nctx)
-{
- prof_thr_cnt_t *thr_cnt;
- prof_cnt_t tcnt;
-
- cassert(config_prof);
-
- malloc_mutex_lock(ctx->lock);
-
- memcpy(&ctx->cnt_summed, &ctx->cnt_merged, sizeof(prof_cnt_t));
- ql_foreach(thr_cnt, &ctx->cnts_ql, cnts_link) {
- volatile unsigned *epoch = &thr_cnt->epoch;
-
- while (true) {
- unsigned epoch0 = *epoch;
-
- /* Make sure epoch is even. */
- if (epoch0 & 1U)
- continue;
-
- memcpy(&tcnt, &thr_cnt->cnts, sizeof(prof_cnt_t));
-
- /* Terminate if epoch didn't change while reading. */
- if (*epoch == epoch0)
- break;
- }
-
- ctx->cnt_summed.curobjs += tcnt.curobjs;
- ctx->cnt_summed.curbytes += tcnt.curbytes;
- if (opt_prof_accum) {
- ctx->cnt_summed.accumobjs += tcnt.accumobjs;
- ctx->cnt_summed.accumbytes += tcnt.accumbytes;
- }
- }
-
- if (ctx->cnt_summed.curobjs != 0)
- (*leak_nctx)++;
-
- /* Add to cnt_all. */
- cnt_all->curobjs += ctx->cnt_summed.curobjs;
- cnt_all->curbytes += ctx->cnt_summed.curbytes;
- if (opt_prof_accum) {
- cnt_all->accumobjs += ctx->cnt_summed.accumobjs;
- cnt_all->accumbytes += ctx->cnt_summed.accumbytes;
- }
-
- malloc_mutex_unlock(ctx->lock);
-}
-
-static void
-prof_ctx_destroy(prof_ctx_t *ctx)
-{
- prof_tdata_t *prof_tdata;
-
- cassert(config_prof);
-
- /*
- * Check that ctx is still unused by any thread cache before destroying
- * it. prof_lookup() increments ctx->nlimbo in order to avoid a race
- * condition with this function, as does prof_ctx_merge() in order to
- * avoid a race between the main body of prof_ctx_merge() and entry
- * into this function.
- */
- prof_tdata = prof_tdata_get(false);
- assert((uintptr_t)prof_tdata > (uintptr_t)PROF_TDATA_STATE_MAX);
- prof_enter(prof_tdata);
- malloc_mutex_lock(ctx->lock);
- if (ql_first(&ctx->cnts_ql) == NULL && ctx->cnt_merged.curobjs == 0 &&
- ctx->nlimbo == 1) {
- assert(ctx->cnt_merged.curbytes == 0);
- assert(ctx->cnt_merged.accumobjs == 0);
- assert(ctx->cnt_merged.accumbytes == 0);
- /* Remove ctx from bt2ctx. */
- if (ckh_remove(&bt2ctx, ctx->bt, NULL, NULL))
- assert(false);
- prof_leave(prof_tdata);
- /* Destroy ctx. */
- malloc_mutex_unlock(ctx->lock);
- bt_destroy(ctx->bt);
- idalloc(ctx);
- } else {
- /*
- * Compensate for increment in prof_ctx_merge() or
- * prof_lookup().
- */
- ctx->nlimbo--;
- malloc_mutex_unlock(ctx->lock);
- prof_leave(prof_tdata);
- }
-}
-
-static void
-prof_ctx_merge(prof_ctx_t *ctx, prof_thr_cnt_t *cnt)
-{
- bool destroy;
-
- cassert(config_prof);
-
- /* Merge cnt stats and detach from ctx. */
- malloc_mutex_lock(ctx->lock);
- ctx->cnt_merged.curobjs += cnt->cnts.curobjs;
- ctx->cnt_merged.curbytes += cnt->cnts.curbytes;
- ctx->cnt_merged.accumobjs += cnt->cnts.accumobjs;
- ctx->cnt_merged.accumbytes += cnt->cnts.accumbytes;
- ql_remove(&ctx->cnts_ql, cnt, cnts_link);
- if (opt_prof_accum == false && ql_first(&ctx->cnts_ql) == NULL &&
- ctx->cnt_merged.curobjs == 0 && ctx->nlimbo == 0) {
- /*
- * Increment ctx->nlimbo in order to keep another thread from
- * winning the race to destroy ctx while this one has ctx->lock
- * dropped. Without this, it would be possible for another
- * thread to:
- *
- * 1) Sample an allocation associated with ctx.
- * 2) Deallocate the sampled object.
- * 3) Successfully prof_ctx_destroy(ctx).
- *
- * The result would be that ctx no longer exists by the time
- * this thread accesses it in prof_ctx_destroy().
- */
- ctx->nlimbo++;
- destroy = true;
- } else
- destroy = false;
- malloc_mutex_unlock(ctx->lock);
- if (destroy)
- prof_ctx_destroy(ctx);
-}
-
-static bool
-prof_dump_ctx(bool propagate_err, prof_ctx_t *ctx, prof_bt_t *bt)
-{
- unsigned i;
-
- cassert(config_prof);
-
- /*
- * Current statistics can sum to 0 as a result of unmerged per thread
- * statistics. Additionally, interval- and growth-triggered dumps can
- * occur between the time a ctx is created and when its statistics are
- * filled in. Avoid dumping any ctx that is an artifact of either
- * implementation detail.
- */
- if ((opt_prof_accum == false && ctx->cnt_summed.curobjs == 0) ||
- (opt_prof_accum && ctx->cnt_summed.accumobjs == 0)) {
- assert(ctx->cnt_summed.curobjs == 0);
- assert(ctx->cnt_summed.curbytes == 0);
- assert(ctx->cnt_summed.accumobjs == 0);
- assert(ctx->cnt_summed.accumbytes == 0);
- return (false);
- }
-
- if (prof_printf(propagate_err, "%"PRId64": %"PRId64
- " [%"PRIu64": %"PRIu64"] @",
- ctx->cnt_summed.curobjs, ctx->cnt_summed.curbytes,
- ctx->cnt_summed.accumobjs, ctx->cnt_summed.accumbytes))
- return (true);
-
- for (i = 0; i < bt->len; i++) {
- if (prof_printf(propagate_err, " %#"PRIxPTR,
- (uintptr_t)bt->vec[i]))
- return (true);
- }
-
- if (prof_write(propagate_err, "\n"))
- return (true);
-
- return (false);
-}
-
-static bool
-prof_dump_maps(bool propagate_err)
-{
- int mfd;
- char filename[PATH_MAX + 1];
-
- cassert(config_prof);
-
- malloc_snprintf(filename, sizeof(filename), "/proc/%d/maps",
- (int)getpid());
- mfd = open(filename, O_RDONLY);
- if (mfd != -1) {
- ssize_t nread;
-
- if (prof_write(propagate_err, "\nMAPPED_LIBRARIES:\n") &&
- propagate_err)
- return (true);
- nread = 0;
- do {
- prof_dump_buf_end += nread;
- if (prof_dump_buf_end == PROF_DUMP_BUFSIZE) {
- /* Make space in prof_dump_buf before read(). */
- if (prof_flush(propagate_err) && propagate_err)
- return (true);
- }
- nread = read(mfd, &prof_dump_buf[prof_dump_buf_end],
- PROF_DUMP_BUFSIZE - prof_dump_buf_end);
- } while (nread > 0);
- close(mfd);
- } else
- return (true);
-
- return (false);
-}
-
-static bool
-prof_dump(bool propagate_err, const char *filename, bool leakcheck)
-{
- prof_tdata_t *prof_tdata;
- prof_cnt_t cnt_all;
- size_t tabind;
- union {
- prof_bt_t *p;
- void *v;
- } bt;
- union {
- prof_ctx_t *p;
- void *v;
- } ctx;
- size_t leak_nctx;
-
- cassert(config_prof);
-
- prof_tdata = prof_tdata_get(false);
- if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
- return (true);
- prof_enter(prof_tdata);
- prof_dump_fd = creat(filename, 0644);
- if (prof_dump_fd == -1) {
- if (propagate_err == false) {
- malloc_printf(
- "<jemalloc>: creat(\"%s\"), 0644) failed\n",
- filename);
- if (opt_abort)
- abort();
- }
- goto label_error;
- }
-
- /* Merge per thread profile stats, and sum them in cnt_all. */
- memset(&cnt_all, 0, sizeof(prof_cnt_t));
- leak_nctx = 0;
- for (tabind = 0; ckh_iter(&bt2ctx, &tabind, NULL, &ctx.v) == false;)
- prof_ctx_sum(ctx.p, &cnt_all, &leak_nctx);
-
- /* Dump profile header. */
- if (opt_lg_prof_sample == 0) {
- if (prof_printf(propagate_err,
- "heap profile: %"PRId64": %"PRId64
- " [%"PRIu64": %"PRIu64"] @ heapprofile\n",
- cnt_all.curobjs, cnt_all.curbytes,
- cnt_all.accumobjs, cnt_all.accumbytes))
- goto label_error;
- } else {
- if (prof_printf(propagate_err,
- "heap profile: %"PRId64": %"PRId64
- " [%"PRIu64": %"PRIu64"] @ heap_v2/%"PRIu64"\n",
- cnt_all.curobjs, cnt_all.curbytes,
- cnt_all.accumobjs, cnt_all.accumbytes,
- ((uint64_t)1U << opt_lg_prof_sample)))
- goto label_error;
- }
-
- /* Dump per ctx profile stats. */
- for (tabind = 0; ckh_iter(&bt2ctx, &tabind, &bt.v, &ctx.v)
- == false;) {
- if (prof_dump_ctx(propagate_err, ctx.p, bt.p))
- goto label_error;
- }
-
- /* Dump /proc/<pid>/maps if possible. */
- if (prof_dump_maps(propagate_err))
- goto label_error;
-
- if (prof_flush(propagate_err))
- goto label_error;
- close(prof_dump_fd);
- prof_leave(prof_tdata);
-
- if (leakcheck && cnt_all.curbytes != 0) {
- malloc_printf("<jemalloc>: Leak summary: %"PRId64" byte%s, %"
- PRId64" object%s, %zu context%s\n",
- cnt_all.curbytes, (cnt_all.curbytes != 1) ? "s" : "",
- cnt_all.curobjs, (cnt_all.curobjs != 1) ? "s" : "",
- leak_nctx, (leak_nctx != 1) ? "s" : "");
- malloc_printf(
- "<jemalloc>: Run pprof on \"%s\" for leak detail\n",
- filename);
- }
-
- return (false);
-label_error:
- prof_leave(prof_tdata);
- return (true);
-}
-
-#define DUMP_FILENAME_BUFSIZE (PATH_MAX + 1)
-static void
-prof_dump_filename(char *filename, char v, int64_t vseq)
-{
-
- cassert(config_prof);
-
- if (vseq != UINT64_C(0xffffffffffffffff)) {
- /* "<prefix>.<pid>.<seq>.v<vseq>.heap" */
- malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
- "%s.%d.%"PRIu64".%c%"PRId64".heap",
- opt_prof_prefix, (int)getpid(), prof_dump_seq, v, vseq);
- } else {
- /* "<prefix>.<pid>.<seq>.<v>.heap" */
- malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
- "%s.%d.%"PRIu64".%c.heap",
- opt_prof_prefix, (int)getpid(), prof_dump_seq, v);
- }
- prof_dump_seq++;
-}
-
-static void
-prof_fdump(void)
-{
- char filename[DUMP_FILENAME_BUFSIZE];
-
- cassert(config_prof);
-
- if (prof_booted == false)
- return;
-
- if (opt_prof_final && opt_prof_prefix[0] != '\0') {
- malloc_mutex_lock(&prof_dump_seq_mtx);
- prof_dump_filename(filename, 'f', UINT64_C(0xffffffffffffffff));
- malloc_mutex_unlock(&prof_dump_seq_mtx);
- prof_dump(false, filename, opt_prof_leak);
- }
-}
-
-void
-prof_idump(void)
-{
- prof_tdata_t *prof_tdata;
- char filename[PATH_MAX + 1];
-
- cassert(config_prof);
-
- if (prof_booted == false)
- return;
- prof_tdata = prof_tdata_get(false);
- if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
- return;
- if (prof_tdata->enq) {
- prof_tdata->enq_idump = true;
- return;
- }
-
- if (opt_prof_prefix[0] != '\0') {
- malloc_mutex_lock(&prof_dump_seq_mtx);
- prof_dump_filename(filename, 'i', prof_dump_iseq);
- prof_dump_iseq++;
- malloc_mutex_unlock(&prof_dump_seq_mtx);
- prof_dump(false, filename, false);
- }
-}
-
-bool
-prof_mdump(const char *filename)
-{
- char filename_buf[DUMP_FILENAME_BUFSIZE];
-
- cassert(config_prof);
-
- if (opt_prof == false || prof_booted == false)
- return (true);
-
- if (filename == NULL) {
- /* No filename specified, so automatically generate one. */
- if (opt_prof_prefix[0] == '\0')
- return (true);
- malloc_mutex_lock(&prof_dump_seq_mtx);
- prof_dump_filename(filename_buf, 'm', prof_dump_mseq);
- prof_dump_mseq++;
- malloc_mutex_unlock(&prof_dump_seq_mtx);
- filename = filename_buf;
- }
- return (prof_dump(true, filename, false));
-}
-
-void
-prof_gdump(void)
-{
- prof_tdata_t *prof_tdata;
- char filename[DUMP_FILENAME_BUFSIZE];
-
- cassert(config_prof);
-
- if (prof_booted == false)
- return;
- prof_tdata = prof_tdata_get(false);
- if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
- return;
- if (prof_tdata->enq) {
- prof_tdata->enq_gdump = true;
- return;
- }
-
- if (opt_prof_prefix[0] != '\0') {
- malloc_mutex_lock(&prof_dump_seq_mtx);
- prof_dump_filename(filename, 'u', prof_dump_useq);
- prof_dump_useq++;
- malloc_mutex_unlock(&prof_dump_seq_mtx);
- prof_dump(false, filename, false);
- }
-}
-
-static void
-prof_bt_hash(const void *key, size_t r_hash[2])
-{
- prof_bt_t *bt = (prof_bt_t *)key;
-
- cassert(config_prof);
-
- hash(bt->vec, bt->len * sizeof(void *), 0x94122f33U, r_hash);
-}
-
-static bool
-prof_bt_keycomp(const void *k1, const void *k2)
-{
- const prof_bt_t *bt1 = (prof_bt_t *)k1;
- const prof_bt_t *bt2 = (prof_bt_t *)k2;
-
- cassert(config_prof);
-
- if (bt1->len != bt2->len)
- return (false);
- return (memcmp(bt1->vec, bt2->vec, bt1->len * sizeof(void *)) == 0);
-}
-
-static malloc_mutex_t *
-prof_ctx_mutex_choose(void)
-{
- unsigned nctxs = atomic_add_u(&cum_ctxs, 1);
-
- return (&ctx_locks[(nctxs - 1) % PROF_NCTX_LOCKS]);
-}
-
-prof_tdata_t *
-prof_tdata_init(void)
-{
- prof_tdata_t *prof_tdata;
-
- cassert(config_prof);
-
- /* Initialize an empty cache for this thread. */
- prof_tdata = (prof_tdata_t *)imalloc(sizeof(prof_tdata_t));
- if (prof_tdata == NULL)
- return (NULL);
-
- if (ckh_new(&prof_tdata->bt2cnt, PROF_CKH_MINITEMS,
- prof_bt_hash, prof_bt_keycomp)) {
- idalloc(prof_tdata);
- return (NULL);
- }
- ql_new(&prof_tdata->lru_ql);
-
- prof_tdata->vec = imalloc(sizeof(void *) * PROF_BT_MAX);
- if (prof_tdata->vec == NULL) {
- ckh_delete(&prof_tdata->bt2cnt);
- idalloc(prof_tdata);
- return (NULL);
- }
-
- prof_tdata->prng_state = 0;
- prof_tdata->threshold = 0;
- prof_tdata->accum = 0;
-
- prof_tdata->enq = false;
- prof_tdata->enq_idump = false;
- prof_tdata->enq_gdump = false;
-
- prof_tdata_tsd_set(&prof_tdata);
-
- return (prof_tdata);
-}
-
-void
-prof_tdata_cleanup(void *arg)
-{
- prof_thr_cnt_t *cnt;
- prof_tdata_t *prof_tdata = *(prof_tdata_t **)arg;
-
- cassert(config_prof);
-
- if (prof_tdata == PROF_TDATA_STATE_REINCARNATED) {
- /*
- * Another destructor deallocated memory after this destructor
- * was called. Reset prof_tdata to PROF_TDATA_STATE_PURGATORY
- * in order to receive another callback.
- */
- prof_tdata = PROF_TDATA_STATE_PURGATORY;
- prof_tdata_tsd_set(&prof_tdata);
- } else if (prof_tdata == PROF_TDATA_STATE_PURGATORY) {
- /*
- * The previous time this destructor was called, we set the key
- * to PROF_TDATA_STATE_PURGATORY so that other destructors
- * wouldn't cause re-creation of the prof_tdata. This time, do
- * nothing, so that the destructor will not be called again.
- */
- } else if (prof_tdata != NULL) {
- /*
- * Delete the hash table. All of its contents can still be
- * iterated over via the LRU.
- */
- ckh_delete(&prof_tdata->bt2cnt);
- /*
- * Iteratively merge cnt's into the global stats and delete
- * them.
- */
- while ((cnt = ql_last(&prof_tdata->lru_ql, lru_link)) != NULL) {
- ql_remove(&prof_tdata->lru_ql, cnt, lru_link);
- prof_ctx_merge(cnt->ctx, cnt);
- idalloc(cnt);
- }
- idalloc(prof_tdata->vec);
- idalloc(prof_tdata);
- prof_tdata = PROF_TDATA_STATE_PURGATORY;
- prof_tdata_tsd_set(&prof_tdata);
- }
-}
-
-void
-prof_boot0(void)
-{
-
- cassert(config_prof);
-
- memcpy(opt_prof_prefix, PROF_PREFIX_DEFAULT,
- sizeof(PROF_PREFIX_DEFAULT));
-}
-
-void
-prof_boot1(void)
-{
-
- cassert(config_prof);
-
- /*
- * opt_prof and prof_promote must be in their final state before any
- * arenas are initialized, so this function must be executed early.
- */
-
- if (opt_prof_leak && opt_prof == false) {
- /*
- * Enable opt_prof, but in such a way that profiles are never
- * automatically dumped.
- */
- opt_prof = true;
- opt_prof_gdump = false;
- } else if (opt_prof) {
- if (opt_lg_prof_interval >= 0) {
- prof_interval = (((uint64_t)1U) <<
- opt_lg_prof_interval);
- }
- }
-
- prof_promote = (opt_prof && opt_lg_prof_sample > LG_PAGE);
-}
-
-bool
-prof_boot2(void)
-{
-
- cassert(config_prof);
-
- if (opt_prof) {
- unsigned i;
-
- if (ckh_new(&bt2ctx, PROF_CKH_MINITEMS, prof_bt_hash,
- prof_bt_keycomp))
- return (true);
- if (malloc_mutex_init(&bt2ctx_mtx))
- return (true);
- if (prof_tdata_tsd_boot()) {
- malloc_write(
- "<jemalloc>: Error in pthread_key_create()\n");
- abort();
- }
-
- if (malloc_mutex_init(&prof_dump_seq_mtx))
- return (true);
-
- if (atexit(prof_fdump) != 0) {
- malloc_write("<jemalloc>: Error in atexit()\n");
- if (opt_abort)
- abort();
- }
-
- ctx_locks = (malloc_mutex_t *)base_alloc(PROF_NCTX_LOCKS *
- sizeof(malloc_mutex_t));
- if (ctx_locks == NULL)
- return (true);
- for (i = 0; i < PROF_NCTX_LOCKS; i++) {
- if (malloc_mutex_init(&ctx_locks[i]))
- return (true);
- }
- }
-
-#ifdef JEMALLOC_PROF_LIBGCC
- /*
- * Cause the backtracing machinery to allocate its internal state
- * before enabling profiling.
- */
- _Unwind_Backtrace(prof_unwind_init_callback, NULL);
-#endif
-
- prof_booted = true;
-
- return (false);
-}
-
-void
-prof_prefork(void)
-{
-
- if (opt_prof) {
- unsigned i;
-
- malloc_mutex_lock(&bt2ctx_mtx);
- malloc_mutex_lock(&prof_dump_seq_mtx);
- for (i = 0; i < PROF_NCTX_LOCKS; i++)
- malloc_mutex_lock(&ctx_locks[i]);
- }
-}
-
-void
-prof_postfork_parent(void)
-{
-
- if (opt_prof) {
- unsigned i;
-
- for (i = 0; i < PROF_NCTX_LOCKS; i++)
- malloc_mutex_postfork_parent(&ctx_locks[i]);
- malloc_mutex_postfork_parent(&prof_dump_seq_mtx);
- malloc_mutex_postfork_parent(&bt2ctx_mtx);
- }
-}
-
-void
-prof_postfork_child(void)
-{
-
- if (opt_prof) {
- unsigned i;
-
- for (i = 0; i < PROF_NCTX_LOCKS; i++)
- malloc_mutex_postfork_child(&ctx_locks[i]);
- malloc_mutex_postfork_child(&prof_dump_seq_mtx);
- malloc_mutex_postfork_child(&bt2ctx_mtx);
- }
-}
-
-/******************************************************************************/
diff --git a/extra/jemalloc/src/quarantine.c b/extra/jemalloc/src/quarantine.c
deleted file mode 100644
index f96a948d5c7..00000000000
--- a/extra/jemalloc/src/quarantine.c
+++ /dev/null
@@ -1,190 +0,0 @@
-#define JEMALLOC_QUARANTINE_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/*
- * quarantine pointers close to NULL are used to encode state information that
- * is used for cleaning up during thread shutdown.
- */
-#define QUARANTINE_STATE_REINCARNATED ((quarantine_t *)(uintptr_t)1)
-#define QUARANTINE_STATE_PURGATORY ((quarantine_t *)(uintptr_t)2)
-#define QUARANTINE_STATE_MAX QUARANTINE_STATE_PURGATORY
-
-/******************************************************************************/
-/* Data. */
-
-malloc_tsd_data(, quarantine, quarantine_t *, NULL)
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static quarantine_t *quarantine_grow(quarantine_t *quarantine);
-static void quarantine_drain_one(quarantine_t *quarantine);
-static void quarantine_drain(quarantine_t *quarantine, size_t upper_bound);
-
-/******************************************************************************/
-
-quarantine_t *
-quarantine_init(size_t lg_maxobjs)
-{
- quarantine_t *quarantine;
-
- quarantine = (quarantine_t *)imalloc(offsetof(quarantine_t, objs) +
- ((ZU(1) << lg_maxobjs) * sizeof(quarantine_obj_t)));
- if (quarantine == NULL)
- return (NULL);
- quarantine->curbytes = 0;
- quarantine->curobjs = 0;
- quarantine->first = 0;
- quarantine->lg_maxobjs = lg_maxobjs;
-
- quarantine_tsd_set(&quarantine);
-
- return (quarantine);
-}
-
-static quarantine_t *
-quarantine_grow(quarantine_t *quarantine)
-{
- quarantine_t *ret;
-
- ret = quarantine_init(quarantine->lg_maxobjs + 1);
- if (ret == NULL) {
- quarantine_drain_one(quarantine);
- return (quarantine);
- }
-
- ret->curbytes = quarantine->curbytes;
- ret->curobjs = quarantine->curobjs;
- if (quarantine->first + quarantine->curobjs <= (ZU(1) <<
- quarantine->lg_maxobjs)) {
- /* objs ring buffer data are contiguous. */
- memcpy(ret->objs, &quarantine->objs[quarantine->first],
- quarantine->curobjs * sizeof(quarantine_obj_t));
- } else {
- /* objs ring buffer data wrap around. */
- size_t ncopy_a = (ZU(1) << quarantine->lg_maxobjs) -
- quarantine->first;
- size_t ncopy_b = quarantine->curobjs - ncopy_a;
-
- memcpy(ret->objs, &quarantine->objs[quarantine->first], ncopy_a
- * sizeof(quarantine_obj_t));
- memcpy(&ret->objs[ncopy_a], quarantine->objs, ncopy_b *
- sizeof(quarantine_obj_t));
- }
- idalloc(quarantine);
-
- return (ret);
-}
-
-static void
-quarantine_drain_one(quarantine_t *quarantine)
-{
- quarantine_obj_t *obj = &quarantine->objs[quarantine->first];
- assert(obj->usize == isalloc(obj->ptr, config_prof));
- idalloc(obj->ptr);
- quarantine->curbytes -= obj->usize;
- quarantine->curobjs--;
- quarantine->first = (quarantine->first + 1) & ((ZU(1) <<
- quarantine->lg_maxobjs) - 1);
-}
-
-static void
-quarantine_drain(quarantine_t *quarantine, size_t upper_bound)
-{
-
- while (quarantine->curbytes > upper_bound && quarantine->curobjs > 0)
- quarantine_drain_one(quarantine);
-}
-
-void
-quarantine(void *ptr)
-{
- quarantine_t *quarantine;
- size_t usize = isalloc(ptr, config_prof);
-
- cassert(config_fill);
- assert(opt_quarantine);
-
- quarantine = *quarantine_tsd_get();
- if ((uintptr_t)quarantine <= (uintptr_t)QUARANTINE_STATE_MAX) {
- if (quarantine == QUARANTINE_STATE_PURGATORY) {
- /*
- * Make a note that quarantine() was called after
- * quarantine_cleanup() was called.
- */
- quarantine = QUARANTINE_STATE_REINCARNATED;
- quarantine_tsd_set(&quarantine);
- }
- idalloc(ptr);
- return;
- }
- /*
- * Drain one or more objects if the quarantine size limit would be
- * exceeded by appending ptr.
- */
- if (quarantine->curbytes + usize > opt_quarantine) {
- size_t upper_bound = (opt_quarantine >= usize) ? opt_quarantine
- - usize : 0;
- quarantine_drain(quarantine, upper_bound);
- }
- /* Grow the quarantine ring buffer if it's full. */
- if (quarantine->curobjs == (ZU(1) << quarantine->lg_maxobjs))
- quarantine = quarantine_grow(quarantine);
- /* quarantine_grow() must free a slot if it fails to grow. */
- assert(quarantine->curobjs < (ZU(1) << quarantine->lg_maxobjs));
- /* Append ptr if its size doesn't exceed the quarantine size. */
- if (quarantine->curbytes + usize <= opt_quarantine) {
- size_t offset = (quarantine->first + quarantine->curobjs) &
- ((ZU(1) << quarantine->lg_maxobjs) - 1);
- quarantine_obj_t *obj = &quarantine->objs[offset];
- obj->ptr = ptr;
- obj->usize = usize;
- quarantine->curbytes += usize;
- quarantine->curobjs++;
- if (opt_junk)
- memset(ptr, 0x5a, usize);
- } else {
- assert(quarantine->curbytes == 0);
- idalloc(ptr);
- }
-}
-
-void
-quarantine_cleanup(void *arg)
-{
- quarantine_t *quarantine = *(quarantine_t **)arg;
-
- if (quarantine == QUARANTINE_STATE_REINCARNATED) {
- /*
- * Another destructor deallocated memory after this destructor
- * was called. Reset quarantine to QUARANTINE_STATE_PURGATORY
- * in order to receive another callback.
- */
- quarantine = QUARANTINE_STATE_PURGATORY;
- quarantine_tsd_set(&quarantine);
- } else if (quarantine == QUARANTINE_STATE_PURGATORY) {
- /*
- * The previous time this destructor was called, we set the key
- * to QUARANTINE_STATE_PURGATORY so that other destructors
- * wouldn't cause re-creation of the quarantine. This time, do
- * nothing, so that the destructor will not be called again.
- */
- } else if (quarantine != NULL) {
- quarantine_drain(quarantine, 0);
- idalloc(quarantine);
- quarantine = QUARANTINE_STATE_PURGATORY;
- quarantine_tsd_set(&quarantine);
- }
-}
-
-bool
-quarantine_boot(void)
-{
-
- cassert(config_fill);
-
- if (quarantine_tsd_boot())
- return (true);
-
- return (false);
-}
diff --git a/extra/jemalloc/src/rtree.c b/extra/jemalloc/src/rtree.c
deleted file mode 100644
index 90c6935a0ed..00000000000
--- a/extra/jemalloc/src/rtree.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#define JEMALLOC_RTREE_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-rtree_t *
-rtree_new(unsigned bits)
-{
- rtree_t *ret;
- unsigned bits_per_level, height, i;
-
- bits_per_level = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(void *)))) - 1;
- height = bits / bits_per_level;
- if (height * bits_per_level != bits)
- height++;
- assert(height * bits_per_level >= bits);
-
- ret = (rtree_t*)base_alloc(offsetof(rtree_t, level2bits) +
- (sizeof(unsigned) * height));
- if (ret == NULL)
- return (NULL);
- memset(ret, 0, offsetof(rtree_t, level2bits) + (sizeof(unsigned) *
- height));
-
- if (malloc_mutex_init(&ret->mutex)) {
- /* Leak the rtree. */
- return (NULL);
- }
- ret->height = height;
- if (bits_per_level * height > bits)
- ret->level2bits[0] = bits % bits_per_level;
- else
- ret->level2bits[0] = bits_per_level;
- for (i = 1; i < height; i++)
- ret->level2bits[i] = bits_per_level;
-
- ret->root = (void**)base_alloc(sizeof(void *) << ret->level2bits[0]);
- if (ret->root == NULL) {
- /*
- * We leak the rtree here, since there's no generic base
- * deallocation.
- */
- return (NULL);
- }
- memset(ret->root, 0, sizeof(void *) << ret->level2bits[0]);
-
- return (ret);
-}
-
-void
-rtree_prefork(rtree_t *rtree)
-{
-
- malloc_mutex_prefork(&rtree->mutex);
-}
-
-void
-rtree_postfork_parent(rtree_t *rtree)
-{
-
- malloc_mutex_postfork_parent(&rtree->mutex);
-}
-
-void
-rtree_postfork_child(rtree_t *rtree)
-{
-
- malloc_mutex_postfork_child(&rtree->mutex);
-}
diff --git a/extra/jemalloc/src/stats.c b/extra/jemalloc/src/stats.c
deleted file mode 100644
index 43f87af6700..00000000000
--- a/extra/jemalloc/src/stats.c
+++ /dev/null
@@ -1,549 +0,0 @@
-#define JEMALLOC_STATS_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-#define CTL_GET(n, v, t) do { \
- size_t sz = sizeof(t); \
- xmallctl(n, v, &sz, NULL, 0); \
-} while (0)
-
-#define CTL_I_GET(n, v, t) do { \
- size_t mib[6]; \
- size_t miblen = sizeof(mib) / sizeof(size_t); \
- size_t sz = sizeof(t); \
- xmallctlnametomib(n, mib, &miblen); \
- mib[2] = i; \
- xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \
-} while (0)
-
-#define CTL_J_GET(n, v, t) do { \
- size_t mib[6]; \
- size_t miblen = sizeof(mib) / sizeof(size_t); \
- size_t sz = sizeof(t); \
- xmallctlnametomib(n, mib, &miblen); \
- mib[2] = j; \
- xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \
-} while (0)
-
-#define CTL_IJ_GET(n, v, t) do { \
- size_t mib[6]; \
- size_t miblen = sizeof(mib) / sizeof(size_t); \
- size_t sz = sizeof(t); \
- xmallctlnametomib(n, mib, &miblen); \
- mib[2] = i; \
- mib[4] = j; \
- xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \
-} while (0)
-
-/******************************************************************************/
-/* Data. */
-
-bool opt_stats_print = false;
-
-size_t stats_cactive = 0;
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static void stats_arena_bins_print(void (*write_cb)(void *, const char *),
- void *cbopaque, unsigned i);
-static void stats_arena_lruns_print(void (*write_cb)(void *, const char *),
- void *cbopaque, unsigned i);
-static void stats_arena_print(void (*write_cb)(void *, const char *),
- void *cbopaque, unsigned i, bool bins, bool large);
-
-/******************************************************************************/
-
-static void
-stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
- unsigned i)
-{
- size_t page;
- bool config_tcache;
- unsigned nbins, j, gap_start;
-
- CTL_GET("arenas.page", &page, size_t);
-
- CTL_GET("config.tcache", &config_tcache, bool);
- if (config_tcache) {
- malloc_cprintf(write_cb, cbopaque,
- "bins: bin size regs pgs allocated nmalloc"
- " ndalloc nrequests nfills nflushes"
- " newruns reruns curruns\n");
- } else {
- malloc_cprintf(write_cb, cbopaque,
- "bins: bin size regs pgs allocated nmalloc"
- " ndalloc newruns reruns curruns\n");
- }
- CTL_GET("arenas.nbins", &nbins, unsigned);
- for (j = 0, gap_start = UINT_MAX; j < nbins; j++) {
- uint64_t nruns;
-
- CTL_IJ_GET("stats.arenas.0.bins.0.nruns", &nruns, uint64_t);
- if (nruns == 0) {
- if (gap_start == UINT_MAX)
- gap_start = j;
- } else {
- size_t reg_size, run_size, allocated;
- uint32_t nregs;
- uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;
- uint64_t reruns;
- size_t curruns;
-
- if (gap_start != UINT_MAX) {
- if (j > gap_start + 1) {
- /* Gap of more than one size class. */
- malloc_cprintf(write_cb, cbopaque,
- "[%u..%u]\n", gap_start,
- j - 1);
- } else {
- /* Gap of one size class. */
- malloc_cprintf(write_cb, cbopaque,
- "[%u]\n", gap_start);
- }
- gap_start = UINT_MAX;
- }
- CTL_J_GET("arenas.bin.0.size", &reg_size, size_t);
- CTL_J_GET("arenas.bin.0.nregs", &nregs, uint32_t);
- CTL_J_GET("arenas.bin.0.run_size", &run_size, size_t);
- CTL_IJ_GET("stats.arenas.0.bins.0.allocated",
- &allocated, size_t);
- CTL_IJ_GET("stats.arenas.0.bins.0.nmalloc",
- &nmalloc, uint64_t);
- CTL_IJ_GET("stats.arenas.0.bins.0.ndalloc",
- &ndalloc, uint64_t);
- if (config_tcache) {
- CTL_IJ_GET("stats.arenas.0.bins.0.nrequests",
- &nrequests, uint64_t);
- CTL_IJ_GET("stats.arenas.0.bins.0.nfills",
- &nfills, uint64_t);
- CTL_IJ_GET("stats.arenas.0.bins.0.nflushes",
- &nflushes, uint64_t);
- }
- CTL_IJ_GET("stats.arenas.0.bins.0.nreruns", &reruns,
- uint64_t);
- CTL_IJ_GET("stats.arenas.0.bins.0.curruns", &curruns,
- size_t);
- if (config_tcache) {
- malloc_cprintf(write_cb, cbopaque,
- "%13u %5zu %4u %3zu %12zu %12"PRIu64
- " %12"PRIu64" %12"PRIu64" %12"PRIu64
- " %12"PRIu64" %12"PRIu64" %12"PRIu64
- " %12zu\n",
- j, reg_size, nregs, run_size / page,
- allocated, nmalloc, ndalloc, nrequests,
- nfills, nflushes, nruns, reruns, curruns);
- } else {
- malloc_cprintf(write_cb, cbopaque,
- "%13u %5zu %4u %3zu %12zu %12"PRIu64
- " %12"PRIu64" %12"PRIu64" %12"PRIu64
- " %12zu\n",
- j, reg_size, nregs, run_size / page,
- allocated, nmalloc, ndalloc, nruns, reruns,
- curruns);
- }
- }
- }
- if (gap_start != UINT_MAX) {
- if (j > gap_start + 1) {
- /* Gap of more than one size class. */
- malloc_cprintf(write_cb, cbopaque, "[%u..%u]\n",
- gap_start, j - 1);
- } else {
- /* Gap of one size class. */
- malloc_cprintf(write_cb, cbopaque, "[%u]\n", gap_start);
- }
- }
-}
-
-static void
-stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
- unsigned i)
-{
- size_t page, nlruns, j;
- ssize_t gap_start;
-
- CTL_GET("arenas.page", &page, size_t);
-
- malloc_cprintf(write_cb, cbopaque,
- "large: size pages nmalloc ndalloc nrequests"
- " curruns\n");
- CTL_GET("arenas.nlruns", &nlruns, size_t);
- for (j = 0, gap_start = -1; j < nlruns; j++) {
- uint64_t nmalloc, ndalloc, nrequests;
- size_t run_size, curruns;
-
- CTL_IJ_GET("stats.arenas.0.lruns.0.nmalloc", &nmalloc,
- uint64_t);
- CTL_IJ_GET("stats.arenas.0.lruns.0.ndalloc", &ndalloc,
- uint64_t);
- CTL_IJ_GET("stats.arenas.0.lruns.0.nrequests", &nrequests,
- uint64_t);
- if (nrequests == 0) {
- if (gap_start == -1)
- gap_start = j;
- } else {
- CTL_J_GET("arenas.lrun.0.size", &run_size, size_t);
- CTL_IJ_GET("stats.arenas.0.lruns.0.curruns", &curruns,
- size_t);
- if (gap_start != -1) {
- malloc_cprintf(write_cb, cbopaque, "[%zu]\n",
- j - gap_start);
- gap_start = -1;
- }
- malloc_cprintf(write_cb, cbopaque,
- "%13zu %5zu %12"PRIu64" %12"PRIu64" %12"PRIu64
- " %12zu\n",
- run_size, run_size / page, nmalloc, ndalloc,
- nrequests, curruns);
- }
- }
- if (gap_start != -1)
- malloc_cprintf(write_cb, cbopaque, "[%zu]\n", j - gap_start);
-}
-
-static void
-stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
- unsigned i, bool bins, bool large)
-{
- unsigned nthreads;
- const char *dss;
- size_t page, pactive, pdirty, mapped;
- uint64_t npurge, nmadvise, purged;
- size_t small_allocated;
- uint64_t small_nmalloc, small_ndalloc, small_nrequests;
- size_t large_allocated;
- uint64_t large_nmalloc, large_ndalloc, large_nrequests;
-
- CTL_GET("arenas.page", &page, size_t);
-
- CTL_I_GET("stats.arenas.0.nthreads", &nthreads, unsigned);
- malloc_cprintf(write_cb, cbopaque,
- "assigned threads: %u\n", nthreads);
- CTL_I_GET("stats.arenas.0.dss", &dss, const char *);
- malloc_cprintf(write_cb, cbopaque, "dss allocation precedence: %s\n",
- dss);
- CTL_I_GET("stats.arenas.0.pactive", &pactive, size_t);
- CTL_I_GET("stats.arenas.0.pdirty", &pdirty, size_t);
- CTL_I_GET("stats.arenas.0.npurge", &npurge, uint64_t);
- CTL_I_GET("stats.arenas.0.nmadvise", &nmadvise, uint64_t);
- CTL_I_GET("stats.arenas.0.purged", &purged, uint64_t);
- malloc_cprintf(write_cb, cbopaque,
- "dirty pages: %zu:%zu active:dirty, %"PRIu64" sweep%s,"
- " %"PRIu64" madvise%s, %"PRIu64" purged\n",
- pactive, pdirty, npurge, npurge == 1 ? "" : "s",
- nmadvise, nmadvise == 1 ? "" : "s", purged);
-
- malloc_cprintf(write_cb, cbopaque,
- " allocated nmalloc ndalloc nrequests\n");
- CTL_I_GET("stats.arenas.0.small.allocated", &small_allocated, size_t);
- CTL_I_GET("stats.arenas.0.small.nmalloc", &small_nmalloc, uint64_t);
- CTL_I_GET("stats.arenas.0.small.ndalloc", &small_ndalloc, uint64_t);
- CTL_I_GET("stats.arenas.0.small.nrequests", &small_nrequests, uint64_t);
- malloc_cprintf(write_cb, cbopaque,
- "small: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n",
- small_allocated, small_nmalloc, small_ndalloc, small_nrequests);
- CTL_I_GET("stats.arenas.0.large.allocated", &large_allocated, size_t);
- CTL_I_GET("stats.arenas.0.large.nmalloc", &large_nmalloc, uint64_t);
- CTL_I_GET("stats.arenas.0.large.ndalloc", &large_ndalloc, uint64_t);
- CTL_I_GET("stats.arenas.0.large.nrequests", &large_nrequests, uint64_t);
- malloc_cprintf(write_cb, cbopaque,
- "large: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n",
- large_allocated, large_nmalloc, large_ndalloc, large_nrequests);
- malloc_cprintf(write_cb, cbopaque,
- "total: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n",
- small_allocated + large_allocated,
- small_nmalloc + large_nmalloc,
- small_ndalloc + large_ndalloc,
- small_nrequests + large_nrequests);
- malloc_cprintf(write_cb, cbopaque, "active: %12zu\n", pactive * page);
- CTL_I_GET("stats.arenas.0.mapped", &mapped, size_t);
- malloc_cprintf(write_cb, cbopaque, "mapped: %12zu\n", mapped);
-
- if (bins)
- stats_arena_bins_print(write_cb, cbopaque, i);
- if (large)
- stats_arena_lruns_print(write_cb, cbopaque, i);
-}
-
-void
-stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
- const char *opts)
-{
- int err;
- uint64_t epoch;
- size_t u64sz;
- bool general = true;
- bool merged = true;
- bool unmerged = true;
- bool bins = true;
- bool large = true;
-
- /*
- * Refresh stats, in case mallctl() was called by the application.
- *
- * Check for OOM here, since refreshing the ctl cache can trigger
- * allocation. In practice, none of the subsequent mallctl()-related
- * calls in this function will cause OOM if this one succeeds.
- * */
- epoch = 1;
- u64sz = sizeof(uint64_t);
- err = je_mallctl("epoch", &epoch, &u64sz, &epoch, sizeof(uint64_t));
- if (err != 0) {
- if (err == EAGAIN) {
- malloc_write("<jemalloc>: Memory allocation failure in "
- "mallctl(\"epoch\", ...)\n");
- return;
- }
- malloc_write("<jemalloc>: Failure in mallctl(\"epoch\", "
- "...)\n");
- abort();
- }
-
- if (opts != NULL) {
- unsigned i;
-
- for (i = 0; opts[i] != '\0'; i++) {
- switch (opts[i]) {
- case 'g':
- general = false;
- break;
- case 'm':
- merged = false;
- break;
- case 'a':
- unmerged = false;
- break;
- case 'b':
- bins = false;
- break;
- case 'l':
- large = false;
- break;
- default:;
- }
- }
- }
-
- malloc_cprintf(write_cb, cbopaque,
- "___ Begin jemalloc statistics ___\n");
- if (general) {
- int err;
- const char *cpv;
- bool bv;
- unsigned uv;
- ssize_t ssv;
- size_t sv, bsz, ssz, sssz, cpsz;
-
- bsz = sizeof(bool);
- ssz = sizeof(size_t);
- sssz = sizeof(ssize_t);
- cpsz = sizeof(const char *);
-
- CTL_GET("version", &cpv, const char *);
- malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv);
- CTL_GET("config.debug", &bv, bool);
- malloc_cprintf(write_cb, cbopaque, "Assertions %s\n",
- bv ? "enabled" : "disabled");
-
-#define OPT_WRITE_BOOL(n) \
- if ((err = je_mallctl("opt."#n, &bv, &bsz, NULL, 0)) \
- == 0) { \
- malloc_cprintf(write_cb, cbopaque, \
- " opt."#n": %s\n", bv ? "true" : "false"); \
- }
-#define OPT_WRITE_SIZE_T(n) \
- if ((err = je_mallctl("opt."#n, &sv, &ssz, NULL, 0)) \
- == 0) { \
- malloc_cprintf(write_cb, cbopaque, \
- " opt."#n": %zu\n", sv); \
- }
-#define OPT_WRITE_SSIZE_T(n) \
- if ((err = je_mallctl("opt."#n, &ssv, &sssz, NULL, 0)) \
- == 0) { \
- malloc_cprintf(write_cb, cbopaque, \
- " opt."#n": %zd\n", ssv); \
- }
-#define OPT_WRITE_CHAR_P(n) \
- if ((err = je_mallctl("opt."#n, &cpv, &cpsz, NULL, 0)) \
- == 0) { \
- malloc_cprintf(write_cb, cbopaque, \
- " opt."#n": \"%s\"\n", cpv); \
- }
-
- malloc_cprintf(write_cb, cbopaque,
- "Run-time option settings:\n");
- OPT_WRITE_BOOL(abort)
- OPT_WRITE_SIZE_T(lg_chunk)
- OPT_WRITE_CHAR_P(dss)
- OPT_WRITE_SIZE_T(narenas)
- OPT_WRITE_SSIZE_T(lg_dirty_mult)
- OPT_WRITE_BOOL(stats_print)
- OPT_WRITE_BOOL(junk)
- OPT_WRITE_SIZE_T(quarantine)
- OPT_WRITE_BOOL(redzone)
- OPT_WRITE_BOOL(zero)
- OPT_WRITE_BOOL(utrace)
- OPT_WRITE_BOOL(valgrind)
- OPT_WRITE_BOOL(xmalloc)
- OPT_WRITE_BOOL(tcache)
- OPT_WRITE_SSIZE_T(lg_tcache_max)
- OPT_WRITE_BOOL(prof)
- OPT_WRITE_CHAR_P(prof_prefix)
- OPT_WRITE_BOOL(prof_active)
- OPT_WRITE_SSIZE_T(lg_prof_sample)
- OPT_WRITE_BOOL(prof_accum)
- OPT_WRITE_SSIZE_T(lg_prof_interval)
- OPT_WRITE_BOOL(prof_gdump)
- OPT_WRITE_BOOL(prof_final)
- OPT_WRITE_BOOL(prof_leak)
-
-#undef OPT_WRITE_BOOL
-#undef OPT_WRITE_SIZE_T
-#undef OPT_WRITE_SSIZE_T
-#undef OPT_WRITE_CHAR_P
-
- malloc_cprintf(write_cb, cbopaque, "CPUs: %u\n", ncpus);
-
- CTL_GET("arenas.narenas", &uv, unsigned);
- malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv);
-
- malloc_cprintf(write_cb, cbopaque, "Pointer size: %zu\n",
- sizeof(void *));
-
- CTL_GET("arenas.quantum", &sv, size_t);
- malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", sv);
-
- CTL_GET("arenas.page", &sv, size_t);
- malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv);
-
- CTL_GET("opt.lg_dirty_mult", &ssv, ssize_t);
- if (ssv >= 0) {
- malloc_cprintf(write_cb, cbopaque,
- "Min active:dirty page ratio per arena: %u:1\n",
- (1U << ssv));
- } else {
- malloc_cprintf(write_cb, cbopaque,
- "Min active:dirty page ratio per arena: N/A\n");
- }
- if ((err = je_mallctl("arenas.tcache_max", &sv, &ssz, NULL, 0))
- == 0) {
- malloc_cprintf(write_cb, cbopaque,
- "Maximum thread-cached size class: %zu\n", sv);
- }
- if ((err = je_mallctl("opt.prof", &bv, &bsz, NULL, 0)) == 0 &&
- bv) {
- CTL_GET("opt.lg_prof_sample", &sv, size_t);
- malloc_cprintf(write_cb, cbopaque,
- "Average profile sample interval: %"PRIu64
- " (2^%zu)\n", (((uint64_t)1U) << sv), sv);
-
- CTL_GET("opt.lg_prof_interval", &ssv, ssize_t);
- if (ssv >= 0) {
- malloc_cprintf(write_cb, cbopaque,
- "Average profile dump interval: %"PRIu64
- " (2^%zd)\n",
- (((uint64_t)1U) << ssv), ssv);
- } else {
- malloc_cprintf(write_cb, cbopaque,
- "Average profile dump interval: N/A\n");
- }
- }
- CTL_GET("opt.lg_chunk", &sv, size_t);
- malloc_cprintf(write_cb, cbopaque, "Chunk size: %zu (2^%zu)\n",
- (ZU(1) << sv), sv);
- }
-
- if (config_stats) {
- size_t *cactive;
- size_t allocated, active, mapped;
- size_t chunks_current, chunks_high;
- uint64_t chunks_total;
- size_t huge_allocated;
- uint64_t huge_nmalloc, huge_ndalloc;
-
- CTL_GET("stats.cactive", &cactive, size_t *);
- CTL_GET("stats.allocated", &allocated, size_t);
- CTL_GET("stats.active", &active, size_t);
- CTL_GET("stats.mapped", &mapped, size_t);
- malloc_cprintf(write_cb, cbopaque,
- "Allocated: %zu, active: %zu, mapped: %zu\n",
- allocated, active, mapped);
- malloc_cprintf(write_cb, cbopaque,
- "Current active ceiling: %zu\n", atomic_read_z(cactive));
-
- /* Print chunk stats. */
- CTL_GET("stats.chunks.total", &chunks_total, uint64_t);
- CTL_GET("stats.chunks.high", &chunks_high, size_t);
- CTL_GET("stats.chunks.current", &chunks_current, size_t);
- malloc_cprintf(write_cb, cbopaque, "chunks: nchunks "
- "highchunks curchunks\n");
- malloc_cprintf(write_cb, cbopaque,
- " %13"PRIu64" %12zu %12zu\n",
- chunks_total, chunks_high, chunks_current);
-
- /* Print huge stats. */
- CTL_GET("stats.huge.nmalloc", &huge_nmalloc, uint64_t);
- CTL_GET("stats.huge.ndalloc", &huge_ndalloc, uint64_t);
- CTL_GET("stats.huge.allocated", &huge_allocated, size_t);
- malloc_cprintf(write_cb, cbopaque,
- "huge: nmalloc ndalloc allocated\n");
- malloc_cprintf(write_cb, cbopaque,
- " %12"PRIu64" %12"PRIu64" %12zu\n",
- huge_nmalloc, huge_ndalloc, huge_allocated);
-
- if (merged) {
- unsigned narenas;
-
- CTL_GET("arenas.narenas", &narenas, unsigned);
- {
- VARIABLE_ARRAY(bool, initialized, narenas);
- size_t isz;
- unsigned i, ninitialized;
-
- isz = sizeof(bool) * narenas;
- xmallctl("arenas.initialized", initialized,
- &isz, NULL, 0);
- for (i = ninitialized = 0; i < narenas; i++) {
- if (initialized[i])
- ninitialized++;
- }
-
- if (ninitialized > 1 || unmerged == false) {
- /* Print merged arena stats. */
- malloc_cprintf(write_cb, cbopaque,
- "\nMerged arenas stats:\n");
- stats_arena_print(write_cb, cbopaque,
- narenas, bins, large);
- }
- }
- }
-
- if (unmerged) {
- unsigned narenas;
-
- /* Print stats for each arena. */
-
- CTL_GET("arenas.narenas", &narenas, unsigned);
- {
- VARIABLE_ARRAY(bool, initialized, narenas);
- size_t isz;
- unsigned i;
-
- isz = sizeof(bool) * narenas;
- xmallctl("arenas.initialized", initialized,
- &isz, NULL, 0);
-
- for (i = 0; i < narenas; i++) {
- if (initialized[i]) {
- malloc_cprintf(write_cb,
- cbopaque,
- "\narenas[%u]:\n", i);
- stats_arena_print(write_cb,
- cbopaque, i, bins, large);
- }
- }
- }
- }
- }
- malloc_cprintf(write_cb, cbopaque, "--- End jemalloc statistics ---\n");
-}
diff --git a/extra/jemalloc/src/tcache.c b/extra/jemalloc/src/tcache.c
deleted file mode 100644
index 98ed19edd52..00000000000
--- a/extra/jemalloc/src/tcache.c
+++ /dev/null
@@ -1,476 +0,0 @@
-#define JEMALLOC_TCACHE_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Data. */
-
-malloc_tsd_data(, tcache, tcache_t *, NULL)
-malloc_tsd_data(, tcache_enabled, tcache_enabled_t, tcache_enabled_default)
-
-bool opt_tcache = true;
-ssize_t opt_lg_tcache_max = LG_TCACHE_MAXCLASS_DEFAULT;
-
-tcache_bin_info_t *tcache_bin_info;
-static unsigned stack_nelms; /* Total stack elms per tcache. */
-
-size_t nhbins;
-size_t tcache_maxclass;
-
-/******************************************************************************/
-
-size_t tcache_salloc(const void *ptr)
-{
-
- return (arena_salloc(ptr, false));
-}
-
-void
-tcache_event_hard(tcache_t *tcache)
-{
- size_t binind = tcache->next_gc_bin;
- tcache_bin_t *tbin = &tcache->tbins[binind];
- tcache_bin_info_t *tbin_info = &tcache_bin_info[binind];
-
- if (tbin->low_water > 0) {
- /*
- * Flush (ceiling) 3/4 of the objects below the low water mark.
- */
- if (binind < NBINS) {
- tcache_bin_flush_small(tbin, binind, tbin->ncached -
- tbin->low_water + (tbin->low_water >> 2), tcache);
- } else {
- tcache_bin_flush_large(tbin, binind, tbin->ncached -
- tbin->low_water + (tbin->low_water >> 2), tcache);
- }
- /*
- * Reduce fill count by 2X. Limit lg_fill_div such that the
- * fill count is always at least 1.
- */
- if ((tbin_info->ncached_max >> (tbin->lg_fill_div+1)) >= 1)
- tbin->lg_fill_div++;
- } else if (tbin->low_water < 0) {
- /*
- * Increase fill count by 2X. Make sure lg_fill_div stays
- * greater than 0.
- */
- if (tbin->lg_fill_div > 1)
- tbin->lg_fill_div--;
- }
- tbin->low_water = tbin->ncached;
-
- tcache->next_gc_bin++;
- if (tcache->next_gc_bin == nhbins)
- tcache->next_gc_bin = 0;
- tcache->ev_cnt = 0;
-}
-
-void *
-tcache_alloc_small_hard(tcache_t *tcache, tcache_bin_t *tbin, size_t binind)
-{
- void *ret;
-
- arena_tcache_fill_small(tcache->arena, tbin, binind,
- config_prof ? tcache->prof_accumbytes : 0);
- if (config_prof)
- tcache->prof_accumbytes = 0;
- ret = tcache_alloc_easy(tbin);
-
- return (ret);
-}
-
-void
-tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem,
- tcache_t *tcache)
-{
- void *ptr;
- unsigned i, nflush, ndeferred;
- bool merged_stats = false;
-
- assert(binind < NBINS);
- assert(rem <= tbin->ncached);
-
- for (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) {
- /* Lock the arena bin associated with the first object. */
- arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(
- tbin->avail[0]);
- arena_t *arena = chunk->arena;
- arena_bin_t *bin = &arena->bins[binind];
-
- if (config_prof && arena == tcache->arena) {
- if (arena_prof_accum(arena, tcache->prof_accumbytes))
- prof_idump();
- tcache->prof_accumbytes = 0;
- }
-
- malloc_mutex_lock(&bin->lock);
- if (config_stats && arena == tcache->arena) {
- assert(merged_stats == false);
- merged_stats = true;
- bin->stats.nflushes++;
- bin->stats.nrequests += tbin->tstats.nrequests;
- tbin->tstats.nrequests = 0;
- }
- ndeferred = 0;
- for (i = 0; i < nflush; i++) {
- ptr = tbin->avail[i];
- assert(ptr != NULL);
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk->arena == arena) {
- size_t pageind = ((uintptr_t)ptr -
- (uintptr_t)chunk) >> LG_PAGE;
- arena_chunk_map_t *mapelm =
- arena_mapp_get(chunk, pageind);
- if (config_fill && opt_junk) {
- arena_alloc_junk_small(ptr,
- &arena_bin_info[binind], true);
- }
- arena_dalloc_bin_locked(arena, chunk, ptr,
- mapelm);
- } else {
- /*
- * This object was allocated via a different
- * arena bin than the one that is currently
- * locked. Stash the object, so that it can be
- * handled in a future pass.
- */
- tbin->avail[ndeferred] = ptr;
- ndeferred++;
- }
- }
- malloc_mutex_unlock(&bin->lock);
- }
- if (config_stats && merged_stats == false) {
- /*
- * The flush loop didn't happen to flush to this thread's
- * arena, so the stats didn't get merged. Manually do so now.
- */
- arena_bin_t *bin = &tcache->arena->bins[binind];
- malloc_mutex_lock(&bin->lock);
- bin->stats.nflushes++;
- bin->stats.nrequests += tbin->tstats.nrequests;
- tbin->tstats.nrequests = 0;
- malloc_mutex_unlock(&bin->lock);
- }
-
- memmove(tbin->avail, &tbin->avail[tbin->ncached - rem],
- rem * sizeof(void *));
- tbin->ncached = rem;
- if ((int)tbin->ncached < tbin->low_water)
- tbin->low_water = tbin->ncached;
-}
-
-void
-tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem,
- tcache_t *tcache)
-{
- void *ptr;
- unsigned i, nflush, ndeferred;
- bool merged_stats = false;
-
- assert(binind < nhbins);
- assert(rem <= tbin->ncached);
-
- for (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) {
- /* Lock the arena associated with the first object. */
- arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(
- tbin->avail[0]);
- arena_t *arena = chunk->arena;
- UNUSED bool idump;
-
- if (config_prof)
- idump = false;
- malloc_mutex_lock(&arena->lock);
- if ((config_prof || config_stats) && arena == tcache->arena) {
- if (config_prof) {
- idump = arena_prof_accum_locked(arena,
- tcache->prof_accumbytes);
- tcache->prof_accumbytes = 0;
- }
- if (config_stats) {
- merged_stats = true;
- arena->stats.nrequests_large +=
- tbin->tstats.nrequests;
- arena->stats.lstats[binind - NBINS].nrequests +=
- tbin->tstats.nrequests;
- tbin->tstats.nrequests = 0;
- }
- }
- ndeferred = 0;
- for (i = 0; i < nflush; i++) {
- ptr = tbin->avail[i];
- assert(ptr != NULL);
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk->arena == arena)
- arena_dalloc_large_locked(arena, chunk, ptr);
- else {
- /*
- * This object was allocated via a different
- * arena than the one that is currently locked.
- * Stash the object, so that it can be handled
- * in a future pass.
- */
- tbin->avail[ndeferred] = ptr;
- ndeferred++;
- }
- }
- malloc_mutex_unlock(&arena->lock);
- if (config_prof && idump)
- prof_idump();
- }
- if (config_stats && merged_stats == false) {
- /*
- * The flush loop didn't happen to flush to this thread's
- * arena, so the stats didn't get merged. Manually do so now.
- */
- arena_t *arena = tcache->arena;
- malloc_mutex_lock(&arena->lock);
- arena->stats.nrequests_large += tbin->tstats.nrequests;
- arena->stats.lstats[binind - NBINS].nrequests +=
- tbin->tstats.nrequests;
- tbin->tstats.nrequests = 0;
- malloc_mutex_unlock(&arena->lock);
- }
-
- memmove(tbin->avail, &tbin->avail[tbin->ncached - rem],
- rem * sizeof(void *));
- tbin->ncached = rem;
- if ((int)tbin->ncached < tbin->low_water)
- tbin->low_water = tbin->ncached;
-}
-
-void
-tcache_arena_associate(tcache_t *tcache, arena_t *arena)
-{
-
- if (config_stats) {
- /* Link into list of extant tcaches. */
- malloc_mutex_lock(&arena->lock);
- ql_elm_new(tcache, link);
- ql_tail_insert(&arena->tcache_ql, tcache, link);
- malloc_mutex_unlock(&arena->lock);
- }
- tcache->arena = arena;
-}
-
-void
-tcache_arena_dissociate(tcache_t *tcache)
-{
-
- if (config_stats) {
- /* Unlink from list of extant tcaches. */
- malloc_mutex_lock(&tcache->arena->lock);
- ql_remove(&tcache->arena->tcache_ql, tcache, link);
- malloc_mutex_unlock(&tcache->arena->lock);
- tcache_stats_merge(tcache, tcache->arena);
- }
-}
-
-tcache_t *
-tcache_create(arena_t *arena)
-{
- tcache_t *tcache;
- size_t size, stack_offset;
- unsigned i;
-
- size = offsetof(tcache_t, tbins) + (sizeof(tcache_bin_t) * nhbins);
- /* Naturally align the pointer stacks. */
- size = PTR_CEILING(size);
- stack_offset = size;
- size += stack_nelms * sizeof(void *);
- /*
- * Round up to the nearest multiple of the cacheline size, in order to
- * avoid the possibility of false cacheline sharing.
- *
- * That this works relies on the same logic as in ipalloc(), but we
- * cannot directly call ipalloc() here due to tcache bootstrapping
- * issues.
- */
- size = (size + CACHELINE_MASK) & (-CACHELINE);
-
- if (size <= SMALL_MAXCLASS)
- tcache = (tcache_t *)arena_malloc_small(arena, size, true);
- else if (size <= tcache_maxclass)
- tcache = (tcache_t *)arena_malloc_large(arena, size, true);
- else
- tcache = (tcache_t *)icallocx(size, false, arena);
-
- if (tcache == NULL)
- return (NULL);
-
- tcache_arena_associate(tcache, arena);
-
- assert((TCACHE_NSLOTS_SMALL_MAX & 1U) == 0);
- for (i = 0; i < nhbins; i++) {
- tcache->tbins[i].lg_fill_div = 1;
- tcache->tbins[i].avail = (void **)((uintptr_t)tcache +
- (uintptr_t)stack_offset);
- stack_offset += tcache_bin_info[i].ncached_max * sizeof(void *);
- }
-
- tcache_tsd_set(&tcache);
-
- return (tcache);
-}
-
-void
-tcache_destroy(tcache_t *tcache)
-{
- unsigned i;
- size_t tcache_size;
-
- tcache_arena_dissociate(tcache);
-
- for (i = 0; i < NBINS; i++) {
- tcache_bin_t *tbin = &tcache->tbins[i];
- tcache_bin_flush_small(tbin, i, 0, tcache);
-
- if (config_stats && tbin->tstats.nrequests != 0) {
- arena_t *arena = tcache->arena;
- arena_bin_t *bin = &arena->bins[i];
- malloc_mutex_lock(&bin->lock);
- bin->stats.nrequests += tbin->tstats.nrequests;
- malloc_mutex_unlock(&bin->lock);
- }
- }
-
- for (; i < nhbins; i++) {
- tcache_bin_t *tbin = &tcache->tbins[i];
- tcache_bin_flush_large(tbin, i, 0, tcache);
-
- if (config_stats && tbin->tstats.nrequests != 0) {
- arena_t *arena = tcache->arena;
- malloc_mutex_lock(&arena->lock);
- arena->stats.nrequests_large += tbin->tstats.nrequests;
- arena->stats.lstats[i - NBINS].nrequests +=
- tbin->tstats.nrequests;
- malloc_mutex_unlock(&arena->lock);
- }
- }
-
- if (config_prof && tcache->prof_accumbytes > 0 &&
- arena_prof_accum(tcache->arena, tcache->prof_accumbytes))
- prof_idump();
-
- tcache_size = arena_salloc(tcache, false);
- if (tcache_size <= SMALL_MAXCLASS) {
- arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache);
- arena_t *arena = chunk->arena;
- size_t pageind = ((uintptr_t)tcache - (uintptr_t)chunk) >>
- LG_PAGE;
- arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind);
-
- arena_dalloc_bin(arena, chunk, tcache, pageind, mapelm);
- } else if (tcache_size <= tcache_maxclass) {
- arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache);
- arena_t *arena = chunk->arena;
-
- arena_dalloc_large(arena, chunk, tcache);
- } else
- idallocx(tcache, false);
-}
-
-void
-tcache_thread_cleanup(void *arg)
-{
- tcache_t *tcache = *(tcache_t **)arg;
-
- if (tcache == TCACHE_STATE_DISABLED) {
- /* Do nothing. */
- } else if (tcache == TCACHE_STATE_REINCARNATED) {
- /*
- * Another destructor called an allocator function after this
- * destructor was called. Reset tcache to
- * TCACHE_STATE_PURGATORY in order to receive another callback.
- */
- tcache = TCACHE_STATE_PURGATORY;
- tcache_tsd_set(&tcache);
- } else if (tcache == TCACHE_STATE_PURGATORY) {
- /*
- * The previous time this destructor was called, we set the key
- * to TCACHE_STATE_PURGATORY so that other destructors wouldn't
- * cause re-creation of the tcache. This time, do nothing, so
- * that the destructor will not be called again.
- */
- } else if (tcache != NULL) {
- assert(tcache != TCACHE_STATE_PURGATORY);
- tcache_destroy(tcache);
- tcache = TCACHE_STATE_PURGATORY;
- tcache_tsd_set(&tcache);
- }
-}
-
-void
-tcache_stats_merge(tcache_t *tcache, arena_t *arena)
-{
- unsigned i;
-
- /* Merge and reset tcache stats. */
- for (i = 0; i < NBINS; i++) {
- arena_bin_t *bin = &arena->bins[i];
- tcache_bin_t *tbin = &tcache->tbins[i];
- malloc_mutex_lock(&bin->lock);
- bin->stats.nrequests += tbin->tstats.nrequests;
- malloc_mutex_unlock(&bin->lock);
- tbin->tstats.nrequests = 0;
- }
-
- for (; i < nhbins; i++) {
- malloc_large_stats_t *lstats = &arena->stats.lstats[i - NBINS];
- tcache_bin_t *tbin = &tcache->tbins[i];
- arena->stats.nrequests_large += tbin->tstats.nrequests;
- lstats->nrequests += tbin->tstats.nrequests;
- tbin->tstats.nrequests = 0;
- }
-}
-
-bool
-tcache_boot0(void)
-{
- unsigned i;
-
- /*
- * If necessary, clamp opt_lg_tcache_max, now that arena_maxclass is
- * known.
- */
- if (opt_lg_tcache_max < 0 || (1U << opt_lg_tcache_max) < SMALL_MAXCLASS)
- tcache_maxclass = SMALL_MAXCLASS;
- else if ((1U << opt_lg_tcache_max) > arena_maxclass)
- tcache_maxclass = arena_maxclass;
- else
- tcache_maxclass = (1U << opt_lg_tcache_max);
-
- nhbins = NBINS + (tcache_maxclass >> LG_PAGE);
-
- /* Initialize tcache_bin_info. */
- tcache_bin_info = (tcache_bin_info_t *)base_alloc(nhbins *
- sizeof(tcache_bin_info_t));
- if (tcache_bin_info == NULL)
- return (true);
- stack_nelms = 0;
- for (i = 0; i < NBINS; i++) {
- if ((arena_bin_info[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MAX) {
- tcache_bin_info[i].ncached_max =
- (arena_bin_info[i].nregs << 1);
- } else {
- tcache_bin_info[i].ncached_max =
- TCACHE_NSLOTS_SMALL_MAX;
- }
- stack_nelms += tcache_bin_info[i].ncached_max;
- }
- for (; i < nhbins; i++) {
- tcache_bin_info[i].ncached_max = TCACHE_NSLOTS_LARGE;
- stack_nelms += tcache_bin_info[i].ncached_max;
- }
-
- return (false);
-}
-
-bool
-tcache_boot1(void)
-{
-
- if (tcache_tsd_boot() || tcache_enabled_tsd_boot())
- return (true);
-
- return (false);
-}
diff --git a/extra/jemalloc/src/tsd.c b/extra/jemalloc/src/tsd.c
deleted file mode 100644
index 961a546329c..00000000000
--- a/extra/jemalloc/src/tsd.c
+++ /dev/null
@@ -1,107 +0,0 @@
-#define JEMALLOC_TSD_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Data. */
-
-static unsigned ncleanups;
-static malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX];
-
-/******************************************************************************/
-
-void *
-malloc_tsd_malloc(size_t size)
-{
-
- /* Avoid choose_arena() in order to dodge bootstrapping issues. */
- return (arena_malloc(arenas[0], size, false, false));
-}
-
-void
-malloc_tsd_dalloc(void *wrapper)
-{
-
- idalloc(wrapper);
-}
-
-void
-malloc_tsd_no_cleanup(void *arg)
-{
-
- not_reached();
-}
-
-#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)
-#ifndef _WIN32
-JEMALLOC_EXPORT
-#endif
-void
-_malloc_thread_cleanup(void)
-{
- bool pending[MALLOC_TSD_CLEANUPS_MAX], again;
- unsigned i;
-
- for (i = 0; i < ncleanups; i++)
- pending[i] = true;
-
- do {
- again = false;
- for (i = 0; i < ncleanups; i++) {
- if (pending[i]) {
- pending[i] = cleanups[i]();
- if (pending[i])
- again = true;
- }
- }
- } while (again);
-}
-#endif
-
-void
-malloc_tsd_cleanup_register(bool (*f)(void))
-{
-
- assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);
- cleanups[ncleanups] = f;
- ncleanups++;
-}
-
-void
-malloc_tsd_boot(void)
-{
-
- ncleanups = 0;
-}
-
-#ifdef _WIN32
-static BOOL WINAPI
-_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
-
- switch (fdwReason) {
-#ifdef JEMALLOC_LAZY_LOCK
- case DLL_THREAD_ATTACH:
- isthreaded = true;
- break;
-#endif
- case DLL_THREAD_DETACH:
- _malloc_thread_cleanup();
- break;
- default:
- break;
- }
- return (true);
-}
-
-#ifdef _MSC_VER
-# ifdef _M_IX86
-# pragma comment(linker, "/INCLUDE:__tls_used")
-# else
-# pragma comment(linker, "/INCLUDE:_tls_used")
-# endif
-# pragma section(".CRT$XLY",long,read)
-#endif
-JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used)
-static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL,
- DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;
-#endif
diff --git a/extra/jemalloc/src/util.c b/extra/jemalloc/src/util.c
deleted file mode 100644
index b3a01143698..00000000000
--- a/extra/jemalloc/src/util.c
+++ /dev/null
@@ -1,641 +0,0 @@
-#define assert(e) do { \
- if (config_debug && !(e)) { \
- malloc_write("<jemalloc>: Failed assertion\n"); \
- abort(); \
- } \
-} while (0)
-
-#define not_reached() do { \
- if (config_debug) { \
- malloc_write("<jemalloc>: Unreachable code reached\n"); \
- abort(); \
- } \
-} while (0)
-
-#define not_implemented() do { \
- if (config_debug) { \
- malloc_write("<jemalloc>: Not implemented\n"); \
- abort(); \
- } \
-} while (0)
-
-#define JEMALLOC_UTIL_C_
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static void wrtmessage(void *cbopaque, const char *s);
-#define U2S_BUFSIZE ((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)
-static char *u2s(uintmax_t x, unsigned base, bool uppercase, char *s,
- size_t *slen_p);
-#define D2S_BUFSIZE (1 + U2S_BUFSIZE)
-static char *d2s(intmax_t x, char sign, char *s, size_t *slen_p);
-#define O2S_BUFSIZE (1 + U2S_BUFSIZE)
-static char *o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p);
-#define X2S_BUFSIZE (2 + U2S_BUFSIZE)
-static char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,
- size_t *slen_p);
-
-/******************************************************************************/
-
-/* malloc_message() setup. */
-static void
-wrtmessage(void *cbopaque, const char *s)
-{
-
-#ifdef SYS_write
- /*
- * Use syscall(2) rather than write(2) when possible in order to avoid
- * the possibility of memory allocation within libc. This is necessary
- * on FreeBSD; most operating systems do not have this problem though.
- */
- UNUSED int result = syscall(SYS_write, STDERR_FILENO, s, strlen(s));
-#else
- UNUSED int result = write(STDERR_FILENO, s, strlen(s));
-#endif
-}
-
-JEMALLOC_EXPORT void (*je_malloc_message)(void *, const char *s);
-
-/*
- * Wrapper around malloc_message() that avoids the need for
- * je_malloc_message(...) throughout the code.
- */
-void
-malloc_write(const char *s)
-{
-
- if (je_malloc_message != NULL)
- je_malloc_message(NULL, s);
- else
- wrtmessage(NULL, s);
-}
-
-/*
- * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
- * provide a wrapper.
- */
-int
-buferror(char *buf, size_t buflen)
-{
-
-#ifdef _WIN32
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
- (LPSTR)buf, buflen, NULL);
- return (0);
-#elif defined(_GNU_SOURCE)
- char *b = strerror_r(errno, buf, buflen);
- if (b != buf) {
- strncpy(buf, b, buflen);
- buf[buflen-1] = '\0';
- }
- return (0);
-#else
- return (strerror_r(errno, buf, buflen));
-#endif
-}
-
-uintmax_t
-malloc_strtoumax(const char *nptr, char **endptr, int base)
-{
- uintmax_t ret, digit;
- int b;
- bool neg;
- const char *p, *ns;
-
- if (base < 0 || base == 1 || base > 36) {
- set_errno(EINVAL);
- return (UINTMAX_MAX);
- }
- b = base;
-
- /* Swallow leading whitespace and get sign, if any. */
- neg = false;
- p = nptr;
- while (true) {
- switch (*p) {
- case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
- p++;
- break;
- case '-':
- neg = true;
- /* Fall through. */
- case '+':
- p++;
- /* Fall through. */
- default:
- goto label_prefix;
- }
- }
-
- /* Get prefix, if any. */
- label_prefix:
- /*
- * Note where the first non-whitespace/sign character is so that it is
- * possible to tell whether any digits are consumed (e.g., " 0" vs.
- * " -x").
- */
- ns = p;
- if (*p == '0') {
- switch (p[1]) {
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7':
- if (b == 0)
- b = 8;
- if (b == 8)
- p++;
- break;
- case 'x':
- switch (p[2]) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f':
- if (b == 0)
- b = 16;
- if (b == 16)
- p += 2;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
- if (b == 0)
- b = 10;
-
- /* Convert. */
- ret = 0;
- while ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b)
- || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b)
- || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) {
- uintmax_t pret = ret;
- ret *= b;
- ret += digit;
- if (ret < pret) {
- /* Overflow. */
- set_errno(ERANGE);
- return (UINTMAX_MAX);
- }
- p++;
- }
- if (neg)
- ret = -ret;
-
- if (endptr != NULL) {
- if (p == ns) {
- /* No characters were converted. */
- *endptr = (char *)nptr;
- } else
- *endptr = (char *)p;
- }
-
- return (ret);
-}
-
-static char *
-u2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p)
-{
- unsigned i;
-
- i = U2S_BUFSIZE - 1;
- s[i] = '\0';
- switch (base) {
- case 10:
- do {
- i--;
- s[i] = "0123456789"[x % (uint64_t)10];
- x /= (uint64_t)10;
- } while (x > 0);
- break;
- case 16: {
- const char *digits = (uppercase)
- ? "0123456789ABCDEF"
- : "0123456789abcdef";
-
- do {
- i--;
- s[i] = digits[x & 0xf];
- x >>= 4;
- } while (x > 0);
- break;
- } default: {
- const char *digits = (uppercase)
- ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- : "0123456789abcdefghijklmnopqrstuvwxyz";
-
- assert(base >= 2 && base <= 36);
- do {
- i--;
- s[i] = digits[x % (uint64_t)base];
- x /= (uint64_t)base;
- } while (x > 0);
- }}
-
- *slen_p = U2S_BUFSIZE - 1 - i;
- return (&s[i]);
-}
-
-static char *
-d2s(intmax_t x, char sign, char *s, size_t *slen_p)
-{
- bool neg;
-
- if ((neg = (x < 0)))
- x = -x;
- s = u2s(x, 10, false, s, slen_p);
- if (neg)
- sign = '-';
- switch (sign) {
- case '-':
- if (neg == false)
- break;
- /* Fall through. */
- case ' ':
- case '+':
- s--;
- (*slen_p)++;
- *s = sign;
- break;
- default: not_reached();
- }
- return (s);
-}
-
-static char *
-o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p)
-{
-
- s = u2s(x, 8, false, s, slen_p);
- if (alt_form && *s != '0') {
- s--;
- (*slen_p)++;
- *s = '0';
- }
- return (s);
-}
-
-static char *
-x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p)
-{
-
- s = u2s(x, 16, uppercase, s, slen_p);
- if (alt_form) {
- s -= 2;
- (*slen_p) += 2;
- memcpy(s, uppercase ? "0X" : "0x", 2);
- }
- return (s);
-}
-
-int
-malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap)
-{
- int ret;
- size_t i;
- const char *f;
-
-#define APPEND_C(c) do { \
- if (i < size) \
- str[i] = (c); \
- i++; \
-} while (0)
-#define APPEND_S(s, slen) do { \
- if (i < size) { \
- size_t cpylen = (slen <= size - i) ? slen : size - i; \
- memcpy(&str[i], s, cpylen); \
- } \
- i += slen; \
-} while (0)
-#define APPEND_PADDED_S(s, slen, width, left_justify) do { \
- /* Left padding. */ \
- size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ? \
- (size_t)width - slen : 0); \
- if (left_justify == false && pad_len != 0) { \
- size_t j; \
- for (j = 0; j < pad_len; j++) \
- APPEND_C(' '); \
- } \
- /* Value. */ \
- APPEND_S(s, slen); \
- /* Right padding. */ \
- if (left_justify && pad_len != 0) { \
- size_t j; \
- for (j = 0; j < pad_len; j++) \
- APPEND_C(' '); \
- } \
-} while (0)
-#define GET_ARG_NUMERIC(val, len) do { \
- switch (len) { \
- case '?': \
- val = va_arg(ap, int); \
- break; \
- case '?' | 0x80: \
- val = va_arg(ap, unsigned int); \
- break; \
- case 'l': \
- val = va_arg(ap, long); \
- break; \
- case 'l' | 0x80: \
- val = va_arg(ap, unsigned long); \
- break; \
- case 'q': \
- val = va_arg(ap, long long); \
- break; \
- case 'q' | 0x80: \
- val = va_arg(ap, unsigned long long); \
- break; \
- case 'j': \
- val = va_arg(ap, intmax_t); \
- break; \
- case 't': \
- val = va_arg(ap, ptrdiff_t); \
- break; \
- case 'z': \
- val = va_arg(ap, ssize_t); \
- break; \
- case 'z' | 0x80: \
- val = va_arg(ap, size_t); \
- break; \
- case 'p': /* Synthetic; used for %p. */ \
- val = va_arg(ap, uintptr_t); \
- break; \
- default: not_reached(); \
- } \
-} while (0)
-
- i = 0;
- f = format;
- while (true) {
- switch (*f) {
- case '\0': goto label_out;
- case '%': {
- bool alt_form = false;
- bool left_justify = false;
- bool plus_space = false;
- bool plus_plus = false;
- int prec = -1;
- int width = -1;
- unsigned char len = '?';
-
- f++;
- if (*f == '%') {
- /* %% */
- APPEND_C(*f);
- break;
- }
- /* Flags. */
- while (true) {
- switch (*f) {
- case '#':
- assert(alt_form == false);
- alt_form = true;
- break;
- case '-':
- assert(left_justify == false);
- left_justify = true;
- break;
- case ' ':
- assert(plus_space == false);
- plus_space = true;
- break;
- case '+':
- assert(plus_plus == false);
- plus_plus = true;
- break;
- default: goto label_width;
- }
- f++;
- }
- /* Width. */
- label_width:
- switch (*f) {
- case '*':
- width = va_arg(ap, int);
- f++;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9': {
- uintmax_t uwidth;
- set_errno(0);
- uwidth = malloc_strtoumax(f, (char **)&f, 10);
- assert(uwidth != UINTMAX_MAX || get_errno() !=
- ERANGE);
- width = (int)uwidth;
- if (*f == '.') {
- f++;
- goto label_precision;
- } else
- goto label_length;
- break;
- } case '.':
- f++;
- goto label_precision;
- default: goto label_length;
- }
- /* Precision. */
- label_precision:
- switch (*f) {
- case '*':
- prec = va_arg(ap, int);
- f++;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9': {
- uintmax_t uprec;
- set_errno(0);
- uprec = malloc_strtoumax(f, (char **)&f, 10);
- assert(uprec != UINTMAX_MAX || get_errno() !=
- ERANGE);
- prec = (int)uprec;
- break;
- }
- default: break;
- }
- /* Length. */
- label_length:
- switch (*f) {
- case 'l':
- f++;
- if (*f == 'l') {
- len = 'q';
- f++;
- } else
- len = 'l';
- break;
- case 'j':
- len = 'j';
- f++;
- break;
- case 't':
- len = 't';
- f++;
- break;
- case 'z':
- len = 'z';
- f++;
- break;
- default: break;
- }
- /* Conversion specifier. */
- switch (*f) {
- char *s;
- size_t slen;
- case 'd': case 'i': {
- intmax_t val JEMALLOC_CC_SILENCE_INIT(0);
- char buf[D2S_BUFSIZE];
-
- GET_ARG_NUMERIC(val, len);
- s = d2s(val, (plus_plus ? '+' : (plus_space ?
- ' ' : '-')), buf, &slen);
- APPEND_PADDED_S(s, slen, width, left_justify);
- f++;
- break;
- } case 'o': {
- uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
- char buf[O2S_BUFSIZE];
-
- GET_ARG_NUMERIC(val, len | 0x80);
- s = o2s(val, alt_form, buf, &slen);
- APPEND_PADDED_S(s, slen, width, left_justify);
- f++;
- break;
- } case 'u': {
- uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
- char buf[U2S_BUFSIZE];
-
- GET_ARG_NUMERIC(val, len | 0x80);
- s = u2s(val, 10, false, buf, &slen);
- APPEND_PADDED_S(s, slen, width, left_justify);
- f++;
- break;
- } case 'x': case 'X': {
- uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
- char buf[X2S_BUFSIZE];
-
- GET_ARG_NUMERIC(val, len | 0x80);
- s = x2s(val, alt_form, *f == 'X', buf, &slen);
- APPEND_PADDED_S(s, slen, width, left_justify);
- f++;
- break;
- } case 'c': {
- unsigned char val;
- char buf[2];
-
- assert(len == '?' || len == 'l');
- assert_not_implemented(len != 'l');
- val = va_arg(ap, int);
- buf[0] = val;
- buf[1] = '\0';
- APPEND_PADDED_S(buf, 1, width, left_justify);
- f++;
- break;
- } case 's':
- assert(len == '?' || len == 'l');
- assert_not_implemented(len != 'l');
- s = va_arg(ap, char *);
- slen = (prec == -1) ? strlen(s) : prec;
- APPEND_PADDED_S(s, slen, width, left_justify);
- f++;
- break;
- case 'p': {
- uintmax_t val;
- char buf[X2S_BUFSIZE];
-
- GET_ARG_NUMERIC(val, 'p');
- s = x2s(val, true, false, buf, &slen);
- APPEND_PADDED_S(s, slen, width, left_justify);
- f++;
- break;
- }
- default: not_implemented();
- }
- break;
- } default: {
- APPEND_C(*f);
- f++;
- break;
- }}
- }
- label_out:
- if (i < size)
- str[i] = '\0';
- else
- str[size - 1] = '\0';
- ret = i;
-
-#undef APPEND_C
-#undef APPEND_S
-#undef APPEND_PADDED_S
-#undef GET_ARG_NUMERIC
- return (ret);
-}
-
-JEMALLOC_ATTR(format(printf, 3, 4))
-int
-malloc_snprintf(char *str, size_t size, const char *format, ...)
-{
- int ret;
- va_list ap;
-
- va_start(ap, format);
- ret = malloc_vsnprintf(str, size, format, ap);
- va_end(ap);
-
- return (ret);
-}
-
-void
-malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,
- const char *format, va_list ap)
-{
- char buf[MALLOC_PRINTF_BUFSIZE];
-
- if (write_cb == NULL) {
- /*
- * The caller did not provide an alternate write_cb callback
- * function, so use the default one. malloc_write() is an
- * inline function, so use malloc_message() directly here.
- */
- write_cb = (je_malloc_message != NULL) ? je_malloc_message :
- wrtmessage;
- cbopaque = NULL;
- }
-
- malloc_vsnprintf(buf, sizeof(buf), format, ap);
- write_cb(cbopaque, buf);
-}
-
-/*
- * Print to a callback function in such a way as to (hopefully) avoid memory
- * allocation.
- */
-JEMALLOC_ATTR(format(printf, 3, 4))
-void
-malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque,
- const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- malloc_vcprintf(write_cb, cbopaque, format, ap);
- va_end(ap);
-}
-
-/* Print to stderr in such a way as to avoid memory allocation. */
-JEMALLOC_ATTR(format(printf, 1, 2))
-void
-malloc_printf(const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- malloc_vcprintf(NULL, NULL, format, ap);
- va_end(ap);
-}
diff --git a/extra/jemalloc/src/zone.c b/extra/jemalloc/src/zone.c
deleted file mode 100644
index c62c183f65e..00000000000
--- a/extra/jemalloc/src/zone.c
+++ /dev/null
@@ -1,258 +0,0 @@
-#include "jemalloc/internal/jemalloc_internal.h"
-#ifndef JEMALLOC_ZONE
-# error "This source file is for zones on Darwin (OS X)."
-#endif
-
-/*
- * The malloc_default_purgeable_zone function is only available on >= 10.6.
- * We need to check whether it is present at runtime, thus the weak_import.
- */
-extern malloc_zone_t *malloc_default_purgeable_zone(void)
-JEMALLOC_ATTR(weak_import);
-
-/******************************************************************************/
-/* Data. */
-
-static malloc_zone_t zone;
-static struct malloc_introspection_t zone_introspect;
-
-/******************************************************************************/
-/* Function prototypes for non-inline static functions. */
-
-static size_t zone_size(malloc_zone_t *zone, void *ptr);
-static void *zone_malloc(malloc_zone_t *zone, size_t size);
-static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size);
-static void *zone_valloc(malloc_zone_t *zone, size_t size);
-static void zone_free(malloc_zone_t *zone, void *ptr);
-static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size);
-#if (JEMALLOC_ZONE_VERSION >= 5)
-static void *zone_memalign(malloc_zone_t *zone, size_t alignment,
-#endif
-#if (JEMALLOC_ZONE_VERSION >= 6)
- size_t size);
-static void zone_free_definite_size(malloc_zone_t *zone, void *ptr,
- size_t size);
-#endif
-static void *zone_destroy(malloc_zone_t *zone);
-static size_t zone_good_size(malloc_zone_t *zone, size_t size);
-static void zone_force_lock(malloc_zone_t *zone);
-static void zone_force_unlock(malloc_zone_t *zone);
-
-/******************************************************************************/
-/*
- * Functions.
- */
-
-static size_t
-zone_size(malloc_zone_t *zone, void *ptr)
-{
-
- /*
- * There appear to be places within Darwin (such as setenv(3)) that
- * cause calls to this function with pointers that *no* zone owns. If
- * we knew that all pointers were owned by *some* zone, we could split
- * our zone into two parts, and use one as the default allocator and
- * the other as the default deallocator/reallocator. Since that will
- * not work in practice, we must check all pointers to assure that they
- * reside within a mapped chunk before determining size.
- */
- return (ivsalloc(ptr, config_prof));
-}
-
-static void *
-zone_malloc(malloc_zone_t *zone, size_t size)
-{
-
- return (je_malloc(size));
-}
-
-static void *
-zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
-{
-
- return (je_calloc(num, size));
-}
-
-static void *
-zone_valloc(malloc_zone_t *zone, size_t size)
-{
- void *ret = NULL; /* Assignment avoids useless compiler warning. */
-
- je_posix_memalign(&ret, PAGE, size);
-
- return (ret);
-}
-
-static void
-zone_free(malloc_zone_t *zone, void *ptr)
-{
-
- if (ivsalloc(ptr, config_prof) != 0) {
- je_free(ptr);
- return;
- }
-
- free(ptr);
-}
-
-static void *
-zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
-{
-
- if (ivsalloc(ptr, config_prof) != 0)
- return (je_realloc(ptr, size));
-
- return (realloc(ptr, size));
-}
-
-#if (JEMALLOC_ZONE_VERSION >= 5)
-static void *
-zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
-{
- void *ret = NULL; /* Assignment avoids useless compiler warning. */
-
- je_posix_memalign(&ret, alignment, size);
-
- return (ret);
-}
-#endif
-
-#if (JEMALLOC_ZONE_VERSION >= 6)
-static void
-zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
-{
-
- if (ivsalloc(ptr, config_prof) != 0) {
- assert(ivsalloc(ptr, config_prof) == size);
- je_free(ptr);
- return;
- }
-
- free(ptr);
-}
-#endif
-
-static void *
-zone_destroy(malloc_zone_t *zone)
-{
-
- /* This function should never be called. */
- assert(false);
- return (NULL);
-}
-
-static size_t
-zone_good_size(malloc_zone_t *zone, size_t size)
-{
-
- if (size == 0)
- size = 1;
- return (s2u(size));
-}
-
-static void
-zone_force_lock(malloc_zone_t *zone)
-{
-
- if (isthreaded)
- jemalloc_prefork();
-}
-
-static void
-zone_force_unlock(malloc_zone_t *zone)
-{
-
- if (isthreaded)
- jemalloc_postfork_parent();
-}
-
-JEMALLOC_ATTR(constructor)
-void
-register_zone(void)
-{
-
- /*
- * If something else replaced the system default zone allocator, don't
- * register jemalloc's.
- */
- malloc_zone_t *default_zone = malloc_default_zone();
- if (!default_zone->zone_name ||
- strcmp(default_zone->zone_name, "DefaultMallocZone") != 0) {
- return;
- }
-
- zone.size = (void *)zone_size;
- zone.malloc = (void *)zone_malloc;
- zone.calloc = (void *)zone_calloc;
- zone.valloc = (void *)zone_valloc;
- zone.free = (void *)zone_free;
- zone.realloc = (void *)zone_realloc;
- zone.destroy = (void *)zone_destroy;
- zone.zone_name = "jemalloc_zone";
- zone.batch_malloc = NULL;
- zone.batch_free = NULL;
- zone.introspect = &zone_introspect;
- zone.version = JEMALLOC_ZONE_VERSION;
-#if (JEMALLOC_ZONE_VERSION >= 5)
- zone.memalign = zone_memalign;
-#endif
-#if (JEMALLOC_ZONE_VERSION >= 6)
- zone.free_definite_size = zone_free_definite_size;
-#endif
-#if (JEMALLOC_ZONE_VERSION >= 8)
- zone.pressure_relief = NULL;
-#endif
-
- zone_introspect.enumerator = NULL;
- zone_introspect.good_size = (void *)zone_good_size;
- zone_introspect.check = NULL;
- zone_introspect.print = NULL;
- zone_introspect.log = NULL;
- zone_introspect.force_lock = (void *)zone_force_lock;
- zone_introspect.force_unlock = (void *)zone_force_unlock;
- zone_introspect.statistics = NULL;
-#if (JEMALLOC_ZONE_VERSION >= 6)
- zone_introspect.zone_locked = NULL;
-#endif
-#if (JEMALLOC_ZONE_VERSION >= 7)
- zone_introspect.enable_discharge_checking = NULL;
- zone_introspect.disable_discharge_checking = NULL;
- zone_introspect.discharge = NULL;
-#ifdef __BLOCKS__
- zone_introspect.enumerate_discharged_pointers = NULL;
-#else
- zone_introspect.enumerate_unavailable_without_blocks = NULL;
-#endif
-#endif
-
- /*
- * The default purgeable zone is created lazily by OSX's libc. It uses
- * the default zone when it is created for "small" allocations
- * (< 15 KiB), but assumes the default zone is a scalable_zone. This
- * obviously fails when the default zone is the jemalloc zone, so
- * malloc_default_purgeable_zone is called beforehand so that the
- * default purgeable zone is created when the default zone is still
- * a scalable_zone. As purgeable zones only exist on >= 10.6, we need
- * to check for the existence of malloc_default_purgeable_zone() at
- * run time.
- */
- if (malloc_default_purgeable_zone != NULL)
- malloc_default_purgeable_zone();
-
- /* Register the custom zone. At this point it won't be the default. */
- malloc_zone_register(&zone);
-
- /*
- * Unregister and reregister the default zone. On OSX >= 10.6,
- * unregistering takes the last registered zone and places it at the
- * location of the specified zone. Unregistering the default zone thus
- * makes the last registered one the default. On OSX < 10.6,
- * unregistering shifts all registered zones. The first registered zone
- * then becomes the default.
- */
- do {
- default_zone = malloc_default_zone();
- malloc_zone_unregister(default_zone);
- malloc_zone_register(default_zone);
- } while (malloc_default_zone() != &zone);
-}
diff --git a/extra/jemalloc/test/ALLOCM_ARENA.c b/extra/jemalloc/test/ALLOCM_ARENA.c
deleted file mode 100644
index 2c52485e890..00000000000
--- a/extra/jemalloc/test/ALLOCM_ARENA.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-#define NTHREADS 10
-
-void *
-je_thread_start(void *arg)
-{
- unsigned thread_ind = (unsigned)(uintptr_t)arg;
- unsigned arena_ind;
- int r;
- void *p;
- size_t rsz, sz;
-
- sz = sizeof(arena_ind);
- if (mallctl("arenas.extend", &arena_ind, &sz, NULL, 0)
- != 0) {
- malloc_printf("Error in arenas.extend\n");
- abort();
- }
-
- if (thread_ind % 4 != 3) {
- size_t mib[3];
- size_t miblen = sizeof(mib) / sizeof(size_t);
- const char *dss_precs[] = {"disabled", "primary", "secondary"};
- const char *dss = dss_precs[thread_ind % 4];
- if (mallctlnametomib("arena.0.dss", mib, &miblen) != 0) {
- malloc_printf("Error in mallctlnametomib()\n");
- abort();
- }
- mib[1] = arena_ind;
- if (mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss,
- sizeof(const char *))) {
- malloc_printf("Error in mallctlbymib()\n");
- abort();
- }
- }
-
- r = allocm(&p, &rsz, 1, ALLOCM_ARENA(arena_ind));
- if (r != ALLOCM_SUCCESS) {
- malloc_printf("Unexpected allocm() error\n");
- abort();
- }
- dallocm(p, 0);
-
- return (NULL);
-}
-
-int
-main(void)
-{
- je_thread_t threads[NTHREADS];
- unsigned i;
-
- malloc_printf("Test begin\n");
-
- for (i = 0; i < NTHREADS; i++) {
- je_thread_create(&threads[i], je_thread_start,
- (void *)(uintptr_t)i);
- }
-
- for (i = 0; i < NTHREADS; i++)
- je_thread_join(threads[i], NULL);
-
- malloc_printf("Test end\n");
- return (0);
-}
diff --git a/extra/jemalloc/test/ALLOCM_ARENA.exp b/extra/jemalloc/test/ALLOCM_ARENA.exp
deleted file mode 100644
index 369a88dd240..00000000000
--- a/extra/jemalloc/test/ALLOCM_ARENA.exp
+++ /dev/null
@@ -1,2 +0,0 @@
-Test begin
-Test end
diff --git a/extra/jemalloc/test/aligned_alloc.c b/extra/jemalloc/test/aligned_alloc.c
deleted file mode 100644
index 5a9b0caea78..00000000000
--- a/extra/jemalloc/test/aligned_alloc.c
+++ /dev/null
@@ -1,119 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-#define CHUNK 0x400000
-/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
-#define MAXALIGN ((size_t)0x2000000LU)
-#define NITER 4
-
-int
-main(void)
-{
- size_t alignment, size, total;
- unsigned i;
- void *p, *ps[NITER];
-
- malloc_printf("Test begin\n");
-
- /* Test error conditions. */
- alignment = 0;
- set_errno(0);
- p = aligned_alloc(alignment, 1);
- if (p != NULL || get_errno() != EINVAL) {
- malloc_printf(
- "Expected error for invalid alignment %zu\n", alignment);
- }
-
- for (alignment = sizeof(size_t); alignment < MAXALIGN;
- alignment <<= 1) {
- set_errno(0);
- p = aligned_alloc(alignment + 1, 1);
- if (p != NULL || get_errno() != EINVAL) {
- malloc_printf(
- "Expected error for invalid alignment %zu\n",
- alignment + 1);
- }
- }
-
-#if LG_SIZEOF_PTR == 3
- alignment = UINT64_C(0x8000000000000000);
- size = UINT64_C(0x8000000000000000);
-#else
- alignment = 0x80000000LU;
- size = 0x80000000LU;
-#endif
- set_errno(0);
- p = aligned_alloc(alignment, size);
- if (p != NULL || get_errno() != ENOMEM) {
- malloc_printf(
- "Expected error for aligned_alloc(%zu, %zu)\n",
- alignment, size);
- }
-
-#if LG_SIZEOF_PTR == 3
- alignment = UINT64_C(0x4000000000000000);
- size = UINT64_C(0x8400000000000001);
-#else
- alignment = 0x40000000LU;
- size = 0x84000001LU;
-#endif
- set_errno(0);
- p = aligned_alloc(alignment, size);
- if (p != NULL || get_errno() != ENOMEM) {
- malloc_printf(
- "Expected error for aligned_alloc(%zu, %zu)\n",
- alignment, size);
- }
-
- alignment = 0x10LU;
-#if LG_SIZEOF_PTR == 3
- size = UINT64_C(0xfffffffffffffff0);
-#else
- size = 0xfffffff0LU;
-#endif
- set_errno(0);
- p = aligned_alloc(alignment, size);
- if (p != NULL || get_errno() != ENOMEM) {
- malloc_printf(
- "Expected error for aligned_alloc(&p, %zu, %zu)\n",
- alignment, size);
- }
-
- for (i = 0; i < NITER; i++)
- ps[i] = NULL;
-
- for (alignment = 8;
- alignment <= MAXALIGN;
- alignment <<= 1) {
- total = 0;
- malloc_printf("Alignment: %zu\n", alignment);
- for (size = 1;
- size < 3 * alignment && size < (1U << 31);
- size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
- for (i = 0; i < NITER; i++) {
- ps[i] = aligned_alloc(alignment, size);
- if (ps[i] == NULL) {
- char buf[BUFERROR_BUF];
-
- buferror(buf, sizeof(buf));
- malloc_printf(
- "Error for size %zu (%#zx): %s\n",
- size, size, buf);
- exit(1);
- }
- total += malloc_usable_size(ps[i]);
- if (total >= (MAXALIGN << 1))
- break;
- }
- for (i = 0; i < NITER; i++) {
- if (ps[i] != NULL) {
- free(ps[i]);
- ps[i] = NULL;
- }
- }
- }
- }
-
- malloc_printf("Test end\n");
- return (0);
-}
diff --git a/extra/jemalloc/test/aligned_alloc.exp b/extra/jemalloc/test/aligned_alloc.exp
deleted file mode 100644
index b5061c7277e..00000000000
--- a/extra/jemalloc/test/aligned_alloc.exp
+++ /dev/null
@@ -1,25 +0,0 @@
-Test begin
-Alignment: 8
-Alignment: 16
-Alignment: 32
-Alignment: 64
-Alignment: 128
-Alignment: 256
-Alignment: 512
-Alignment: 1024
-Alignment: 2048
-Alignment: 4096
-Alignment: 8192
-Alignment: 16384
-Alignment: 32768
-Alignment: 65536
-Alignment: 131072
-Alignment: 262144
-Alignment: 524288
-Alignment: 1048576
-Alignment: 2097152
-Alignment: 4194304
-Alignment: 8388608
-Alignment: 16777216
-Alignment: 33554432
-Test end
diff --git a/extra/jemalloc/test/allocated.c b/extra/jemalloc/test/allocated.c
deleted file mode 100644
index 9884905d810..00000000000
--- a/extra/jemalloc/test/allocated.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-void *
-je_thread_start(void *arg)
-{
- int err;
- void *p;
- uint64_t a0, a1, d0, d1;
- uint64_t *ap0, *ap1, *dp0, *dp1;
- size_t sz, usize;
-
- sz = sizeof(a0);
- if ((err = mallctl("thread.allocated", &a0, &sz, NULL, 0))) {
- if (err == ENOENT) {
-#ifdef JEMALLOC_STATS
- assert(false);
-#endif
- goto label_return;
- }
- malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
- strerror(err));
- exit(1);
- }
- sz = sizeof(ap0);
- if ((err = mallctl("thread.allocatedp", &ap0, &sz, NULL, 0))) {
- if (err == ENOENT) {
-#ifdef JEMALLOC_STATS
- assert(false);
-#endif
- goto label_return;
- }
- malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
- strerror(err));
- exit(1);
- }
- assert(*ap0 == a0);
-
- sz = sizeof(d0);
- if ((err = mallctl("thread.deallocated", &d0, &sz, NULL, 0))) {
- if (err == ENOENT) {
-#ifdef JEMALLOC_STATS
- assert(false);
-#endif
- goto label_return;
- }
- malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
- strerror(err));
- exit(1);
- }
- sz = sizeof(dp0);
- if ((err = mallctl("thread.deallocatedp", &dp0, &sz, NULL, 0))) {
- if (err == ENOENT) {
-#ifdef JEMALLOC_STATS
- assert(false);
-#endif
- goto label_return;
- }
- malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
- strerror(err));
- exit(1);
- }
- assert(*dp0 == d0);
-
- p = malloc(1);
- if (p == NULL) {
- malloc_printf("%s(): Error in malloc()\n", __func__);
- exit(1);
- }
-
- sz = sizeof(a1);
- mallctl("thread.allocated", &a1, &sz, NULL, 0);
- sz = sizeof(ap1);
- mallctl("thread.allocatedp", &ap1, &sz, NULL, 0);
- assert(*ap1 == a1);
- assert(ap0 == ap1);
-
- usize = malloc_usable_size(p);
- assert(a0 + usize <= a1);
-
- free(p);
-
- sz = sizeof(d1);
- mallctl("thread.deallocated", &d1, &sz, NULL, 0);
- sz = sizeof(dp1);
- mallctl("thread.deallocatedp", &dp1, &sz, NULL, 0);
- assert(*dp1 == d1);
- assert(dp0 == dp1);
-
- assert(d0 + usize <= d1);
-
-label_return:
- return (NULL);
-}
-
-int
-main(void)
-{
- int ret = 0;
- je_thread_t thread;
-
- malloc_printf("Test begin\n");
-
- je_thread_start(NULL);
-
- je_thread_create(&thread, je_thread_start, NULL);
- je_thread_join(thread, (void *)&ret);
-
- je_thread_start(NULL);
-
- je_thread_create(&thread, je_thread_start, NULL);
- je_thread_join(thread, (void *)&ret);
-
- je_thread_start(NULL);
-
- malloc_printf("Test end\n");
- return (ret);
-}
diff --git a/extra/jemalloc/test/allocated.exp b/extra/jemalloc/test/allocated.exp
deleted file mode 100644
index 369a88dd240..00000000000
--- a/extra/jemalloc/test/allocated.exp
+++ /dev/null
@@ -1,2 +0,0 @@
-Test begin
-Test end
diff --git a/extra/jemalloc/test/allocm.c b/extra/jemalloc/test/allocm.c
deleted file mode 100644
index 80be673b8fd..00000000000
--- a/extra/jemalloc/test/allocm.c
+++ /dev/null
@@ -1,194 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-#define CHUNK 0x400000
-/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
-#define MAXALIGN ((size_t)0x2000000LU)
-#define NITER 4
-
-int
-main(void)
-{
- int r;
- void *p;
- size_t nsz, rsz, sz, alignment, total;
- unsigned i;
- void *ps[NITER];
-
- malloc_printf("Test begin\n");
-
- sz = 42;
- nsz = 0;
- r = nallocm(&nsz, sz, 0);
- if (r != ALLOCM_SUCCESS) {
- malloc_printf("Unexpected nallocm() error\n");
- abort();
- }
- rsz = 0;
- r = allocm(&p, &rsz, sz, 0);
- if (r != ALLOCM_SUCCESS) {
- malloc_printf("Unexpected allocm() error\n");
- abort();
- }
- if (rsz < sz)
- malloc_printf("Real size smaller than expected\n");
- if (nsz != rsz)
- malloc_printf("nallocm()/allocm() rsize mismatch\n");
- if (dallocm(p, 0) != ALLOCM_SUCCESS)
- malloc_printf("Unexpected dallocm() error\n");
-
- r = allocm(&p, NULL, sz, 0);
- if (r != ALLOCM_SUCCESS) {
- malloc_printf("Unexpected allocm() error\n");
- abort();
- }
- if (dallocm(p, 0) != ALLOCM_SUCCESS)
- malloc_printf("Unexpected dallocm() error\n");
-
- nsz = 0;
- r = nallocm(&nsz, sz, ALLOCM_ZERO);
- if (r != ALLOCM_SUCCESS) {
- malloc_printf("Unexpected nallocm() error\n");
- abort();
- }
- rsz = 0;
- r = allocm(&p, &rsz, sz, ALLOCM_ZERO);
- if (r != ALLOCM_SUCCESS) {
- malloc_printf("Unexpected allocm() error\n");
- abort();
- }
- if (nsz != rsz)
- malloc_printf("nallocm()/allocm() rsize mismatch\n");
- if (dallocm(p, 0) != ALLOCM_SUCCESS)
- malloc_printf("Unexpected dallocm() error\n");
-
-#if LG_SIZEOF_PTR == 3
- alignment = UINT64_C(0x8000000000000000);
- sz = UINT64_C(0x8000000000000000);
-#else
- alignment = 0x80000000LU;
- sz = 0x80000000LU;
-#endif
- nsz = 0;
- r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment));
- if (r == ALLOCM_SUCCESS) {
- malloc_printf(
- "Expected error for nallocm(&nsz, %zu, %#x)\n",
- sz, ALLOCM_ALIGN(alignment));
- }
- rsz = 0;
- r = allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment));
- if (r == ALLOCM_SUCCESS) {
- malloc_printf(
- "Expected error for allocm(&p, %zu, %#x)\n",
- sz, ALLOCM_ALIGN(alignment));
- }
- if (nsz != rsz)
- malloc_printf("nallocm()/allocm() rsize mismatch\n");
-
-#if LG_SIZEOF_PTR == 3
- alignment = UINT64_C(0x4000000000000000);
- sz = UINT64_C(0x8400000000000001);
-#else
- alignment = 0x40000000LU;
- sz = 0x84000001LU;
-#endif
- nsz = 0;
- r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment));
- if (r != ALLOCM_SUCCESS)
- malloc_printf("Unexpected nallocm() error\n");
- rsz = 0;
- r = allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment));
- if (r == ALLOCM_SUCCESS) {
- malloc_printf(
- "Expected error for allocm(&p, %zu, %#x)\n",
- sz, ALLOCM_ALIGN(alignment));
- }
-
- alignment = 0x10LU;
-#if LG_SIZEOF_PTR == 3
- sz = UINT64_C(0xfffffffffffffff0);
-#else
- sz = 0xfffffff0LU;
-#endif
- nsz = 0;
- r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment));
- if (r == ALLOCM_SUCCESS) {
- malloc_printf(
- "Expected error for nallocm(&nsz, %zu, %#x)\n",
- sz, ALLOCM_ALIGN(alignment));
- }
- rsz = 0;
- r = allocm(&p, &rsz, sz, ALLOCM_ALIGN(alignment));
- if (r == ALLOCM_SUCCESS) {
- malloc_printf(
- "Expected error for allocm(&p, %zu, %#x)\n",
- sz, ALLOCM_ALIGN(alignment));
- }
- if (nsz != rsz)
- malloc_printf("nallocm()/allocm() rsize mismatch\n");
-
- for (i = 0; i < NITER; i++)
- ps[i] = NULL;
-
- for (alignment = 8;
- alignment <= MAXALIGN;
- alignment <<= 1) {
- total = 0;
- malloc_printf("Alignment: %zu\n", alignment);
- for (sz = 1;
- sz < 3 * alignment && sz < (1U << 31);
- sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
- for (i = 0; i < NITER; i++) {
- nsz = 0;
- r = nallocm(&nsz, sz,
- ALLOCM_ALIGN(alignment) | ALLOCM_ZERO);
- if (r != ALLOCM_SUCCESS) {
- malloc_printf(
- "nallocm() error for size %zu"
- " (%#zx): %d\n",
- sz, sz, r);
- exit(1);
- }
- rsz = 0;
- r = allocm(&ps[i], &rsz, sz,
- ALLOCM_ALIGN(alignment) | ALLOCM_ZERO);
- if (r != ALLOCM_SUCCESS) {
- malloc_printf(
- "allocm() error for size %zu"
- " (%#zx): %d\n",
- sz, sz, r);
- exit(1);
- }
- if (rsz < sz) {
- malloc_printf(
- "Real size smaller than"
- " expected\n");
- }
- if (nsz != rsz) {
- malloc_printf(
- "nallocm()/allocm() rsize"
- " mismatch\n");
- }
- if ((uintptr_t)p & (alignment-1)) {
- malloc_printf(
- "%p inadequately aligned for"
- " alignment: %zu\n", p, alignment);
- }
- sallocm(ps[i], &rsz, 0);
- total += rsz;
- if (total >= (MAXALIGN << 1))
- break;
- }
- for (i = 0; i < NITER; i++) {
- if (ps[i] != NULL) {
- dallocm(ps[i], 0);
- ps[i] = NULL;
- }
- }
- }
- }
-
- malloc_printf("Test end\n");
- return (0);
-}
diff --git a/extra/jemalloc/test/allocm.exp b/extra/jemalloc/test/allocm.exp
deleted file mode 100644
index b5061c7277e..00000000000
--- a/extra/jemalloc/test/allocm.exp
+++ /dev/null
@@ -1,25 +0,0 @@
-Test begin
-Alignment: 8
-Alignment: 16
-Alignment: 32
-Alignment: 64
-Alignment: 128
-Alignment: 256
-Alignment: 512
-Alignment: 1024
-Alignment: 2048
-Alignment: 4096
-Alignment: 8192
-Alignment: 16384
-Alignment: 32768
-Alignment: 65536
-Alignment: 131072
-Alignment: 262144
-Alignment: 524288
-Alignment: 1048576
-Alignment: 2097152
-Alignment: 4194304
-Alignment: 8388608
-Alignment: 16777216
-Alignment: 33554432
-Test end
diff --git a/extra/jemalloc/test/bitmap.c b/extra/jemalloc/test/bitmap.c
deleted file mode 100644
index b2cb63004bc..00000000000
--- a/extra/jemalloc/test/bitmap.c
+++ /dev/null
@@ -1,153 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-#if (LG_BITMAP_MAXBITS > 12)
-# define MAXBITS 4500
-#else
-# define MAXBITS (1U << LG_BITMAP_MAXBITS)
-#endif
-
-static void
-test_bitmap_size(void)
-{
- size_t i, prev_size;
-
- prev_size = 0;
- for (i = 1; i <= MAXBITS; i++) {
- size_t size = bitmap_size(i);
- assert(size >= prev_size);
- prev_size = size;
- }
-}
-
-static void
-test_bitmap_init(void)
-{
- size_t i;
-
- for (i = 1; i <= MAXBITS; i++) {
- bitmap_info_t binfo;
- bitmap_info_init(&binfo, i);
- {
- size_t j;
- bitmap_t *bitmap = malloc(sizeof(bitmap_t) *
- bitmap_info_ngroups(&binfo));
- bitmap_init(bitmap, &binfo);
-
- for (j = 0; j < i; j++)
- assert(bitmap_get(bitmap, &binfo, j) == false);
- free(bitmap);
-
- }
- }
-}
-
-static void
-test_bitmap_set(void)
-{
- size_t i;
-
- for (i = 1; i <= MAXBITS; i++) {
- bitmap_info_t binfo;
- bitmap_info_init(&binfo, i);
- {
- size_t j;
- bitmap_t *bitmap = malloc(sizeof(bitmap_t) *
- bitmap_info_ngroups(&binfo));
- bitmap_init(bitmap, &binfo);
-
- for (j = 0; j < i; j++)
- bitmap_set(bitmap, &binfo, j);
- assert(bitmap_full(bitmap, &binfo));
- free(bitmap);
- }
- }
-}
-
-static void
-test_bitmap_unset(void)
-{
- size_t i;
-
- for (i = 1; i <= MAXBITS; i++) {
- bitmap_info_t binfo;
- bitmap_info_init(&binfo, i);
- {
- size_t j;
- bitmap_t *bitmap = malloc(sizeof(bitmap_t) *
- bitmap_info_ngroups(&binfo));
- bitmap_init(bitmap, &binfo);
-
- for (j = 0; j < i; j++)
- bitmap_set(bitmap, &binfo, j);
- assert(bitmap_full(bitmap, &binfo));
- for (j = 0; j < i; j++)
- bitmap_unset(bitmap, &binfo, j);
- for (j = 0; j < i; j++)
- bitmap_set(bitmap, &binfo, j);
- assert(bitmap_full(bitmap, &binfo));
- free(bitmap);
- }
- }
-}
-
-static void
-test_bitmap_sfu(void)
-{
- size_t i;
-
- for (i = 1; i <= MAXBITS; i++) {
- bitmap_info_t binfo;
- bitmap_info_init(&binfo, i);
- {
- ssize_t j;
- bitmap_t *bitmap = malloc(sizeof(bitmap_t) *
- bitmap_info_ngroups(&binfo));
- bitmap_init(bitmap, &binfo);
-
- /* Iteratively set bits starting at the beginning. */
- for (j = 0; j < i; j++)
- assert(bitmap_sfu(bitmap, &binfo) == j);
- assert(bitmap_full(bitmap, &binfo));
-
- /*
- * Iteratively unset bits starting at the end, and
- * verify that bitmap_sfu() reaches the unset bits.
- */
- for (j = i - 1; j >= 0; j--) {
- bitmap_unset(bitmap, &binfo, j);
- assert(bitmap_sfu(bitmap, &binfo) == j);
- bitmap_unset(bitmap, &binfo, j);
- }
- assert(bitmap_get(bitmap, &binfo, 0) == false);
-
- /*
- * Iteratively set bits starting at the beginning, and
- * verify that bitmap_sfu() looks past them.
- */
- for (j = 1; j < i; j++) {
- bitmap_set(bitmap, &binfo, j - 1);
- assert(bitmap_sfu(bitmap, &binfo) == j);
- bitmap_unset(bitmap, &binfo, j);
- }
- assert(bitmap_sfu(bitmap, &binfo) == i - 1);
- assert(bitmap_full(bitmap, &binfo));
- free(bitmap);
- }
- }
-}
-
-int
-main(void)
-{
- malloc_printf("Test begin\n");
-
- test_bitmap_size();
- test_bitmap_init();
- test_bitmap_set();
- test_bitmap_unset();
- test_bitmap_sfu();
-
- malloc_printf("Test end\n");
- return (0);
-}
diff --git a/extra/jemalloc/test/bitmap.exp b/extra/jemalloc/test/bitmap.exp
deleted file mode 100644
index 369a88dd240..00000000000
--- a/extra/jemalloc/test/bitmap.exp
+++ /dev/null
@@ -1,2 +0,0 @@
-Test begin
-Test end
diff --git a/extra/jemalloc/test/jemalloc_test.h.in b/extra/jemalloc/test/jemalloc_test.h.in
deleted file mode 100644
index e38b48efa41..00000000000
--- a/extra/jemalloc/test/jemalloc_test.h.in
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * This header should be included by tests, rather than directly including
- * jemalloc/jemalloc.h, because --with-install-suffix may cause the header to
- * have a different name.
- */
-#include "jemalloc/jemalloc@install_suffix@.h"
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/* Abstraction layer for threading in tests */
-#ifdef _WIN32
-#include <windows.h>
-
-typedef HANDLE je_thread_t;
-
-void
-je_thread_create(je_thread_t *thread, void *(*proc)(void *), void *arg)
-{
- LPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc;
- *thread = CreateThread(NULL, 0, routine, arg, 0, NULL);
- if (*thread == NULL) {
- malloc_printf("Error in CreateThread()\n");
- exit(1);
- }
-}
-
-void
-je_thread_join(je_thread_t thread, void **ret)
-{
- WaitForSingleObject(thread, INFINITE);
-}
-
-#else
-#include <pthread.h>
-
-typedef pthread_t je_thread_t;
-
-void
-je_thread_create(je_thread_t *thread, void *(*proc)(void *), void *arg)
-{
-
- if (pthread_create(thread, NULL, proc, arg) != 0) {
- malloc_printf("Error in pthread_create()\n");
- exit(1);
- }
-}
-
-void
-je_thread_join(je_thread_t thread, void **ret)
-{
-
- pthread_join(thread, ret);
-}
-#endif
diff --git a/extra/jemalloc/test/mremap.c b/extra/jemalloc/test/mremap.c
deleted file mode 100644
index 47efa7c415b..00000000000
--- a/extra/jemalloc/test/mremap.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-int
-main(void)
-{
- int ret, err;
- size_t sz, lg_chunk, chunksize, i;
- char *p, *q;
-
- malloc_printf("Test begin\n");
-
- sz = sizeof(lg_chunk);
- if ((err = mallctl("opt.lg_chunk", &lg_chunk, &sz, NULL, 0))) {
- assert(err != ENOENT);
- malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
- strerror(err));
- ret = 1;
- goto label_return;
- }
- chunksize = ((size_t)1U) << lg_chunk;
-
- p = (char *)malloc(chunksize);
- if (p == NULL) {
- malloc_printf("malloc(%zu) --> %p\n", chunksize, p);
- ret = 1;
- goto label_return;
- }
- memset(p, 'a', chunksize);
-
- q = (char *)realloc(p, chunksize * 2);
- if (q == NULL) {
- malloc_printf("realloc(%p, %zu) --> %p\n", p, chunksize * 2,
- q);
- ret = 1;
- goto label_return;
- }
- for (i = 0; i < chunksize; i++) {
- assert(q[i] == 'a');
- }
-
- p = q;
-
- q = (char *)realloc(p, chunksize);
- if (q == NULL) {
- malloc_printf("realloc(%p, %zu) --> %p\n", p, chunksize, q);
- ret = 1;
- goto label_return;
- }
- for (i = 0; i < chunksize; i++) {
- assert(q[i] == 'a');
- }
-
- free(q);
-
- ret = 0;
-label_return:
- malloc_printf("Test end\n");
- return (ret);
-}
diff --git a/extra/jemalloc/test/mremap.exp b/extra/jemalloc/test/mremap.exp
deleted file mode 100644
index 369a88dd240..00000000000
--- a/extra/jemalloc/test/mremap.exp
+++ /dev/null
@@ -1,2 +0,0 @@
-Test begin
-Test end
diff --git a/extra/jemalloc/test/posix_memalign.c b/extra/jemalloc/test/posix_memalign.c
deleted file mode 100644
index 2185bcf762a..00000000000
--- a/extra/jemalloc/test/posix_memalign.c
+++ /dev/null
@@ -1,115 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-#define CHUNK 0x400000
-/* #define MAXALIGN ((size_t)UINT64_C(0x80000000000)) */
-#define MAXALIGN ((size_t)0x2000000LU)
-#define NITER 4
-
-int
-main(void)
-{
- size_t alignment, size, total;
- unsigned i;
- int err;
- void *p, *ps[NITER];
-
- malloc_printf("Test begin\n");
-
- /* Test error conditions. */
- for (alignment = 0; alignment < sizeof(void *); alignment++) {
- err = posix_memalign(&p, alignment, 1);
- if (err != EINVAL) {
- malloc_printf(
- "Expected error for invalid alignment %zu\n",
- alignment);
- }
- }
-
- for (alignment = sizeof(size_t); alignment < MAXALIGN;
- alignment <<= 1) {
- err = posix_memalign(&p, alignment + 1, 1);
- if (err == 0) {
- malloc_printf(
- "Expected error for invalid alignment %zu\n",
- alignment + 1);
- }
- }
-
-#if LG_SIZEOF_PTR == 3
- alignment = UINT64_C(0x8000000000000000);
- size = UINT64_C(0x8000000000000000);
-#else
- alignment = 0x80000000LU;
- size = 0x80000000LU;
-#endif
- err = posix_memalign(&p, alignment, size);
- if (err == 0) {
- malloc_printf(
- "Expected error for posix_memalign(&p, %zu, %zu)\n",
- alignment, size);
- }
-
-#if LG_SIZEOF_PTR == 3
- alignment = UINT64_C(0x4000000000000000);
- size = UINT64_C(0x8400000000000001);
-#else
- alignment = 0x40000000LU;
- size = 0x84000001LU;
-#endif
- err = posix_memalign(&p, alignment, size);
- if (err == 0) {
- malloc_printf(
- "Expected error for posix_memalign(&p, %zu, %zu)\n",
- alignment, size);
- }
-
- alignment = 0x10LU;
-#if LG_SIZEOF_PTR == 3
- size = UINT64_C(0xfffffffffffffff0);
-#else
- size = 0xfffffff0LU;
-#endif
- err = posix_memalign(&p, alignment, size);
- if (err == 0) {
- malloc_printf(
- "Expected error for posix_memalign(&p, %zu, %zu)\n",
- alignment, size);
- }
-
- for (i = 0; i < NITER; i++)
- ps[i] = NULL;
-
- for (alignment = 8;
- alignment <= MAXALIGN;
- alignment <<= 1) {
- total = 0;
- malloc_printf("Alignment: %zu\n", alignment);
- for (size = 1;
- size < 3 * alignment && size < (1U << 31);
- size += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
- for (i = 0; i < NITER; i++) {
- err = posix_memalign(&ps[i],
- alignment, size);
- if (err) {
- malloc_printf(
- "Error for size %zu (%#zx): %s\n",
- size, size, strerror(err));
- exit(1);
- }
- total += malloc_usable_size(ps[i]);
- if (total >= (MAXALIGN << 1))
- break;
- }
- for (i = 0; i < NITER; i++) {
- if (ps[i] != NULL) {
- free(ps[i]);
- ps[i] = NULL;
- }
- }
- }
- }
-
- malloc_printf("Test end\n");
- return (0);
-}
diff --git a/extra/jemalloc/test/posix_memalign.exp b/extra/jemalloc/test/posix_memalign.exp
deleted file mode 100644
index b5061c7277e..00000000000
--- a/extra/jemalloc/test/posix_memalign.exp
+++ /dev/null
@@ -1,25 +0,0 @@
-Test begin
-Alignment: 8
-Alignment: 16
-Alignment: 32
-Alignment: 64
-Alignment: 128
-Alignment: 256
-Alignment: 512
-Alignment: 1024
-Alignment: 2048
-Alignment: 4096
-Alignment: 8192
-Alignment: 16384
-Alignment: 32768
-Alignment: 65536
-Alignment: 131072
-Alignment: 262144
-Alignment: 524288
-Alignment: 1048576
-Alignment: 2097152
-Alignment: 4194304
-Alignment: 8388608
-Alignment: 16777216
-Alignment: 33554432
-Test end
diff --git a/extra/jemalloc/test/rallocm.c b/extra/jemalloc/test/rallocm.c
deleted file mode 100644
index c5dedf48d7b..00000000000
--- a/extra/jemalloc/test/rallocm.c
+++ /dev/null
@@ -1,127 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-int
-main(void)
-{
- size_t pagesize;
- void *p, *q;
- size_t sz, tsz;
- int r;
-
- malloc_printf("Test begin\n");
-
- /* Get page size. */
- {
-#ifdef _WIN32
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- pagesize = (size_t)si.dwPageSize;
-#else
- long result = sysconf(_SC_PAGESIZE);
- assert(result != -1);
- pagesize = (size_t)result;
-#endif
- }
-
- r = allocm(&p, &sz, 42, 0);
- if (r != ALLOCM_SUCCESS) {
- malloc_printf("Unexpected allocm() error\n");
- abort();
- }
-
- q = p;
- r = rallocm(&q, &tsz, sz, 0, ALLOCM_NO_MOVE);
- if (r != ALLOCM_SUCCESS)
- malloc_printf("Unexpected rallocm() error\n");
- if (q != p)
- malloc_printf("Unexpected object move\n");
- if (tsz != sz) {
- malloc_printf("Unexpected size change: %zu --> %zu\n",
- sz, tsz);
- }
-
- q = p;
- r = rallocm(&q, &tsz, sz, 5, ALLOCM_NO_MOVE);
- if (r != ALLOCM_SUCCESS)
- malloc_printf("Unexpected rallocm() error\n");
- if (q != p)
- malloc_printf("Unexpected object move\n");
- if (tsz != sz) {
- malloc_printf("Unexpected size change: %zu --> %zu\n",
- sz, tsz);
- }
-
- q = p;
- r = rallocm(&q, &tsz, sz + 5, 0, ALLOCM_NO_MOVE);
- if (r != ALLOCM_ERR_NOT_MOVED)
- malloc_printf("Unexpected rallocm() result\n");
- if (q != p)
- malloc_printf("Unexpected object move\n");
- if (tsz != sz) {
- malloc_printf("Unexpected size change: %zu --> %zu\n",
- sz, tsz);
- }
-
- q = p;
- r = rallocm(&q, &tsz, sz + 5, 0, 0);
- if (r != ALLOCM_SUCCESS)
- malloc_printf("Unexpected rallocm() error\n");
- if (q == p)
- malloc_printf("Expected object move\n");
- if (tsz == sz) {
- malloc_printf("Expected size change: %zu --> %zu\n",
- sz, tsz);
- }
- p = q;
- sz = tsz;
-
- r = rallocm(&q, &tsz, pagesize*2, 0, 0);
- if (r != ALLOCM_SUCCESS)
- malloc_printf("Unexpected rallocm() error\n");
- if (q == p)
- malloc_printf("Expected object move\n");
- if (tsz == sz) {
- malloc_printf("Expected size change: %zu --> %zu\n",
- sz, tsz);
- }
- p = q;
- sz = tsz;
-
- r = rallocm(&q, &tsz, pagesize*4, 0, 0);
- if (r != ALLOCM_SUCCESS)
- malloc_printf("Unexpected rallocm() error\n");
- if (tsz == sz) {
- malloc_printf("Expected size change: %zu --> %zu\n",
- sz, tsz);
- }
- p = q;
- sz = tsz;
-
- r = rallocm(&q, &tsz, pagesize*2, 0, ALLOCM_NO_MOVE);
- if (r != ALLOCM_SUCCESS)
- malloc_printf("Unexpected rallocm() error\n");
- if (q != p)
- malloc_printf("Unexpected object move\n");
- if (tsz == sz) {
- malloc_printf("Expected size change: %zu --> %zu\n",
- sz, tsz);
- }
- sz = tsz;
-
- r = rallocm(&q, &tsz, pagesize*4, 0, ALLOCM_NO_MOVE);
- if (r != ALLOCM_SUCCESS)
- malloc_printf("Unexpected rallocm() error\n");
- if (q != p)
- malloc_printf("Unexpected object move\n");
- if (tsz == sz) {
- malloc_printf("Expected size change: %zu --> %zu\n",
- sz, tsz);
- }
- sz = tsz;
-
- dallocm(p, 0);
-
- malloc_printf("Test end\n");
- return (0);
-}
diff --git a/extra/jemalloc/test/rallocm.exp b/extra/jemalloc/test/rallocm.exp
deleted file mode 100644
index 369a88dd240..00000000000
--- a/extra/jemalloc/test/rallocm.exp
+++ /dev/null
@@ -1,2 +0,0 @@
-Test begin
-Test end
diff --git a/extra/jemalloc/test/thread_arena.c b/extra/jemalloc/test/thread_arena.c
deleted file mode 100644
index c5a21fa0c70..00000000000
--- a/extra/jemalloc/test/thread_arena.c
+++ /dev/null
@@ -1,81 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-#define NTHREADS 10
-
-void *
-je_thread_start(void *arg)
-{
- unsigned main_arena_ind = *(unsigned *)arg;
- void *p;
- unsigned arena_ind;
- size_t size;
- int err;
-
- p = malloc(1);
- if (p == NULL) {
- malloc_printf("%s(): Error in malloc()\n", __func__);
- return (void *)1;
- }
- free(p);
-
- size = sizeof(arena_ind);
- if ((err = mallctl("thread.arena", &arena_ind, &size, &main_arena_ind,
- sizeof(main_arena_ind)))) {
- malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
- strerror(err));
- return (void *)1;
- }
-
- size = sizeof(arena_ind);
- if ((err = mallctl("thread.arena", &arena_ind, &size, NULL,
- 0))) {
- malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
- strerror(err));
- return (void *)1;
- }
- assert(arena_ind == main_arena_ind);
-
- return (NULL);
-}
-
-int
-main(void)
-{
- int ret = 0;
- void *p;
- unsigned arena_ind;
- size_t size;
- int err;
- je_thread_t threads[NTHREADS];
- unsigned i;
-
- malloc_printf("Test begin\n");
-
- p = malloc(1);
- if (p == NULL) {
- malloc_printf("%s(): Error in malloc()\n", __func__);
- ret = 1;
- goto label_return;
- }
-
- size = sizeof(arena_ind);
- if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) {
- malloc_printf("%s(): Error in mallctl(): %s\n", __func__,
- strerror(err));
- ret = 1;
- goto label_return;
- }
-
- for (i = 0; i < NTHREADS; i++) {
- je_thread_create(&threads[i], je_thread_start,
- (void *)&arena_ind);
- }
-
- for (i = 0; i < NTHREADS; i++)
- je_thread_join(threads[i], (void *)&ret);
-
-label_return:
- malloc_printf("Test end\n");
- return (ret);
-}
diff --git a/extra/jemalloc/test/thread_arena.exp b/extra/jemalloc/test/thread_arena.exp
deleted file mode 100644
index 369a88dd240..00000000000
--- a/extra/jemalloc/test/thread_arena.exp
+++ /dev/null
@@ -1,2 +0,0 @@
-Test begin
-Test end
diff --git a/extra/jemalloc/test/thread_tcache_enabled.c b/extra/jemalloc/test/thread_tcache_enabled.c
deleted file mode 100644
index 2061b7bbaff..00000000000
--- a/extra/jemalloc/test/thread_tcache_enabled.c
+++ /dev/null
@@ -1,91 +0,0 @@
-#define JEMALLOC_MANGLE
-#include "jemalloc_test.h"
-
-void *
-je_thread_start(void *arg)
-{
- int err;
- size_t sz;
- bool e0, e1;
-
- sz = sizeof(bool);
- if ((err = mallctl("thread.tcache.enabled", &e0, &sz, NULL, 0))) {
- if (err == ENOENT) {
-#ifdef JEMALLOC_TCACHE
- assert(false);
-#endif
- }
- goto label_return;
- }
-
- if (e0) {
- e1 = false;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz)
- == 0);
- assert(e0);
- }
-
- e1 = true;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0);
- assert(e0 == false);
-
- e1 = true;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0);
- assert(e0);
-
- e1 = false;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0);
- assert(e0);
-
- e1 = false;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0);
- assert(e0 == false);
-
- free(malloc(1));
- e1 = true;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0);
- assert(e0 == false);
-
- free(malloc(1));
- e1 = true;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0);
- assert(e0);
-
- free(malloc(1));
- e1 = false;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0);
- assert(e0);
-
- free(malloc(1));
- e1 = false;
- assert(mallctl("thread.tcache.enabled", &e0, &sz, &e1, sz) == 0);
- assert(e0 == false);
-
- free(malloc(1));
-label_return:
- return (NULL);
-}
-
-int
-main(void)
-{
- int ret = 0;
- je_thread_t thread;
-
- malloc_printf("Test begin\n");
-
- je_thread_start(NULL);
-
- je_thread_create(&thread, je_thread_start, NULL);
- je_thread_join(thread, (void *)&ret);
-
- je_thread_start(NULL);
-
- je_thread_create(&thread, je_thread_start, NULL);
- je_thread_join(thread, (void *)&ret);
-
- je_thread_start(NULL);
-
- malloc_printf("Test end\n");
- return (ret);
-}
diff --git a/extra/jemalloc/test/thread_tcache_enabled.exp b/extra/jemalloc/test/thread_tcache_enabled.exp
deleted file mode 100644
index 369a88dd240..00000000000
--- a/extra/jemalloc/test/thread_tcache_enabled.exp
+++ /dev/null
@@ -1,2 +0,0 @@
-Test begin
-Test end
diff --git a/include/myisam.h b/include/myisam.h
index 853fac20ae4..88ce401fabc 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -41,6 +41,12 @@ extern "C" {
#endif
#define MI_MAX_POSSIBLE_KEY_BUFF HA_MAX_POSSIBLE_KEY_BUFF
+/*
+ The following defines can be increased if necessary.
+ But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and MI_MAX_KEY_LENGTH.
+*/
+#define MI_MAX_KEY_LENGTH 1000 /* Max length in bytes */
+#define MI_MAX_KEY_SEG 16 /* Max segments for key */
#define MI_NAME_IEXT ".MYI"
#define MI_NAME_DEXT ".MYD"
diff --git a/mysql-test/disabled.def b/mysql-test/disabled.def
index e5fa24786e1..bb0e243326a 100644
--- a/mysql-test/disabled.def
+++ b/mysql-test/disabled.def
@@ -20,3 +20,4 @@ mysql_embedded : Bug#12561297 2011-05-14 Anitha Dependent on PB2 chang
ssl_crl_clients_valid : broken upstream
ssl_crl : broken upstream
ssl_crl_clrpath : broken upstream
+file_contents : MDEV-6526 these files are not installed anymore
diff --git a/mysql-test/include/mysqlhotcopy.inc b/mysql-test/include/mysqlhotcopy.inc
index 779ed7f36e0..f775d782b28 100644
--- a/mysql-test/include/mysqlhotcopy.inc
+++ b/mysql-test/include/mysqlhotcopy.inc
@@ -109,7 +109,7 @@ DROP DATABASE hotcopy_save;
--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
--list_files $MYSQLD_DATADIR/hotcopy_save
--replace_result $MASTER_MYSOCK MASTER_MYSOCK
---error 9,11,2304
+--error 1
--exec $MYSQLHOTCOPY --quiet -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save
--replace_result $MASTER_MYSOCK MASTER_MYSOCK
--exec $MYSQLHOTCOPY --quiet --allowold -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save
diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result
index 87267124ff0..e359a8f89c5 100644
--- a/mysql-test/r/derived_view.result
+++ b/mysql-test/r/derived_view.result
@@ -2406,6 +2406,94 @@ deallocate prepare stmt;
drop table t1,t2;
set optimizer_switch=@save_optimizer_switch5740;
#
+# Bug mdev-5721: possible long key access to a materialized derived table
+# (see also the test case for Bug#13261277 that is actually the same bug)
+#
+CREATE TABLE t1 (
+id varchar(255) NOT NULL DEFAULT '',
+familyid int(11) DEFAULT NULL,
+withdrawndate date DEFAULT NULL,
+KEY index_td_familyid_id (familyid,id)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+CREATE TABLE t2 (
+id int(11) NOT NULL AUTO_INCREMENT,
+activefromts datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+shortdescription text,
+useraccessfamily varchar(512) DEFAULT NULL,
+serialized longtext,
+PRIMARY KEY (id)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+insert into t1 values ('picture/89/1369722032695.pmd',89,NULL);
+insert into t1 values ('picture/90/1369832057370.pmd',90,NULL);
+insert into t2 values (38,'2013-03-04 07:49:22','desc','CODE','string');
+EXPLAIN
+SELECT * FROM t2 x,
+(SELECT t2.useraccessfamily, t2.serialized AS picturesubuser, COUNT(*)
+FROM t2, t1 GROUP BY t2.useraccessfamily, picturesubuser) y
+WHERE x.useraccessfamily = y.useraccessfamily;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY x system NULL NULL NULL NULL 1
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 Using where
+2 DERIVED t2 system NULL NULL NULL NULL 1
+2 DERIVED t1 index NULL index_td_familyid_id 772 NULL 2 Using index
+SELECT * FROM t2 x,
+(SELECT t2.useraccessfamily, t2.serialized AS picturesubuser, COUNT(*)
+FROM t2, t1 GROUP BY t2.useraccessfamily, picturesubuser) y
+WHERE x.useraccessfamily = y.useraccessfamily;
+id activefromts shortdescription useraccessfamily serialized useraccessfamily picturesubuser COUNT(*)
+38 2013-03-04 07:49:22 desc CODE string CODE string 2
+DROP TABLE t1,t2;
+#
+# Bug#13261277: Unchecked key length caused missing records.
+#
+CREATE TABLE t1 (
+col_varchar varchar(1024) CHARACTER SET utf8 DEFAULT NULL,
+stub1 varchar(1024) CHARACTER SET utf8 DEFAULT NULL,
+stub2 varchar(1024) CHARACTER SET utf8 DEFAULT NULL,
+stub3 varchar(1024) CHARACTER SET utf8 DEFAULT NULL
+);
+INSERT INTO t1 VALUES
+('d','d','l','ther'),
+(NULL,'s','NJBIQ','trzetuchv'),
+(-715390976,'coul','MYWFB','cfhtrzetu'),
+(1696792576,'f','i\'s','c'),
+ (1,'i','ltpemcfhtr','gsltpemcf'),
+ (-663027712,'mgsltpemcf','sa','amgsltpem'),
+ (-1686700032,'JPRVK','i','vamgsltpe'),
+ (NULL,'STUNB','UNVJV','u'),
+ (5,'oka','qyihvamgsl','AXSMD'),
+ (NULL,'tqwmqyihva','h','yntqwmqyi'),
+ (3,'EGMJN','e','e');
+CREATE TABLE t2 (
+col_varchar varchar(10) DEFAULT NULL,
+col_int INT DEFAULT NULL
+);
+INSERT INTO t2 VALUES ('d',9);
+set optimizer_switch='derived_merge=off,derived_with_keys=on';
+SET @save_heap_size= @@max_heap_table_size;
+SET @@max_heap_table_size= 16384;
+SELECT t2.col_int
+FROM t2
+RIGHT JOIN ( SELECT * FROM t1 ) AS dt
+ON t2.col_varchar = dt.col_varchar
+WHERE t2.col_int IS NOT NULL ;
+col_int
+9
+# Shouldn't use auto_key0 for derived table
+EXPLAIN
+SELECT t2.col_int
+FROM t2
+RIGHT JOIN ( SELECT * FROM t1 ) AS dt
+ON t2.col_varchar = dt.col_varchar
+WHERE t2.col_int IS NOT NULL ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 system NULL NULL NULL NULL 1
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 Using where
+2 DERIVED t1 ALL NULL NULL NULL NULL 11
+SET @@max_heap_table_size= @save_heap_size;
+SET optimizer_switch=@save_optimizer_switch;
+DROP TABLE t1,t2;
+#
# end of 5.3 tests
#
set optimizer_switch=@exit_optimizer_switch;
diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result
index 53812bfa227..253fb61dc27 100644
--- a/mysql-test/r/join_cache.result
+++ b/mysql-test/r/join_cache.result
@@ -5591,7 +5591,7 @@ set optimizer_switch=@tmp_optimizer_switch;
DROP TABLE t1,t2,t3;
#
# Bug #1058071: LEFT JOIN using blobs
-# (mdev-564) when join buffer size is small
+# (MDEV-564) when join buffer size is small
#
CREATE TABLE t1 (
col269 decimal(31,10) unsigned DEFAULT NULL,
@@ -5656,6 +5656,154 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 10
1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
drop table t0,t1,t2;
+# MDEV-6292: huge performance degradation for a sequence
+# of LEFT JOIN operations when using join buffer
+#
+CREATE TABLE t1 (
+id int(11) NOT NULL AUTO_INCREMENT,
+col1 varchar(255) NOT NULL DEFAULT '',
+PRIMARY KEY (id)
+) ENGINE=INNODB;
+CREATE TABLE t2 (
+id int(11) NOT NULL AUTO_INCREMENT,
+parent_id smallint(3) NOT NULL DEFAULT '0',
+col2 varchar(25) NOT NULL DEFAULT '',
+PRIMARY KEY (id)
+) ENGINE=INNODB;
+set join_buffer_size=8192;
+set join_cache_level=0;
+set @init_time:=now();
+SELECT t.*
+FROM
+t1 t
+LEFT JOIN t2 c1 ON c1.parent_id = t.id AND c1.col2 = "val"
+ LEFT JOIN t2 c2 ON c2.parent_id = t.id AND c2.col2 = "val"
+ LEFT JOIN t2 c3 ON c3.parent_id = t.id AND c3.col2 = "val"
+ LEFT JOIN t2 c4 ON c4.parent_id = t.id AND c4.col2 = "val"
+ LEFT JOIN t2 c5 ON c5.parent_id = t.id AND c5.col2 = "val"
+ LEFT JOIN t2 c6 ON c6.parent_id = t.id AND c6.col2 = "val"
+ LEFT JOIN t2 c7 ON c7.parent_id = t.id AND c7.col2 = "val"
+ LEFT JOIN t2 c8 ON c8.parent_id = t.id AND c8.col2 = "val"
+ LEFT JOIN t2 c9 ON c9.parent_id = t.id AND c9.col2 = "val"
+ LEFT JOIN t2 c10 ON c10.parent_id = t.id AND c10.col2 = "val"
+ LEFT JOIN t2 c11 ON c11.parent_id = t.id AND c11.col2 = "val"
+ LEFT JOIN t2 c12 ON c12.parent_id = t.id AND c12.col2 = "val"
+ LEFT JOIN t2 c13 ON c13.parent_id = t.id AND c13.col2 = "val"
+ LEFT JOIN t2 c14 ON c14.parent_id = t.id AND c14.col2 = "val"
+ LEFT JOIN t2 c15 ON c15.parent_id = t.id AND c15.col2 = "val"
+ LEFT JOIN t2 c16 ON c16.parent_id = t.id AND c16.col2 = "val"
+ LEFT JOIN t2 c17 ON c17.parent_id = t.id AND c17.col2 = "val"
+ LEFT JOIN t2 c18 ON c18.parent_id = t.id AND c18.col2 = "val"
+ LEFT JOIN t2 c19 ON c19.parent_id = t.id AND c19.col2 = "val"
+ LEFT JOIN t2 c20 ON c20.parent_id = t.id AND c20.col2 = "val"
+ LEFT JOIN t2 c21 ON c21.parent_id = t.id AND c21.col2 = "val"
+ LEFT JOIN t2 c22 ON c22.parent_id = t.id AND c22.col2 = "val"
+ LEFT JOIN t2 c23 ON c23.parent_id = t.id AND c23.col2 = "val"
+ LEFT JOIN t2 c24 ON c24.parent_id = t.id AND c24.col2 = "val"
+ LEFT JOIN t2 c25 ON c25.parent_id = t.id AND c25.col2 = "val"
+ORDER BY
+col1;
+id col1
+select timestampdiff(second, @init_time, now()) <= 1;
+timestampdiff(second, @init_time, now()) <= 1
+1
+set join_cache_level=2;
+set @init_time:=now();
+SELECT t.*
+FROM
+t1 t
+LEFT JOIN t2 c1 ON c1.parent_id = t.id AND c1.col2 = "val"
+ LEFT JOIN t2 c2 ON c2.parent_id = t.id AND c2.col2 = "val"
+ LEFT JOIN t2 c3 ON c3.parent_id = t.id AND c3.col2 = "val"
+ LEFT JOIN t2 c4 ON c4.parent_id = t.id AND c4.col2 = "val"
+ LEFT JOIN t2 c5 ON c5.parent_id = t.id AND c5.col2 = "val"
+ LEFT JOIN t2 c6 ON c6.parent_id = t.id AND c6.col2 = "val"
+ LEFT JOIN t2 c7 ON c7.parent_id = t.id AND c7.col2 = "val"
+ LEFT JOIN t2 c8 ON c8.parent_id = t.id AND c8.col2 = "val"
+ LEFT JOIN t2 c9 ON c9.parent_id = t.id AND c9.col2 = "val"
+ LEFT JOIN t2 c10 ON c10.parent_id = t.id AND c10.col2 = "val"
+ LEFT JOIN t2 c11 ON c11.parent_id = t.id AND c11.col2 = "val"
+ LEFT JOIN t2 c12 ON c12.parent_id = t.id AND c12.col2 = "val"
+ LEFT JOIN t2 c13 ON c13.parent_id = t.id AND c13.col2 = "val"
+ LEFT JOIN t2 c14 ON c14.parent_id = t.id AND c14.col2 = "val"
+ LEFT JOIN t2 c15 ON c15.parent_id = t.id AND c15.col2 = "val"
+ LEFT JOIN t2 c16 ON c16.parent_id = t.id AND c16.col2 = "val"
+ LEFT JOIN t2 c17 ON c17.parent_id = t.id AND c17.col2 = "val"
+ LEFT JOIN t2 c18 ON c18.parent_id = t.id AND c18.col2 = "val"
+ LEFT JOIN t2 c19 ON c19.parent_id = t.id AND c19.col2 = "val"
+ LEFT JOIN t2 c20 ON c20.parent_id = t.id AND c20.col2 = "val"
+ LEFT JOIN t2 c21 ON c21.parent_id = t.id AND c21.col2 = "val"
+ LEFT JOIN t2 c22 ON c22.parent_id = t.id AND c22.col2 = "val"
+ LEFT JOIN t2 c23 ON c23.parent_id = t.id AND c23.col2 = "val"
+ LEFT JOIN t2 c24 ON c24.parent_id = t.id AND c24.col2 = "val"
+ LEFT JOIN t2 c25 ON c25.parent_id = t.id AND c25.col2 = "val"
+ORDER BY
+col1;
+id col1
+select timestampdiff(second, @init_time, now()) <= 1;
+timestampdiff(second, @init_time, now()) <= 1
+1
+EXPLAIN
+SELECT t.*
+FROM
+t1 t
+LEFT JOIN t2 c1 ON c1.parent_id = t.id AND c1.col2 = "val"
+ LEFT JOIN t2 c2 ON c2.parent_id = t.id AND c2.col2 = "val"
+ LEFT JOIN t2 c3 ON c3.parent_id = t.id AND c3.col2 = "val"
+ LEFT JOIN t2 c4 ON c4.parent_id = t.id AND c4.col2 = "val"
+ LEFT JOIN t2 c5 ON c5.parent_id = t.id AND c5.col2 = "val"
+ LEFT JOIN t2 c6 ON c6.parent_id = t.id AND c6.col2 = "val"
+ LEFT JOIN t2 c7 ON c7.parent_id = t.id AND c7.col2 = "val"
+ LEFT JOIN t2 c8 ON c8.parent_id = t.id AND c8.col2 = "val"
+ LEFT JOIN t2 c9 ON c9.parent_id = t.id AND c9.col2 = "val"
+ LEFT JOIN t2 c10 ON c10.parent_id = t.id AND c10.col2 = "val"
+ LEFT JOIN t2 c11 ON c11.parent_id = t.id AND c11.col2 = "val"
+ LEFT JOIN t2 c12 ON c12.parent_id = t.id AND c12.col2 = "val"
+ LEFT JOIN t2 c13 ON c13.parent_id = t.id AND c13.col2 = "val"
+ LEFT JOIN t2 c14 ON c14.parent_id = t.id AND c14.col2 = "val"
+ LEFT JOIN t2 c15 ON c15.parent_id = t.id AND c15.col2 = "val"
+ LEFT JOIN t2 c16 ON c16.parent_id = t.id AND c16.col2 = "val"
+ LEFT JOIN t2 c17 ON c17.parent_id = t.id AND c17.col2 = "val"
+ LEFT JOIN t2 c18 ON c18.parent_id = t.id AND c18.col2 = "val"
+ LEFT JOIN t2 c19 ON c19.parent_id = t.id AND c19.col2 = "val"
+ LEFT JOIN t2 c20 ON c20.parent_id = t.id AND c20.col2 = "val"
+ LEFT JOIN t2 c21 ON c21.parent_id = t.id AND c21.col2 = "val"
+ LEFT JOIN t2 c22 ON c22.parent_id = t.id AND c22.col2 = "val"
+ LEFT JOIN t2 c23 ON c23.parent_id = t.id AND c23.col2 = "val"
+ LEFT JOIN t2 c24 ON c24.parent_id = t.id AND c24.col2 = "val"
+ LEFT JOIN t2 c25 ON c25.parent_id = t.id AND c25.col2 = "val"
+ORDER BY
+col1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t ALL NULL NULL NULL NULL 1 Using temporary; Using filesort
+1 SIMPLE c1 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE c2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c3 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c4 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c5 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c6 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c7 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c8 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c9 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c10 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c11 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c12 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c13 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c14 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c15 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c16 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c17 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c18 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c19 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c20 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c21 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c22 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c23 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c24 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE c25 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
+set join_buffer_size=default;
+set join_cache_level = default;
+DROP TABLE t1,t2;
#
# MDEV-5123 Remove duplicated conditions pushed both to join_tab->select_cond and join_tab->cache_select->cond for blocked joins.
#
@@ -5704,7 +5852,7 @@ select @counter;
drop table t1,t2,t3;
set expensive_subquery_limit=default;
#
-# mdev-6071: EXPLAIN chooses to use join buffer while execution turns it down
+# MDEV-6071: EXPLAIN chooses to use join buffer while execution turns it down
#
create table t1 (a int);
insert into t1 values
diff --git a/mysql-test/r/join_nested_jcl6.result b/mysql-test/r/join_nested_jcl6.result
index 6b5a50ba978..3b47645ca79 100644
--- a/mysql-test/r/join_nested_jcl6.result
+++ b/mysql-test/r/join_nested_jcl6.result
@@ -705,18 +705,18 @@ t0.b=t1.b AND
(t8.b=t9.b OR t8.c IS NULL) AND
(t9.a=1);
a b a b a b a b a b a b a b a b a b a b
-1 2 3 2 4 2 1 2 3 2 2 2 6 2 2 2 0 2 1 2
-1 2 3 2 4 2 1 2 4 2 2 2 6 2 2 2 0 2 1 2
1 2 3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL 1 1
1 2 3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL 1 1
+1 2 3 2 4 2 1 2 3 2 2 2 6 2 2 2 0 2 1 2
+1 2 3 2 4 2 1 2 4 2 2 2 6 2 2 2 0 2 1 2
1 2 3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL 1 2
1 2 3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL 1 2
1 2 3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL 1 1
1 2 3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL 1 1
1 2 3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL 1 2
1 2 3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL 1 2
-1 2 3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2 1 2
1 2 3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL 1 1
+1 2 3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2 1 2
1 2 3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL 1 2
1 2 3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL 1 1
1 2 3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL 1 2
diff --git a/mysql-test/r/join_outer_jcl6.result b/mysql-test/r/join_outer_jcl6.result
index 88f2fd7c630..beea0daa1fa 100644
--- a/mysql-test/r/join_outer_jcl6.result
+++ b/mysql-test/r/join_outer_jcl6.result
@@ -696,9 +696,9 @@ insert into t2 values (1,3), (2,3);
insert into t3 values (2,4), (3,4);
select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null;
a1 a2 b1 b2 c1 c2
+3 2 NULL NULL 3 4
1 2 1 3 NULL NULL
2 2 2 3 NULL NULL
-3 2 NULL NULL 3 4
explain select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
diff --git a/mysql-test/r/kill_processlist-6619.result b/mysql-test/r/kill_processlist-6619.result
new file mode 100644
index 00000000000..588c8e6d139
--- /dev/null
+++ b/mysql-test/r/kill_processlist-6619.result
@@ -0,0 +1,14 @@
+connect con1,localhost,root,,;
+SHOW PROCESSLIST;
+Id User Host db Command Time State Info Progress
+# root # test Sleep # # NULL 0.000
+# root # test Query # # SHOW PROCESSLIST 0.000
+connection default;
+KILL QUERY con_id;
+connection con1;
+SHOW PROCESSLIST;
+ERROR 70100: Query execution was interrupted
+SHOW PROCESSLIST;
+Id User Host db Command Time State Info Progress
+# root # test Sleep # # NULL 0.000
+# root # test Query # # SHOW PROCESSLIST 0.000
diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result
index b45944a3795..ccccacd09a5 100644
--- a/mysql-test/r/sp-bugs.result
+++ b/mysql-test/r/sp-bugs.result
@@ -275,3 +275,9 @@ END $$
CALL test_5531(1);
DROP PROCEDURE test_5531;
DROP TABLE t1;
+create procedure sp() begin
+commit;
+end|
+start transaction;
+call sp();
+drop procedure sp;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index a93e3a210ed..a42c0c5abcb 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -1793,4 +1793,13 @@ set session rand_seed1=DEFAULT;
ERROR 42000: Variable 'rand_seed1' doesn't have a default value
set autocommit = values(v);
ERROR 42S22: Unknown column 'v' in 'field list'
+set session sql_mode=ansi_quotes;
+select * from information_schema.session_variables where variable_name='sql_mode';
+VARIABLE_NAME VARIABLE_VALUE
+SQL_MODE ANSI_QUOTES
+show global status like 'foobar';
+Variable_name Value
+select * from information_schema.session_variables where variable_name='sql_mode';
+VARIABLE_NAME VARIABLE_VALUE
+SQL_MODE ANSI_QUOTES
End of 5.5 tests
diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test
index de08b1c4d0d..67899837bb2 100644
--- a/mysql-test/t/derived_view.test
+++ b/mysql-test/t/derived_view.test
@@ -1731,6 +1731,99 @@ drop table t1,t2;
set optimizer_switch=@save_optimizer_switch5740;
--echo #
+--echo # Bug mdev-5721: possible long key access to a materialized derived table
+--echo # (see also the test case for Bug#13261277 that is actually the same bug)
+--echo #
+
+CREATE TABLE t1 (
+ id varchar(255) NOT NULL DEFAULT '',
+ familyid int(11) DEFAULT NULL,
+ withdrawndate date DEFAULT NULL,
+ KEY index_td_familyid_id (familyid,id)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+CREATE TABLE t2 (
+ id int(11) NOT NULL AUTO_INCREMENT,
+ activefromts datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ shortdescription text,
+ useraccessfamily varchar(512) DEFAULT NULL,
+ serialized longtext,
+ PRIMARY KEY (id)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+insert into t1 values ('picture/89/1369722032695.pmd',89,NULL);
+insert into t1 values ('picture/90/1369832057370.pmd',90,NULL);
+insert into t2 values (38,'2013-03-04 07:49:22','desc','CODE','string');
+
+EXPLAIN
+SELECT * FROM t2 x,
+(SELECT t2.useraccessfamily, t2.serialized AS picturesubuser, COUNT(*)
+ FROM t2, t1 GROUP BY t2.useraccessfamily, picturesubuser) y
+WHERE x.useraccessfamily = y.useraccessfamily;
+
+SELECT * FROM t2 x,
+(SELECT t2.useraccessfamily, t2.serialized AS picturesubuser, COUNT(*)
+ FROM t2, t1 GROUP BY t2.useraccessfamily, picturesubuser) y
+WHERE x.useraccessfamily = y.useraccessfamily;
+
+DROP TABLE t1,t2;
+
+--echo #
+--echo # Bug#13261277: Unchecked key length caused missing records.
+--echo #
+
+CREATE TABLE t1 (
+ col_varchar varchar(1024) CHARACTER SET utf8 DEFAULT NULL,
+ stub1 varchar(1024) CHARACTER SET utf8 DEFAULT NULL,
+ stub2 varchar(1024) CHARACTER SET utf8 DEFAULT NULL,
+ stub3 varchar(1024) CHARACTER SET utf8 DEFAULT NULL
+);
+
+INSERT INTO t1 VALUES
+ ('d','d','l','ther'),
+ (NULL,'s','NJBIQ','trzetuchv'),
+ (-715390976,'coul','MYWFB','cfhtrzetu'),
+ (1696792576,'f','i\'s','c'),
+ (1,'i','ltpemcfhtr','gsltpemcf'),
+ (-663027712,'mgsltpemcf','sa','amgsltpem'),
+ (-1686700032,'JPRVK','i','vamgsltpe'),
+ (NULL,'STUNB','UNVJV','u'),
+ (5,'oka','qyihvamgsl','AXSMD'),
+ (NULL,'tqwmqyihva','h','yntqwmqyi'),
+ (3,'EGMJN','e','e');
+
+CREATE TABLE t2 (
+ col_varchar varchar(10) DEFAULT NULL,
+ col_int INT DEFAULT NULL
+);
+
+INSERT INTO t2 VALUES ('d',9);
+
+set optimizer_switch='derived_merge=off,derived_with_keys=on';
+
+SET @save_heap_size= @@max_heap_table_size;
+SET @@max_heap_table_size= 16384;
+
+SELECT t2.col_int
+FROM t2
+ RIGHT JOIN ( SELECT * FROM t1 ) AS dt
+ ON t2.col_varchar = dt.col_varchar
+WHERE t2.col_int IS NOT NULL ;
+
+--echo # Shouldn't use auto_key0 for derived table
+EXPLAIN
+SELECT t2.col_int
+FROM t2
+ RIGHT JOIN ( SELECT * FROM t1 ) AS dt
+ ON t2.col_varchar = dt.col_varchar
+WHERE t2.col_int IS NOT NULL ;
+
+SET @@max_heap_table_size= @save_heap_size;
+SET optimizer_switch=@save_optimizer_switch;
+
+DROP TABLE t1,t2;
+
+--echo #
--echo # end of 5.3 tests
--echo #
diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test
index c60a06f0b0b..0e4610b9f54 100644
--- a/mysql-test/t/join_cache.test
+++ b/mysql-test/t/join_cache.test
@@ -3589,7 +3589,7 @@ DROP TABLE t1,t2,t3;
--echo #
--echo # Bug #1058071: LEFT JOIN using blobs
---echo # (mdev-564) when join buffer size is small
+--echo # (MDEV-564) when join buffer size is small
--echo #
CREATE TABLE t1 (
@@ -3656,6 +3656,134 @@ explain select * from t0,t1 left join t2 on t1.b=t2.b order by t0.a, t1.a;
drop table t0,t1,t2;
+--echo # MDEV-6292: huge performance degradation for a sequence
+--echo # of LEFT JOIN operations when using join buffer
+--echo #
+
+--source include/have_innodb.inc
+
+CREATE TABLE t1 (
+ id int(11) NOT NULL AUTO_INCREMENT,
+ col1 varchar(255) NOT NULL DEFAULT '',
+ PRIMARY KEY (id)
+) ENGINE=INNODB;
+
+CREATE TABLE t2 (
+ id int(11) NOT NULL AUTO_INCREMENT,
+ parent_id smallint(3) NOT NULL DEFAULT '0',
+ col2 varchar(25) NOT NULL DEFAULT '',
+ PRIMARY KEY (id)
+) ENGINE=INNODB;
+
+set join_buffer_size=8192;
+
+set join_cache_level=0;
+
+set @init_time:=now();
+SELECT t.*
+FROM
+ t1 t
+ LEFT JOIN t2 c1 ON c1.parent_id = t.id AND c1.col2 = "val"
+ LEFT JOIN t2 c2 ON c2.parent_id = t.id AND c2.col2 = "val"
+ LEFT JOIN t2 c3 ON c3.parent_id = t.id AND c3.col2 = "val"
+ LEFT JOIN t2 c4 ON c4.parent_id = t.id AND c4.col2 = "val"
+ LEFT JOIN t2 c5 ON c5.parent_id = t.id AND c5.col2 = "val"
+ LEFT JOIN t2 c6 ON c6.parent_id = t.id AND c6.col2 = "val"
+ LEFT JOIN t2 c7 ON c7.parent_id = t.id AND c7.col2 = "val"
+ LEFT JOIN t2 c8 ON c8.parent_id = t.id AND c8.col2 = "val"
+ LEFT JOIN t2 c9 ON c9.parent_id = t.id AND c9.col2 = "val"
+ LEFT JOIN t2 c10 ON c10.parent_id = t.id AND c10.col2 = "val"
+ LEFT JOIN t2 c11 ON c11.parent_id = t.id AND c11.col2 = "val"
+ LEFT JOIN t2 c12 ON c12.parent_id = t.id AND c12.col2 = "val"
+ LEFT JOIN t2 c13 ON c13.parent_id = t.id AND c13.col2 = "val"
+ LEFT JOIN t2 c14 ON c14.parent_id = t.id AND c14.col2 = "val"
+ LEFT JOIN t2 c15 ON c15.parent_id = t.id AND c15.col2 = "val"
+ LEFT JOIN t2 c16 ON c16.parent_id = t.id AND c16.col2 = "val"
+ LEFT JOIN t2 c17 ON c17.parent_id = t.id AND c17.col2 = "val"
+ LEFT JOIN t2 c18 ON c18.parent_id = t.id AND c18.col2 = "val"
+ LEFT JOIN t2 c19 ON c19.parent_id = t.id AND c19.col2 = "val"
+ LEFT JOIN t2 c20 ON c20.parent_id = t.id AND c20.col2 = "val"
+ LEFT JOIN t2 c21 ON c21.parent_id = t.id AND c21.col2 = "val"
+ LEFT JOIN t2 c22 ON c22.parent_id = t.id AND c22.col2 = "val"
+ LEFT JOIN t2 c23 ON c23.parent_id = t.id AND c23.col2 = "val"
+ LEFT JOIN t2 c24 ON c24.parent_id = t.id AND c24.col2 = "val"
+ LEFT JOIN t2 c25 ON c25.parent_id = t.id AND c25.col2 = "val"
+ORDER BY
+ col1;
+select timestampdiff(second, @init_time, now()) <= 1;
+
+set join_cache_level=2;
+
+set @init_time:=now();
+SELECT t.*
+FROM
+ t1 t
+ LEFT JOIN t2 c1 ON c1.parent_id = t.id AND c1.col2 = "val"
+ LEFT JOIN t2 c2 ON c2.parent_id = t.id AND c2.col2 = "val"
+ LEFT JOIN t2 c3 ON c3.parent_id = t.id AND c3.col2 = "val"
+ LEFT JOIN t2 c4 ON c4.parent_id = t.id AND c4.col2 = "val"
+ LEFT JOIN t2 c5 ON c5.parent_id = t.id AND c5.col2 = "val"
+ LEFT JOIN t2 c6 ON c6.parent_id = t.id AND c6.col2 = "val"
+ LEFT JOIN t2 c7 ON c7.parent_id = t.id AND c7.col2 = "val"
+ LEFT JOIN t2 c8 ON c8.parent_id = t.id AND c8.col2 = "val"
+ LEFT JOIN t2 c9 ON c9.parent_id = t.id AND c9.col2 = "val"
+ LEFT JOIN t2 c10 ON c10.parent_id = t.id AND c10.col2 = "val"
+ LEFT JOIN t2 c11 ON c11.parent_id = t.id AND c11.col2 = "val"
+ LEFT JOIN t2 c12 ON c12.parent_id = t.id AND c12.col2 = "val"
+ LEFT JOIN t2 c13 ON c13.parent_id = t.id AND c13.col2 = "val"
+ LEFT JOIN t2 c14 ON c14.parent_id = t.id AND c14.col2 = "val"
+ LEFT JOIN t2 c15 ON c15.parent_id = t.id AND c15.col2 = "val"
+ LEFT JOIN t2 c16 ON c16.parent_id = t.id AND c16.col2 = "val"
+ LEFT JOIN t2 c17 ON c17.parent_id = t.id AND c17.col2 = "val"
+ LEFT JOIN t2 c18 ON c18.parent_id = t.id AND c18.col2 = "val"
+ LEFT JOIN t2 c19 ON c19.parent_id = t.id AND c19.col2 = "val"
+ LEFT JOIN t2 c20 ON c20.parent_id = t.id AND c20.col2 = "val"
+ LEFT JOIN t2 c21 ON c21.parent_id = t.id AND c21.col2 = "val"
+ LEFT JOIN t2 c22 ON c22.parent_id = t.id AND c22.col2 = "val"
+ LEFT JOIN t2 c23 ON c23.parent_id = t.id AND c23.col2 = "val"
+ LEFT JOIN t2 c24 ON c24.parent_id = t.id AND c24.col2 = "val"
+ LEFT JOIN t2 c25 ON c25.parent_id = t.id AND c25.col2 = "val"
+ORDER BY
+ col1;
+select timestampdiff(second, @init_time, now()) <= 1;
+
+EXPLAIN
+SELECT t.*
+FROM
+ t1 t
+ LEFT JOIN t2 c1 ON c1.parent_id = t.id AND c1.col2 = "val"
+ LEFT JOIN t2 c2 ON c2.parent_id = t.id AND c2.col2 = "val"
+ LEFT JOIN t2 c3 ON c3.parent_id = t.id AND c3.col2 = "val"
+ LEFT JOIN t2 c4 ON c4.parent_id = t.id AND c4.col2 = "val"
+ LEFT JOIN t2 c5 ON c5.parent_id = t.id AND c5.col2 = "val"
+ LEFT JOIN t2 c6 ON c6.parent_id = t.id AND c6.col2 = "val"
+ LEFT JOIN t2 c7 ON c7.parent_id = t.id AND c7.col2 = "val"
+ LEFT JOIN t2 c8 ON c8.parent_id = t.id AND c8.col2 = "val"
+ LEFT JOIN t2 c9 ON c9.parent_id = t.id AND c9.col2 = "val"
+ LEFT JOIN t2 c10 ON c10.parent_id = t.id AND c10.col2 = "val"
+ LEFT JOIN t2 c11 ON c11.parent_id = t.id AND c11.col2 = "val"
+ LEFT JOIN t2 c12 ON c12.parent_id = t.id AND c12.col2 = "val"
+ LEFT JOIN t2 c13 ON c13.parent_id = t.id AND c13.col2 = "val"
+ LEFT JOIN t2 c14 ON c14.parent_id = t.id AND c14.col2 = "val"
+ LEFT JOIN t2 c15 ON c15.parent_id = t.id AND c15.col2 = "val"
+ LEFT JOIN t2 c16 ON c16.parent_id = t.id AND c16.col2 = "val"
+ LEFT JOIN t2 c17 ON c17.parent_id = t.id AND c17.col2 = "val"
+ LEFT JOIN t2 c18 ON c18.parent_id = t.id AND c18.col2 = "val"
+ LEFT JOIN t2 c19 ON c19.parent_id = t.id AND c19.col2 = "val"
+ LEFT JOIN t2 c20 ON c20.parent_id = t.id AND c20.col2 = "val"
+ LEFT JOIN t2 c21 ON c21.parent_id = t.id AND c21.col2 = "val"
+ LEFT JOIN t2 c22 ON c22.parent_id = t.id AND c22.col2 = "val"
+ LEFT JOIN t2 c23 ON c23.parent_id = t.id AND c23.col2 = "val"
+ LEFT JOIN t2 c24 ON c24.parent_id = t.id AND c24.col2 = "val"
+ LEFT JOIN t2 c25 ON c25.parent_id = t.id AND c25.col2 = "val"
+ORDER BY
+ col1;
+
+set join_buffer_size=default;
+set join_cache_level = default;
+
+DROP TABLE t1,t2;
+
--echo #
--echo # MDEV-5123 Remove duplicated conditions pushed both to join_tab->select_cond and join_tab->cache_select->cond for blocked joins.
--echo #
@@ -3701,7 +3829,7 @@ drop table t1,t2,t3;
set expensive_subquery_limit=default;
--echo #
---echo # mdev-6071: EXPLAIN chooses to use join buffer while execution turns it down
+--echo # MDEV-6071: EXPLAIN chooses to use join buffer while execution turns it down
--echo #
create table t1 (a int);
diff --git a/mysql-test/t/kill_processlist-6619.test b/mysql-test/t/kill_processlist-6619.test
new file mode 100644
index 00000000000..2333f02eac6
--- /dev/null
+++ b/mysql-test/t/kill_processlist-6619.test
@@ -0,0 +1,17 @@
+#
+# MDEV-6619 SHOW PROCESSLIST returns empty result set after KILL QUERY
+#
+--source include/not_embedded.inc
+--enable_connect_log
+--connect (con1,localhost,root,,)
+--let $con_id = `SELECT CONNECTION_ID()`
+--replace_column 1 # 3 # 6 # 7 #
+SHOW PROCESSLIST;
+--connection default
+--replace_result $con_id con_id
+eval KILL QUERY $con_id;
+--connection con1
+--error ER_QUERY_INTERRUPTED
+SHOW PROCESSLIST;
+--replace_column 1 # 3 # 6 # 7 #
+SHOW PROCESSLIST;
diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test
index 8e6a25709aa..4671aee11e1 100644
--- a/mysql-test/t/sp-bugs.test
+++ b/mysql-test/t/sp-bugs.test
@@ -294,3 +294,16 @@ DELIMITER ;$$
CALL test_5531(1);
DROP PROCEDURE test_5531;
DROP TABLE t1;
+
+#
+# MDEV-6601 Assertion `!thd->in_active_multi_stmt_transa ction() || thd->in_multi_stmt_transaction_mode()' failed on executing a stored procedure with commit
+#
+delimiter |;
+create procedure sp() begin
+ commit;
+end|
+delimiter ;|
+start transaction;
+call sp();
+drop procedure sp;
+
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index e7e621081d6..79cd5e1b24d 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -1527,4 +1527,12 @@ set session rand_seed1=DEFAULT;
--error ER_BAD_FIELD_ERROR
set autocommit = values(v);
+#
+# MDEV-6673 I_S.SESSION_VARIABLES shows global values
+#
+set session sql_mode=ansi_quotes;
+select * from information_schema.session_variables where variable_name='sql_mode';
+show global status like 'foobar';
+select * from information_schema.session_variables where variable_name='sql_mode';
+
--echo End of 5.5 tests
diff --git a/plugin/auth_socket/CMakeLists.txt b/plugin/auth_socket/CMakeLists.txt
index ae7dbffe2ae..8137c6b4529 100644
--- a/plugin/auth_socket/CMakeLists.txt
+++ b/plugin/auth_socket/CMakeLists.txt
@@ -22,18 +22,49 @@ int main() {
getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, 0);
}" HAVE_PEERCRED)
-IF (NOT HAVE_PEERCRED)
- # Hi, OpenBSD!
- CHECK_CXX_SOURCE_COMPILES(
- "#include <sys/types.h>
- #include <sys/socket.h>
- int main() {
- struct sockpeercred cred;
- getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, 0);
- }" HAVE_SOCKPEERCRED)
- ADD_DEFINITIONS(-Ducred=sockpeercred)
+IF (HAVE_PEERCRED)
+ ADD_DEFINITIONS(-DHAVE_PEERCRED)
+ SET(ok 1)
+ELSE()
+
+# Hi, OpenBSD!
+CHECK_CXX_SOURCE_COMPILES(
+"#include <sys/types.h>
+#include <sys/socket.h>
+int main() {
+ struct sockpeercred cred;
+ getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, 0);
+ }" HAVE_SOCKPEERCRED)
+
+IF (HAVE_SOCKPEERCRED)
+ ADD_DEFINITIONS(-DHAVE_SOCKPEERCRED)
+ SET(ok 1)
+ELSE()
+
+# FreeBSD, is that you?
+CHECK_CXX_SOURCE_COMPILES(
+"#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/ucred.h>
+int main() {
+ struct xucred cred;
+ getsockopt(0, 0, LOCAL_PEERCRED, &cred, 0);
+ }" HAVE_XUCRED)
+
+IF (HAVE_XUCRED)
+ ADD_DEFINITIONS(-DHAVE_XUCRED)
+ SET(ok 1)
+ELSE()
+
+# Who else? Anyone?
+# C'mon, show your creativity, be different! ifdef's are fun, aren't they?
+
+ENDIF()
+ENDIF()
ENDIF()
-IF(HAVE_PEERCRED OR HAVE_SOCKPEERCRED)
+IF(ok)
MYSQL_ADD_PLUGIN(auth_socket auth_socket.c MODULE_ONLY)
ENDIF()
+
diff --git a/plugin/auth_socket/auth_socket.c b/plugin/auth_socket/auth_socket.c
index 779998395b0..e2fb0b1291b 100644
--- a/plugin/auth_socket/auth_socket.c
+++ b/plugin/auth_socket/auth_socket.c
@@ -27,9 +27,29 @@
#define _GNU_SOURCE 1 /* for struct ucred */
#include <mysql/plugin_auth.h>
-#include <sys/socket.h>
-#include <pwd.h>
#include <string.h>
+#include <pwd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#ifdef HAVE_PEERCRED
+#define level SOL_SOCKET
+
+#elif defined HAVE_SOCKPEERCRED
+#define level SOL_SOCKET
+#define ucred socketpeercred
+
+#elif defined HAVE_XUCRED
+#include <sys/un.h>
+#include <sys/ucred.h>
+#define level 0
+#define SO_PEERCRED LOCAL_PEERCRED
+#define uid cr_uid
+#define ucred xucred
+
+#else
+#error impossible
+#endif
/**
perform the unix socket based authentication
@@ -63,7 +83,7 @@ static int socket_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
return CR_ERROR;
/* get the UID of the client process */
- if (getsockopt(vio_info.socket, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len))
+ if (getsockopt(vio_info.socket, level, SO_PEERCRED, &cred, &cred_len))
return CR_ERROR;
if (cred_len != sizeof(cred))
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index 1ef743725e5..b6ff7e1b28d 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -56,6 +56,9 @@ WARNING: THIS PROGRAM IS STILL IN BETA. Comments/patches welcome.
# Documentation continued at end of file
+# fix CORE::GLOBAL::die to return a predictable exit code
+BEGIN { *CORE::GLOBAL::die= sub { warn @_; exit 1; }; }
+
my $VERSION = "1.23";
my $opt_tmpdir = $ENV{TMPDIR} || "/tmp";
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index f503b2f54e5..4420f2c7e07 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -8589,8 +8589,7 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
ulonglong first_value_part, max_first_value;
handler **file= m_file;
first_value_part= max_first_value= *first_value;
- /* Must lock and find highest value among all partitions. */
- lock_auto_increment();
+ /* Must find highest value among all partitions. */
do
{
/* Only nb_desired_values = 1 makes sense */
@@ -8601,7 +8600,6 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
*first_value= first_value_part;
/* log that the error was between table/partition handler */
sql_print_error("Partition failed to reserve auto_increment value");
- unlock_auto_increment();
DBUG_VOID_RETURN;
}
DBUG_PRINT("info", ("first_value_part: %lu", (ulong) first_value_part));
@@ -8609,7 +8607,6 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
} while (*(++file));
*first_value= max_first_value;
*nb_reserved_values= 1;
- unlock_auto_increment();
}
else
{
diff --git a/sql/handler.cc b/sql/handler.cc
index ff33243ebc9..179311c65bb 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3201,15 +3201,10 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
if (error)
{
if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND)
- {
- /* No entry found, start with 1. */
- nr= 1;
- }
+ /* No entry found, that's fine */;
else
- {
- DBUG_ASSERT(0);
- nr= ULONGLONG_MAX;
- }
+ print_error(error, MYF(0));
+ nr= 1;
}
else
nr= ((ulonglong) table->next_number_field->
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 11dccfe9ffe..13f7facedea 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1159,6 +1159,8 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
Item_change_list old_change_list;
String old_packet;
uint old_server_status;
+ const uint status_backup_mask= SERVER_STATUS_CURSOR_EXISTS |
+ SERVER_STATUS_LAST_ROW_SENT;
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
Object_creation_ctx *saved_creation_ctx;
Diagnostics_area *da= thd->get_stmt_da();
@@ -1292,7 +1294,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
It is probably safe to use same thd->convert_buff everywhere.
*/
old_packet.swap(thd->packet);
- old_server_status= thd->server_status;
+ old_server_status= thd->server_status & status_backup_mask;
/*
Switch to per-instruction arena here. We can do it since we cleanup
@@ -1414,7 +1416,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
thd->spcont->pop_all_cursors(); // To avoid memory leaks after an error
/* Restore all saved */
- thd->server_status= old_server_status;
+ thd->server_status= (thd->server_status & ~status_backup_mask) | old_server_status;
old_packet.swap(thd->packet);
DBUG_ASSERT(thd->change_list.is_empty());
old_change_list.move_elements_to(&thd->change_list);
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index cab9628837c..254b7026e96 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -2094,7 +2094,7 @@ enum_nested_loop_state JOIN_CACHE::join_records(bool skip_last)
goto finish;
if (outer_join_first_inner)
{
- if (next_cache)
+ if (next_cache && join_tab != join_tab->last_inner)
{
/*
Ensure that all matches for outer records from join buffer are to be
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 52015ee5ba7..6aecfca39f4 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9875,6 +9875,25 @@ uint get_next_field_for_derived_key(uchar *arg)
}
+static
+uint get_next_field_for_derived_key_simple(uchar *arg)
+{
+ KEYUSE *keyuse= *(KEYUSE **) arg;
+ if (!keyuse)
+ return (uint) (-1);
+ TABLE *table= keyuse->table;
+ uint key= keyuse->key;
+ uint fldno= keyuse->keypart;
+ for ( ;
+ keyuse->table == table && keyuse->key == key && keyuse->keypart == fldno;
+ keyuse++)
+ ;
+ if (keyuse->key != key)
+ keyuse= 0;
+ *((KEYUSE **) arg)= keyuse;
+ return fldno;
+}
+
static
bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys)
{
@@ -9905,12 +9924,28 @@ bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys)
}
else
{
- if (table->add_tmp_key(table->s->keys, parts,
- get_next_field_for_derived_key,
- (uchar *) &first_keyuse,
- FALSE))
- return TRUE;
- table->reginfo.join_tab->keys.set_bit(table->s->keys);
+ KEYUSE *save_first_keyuse= first_keyuse;
+ if (table->check_tmp_key(table->s->keys, parts,
+ get_next_field_for_derived_key_simple,
+ (uchar *) &first_keyuse))
+
+ {
+ first_keyuse= save_first_keyuse;
+ if (table->add_tmp_key(table->s->keys, parts,
+ get_next_field_for_derived_key,
+ (uchar *) &first_keyuse,
+ FALSE))
+ return TRUE;
+ table->reginfo.join_tab->keys.set_bit(table->s->keys);
+ }
+ else
+ {
+ /* Mark keyuses for this key to be excluded */
+ for (KEYUSE *curr=save_first_keyuse; curr < first_keyuse; curr++)
+ {
+ curr->key= MAX_KEY;
+ }
+ }
first_keyuse= keyuse;
key_count++;
parts= 0;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 87cec1ce2ae..a6d301294bf 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2290,77 +2290,77 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_VOID_RETURN;
+ if (thd->killed)
+ DBUG_VOID_RETURN;
+
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
- if (!thd->killed)
+ I_List_iterator<THD> it(threads);
+ THD *tmp;
+ while ((tmp=it++))
{
- I_List_iterator<THD> it(threads);
- THD *tmp;
- while ((tmp=it++))
+ Security_context *tmp_sctx= tmp->security_ctx;
+ struct st_my_thread_var *mysys_var;
+ if ((tmp->vio_ok() || tmp->system_thread) &&
+ (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user))))
{
- Security_context *tmp_sctx= tmp->security_ctx;
- struct st_my_thread_var *mysys_var;
- if ((tmp->vio_ok() || tmp->system_thread) &&
- (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user))))
+ thread_info *thd_info= new thread_info;
+
+ thd_info->thread_id=tmp->thread_id;
+ thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user :
+ (tmp->system_thread ?
+ "system user" : "unauthenticated user"));
+ if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) &&
+ thd->security_ctx->host_or_ip[0])
{
- thread_info *thd_info= new thread_info;
-
- thd_info->thread_id=tmp->thread_id;
- thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user :
- (tmp->system_thread ?
- "system user" : "unauthenticated user"));
- if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) &&
- thd->security_ctx->host_or_ip[0])
- {
- if ((thd_info->host= (char*) thd->alloc(LIST_PROCESS_HOST_LEN+1)))
- my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
- "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port);
- }
- else
- thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ?
- tmp_sctx->host_or_ip :
- tmp_sctx->host ? tmp_sctx->host : "");
- thd_info->command=(int) tmp->get_command();
- mysql_mutex_lock(&tmp->LOCK_thd_data);
- if ((thd_info->db= tmp->db)) // Safe test
- thd_info->db= thd->strdup(thd_info->db);
- if ((mysys_var= tmp->mysys_var))
- mysql_mutex_lock(&mysys_var->mutex);
- thd_info->proc_info= (char*) (tmp->killed >= KILL_QUERY ?
- "Killed" : 0);
- thd_info->state_info= thread_state_info(tmp);
- if (mysys_var)
- mysql_mutex_unlock(&mysys_var->mutex);
-
- /* Lock THD mutex that protects its data when looking at it. */
- if (tmp->query())
- {
- uint length= MY_MIN(max_query_length, tmp->query_length());
- char *q= thd->strmake(tmp->query(),length);
- /* Safety: in case strmake failed, we set length to 0. */
- thd_info->query_string=
- CSET_STRING(q, q ? length : 0, tmp->query_charset());
- }
+ if ((thd_info->host= (char*) thd->alloc(LIST_PROCESS_HOST_LEN+1)))
+ my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
+ "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port);
+ }
+ else
+ thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ?
+ tmp_sctx->host_or_ip :
+ tmp_sctx->host ? tmp_sctx->host : "");
+ thd_info->command=(int) tmp->get_command();
+ mysql_mutex_lock(&tmp->LOCK_thd_data);
+ if ((thd_info->db= tmp->db)) // Safe test
+ thd_info->db= thd->strdup(thd_info->db);
+ if ((mysys_var= tmp->mysys_var))
+ mysql_mutex_lock(&mysys_var->mutex);
+ thd_info->proc_info= (char*) (tmp->killed >= KILL_QUERY ?
+ "Killed" : 0);
+ thd_info->state_info= thread_state_info(tmp);
+ if (mysys_var)
+ mysql_mutex_unlock(&mysys_var->mutex);
- /*
- Progress report. We need to do this under a lock to ensure that all
- is from the same stage.
- */
- if (tmp->progress.max_counter)
- {
- uint max_stage= MY_MAX(tmp->progress.max_stage, 1);
- thd_info->progress= (((tmp->progress.stage / (double) max_stage) +
- ((tmp->progress.counter /
- (double) tmp->progress.max_counter) /
- (double) max_stage)) *
- 100.0);
- set_if_smaller(thd_info->progress, 100);
- }
- else
- thd_info->progress= 0.0;
- thd_info->start_time= tmp->start_time;
- mysql_mutex_unlock(&tmp->LOCK_thd_data);
- thread_infos.append(thd_info);
+ /* Lock THD mutex that protects its data when looking at it. */
+ if (tmp->query())
+ {
+ uint length= MY_MIN(max_query_length, tmp->query_length());
+ char *q= thd->strmake(tmp->query(),length);
+ /* Safety: in case strmake failed, we set length to 0. */
+ thd_info->query_string=
+ CSET_STRING(q, q ? length : 0, tmp->query_charset());
}
+
+ /*
+ Progress report. We need to do this under a lock to ensure that all
+ is from the same stage.
+ */
+ if (tmp->progress.max_counter)
+ {
+ uint max_stage= MY_MAX(tmp->progress.max_stage, 1);
+ thd_info->progress= (((tmp->progress.stage / (double) max_stage) +
+ ((tmp->progress.counter /
+ (double) tmp->progress.max_counter) /
+ (double) max_stage)) *
+ 100.0);
+ set_if_smaller(thd_info->progress, 100);
+ }
+ else
+ thd_info->progress= 0.0;
+ thd_info->start_time= tmp->start_time;
+ mysql_mutex_unlock(&tmp->LOCK_thd_data);
+ thread_infos.append(thd_info);
}
}
mysql_mutex_unlock(&LOCK_thread_count);
@@ -7304,7 +7304,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
bool upper_case_names= (schema_table_idx != SCH_VARIABLES);
bool sorted_vars= (schema_table_idx == SCH_VARIABLES);
- if (lex->option_type == OPT_GLOBAL ||
+ if ((sorted_vars && lex->option_type == OPT_GLOBAL) ||
schema_table_idx == SCH_GLOBAL_VARIABLES)
option_type= OPT_GLOBAL;
diff --git a/sql/table.cc b/sql/table.cc
index c951351fba8..2347e74e13c 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6117,6 +6117,52 @@ void TABLE::create_key_part_by_field(KEY *keyinfo,
/**
@brief
+ Check validity of a possible key for the derived table
+
+ @param key the number of the key
+ @param key_parts number of components of the key
+ @param next_field_no the call-back function that returns the number of
+ the field used as the next component of the key
+ @param arg the argument for the above function
+
+ @details
+ The function checks whether a possible key satisfies the constraints
+ imposed on the keys of any temporary table.
+
+ @return TRUE if the key is valid
+ @return FALSE otherwise
+*/
+
+bool TABLE::check_tmp_key(uint key, uint key_parts,
+ uint (*next_field_no) (uchar *), uchar *arg)
+{
+ Field **reg_field;
+ uint i;
+ uint key_len= 0;
+
+ for (i= 0; i < key_parts; i++)
+ {
+ uint fld_idx= next_field_no(arg);
+ reg_field= field + fld_idx;
+ uint fld_store_len= (uint16) (*reg_field)->key_length();
+ if ((*reg_field)->real_maybe_null())
+ fld_store_len+= HA_KEY_NULL_LENGTH;
+ if ((*reg_field)->type() == MYSQL_TYPE_BLOB ||
+ (*reg_field)->real_type() == MYSQL_TYPE_VARCHAR ||
+ (*reg_field)->type() == MYSQL_TYPE_GEOMETRY)
+ fld_store_len+= HA_KEY_BLOB_LENGTH;
+ key_len+= fld_store_len;
+ }
+ /*
+ We use MI_MAX_KEY_LENGTH (myisam's default) below because it is
+ smaller than MAX_KEY_LENGTH (heap's default) and it's unknown whether
+ myisam or heap will be used for the temporary table.
+ */
+ return key_len <= MI_MAX_KEY_LENGTH;
+}
+
+/**
+ @brief
Add one key to a temporary table
@param key the number of the key
@@ -6146,6 +6192,7 @@ bool TABLE::add_tmp_key(uint key, uint key_parts,
KEY* keyinfo;
Field **reg_field;
uint i;
+
bool key_start= TRUE;
KEY_PART_INFO* key_part_info=
(KEY_PART_INFO*) alloc_root(&mem_root, sizeof(KEY_PART_INFO)*key_parts);
diff --git a/sql/table.h b/sql/table.h
index 3ac75ec06e1..8e31c0e2600 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1335,6 +1335,8 @@ public:
{ return !db_stat || m_needs_reopen; }
bool alloc_keys(uint key_count);
+ bool check_tmp_key(uint key, uint key_parts,
+ uint (*next_field_no) (uchar *), uchar *arg);
bool add_tmp_key(uint key, uint key_parts,
uint (*next_field_no) (uchar *), uchar *arg,
bool unique);
diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h
index 534b9940e84..8bf57677ecf 100644
--- a/storage/innobase/include/os0sync.h
+++ b/storage/innobase/include/os0sync.h
@@ -741,13 +741,16 @@ architecture. Disable memory barrier for Intel architecture for now. */
#elif defined(HAVE_WINDOWS_MM_FENCE)
# define HAVE_MEMORY_BARRIER
-# include <mmintrin.h>
+# include <intrin.h>
# define os_rmb _mm_lfence()
# define os_wmb _mm_sfence()
# define os_isync os_rmb; os_wmb
# define IB_MEMORY_BARRIER_STARTUP_MSG \
"_mm_lfence() and _mm_sfence() are used for memory barrier"
+# define os_atomic_lock_release_byte(ptr) \
+ (void) InterlockedExchange(ptr, 0)
+
#else
# define os_rmb do { } while(0)
# define os_wmb do { } while(0)
diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt
index 6cbad7162ff..61d0ae8a909 100644
--- a/storage/tokudb/CMakeLists.txt
+++ b/storage/tokudb/CMakeLists.txt
@@ -13,13 +13,14 @@ IF(NOT TOKUDB_OK OR WITHOUT_TOKUDB OR WITHOUT_TOKUDB_STORAGE_ENGINE)
RETURN()
ENDIF()
+IF(NOT LIBJEMALLOC)
+ MESSAGE(WARNING "TokuDB is enabled, but jemalloc is not. This configuration is not supported")
+ENDIF()
+
############################################
-SET(TOKUDB_VERSION "7.1.7")
+SET(TOKUDB_VERSION "7.1.8")
SET(TOKUDB_DEB_FILES "usr/lib/mysql/plugin/ha_tokudb.so\netc/mysql/conf.d/tokudb.cnf\nusr/bin/tokuftdump\nusr/share/doc/mariadb-server-10.0/README-TOKUDB\nusr/share/doc/mariadb-server-10.0/README.md" PARENT_SCOPE)
SET(USE_BDB OFF CACHE BOOL "")
-SET(USE_VALGRIND OFF CACHE BOOL "")
-SET(BUILD_TESTING OFF CACHE BOOL "")
-SET(TOKU_DEBUG_PARANOID OFF CACHE BOOL "")
MARK_AS_ADVANCED(BUILDNAME)
MARK_AS_ADVANCED(BUILD_TESTING)
MARK_AS_ADVANCED(CMAKE_TOKUDB_REVISION)
@@ -32,6 +33,10 @@ MARK_AS_ADVANCED(USE_VALGRIND)
MARK_AS_ADVANCED(XZ_SOURCE_DIR)
############################################
+SET(BUILD_TESTING OFF CACHE BOOL "")
+SET(USE_VALGRIND OFF CACHE BOOL "")
+SET(TOKU_DEBUG_PARANOID OFF CACHE BOOL "")
+
IF(NOT DEFINED TOKUDB_VERSION)
IF(DEFINED ENV{TOKUDB_VERSION})
SET(TOKUDB_VERSION $ENV{TOKUDB_VERSION})
@@ -49,14 +54,36 @@ IF(DEFINED TOKUDB_CHECK_JEMALLOC)
ADD_DEFINITIONS("-DTOKUDB_CHECK_JEMALLOC=${TOKUDB_CHECK_JEMALLOC}")
ENDIF()
+## adds a compiler flag if the compiler supports it
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+
+macro(set_cflags_if_supported)
+ foreach(flag ${ARGN})
+ check_c_compiler_flag(${flag} HAVE_C_${flag})
+ if (HAVE_C_${flag})
+ set(CMAKE_C_FLAGS "${flag} ${CMAKE_C_FLAGS}")
+ endif ()
+ check_cxx_compiler_flag(${flag} HAVE_CXX_${flag})
+ if (HAVE_CXX_${flag})
+ set(CMAKE_CXX_FLAGS "${flag} ${CMAKE_CXX_FLAGS}")
+ endif ()
+ endforeach(flag)
+endmacro(set_cflags_if_supported)
+
+set_cflags_if_supported(-Wno-missing-field-initializers)
+
ADD_SUBDIRECTORY(ft-index)
+# TODO: clean up includes in ft-index
INCLUDE_DIRECTORIES(ft-index)
+INCLUDE_DIRECTORIES(ft-index/include)
INCLUDE_DIRECTORIES(ft-index/portability)
+INCLUDE_DIRECTORIES(ft-index/toku_include)
INCLUDE_DIRECTORIES(ft-index/util)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/ft-index)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/ft-index/buildheader)
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/ft-index/portability)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/ft-index/toku_include)
SET(TOKUDB_PLUGIN_DYNAMIC "ha_tokudb")
SET(TOKUDB_SOURCES ha_tokudb.cc)
diff --git a/storage/tokudb/README.md b/storage/tokudb/README.md
index 1deb3699c5a..e49e26f118d 100644
--- a/storage/tokudb/README.md
+++ b/storage/tokudb/README.md
@@ -24,14 +24,14 @@ working MySQL or MariaDB with Tokutek patches, and with the TokuDB storage
engine, called `make.mysql.bash`. This script will download copies of the
needed source code from github and build everything.
-To build MySQL 5.5.37 with TokuDB 7.1.6:
+To build MySQL 5.5.38 with TokuDB 7.1.7:
```sh
-scripts/make.mysql.bash --mysqlbuild=mysql-5.5.37-tokudb-7.1.6-linux-x86_64
+scripts/make.mysql.bash --mysqlbuild=mysql-5.5.38-tokudb-7.1.7-linux-x86_64
```
-To build MariaDB 5.5.37 with TokuDB 7.1.6:
+To build MariaDB 5.5.38 with TokuDB 7.1.7:
```sh
-scripts/make.mysql.bash --mysqlbuild=mariadb-5.5.37-tokudb-7.1.6-linux-x86_64
+scripts/make.mysql.bash --mysqlbuild=mariadb-5.5.38-tokudb-7.1.7-linux-x86_64
```
Before you start, make sure you have a C++11-compatible compiler (GCC >=
diff --git a/storage/tokudb/ft-index/CMakeLists.txt b/storage/tokudb/ft-index/CMakeLists.txt
index f28e7745295..ce10c0a0219 100644
--- a/storage/tokudb/ft-index/CMakeLists.txt
+++ b/storage/tokudb/ft-index/CMakeLists.txt
@@ -51,12 +51,14 @@ if (USE_VALGRIND AND NOT VALGRIND_INCLUDE_DIR MATCHES NOTFOUND)
)
endif()
include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/toku_include
${CMAKE_CURRENT_SOURCE_DIR}/portability
${CMAKE_CURRENT_SOURCE_DIR} ## so you can include <ft/ft-ops.h> from inside src/
${CMAKE_CURRENT_BINARY_DIR} ## for logging code
)
## include where config.h will be generated
-include_directories(${CMAKE_CURRENT_BINARY_DIR}/portability)
+include_directories(${CMAKE_CURRENT_BINARY_DIR}/toku_include)
## build db.h and include where it will be generated
add_subdirectory(buildheader)
@@ -74,9 +76,11 @@ add_subdirectory(portability)
add_subdirectory(ft)
add_subdirectory(locktree)
add_subdirectory(src)
-add_subdirectory(tools)
+add_subdirectory(utils)
## subdirectories that just install things
+#add_subdirectory(include)
+add_subdirectory(toku_include)
#add_subdirectory(examples)
INSTALL_DOCUMENTATION(README.md README-TOKUDB COMPONENT Server)
diff --git a/storage/tokudb/ft-index/CTestCustom.cmake.in b/storage/tokudb/ft-index/CTestCustom.cmake.in
deleted file mode 100644
index 9861d8e20a2..00000000000
--- a/storage/tokudb/ft-index/CTestCustom.cmake.in
+++ /dev/null
@@ -1,244 +0,0 @@
-cmake_policy(SET CMP0012 NEW)
-
-## these tests shouldn't run with valgrind
-list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE
- ft/bnc-insert-benchmark
- ft/brt-serialize-benchmark
- ft/ft_loader-test-extractor-1
- ft/ft_loader-test-extractor-2
- ft/ft_loader-test-extractor-3
- ft/upgrade_test_simple
- portability/test-cache-line-boundary-fails
- portability/try-leak-lost
- portability/try-leak-reachable
- portability/try-leak-uninit
- util/helgrind_test_circular_buffer
- util/helgrind_test_partitioned_counter
- util/helgrind_test_partitioned_counter_5833
- ydb/diskfull.tdb
- ydb/drd_test_4015.tdb
- ydb/drd_test_groupcommit_count.tdb
- ydb/filesize.tdb
- ydb/helgrind_helgrind1.tdb
- ydb/helgrind_helgrind2.tdb
- ydb/helgrind_helgrind3.tdb
- ydb/helgrind_test_groupcommit_count.tdb
- ydb/hot-optimize-table-tests.tdb
- ydb/insert-dup-prelock.tdb
- ydb/loader-cleanup-test2.tdb
- ydb/loader-cleanup-test3.tdb
- ydb/loader-stress-test4.tdb
- ydb/maxsize-for-loader-B.tdb
- ydb/openlimit17.tdb
- ydb/openlimit17-locktree.tdb
- ydb/preload-db-nested.tdb
- ydb/stress-gc.tdb
- ydb/stress-gc2.tdb
- ydb/stress-test.bdb
- ydb/stress-test.tdb
- ydb/test-5138.tdb
- ydb/test-prepare.tdb
- ydb/test-prepare2.tdb
- ydb/test-prepare3.tdb
- ydb/test-recover1.tdb
- ydb/test-recover2.tdb
- ydb/test-recover3.tdb
- ydb/test-xa-prepare.tdb
- ydb/test4573-logtrim.tdb
- ydb/test_3645.tdb
- ydb/test_groupcommit_perf.bdb
- ydb/test_groupcommit_perf.tdb
- ydb/test_large_update_broadcast_small_cachetable.tdb
- ydb/test_update_broadcast_stress.tdb
- ydb/test_update_stress.tdb
- ydb/upgrade-test-4.tdb
- )
-
-if (NOT @RUN_HELGRIND_TESTS@)
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE
- util/helgrind_test_circular_buffer
- util/helgrind_test_partitioned_counter
- util/helgrind_test_partitioned_counter_5833
- ydb/helgrind_helgrind1.tdb
- ydb/helgrind_helgrind2.tdb
- ydb/helgrind_helgrind3.tdb
- ydb/helgrind_test_groupcommit_count.tdb
- )
-endif ()
-
-if (NOT @RUN_DRD_TESTS@)
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE
- ydb/drd_test_groupcommit_count.tdb
- ydb/drd_test_4015.tdb
- )
-endif ()
-
-## osx's pthreads prefer writers, so this test will deadlock
-if (@CMAKE_SYSTEM_NAME@ STREQUAL Darwin)
- list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE portability/test-pthread-rwlock-rwr)
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE portability/test-pthread-rwlock-rwr)
-endif ()
-
-## tests that are supposed to crash will generate memcheck failures
-set(tests_that_should_fail
- ft/test-assertA
- ft/test-assertB
- portability/try-assert-zero
- portability/try-assert0
- ydb/recover-missing-dbfile-2.abortrecover
- ydb/recover-missing-dbfile.abortrecover
- ydb/test_db_no_env.tdb
- ydb/test_truncate_txn_abort.tdb
- )
-list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE ${tests_that_should_fail})
-
-## don't run drd stress tests with valgrind either (because that would do valgrind twice)
-set(stress_tests
- test_stress0.tdb
- test_stress1.tdb
- test_stress2.tdb
- test_stress3.tdb
- test_stress4.tdb
- test_stress5.tdb
- test_stress6.tdb
- test_stress7.tdb
- test_stress_hot_indexing.tdb
- test_stress_openclose.tdb
- test_stress_with_verify.tdb
- )
-foreach(test ${stress_tests})
- list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE
- ydb/drd_tiny_${test}
- ydb/drd_mid_${test}
- ydb/drd_large_${test}
- )
- if(NOT @RUN_LONG_TESTS@)
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE
- ydb/drd_large_${test}
- )
- endif()
- if (NOT @RUN_DRD_TESTS@)
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE
- ydb/drd_tiny_${test}
- ydb/drd_mid_${test}
- ydb/drd_large_${test}
- )
- endif ()
-endforeach(test)
-
-## upgrade stress tests are 5 minutes long, don't need to run them always
-if(NOT @RUN_LONG_TESTS@)
- foreach(test ${stress_tests})
- if (NOT ${test} MATCHES test_stress_openclose)
- foreach(oldver 4.2.0 5.0.8 5.2.7 6.0.0 6.1.0 6.5.1 6.6.3)
- foreach(p_or_s pristine stressed)
- if (NOT (${test} MATCHES test_stress4 AND ${p_or_s} MATCHES stressed))
- foreach(size 2000)
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE ydb/${test}/upgrade/${oldver}/${p_or_s}/${size})
- endforeach(size)
- endif ()
- endforeach(p_or_s)
- endforeach(oldver)
- endif ()
- endforeach(test)
-endif()
-
-set(tdb_tests_that_should_fail "ydb/${stress_tests}")
-string(REGEX REPLACE ";" ";ydb/" stress_tests "${stress_tests}")
-
-set(recover_stress_tests
- ydb/recover-test_stress1.abortrecover
- ydb/recover-test_stress2.abortrecover
- ydb/recover-test_stress3.abortrecover
- ydb/recover-test_stress_openclose.abortrecover
- )
-
-## we run stress tests separately, only run them if asked to
-if(NOT @RUN_STRESS_TESTS@)
- list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE ${stress_tests} ${recover_stress_tests})
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE ${stress_tests} ${recover_stress_tests})
-endif()
-
-set(perf_tests
- ydb/perf_checkpoint_var.tdb
- ydb/perf_cursor_nop.tdb
- ydb/perf_malloc_free.tdb
- ydb/perf_nop.tdb
- ydb/perf_ptquery.tdb
- ydb/perf_ptquery2.tdb
- ydb/perf_read_write.tdb
- ydb/perf_xmalloc_free.tdb
- )
-
-## we also don't need to run perf tests every time
-if(NOT @RUN_PERF_TESTS@)
- list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE ${perf_tests})
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE ${perf_tests})
-endif()
-
-## don't run perf tests with valgrind (that's slow)
-file(GLOB perf_test_srcs RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/tests" perf_*.cc)
-string(REGEX REPLACE "\\.cc(;|$)" ".tdb\\1" perf_tests "${perf_test_srcs}")
-set(tdb_tests_that_should_fail "ydb/${perf_tests}")
-string(REGEX REPLACE ";" ";ydb/" perf_tests "${perf_tests}")
-list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE ${perf_tests})
-
-## these tests fail often and aren't helpful
-set(known_failing_tests
- ydb/diskfull.tdb
- )
-list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE ${known_failing_tests})
-list(APPEND CTEST_CUSTOM_TESTS_IGNORE ${known_failing_tests})
-
-## these tests take a long time, only run them if asked to
-set(long_running_tests
- ft/is_empty
- ft/upgrade_test_simple
- ydb/checkpoint_1.tdb
- ydb/checkpoint_stress.tdb
- ydb/hotindexer-with-queries.tdb
- ydb/hot-optimize-table-tests.tdb
- ydb/loader-cleanup-test0.tdb
- ydb/loader-cleanup-test0z.tdb
- ydb/loader-cleanup-test2.tdb
- ydb/loader-cleanup-test2z.tdb
- ydb/loader-stress-test4.tdb
- ydb/loader-stress-test4z.tdb
- ydb/manyfiles.tdb
- ydb/preload-db-nested.tdb
- ydb/recover_stress.tdb
- ydb/root_fifo_1.tdb
- ydb/root_fifo_2.tdb
- ydb/root_fifo_31.tdb
- ydb/root_fifo_32.tdb
- ydb/stress-gc.tdb
- ydb/stress-test.tdb
- ydb/test3529.tdb
- ydb/test_logmax.tdb
- ydb/test_txn_nested2.tdb
- ydb/test_update_broadcast_stress.tdb
- ydb/test_update_stress.tdb
- )
-if(NOT @RUN_LONG_TESTS@)
- list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE ${long_running_tests})
- list(APPEND CTEST_CUSTOM_TESTS_IGNORE ${long_running_tests})
-endif()
-
-## ignore log_print.cc in coverage report
-list(APPEND CTEST_CUSTOM_COVERAGE_EXCLUDE "log_print.cc")
-
-list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
- # don't complain about warnings in xz source
- "xz-4.999.9beta/src/liblzma"
- # don't complain about clang missing warnings from xz code
- "clang: warning: unknown warning option"
- # don't complain about warnings in jemalloc source
- "jemalloc/src"
- "jemalloc/internal"
- # don't complain about valgrind headers leaving things unused
- "valgrind/valgrind.h"
- "valgrind/memcheck.h"
- # don't complain about ranlib or libtool on empty archive
- "has no symbols"
- "the table of contents is empty"
- )
diff --git a/storage/tokudb/ft-index/buildheader/CMakeLists.txt b/storage/tokudb/ft-index/buildheader/CMakeLists.txt
index 5da3c98ff48..9a3a6be1cae 100644
--- a/storage/tokudb/ft-index/buildheader/CMakeLists.txt
+++ b/storage/tokudb/ft-index/buildheader/CMakeLists.txt
@@ -26,4 +26,4 @@ if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
DESTINATION include
COMPONENT tokukv_headers
)
-endif ()
+endif () \ No newline at end of file
diff --git a/storage/tokudb/ft-index/buildheader/make_tdb.cc b/storage/tokudb/ft-index/buildheader/make_tdb.cc
index d185aa352fb..037822894cf 100644
--- a/storage/tokudb/ft-index/buildheader/make_tdb.cc
+++ b/storage/tokudb/ft-index/buildheader/make_tdb.cc
@@ -291,6 +291,7 @@ static void print_defines (void) {
printf("#define DB_IS_HOT_INDEX 0x00100000\n"); // private tokudb
printf("#define DBC_DISABLE_PREFETCHING 0x20000000\n"); // private tokudb
printf("#define DB_UPDATE_CMP_DESCRIPTOR 0x40000000\n"); // private tokudb
+ printf("#define TOKUFT_DIRTY_SHUTDOWN %x\n", 1<<31);
{
//dbt flags
@@ -464,7 +465,6 @@ static void print_db_env_struct (void) {
"void (*set_loader_memory_size)(DB_ENV *env, uint64_t (*get_loader_memory_size_callback)(void))",
"uint64_t (*get_loader_memory_size)(DB_ENV *env)",
"void (*set_killed_callback)(DB_ENV *env, uint64_t default_killed_time_msec, uint64_t (*get_killed_time_callback)(uint64_t default_killed_time_msec), int (*killed_callback)(void))",
- "void (*do_backtrace) (DB_ENV *env)",
NULL};
sort_and_dump_fields("db_env", true, extra);
@@ -571,11 +571,13 @@ static void print_db_txn_struct (void) {
STRUCT_SETUP(DB_TXN, api_internal,"void *%s");
STRUCT_SETUP(DB_TXN, commit, "int (*%s) (DB_TXN*, uint32_t)");
STRUCT_SETUP(DB_TXN, prepare, "int (*%s) (DB_TXN*, uint8_t gid[DB_GID_SIZE])");
+ STRUCT_SETUP(DB_TXN, discard, "int (*%s) (DB_TXN*, uint32_t)");
STRUCT_SETUP(DB_TXN, id, "uint32_t (*%s) (DB_TXN *)");
STRUCT_SETUP(DB_TXN, mgrp, "DB_ENV *%s /*In TokuDB, mgrp is a DB_ENV not a DB_TXNMGR*/");
STRUCT_SETUP(DB_TXN, parent, "DB_TXN *%s");
const char *extra[] = {
"int (*txn_stat)(DB_TXN *, struct txn_stat **)",
+ "struct toku_list open_txns",
"int (*commit_with_progress)(DB_TXN*, uint32_t, TXN_PROGRESS_POLL_FUNCTION, void*)",
"int (*abort_with_progress)(DB_TXN*, TXN_PROGRESS_POLL_FUNCTION, void*)",
"int (*xa_prepare) (DB_TXN*, TOKU_XA_XID *)",
@@ -633,6 +635,7 @@ int main (int argc, char *const argv[] __attribute__((__unused__))) {
//printf("#include <inttypes.h>\n");
printf("#if defined(__cplusplus) || defined(__cilkplusplus)\nextern \"C\" {\n#endif\n");
+ printf("#define TOKUDB 1\n");
printf("#define DB_VERSION_MAJOR %d\n", DB_VERSION_MAJOR);
printf("#define DB_VERSION_MINOR %d\n", DB_VERSION_MINOR);
printf("/* As of r40364 (post TokuDB 5.2.7), the patch version number is 100+ the BDB header patch version number.*/\n");
@@ -651,6 +654,7 @@ int main (int argc, char *const argv[] __attribute__((__unused__))) {
" char data[DB_GID_SIZE];\n"
"} TOKU_XA_XID;\n");
+ //Typedef toku_off_t
printf("#ifndef TOKU_OFF_T_DEFINED\n"
"#define TOKU_OFF_T_DEFINED\n"
"typedef int64_t toku_off_t;\n"
@@ -669,10 +673,7 @@ int main (int argc, char *const argv[] __attribute__((__unused__))) {
printf("typedef uint32_t db_recno_t;\n");
printf("typedef int(*YDB_CALLBACK_FUNCTION)(DBT const*, DBT const*, void*);\n");
- printf("struct simple_dbt {\n");
- printf(" uint32_t len;\n");
- printf(" void *data;\n");
- printf("};\n");
+ printf("#include <tdb-internal.h>\n");
//stat64
printf("typedef struct __toku_db_btree_stat64 {\n");
diff --git a/storage/tokudb/ft-index/cmake/merge_archives_unix.cmake.in b/storage/tokudb/ft-index/cmake/merge_archives_unix.cmake.in
index e7140b8dbbc..e52baa6421f 100644
--- a/storage/tokudb/ft-index/cmake/merge_archives_unix.cmake.in
+++ b/storage/tokudb/ft-index/cmake/merge_archives_unix.cmake.in
@@ -26,52 +26,15 @@ SET(CMAKE_RANLIB "@CMAKE_RANLIB@")
SET(TEMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET})
MAKE_DIRECTORY(${TEMP_DIR})
-# Extract each archive to its own subdirectory(avoid object filename
-# clashes) Since the lib may contain objects with the same name, we first
-# list the archive contents, then uniquify the object names as we extract
-# them.
+# Extract each archive to its own subdirectory(avoid object filename clashes)
FOREACH(LIB ${STATIC_LIBS})
GET_FILENAME_COMPONENT(NAME_NO_EXT ${LIB} NAME_WE)
SET(TEMP_SUBDIR ${TEMP_DIR}/${NAME_NO_EXT})
MAKE_DIRECTORY(${TEMP_SUBDIR})
EXECUTE_PROCESS(
- COMMAND ${CMAKE_AR} -t ${LIB}
- OUTPUT_VARIABLE LIB_OBJS
+ COMMAND ${CMAKE_AR} -x ${LIB}
+ WORKING_DIRECTORY ${TEMP_SUBDIR}
)
- STRING(REGEX REPLACE "\n" ";" LIB_OBJ_LIST "${LIB_OBJS}")
- STRING(REGEX REPLACE ";$" "" LIB_OBJ_LIST "${LIB_OBJ_LIST}")
-
- LIST(LENGTH LIB_OBJ_LIST LENGTH_WITH_DUPS)
- SET(LIB_OBJ_LIST_NO_DUPS ${LIB_OBJ_LIST})
- LIST(REMOVE_DUPLICATES LIB_OBJ_LIST_NO_DUPS)
- LIST(LENGTH LIB_OBJ_LIST_NO_DUPS LENGTH_WITHOUT_DUPS)
-
- IF(LENGTH_WITH_DUPS EQUAL LENGTH_WITHOUT_DUPS)
- # Optimization for when lib doesn't actually have duplicate object
- # names, we can just extract everything.
- EXECUTE_PROCESS(
- COMMAND ${CMAKE_AR} -x ${LIB}
- WORKING_DIRECTORY ${TEMP_SUBDIR}
- )
- ELSE()
- LIST(SORT LIB_OBJ_LIST)
- SET(SAME_OBJ_COUNT 1)
- SET(LAST_OBJ_NAME)
- FOREACH(OBJ ${LIB_OBJ_LIST})
- IF(OBJ STREQUAL LAST_OBJ_NAME)
- GET_FILENAME_COMPONENT(OBJ_NO_EXT ${OBJ} NAME_WE)
- FILE(RENAME "${TEMP_SUBDIR}/${OBJ}" "${TEMP_SUBDIR}/${OBJ_NO_EXT}.${SAME_OBJ_COUNT}.o")
- MATH(EXPR SAME_OBJ_COUNT "${SAME_OBJ_COUNT}+1")
- ELSE()
- SET(SAME_OBJ_COUNT 1)
- ENDIF()
- SET(LAST_OBJ_NAME "${OBJ}")
- EXECUTE_PROCESS(
- COMMAND ${CMAKE_AR} -xN ${SAME_OBJ_COUNT} ${LIB} ${OBJ}
- WORKING_DIRECTORY ${TEMP_SUBDIR}
- )
- ENDFOREACH()
- ENDIF()
FILE(GLOB_RECURSE LIB_OBJECTS "${TEMP_SUBDIR}/*.o")
SET(OBJECTS ${OBJECTS} ${LIB_OBJECTS})
@@ -88,7 +51,11 @@ ENDFOREACH()
FILE(TO_NATIVE_PATH ${TARGET_LOCATION} ${TARGET_LOCATION})
# Now pack the objects into library with ar.
EXECUTE_PROCESS(
- COMMAND ${CMAKE_AR} rcs ${TARGET_LOCATION} ${ALL_OBJECTS}
+ COMMAND ${CMAKE_AR} -r ${TARGET_LOCATION} ${ALL_OBJECTS}
+ WORKING_DIRECTORY ${TEMP_DIR}
+)
+EXECUTE_PROCESS(
+ COMMAND ${CMAKE_RANLIB} ${TARGET_LOCATION}
WORKING_DIRECTORY ${TEMP_DIR}
)
diff --git a/storage/tokudb/ft-index/cmake_modules/TokuBuildTagDatabases.cmake b/storage/tokudb/ft-index/cmake_modules/TokuBuildTagDatabases.cmake
index 72c96389872..e764ad30c07 100644
--- a/storage/tokudb/ft-index/cmake_modules/TokuBuildTagDatabases.cmake
+++ b/storage/tokudb/ft-index/cmake_modules/TokuBuildTagDatabases.cmake
@@ -7,6 +7,7 @@ file(GLOB_RECURSE all_srcs
locktree/*.cc
portability/*.cc
src/*.cc
+ toku_include/*.cc
utils/*.cc
util/*.cc
db-benchmark-test/*.cc
@@ -23,12 +24,13 @@ file(GLOB_RECURSE all_hdrs
locktree/*.h
portability/*.h
src/*.h
+ toku_include/*.h
utils/*.h
util/*.h
db-benchmark-test/*.h
)
list(APPEND all_hdrs
- ${CMAKE_CURRENT_BINARY_DIR}/portability/toku_config.h
+ ${CMAKE_CURRENT_BINARY_DIR}/toku_include/toku_config.h
${CMAKE_CURRENT_BINARY_DIR}/buildheader/db.h
${CMAKE_CURRENT_BINARY_DIR}/ft/log_header.h
)
@@ -77,7 +79,7 @@ if (USE_CSCOPE)
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/cscope.out"
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/cscope.in.out"
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/cscope.po.out"
- COMMAND ${CSCOPE} -b -q -R -i"${CMAKE_CURRENT_BINARY_DIR}/cscope.files" -I"${CMAKE_CURRENT_SOURCE_DIR}" -I"${CMAKE_CURRENT_SOURCE_DIR}/include" -I"${CMAKE_CURRENT_SOURCE_DIR}/portability" -I"${CMAKE_CURRENT_SOURCE_DIR}/portability" -I"${CMAKE_CURRENT_SOURCE_DIR}/ft" -I"${CMAKE_CURRENT_SOURCE_DIR}/src" -I"${CMAKE_CURRENT_SOURCE_DIR}/locktree" -I"${CMAKE_CURRENT_SOURCE_DIR}/utils" -I"${CMAKE_CURRENT_SOURCE_DIR}/db-benchmark-test" -I"${CMAKE_CURRENT_BINARY_DIR}" -I"${CMAKE_CURRENT_BINARY_DIR}/portability" -I"${CMAKE_CURRENT_BINARY_DIR}/buildheader"
+ COMMAND ${CSCOPE} -b -q -R -i"${CMAKE_CURRENT_BINARY_DIR}/cscope.files" -I"${CMAKE_CURRENT_SOURCE_DIR}" -I"${CMAKE_CURRENT_SOURCE_DIR}/include" -I"${CMAKE_CURRENT_SOURCE_DIR}/toku_include" -I"${CMAKE_CURRENT_SOURCE_DIR}/portability" -I"${CMAKE_CURRENT_SOURCE_DIR}/ft" -I"${CMAKE_CURRENT_SOURCE_DIR}/src" -I"${CMAKE_CURRENT_SOURCE_DIR}/locktree" -I"${CMAKE_CURRENT_SOURCE_DIR}/utils" -I"${CMAKE_CURRENT_SOURCE_DIR}/db-benchmark-test" -I"${CMAKE_CURRENT_BINARY_DIR}" -I"${CMAKE_CURRENT_BINARY_DIR}/toku_include" -I"${CMAKE_CURRENT_BINARY_DIR}/buildheader"
DEPENDS ${all_srcs} ${all_hdrs} install_tdb_h generate_config_h generate_log_code
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
add_custom_target(build_cscope.out ALL DEPENDS
diff --git a/storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake b/storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake
index 5b6882cc4a1..9e6c9d4834c 100644
--- a/storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake
+++ b/storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake
@@ -94,6 +94,8 @@ if (BUILD_TESTING OR BUILD_FT_TESTS OR BUILD_SRC_TESTS)
## set up full valgrind suppressions file (concatenate the suppressions files)
file(READ ft/valgrind.suppressions valgrind_suppressions)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/valgrind.suppressions" "${valgrind_suppressions}")
+ file(READ src/tests/bdb.suppressions bdb_suppressions)
+ file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/valgrind.suppressions" "${bdb_suppressions}")
file(READ bash.suppressions bash_suppressions)
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/valgrind.suppressions" "${bash_suppressions}")
diff --git a/storage/tokudb/ft-index/ft/CMakeLists.txt b/storage/tokudb/ft-index/ft/CMakeLists.txt
index da8d0f41d8f..3627f1c3dfe 100644
--- a/storage/tokudb/ft-index/ft/CMakeLists.txt
+++ b/storage/tokudb/ft-index/ft/CMakeLists.txt
@@ -52,7 +52,9 @@ set(FT_SOURCES
logfilemgr
logger
log_upgrade
+ memarena
minicron
+ omt
pqueue
queue
quicklz
@@ -67,6 +69,7 @@ set(FT_SOURCES
txn_child_manager
txn_manager
ule
+ x1764
xids
ybt
"${CMAKE_CURRENT_BINARY_DIR}/log_code"
diff --git a/storage/tokudb/ft-index/ft/background_job_manager.cc b/storage/tokudb/ft-index/ft/background_job_manager.cc
index 6849909a2ed..9a9c9467106 100644
--- a/storage/tokudb/ft-index/ft/background_job_manager.cc
+++ b/storage/tokudb/ft-index/ft/background_job_manager.cc
@@ -89,12 +89,11 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-#include <portability/toku_config.h>
+#include "background_job_manager.h"
+#include "toku_config.h"
#include <memory.h>
#include <toku_pthread.h>
-#include "background_job_manager.h"
-
struct background_job_manager_struct {
bool accepting_jobs;
uint32_t num_jobs;
diff --git a/storage/tokudb/ft-index/ft/block_table.cc b/storage/tokudb/ft-index/ft/block_table.cc
index ba7d60b8d42..3e0bae1709a 100644
--- a/storage/tokudb/ft-index/ft/block_table.cc
+++ b/storage/tokudb/ft-index/ft/block_table.cc
@@ -427,7 +427,7 @@ toku_ft_unlock (FT ft) {
unlock_for_blocktable(bt);
}
-// Also used only in ft-serialize-test.
+// Also used only in brt-serialize-test.
void
toku_block_free(BLOCK_TABLE bt, uint64_t offset) {
lock_for_blocktable(bt);
@@ -580,7 +580,7 @@ void toku_serialize_translation_to_wbuf(BLOCK_TABLE bt, int fd, struct wbuf *w,
wbuf_DISKOFF(w, t->block_translation[i].u.diskoff);
wbuf_DISKOFF(w, t->block_translation[i].size);
}
- uint32_t checksum = toku_x1764_finish(&w->checksum);
+ uint32_t checksum = x1764_finish(&w->checksum);
wbuf_int(w, checksum);
*address = t->block_translation[b.b].u.diskoff;
*size = size_translation;
@@ -915,7 +915,7 @@ translation_deserialize_from_buffer(struct translation *t, // destination int
t->type = TRANSLATION_CHECKPOINTED;
{
// check the checksum
- uint32_t x1764 = toku_x1764_memory(translation_buffer, size_on_disk - 4);
+ uint32_t x1764 = x1764_memory(translation_buffer, size_on_disk - 4);
uint64_t offset = size_on_disk - 4;
//printf("%s:%d read from %ld (x1764 offset=%ld) size=%ld\n", __FILE__, __LINE__, block_translation_address_on_disk, offset, block_translation_size_on_disk);
uint32_t stored_x1764 = toku_dtoh32(*(int*)(translation_buffer + offset));
diff --git a/storage/tokudb/ft-index/ft/bndata.cc b/storage/tokudb/ft-index/ft/bndata.cc
index eb543a03ab4..b68a05c119a 100644
--- a/storage/tokudb/ft-index/ft/bndata.cc
+++ b/storage/tokudb/ft-index/ft/bndata.cc
@@ -90,197 +90,46 @@ PATENT RIGHTS GRANT:
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#include <bndata.h>
-#include <ft-ops.h>
-using namespace toku;
-uint32_t bn_data::klpair_disksize(const uint32_t klpair_len, const klpair_struct *klpair) const {
- return sizeof(*klpair) + keylen_from_klpair_len(klpair_len) + leafentry_disksize(get_le_from_klpair(klpair));
+static uint32_t klpair_size(KLPAIR klpair){
+ return sizeof(*klpair) + klpair->keylen + leafentry_memsize(get_le_from_klpair(klpair));
+}
+
+static uint32_t klpair_disksize(KLPAIR klpair){
+ return sizeof(*klpair) + klpair->keylen + leafentry_disksize(get_le_from_klpair(klpair));
}
void bn_data::init_zero() {
toku_mempool_zero(&m_buffer_mempool);
- m_disksize_of_keys = 0;
}
void bn_data::initialize_empty() {
- init_zero();
- m_buffer.create();
-}
-
-void bn_data::add_key(uint32_t keylen) {
- m_disksize_of_keys += sizeof(keylen) + keylen;
-}
-
-void bn_data::add_keys(uint32_t n_keys, uint32_t combined_klpair_len) {
- invariant(n_keys * sizeof(uint32_t) <= combined_klpair_len);
- m_disksize_of_keys += combined_klpair_len;
-}
-
-void bn_data::remove_key(uint32_t keylen) {
- m_disksize_of_keys -= sizeof(keylen) + keylen;
-}
-
-// Deserialize from format optimized for keys being inlined.
-// Currently only supports fixed-length keys.
-void bn_data::initialize_from_separate_keys_and_vals(uint32_t num_entries, struct rbuf *rb, uint32_t data_size, uint32_t version UU(),
- uint32_t key_data_size, uint32_t val_data_size, bool all_keys_same_length,
- uint32_t fixed_klpair_length) {
- paranoid_invariant(version >= FT_LAYOUT_VERSION_26); // Support was added @26
- uint32_t ndone_before = rb->ndone;
- init_zero();
- invariant(all_keys_same_length); // Until otherwise supported.
- bytevec keys_src;
- rbuf_literal_bytes(rb, &keys_src, key_data_size);
- //Generate dmt
- this->m_buffer.create_from_sorted_memory_of_fixed_size_elements(
- keys_src, num_entries, key_data_size, fixed_klpair_length);
- toku_mempool_construct(&this->m_buffer_mempool, val_data_size);
-
- bytevec vals_src;
- rbuf_literal_bytes(rb, &vals_src, val_data_size);
-
- if (num_entries > 0) {
- void *vals_dest = toku_mempool_malloc(&this->m_buffer_mempool, val_data_size, 1);
- paranoid_invariant_notnull(vals_dest);
- memcpy(vals_dest, vals_src, val_data_size);
- }
-
- add_keys(num_entries, num_entries * fixed_klpair_length);
-
- toku_note_deserialized_basement_node(all_keys_same_length);
-
- invariant(rb->ndone - ndone_before == data_size);
-}
-
-static int
-wbufwriteleafentry(const void* key, const uint32_t keylen, const LEAFENTRY &le, const uint32_t UU(idx), struct wbuf * const wb) {
- // need to pack the leafentry as it was in versions
- // where the key was integrated into it (< 26)
- uint32_t begin_spot UU() = wb->ndone;
- uint32_t le_disk_size = leafentry_disksize(le);
- wbuf_nocrc_uint8_t(wb, le->type);
- wbuf_nocrc_uint32_t(wb, keylen);
- if (le->type == LE_CLEAN) {
- wbuf_nocrc_uint32_t(wb, le->u.clean.vallen);
- wbuf_nocrc_literal_bytes(wb, key, keylen);
- wbuf_nocrc_literal_bytes(wb, le->u.clean.val, le->u.clean.vallen);
- }
- else {
- paranoid_invariant(le->type == LE_MVCC);
- wbuf_nocrc_uint32_t(wb, le->u.mvcc.num_cxrs);
- wbuf_nocrc_uint8_t(wb, le->u.mvcc.num_pxrs);
- wbuf_nocrc_literal_bytes(wb, key, keylen);
- wbuf_nocrc_literal_bytes(wb, le->u.mvcc.xrs, le_disk_size - (1 + 4 + 1));
- }
- uint32_t end_spot UU() = wb->ndone;
- paranoid_invariant((end_spot - begin_spot) == keylen + sizeof(keylen) + le_disk_size);
- return 0;
-}
-
-void bn_data::serialize_to_wbuf(struct wbuf *const wb) {
- prepare_to_serialize();
- serialize_header(wb);
- if (m_buffer.value_length_is_fixed()) {
- serialize_rest(wb);
- } else {
- //
- // iterate over leafentries and place them into the buffer
- //
- iterate<struct wbuf, wbufwriteleafentry>(wb);
- }
-}
-
-// If we have fixed-length keys, we prepare the dmt and mempool.
-// The mempool is prepared by removing any fragmented space and ordering leafentries in the same order as their keys.
-void bn_data::prepare_to_serialize(void) {
- if (m_buffer.value_length_is_fixed()) {
- m_buffer.prepare_for_serialize();
- dmt_compress_kvspace(0, nullptr, true); // Gets it ready for easy serialization.
- }
-}
-
-void bn_data::serialize_header(struct wbuf *wb) const {
- bool fixed = m_buffer.value_length_is_fixed();
-
- //key_data_size
- wbuf_nocrc_uint(wb, m_disksize_of_keys);
- //val_data_size
- wbuf_nocrc_uint(wb, toku_mempool_get_used_size(&m_buffer_mempool));
- //fixed_klpair_length
- wbuf_nocrc_uint(wb, m_buffer.get_fixed_length());
- // all_keys_same_length
- wbuf_nocrc_uint8_t(wb, fixed);
- // keys_vals_separate
- wbuf_nocrc_uint8_t(wb, fixed);
-}
-
-void bn_data::serialize_rest(struct wbuf *wb) const {
- //Write keys
- invariant(m_buffer.value_length_is_fixed()); //Assumes prepare_to_serialize was called
- m_buffer.serialize_values(m_disksize_of_keys, wb);
-
- //Write leafentries
- //Just ran dmt_compress_kvspace so there is no fragmentation and also leafentries are in sorted order.
- paranoid_invariant(toku_mempool_get_frag_size(&m_buffer_mempool) == 0);
- uint32_t val_data_size = toku_mempool_get_used_size(&m_buffer_mempool);
- wbuf_nocrc_literal_bytes(wb, toku_mempool_get_base(&m_buffer_mempool), val_data_size);
+ toku_mempool_zero(&m_buffer_mempool);
+ m_buffer.create_no_array();
}
-// Deserialize from rbuf
-void bn_data::deserialize_from_rbuf(uint32_t num_entries, struct rbuf *rb, uint32_t data_size, uint32_t version) {
- uint32_t key_data_size = data_size; // overallocate if < version 26 (best guess that is guaranteed not too small)
- uint32_t val_data_size = data_size; // overallocate if < version 26 (best guess that is guaranteed not too small)
-
- bool all_keys_same_length = false;
- bool keys_vals_separate = false;
- uint32_t fixed_klpair_length = 0;
-
- // In version 25 and older there is no header. Skip reading header for old version.
- if (version >= FT_LAYOUT_VERSION_26) {
- uint32_t ndone_before = rb->ndone;
- key_data_size = rbuf_int(rb);
- val_data_size = rbuf_int(rb);
- fixed_klpair_length = rbuf_int(rb); // 0 if !all_keys_same_length
- all_keys_same_length = rbuf_char(rb);
- keys_vals_separate = rbuf_char(rb);
- invariant(all_keys_same_length == keys_vals_separate); // Until we support otherwise
- uint32_t header_size = rb->ndone - ndone_before;
- data_size -= header_size;
- invariant(header_size == HEADER_LENGTH);
- if (keys_vals_separate) {
- invariant(fixed_klpair_length >= sizeof(klpair_struct) || num_entries == 0);
- initialize_from_separate_keys_and_vals(num_entries, rb, data_size, version,
- key_data_size, val_data_size, all_keys_same_length,
- fixed_klpair_length);
- return;
- }
- }
- // Version >= 26 and version 25 deserialization are now identical except that <= 25 might allocate too much memory.
- bytevec bytes;
- rbuf_literal_bytes(rb, &bytes, data_size);
- const unsigned char *CAST_FROM_VOIDP(buf, bytes);
+void bn_data::initialize_from_data(uint32_t num_entries, unsigned char *buf, uint32_t data_size) {
if (data_size == 0) {
invariant_zero(num_entries);
}
- init_zero();
- klpair_dmt_t::builder dmt_builder;
- dmt_builder.create(num_entries, key_data_size);
-
- // TODO(leif): clean this up (#149)
- unsigned char *newmem = nullptr;
- // add 25% extra wiggle room
- uint32_t allocated_bytes_vals = val_data_size + (val_data_size / 4);
- CAST_FROM_VOIDP(newmem, toku_xmalloc(allocated_bytes_vals));
- const unsigned char* curr_src_pos = buf;
+ KLPAIR *XMALLOC_N(num_entries, array); // create array of pointers to leafentries
+ unsigned char *newmem = NULL;
+ // add same wiggle room that toku_mempool_construct would, 25% extra
+ uint32_t allocated_bytes = data_size + data_size/4;
+ CAST_FROM_VOIDP(newmem, toku_xmalloc(allocated_bytes));
+ unsigned char* curr_src_pos = buf;
unsigned char* curr_dest_pos = newmem;
for (uint32_t i = 0; i < num_entries; i++) {
+ KLPAIR curr_kl = (KLPAIR)curr_dest_pos;
+ array[i] = curr_kl;
+
uint8_t curr_type = curr_src_pos[0];
curr_src_pos++;
// first thing we do is lay out the key,
// to do so, we must extract it from the leafentry
// and write it in
uint32_t keylen = 0;
- const void* keyp = nullptr;
+ void* keyp = NULL;
keylen = *(uint32_t *)curr_src_pos;
curr_src_pos += sizeof(uint32_t);
uint32_t clean_vallen = 0;
@@ -301,10 +150,12 @@ void bn_data::deserialize_from_rbuf(uint32_t num_entries, struct rbuf *rb, uint3
keyp = curr_src_pos;
curr_src_pos += keylen;
}
- uint32_t le_offset = curr_dest_pos - newmem;
- dmt_builder.append(klpair_dmtwriter(keylen, le_offset, keyp));
- add_key(keylen);
-
+ // now that we have the keylen and the key, we can copy it
+ // into the destination
+ *(uint32_t *)curr_dest_pos = keylen;
+ curr_dest_pos += sizeof(keylen);
+ memcpy(curr_dest_pos, keyp, keylen);
+ curr_dest_pos += keylen;
// now curr_dest_pos is pointing to where the leafentry should be packed
curr_dest_pos[0] = curr_type;
curr_dest_pos++;
@@ -322,44 +173,31 @@ void bn_data::deserialize_from_rbuf(uint32_t num_entries, struct rbuf *rb, uint3
*(uint8_t *)curr_dest_pos = num_pxrs;
curr_dest_pos += sizeof(num_pxrs);
// now we need to pack the rest of the data
- uint32_t num_rest_bytes = leafentry_rest_memsize(num_pxrs, num_cxrs, const_cast<uint8_t*>(curr_src_pos));
+ uint32_t num_rest_bytes = leafentry_rest_memsize(num_pxrs, num_cxrs, curr_src_pos);
memcpy(curr_dest_pos, curr_src_pos, num_rest_bytes);
curr_dest_pos += num_rest_bytes;
curr_src_pos += num_rest_bytes;
}
}
- dmt_builder.build(&this->m_buffer);
- toku_note_deserialized_basement_node(m_buffer.value_length_is_fixed());
-
- uint32_t num_bytes_read = (uint32_t)(curr_src_pos - buf);
- invariant(num_bytes_read == data_size);
-
- uint32_t num_bytes_written = curr_dest_pos - newmem + m_disksize_of_keys;
- invariant(num_bytes_written == data_size);
- toku_mempool_init(&m_buffer_mempool, newmem, (size_t)(curr_dest_pos - newmem), allocated_bytes_vals);
-
- invariant(get_disk_size() == data_size);
- // Versions older than 26 might have allocated too much memory. Try to shrink the mempool now that we
- // know how much memory we need.
- if (version < FT_LAYOUT_VERSION_26) {
- // Unnecessary after version 26
- // Reallocate smaller mempool to save memory
- invariant_zero(toku_mempool_get_frag_size(&m_buffer_mempool));
- toku_mempool_realloc_larger(&m_buffer_mempool, toku_mempool_get_used_size(&m_buffer_mempool));
- }
+ uint32_t num_bytes_read UU() = (uint32_t)(curr_src_pos - buf);
+ paranoid_invariant( num_bytes_read == data_size);
+ uint32_t num_bytes_written = curr_dest_pos - newmem;
+ paranoid_invariant( num_bytes_written == data_size);
+ toku_mempool_init(&m_buffer_mempool, newmem, (size_t)(num_bytes_written), allocated_bytes);
+
+ // destroy old omt that was created by toku_create_empty_bn(), so we can create a new one
+ m_buffer.destroy();
+ m_buffer.create_steal_sorted_array(&array, num_entries, num_entries);
}
uint64_t bn_data::get_memory_size() {
uint64_t retval = 0;
- //TODO: Maybe ask for memory_size instead of mempool_footprint (either this todo or the next)
// include fragmentation overhead but do not include space in the
// mempool that has not yet been allocated for leaf entries
size_t poolsize = toku_mempool_footprint(&m_buffer_mempool);
+ invariant(poolsize >= get_disk_size());
retval += poolsize;
- // This one includes not-yet-allocated for nodes (just like old constant-key omt)
- //TODO: Maybe ask for mempool_footprint instead of memory_size.
retval += m_buffer.memory_size();
- invariant(retval >= get_disk_size());
return retval;
}
@@ -367,263 +205,169 @@ void bn_data::delete_leafentry (
uint32_t idx,
uint32_t keylen,
uint32_t old_le_size
- )
+ )
{
- remove_key(keylen);
m_buffer.delete_at(idx);
- toku_mempool_mfree(&m_buffer_mempool, nullptr, old_le_size);
+ toku_mempool_mfree(&m_buffer_mempool, 0, old_le_size + keylen + sizeof(keylen)); // Must pass 0, since le is no good any more.
}
/* mempool support */
-struct dmt_compressor_state {
+struct omt_compressor_state {
struct mempool *new_kvspace;
- class bn_data *bd;
+ KLPAIR *newvals;
};
-static int move_it (const uint32_t, klpair_struct *klpair, const uint32_t idx UU(), struct dmt_compressor_state * const oc) {
- LEAFENTRY old_le = oc->bd->get_le_from_klpair(klpair);
- uint32_t size = leafentry_memsize(old_le);
- void* newdata = toku_mempool_malloc(oc->new_kvspace, size, 1);
+static int move_it (const KLPAIR &klpair, const uint32_t idx, struct omt_compressor_state * const oc) {
+ uint32_t size = klpair_size(klpair);
+ KLPAIR CAST_FROM_VOIDP(newdata, toku_mempool_malloc(oc->new_kvspace, size, 1));
paranoid_invariant_notnull(newdata); // we do this on a fresh mempool, so nothing bad should happen
- memcpy(newdata, old_le, size);
- klpair->le_offset = toku_mempool_get_offset_from_pointer_and_base(oc->new_kvspace, newdata);
+ memcpy(newdata, klpair, size);
+ oc->newvals[idx] = newdata;
return 0;
}
-// Compress things, and grow or shrink the mempool if needed.
-// May (always if force_compress) have a side effect of putting contents of mempool in sorted order.
-void bn_data::dmt_compress_kvspace(size_t added_size, void **maybe_free, bool force_compress) {
- uint32_t total_size_needed = toku_mempool_get_used_size(&m_buffer_mempool) + added_size;
+// Compress things, and grow the mempool if needed.
+void bn_data::omt_compress_kvspace(size_t added_size, void **maybe_free) {
+ uint32_t total_size_needed = toku_mempool_get_used_space(&m_buffer_mempool) + added_size;
+ // set the new mempool size to be twice of the space we actually need.
+ // On top of the 25% that is padded within toku_mempool_construct (which we
+ // should consider getting rid of), that should be good enough.
+ struct mempool new_kvspace;
+ toku_mempool_construct(&new_kvspace, 2*total_size_needed);
+ uint32_t numvals = omt_size();
+ KLPAIR *XMALLOC_N(numvals, newvals);
+ struct omt_compressor_state oc = { &new_kvspace, newvals };
- // If there is no fragmentation, e.g. in serial inserts, we can just increase the size
- // of the mempool and move things over with a cheap memcpy. If force_compress is true,
- // the caller needs the side effect that all contents are put in sorted order.
- bool do_compress = toku_mempool_get_frag_size(&m_buffer_mempool) > 0 || force_compress;
+ m_buffer.iterate_on_range< decltype(oc), move_it >(0, omt_size(), &oc);
- void *old_mempool_base = toku_mempool_get_base(&m_buffer_mempool);
- struct mempool new_kvspace;
- if (do_compress) {
- size_t requested_size = force_compress ? total_size_needed : ((total_size_needed * 3) / 2);
- toku_mempool_construct(&new_kvspace, requested_size);
- struct dmt_compressor_state oc = { &new_kvspace, this };
- m_buffer.iterate_ptr< decltype(oc), move_it >(&oc);
- } else {
- toku_mempool_construct(&new_kvspace, total_size_needed);
- size_t old_offset_limit = toku_mempool_get_offset_limit(&m_buffer_mempool);
- void *new_mempool_base = toku_mempool_malloc(&new_kvspace, old_offset_limit, 1);
- memcpy(new_mempool_base, old_mempool_base, old_offset_limit);
- }
+ m_buffer.destroy();
+ m_buffer.create_steal_sorted_array(&newvals, numvals, numvals);
if (maybe_free) {
- *maybe_free = old_mempool_base;
+ *maybe_free = m_buffer_mempool.base;
} else {
- toku_free(old_mempool_base);
+ toku_free(m_buffer_mempool.base);
}
m_buffer_mempool = new_kvspace;
}
// Effect: Allocate a new object of size SIZE in MP. If MP runs out of space, allocate new a new mempool space, and copy all the items
// from the OMT (which items refer to items in the old mempool) into the new mempool.
-// If MAYBE_FREE is nullptr then free the old mempool's space.
+// If MAYBE_FREE is NULL then free the old mempool's space.
// Otherwise, store the old mempool's space in maybe_free.
-LEAFENTRY bn_data::mempool_malloc_and_update_dmt(size_t size, void **maybe_free) {
+KLPAIR bn_data::mempool_malloc_from_omt(size_t size, void **maybe_free) {
void *v = toku_mempool_malloc(&m_buffer_mempool, size, 1);
- if (v == nullptr) {
- dmt_compress_kvspace(size, maybe_free, false);
+ if (v == NULL) {
+ omt_compress_kvspace(size, maybe_free);
v = toku_mempool_malloc(&m_buffer_mempool, size, 1);
paranoid_invariant_notnull(v);
}
- return (LEAFENTRY)v;
+ return (KLPAIR)v;
}
+//TODO: probably not free the "maybe_free" right away?
void bn_data::get_space_for_overwrite(
uint32_t idx,
- const void* keyp UU(),
- uint32_t keylen UU(),
+ const void* keyp,
+ uint32_t keylen,
uint32_t old_le_size,
uint32_t new_size,
- LEAFENTRY* new_le_space,
- void **const maybe_free
+ LEAFENTRY* new_le_space
)
{
- *maybe_free = nullptr;
- LEAFENTRY new_le = mempool_malloc_and_update_dmt(new_size, maybe_free);
- toku_mempool_mfree(&m_buffer_mempool, nullptr, old_le_size);
- klpair_struct* klp = nullptr;
- uint32_t klpair_len;
- int r = m_buffer.fetch(idx, &klpair_len, &klp);
- invariant_zero(r);
- paranoid_invariant(klp!=nullptr);
- // Key never changes.
- paranoid_invariant(keylen_from_klpair_len(klpair_len) == keylen);
-
- size_t new_le_offset = toku_mempool_get_offset_from_pointer_and_base(&this->m_buffer_mempool, new_le);
- paranoid_invariant(new_le_offset <= UINT32_MAX - new_size); // Not using > 4GB
- klp->le_offset = new_le_offset;
-
- paranoid_invariant(new_le == get_le_from_klpair(klp));
- *new_le_space = new_le;
+ void* maybe_free = nullptr;
+ uint32_t size_alloc = new_size + keylen + sizeof(keylen);
+ KLPAIR new_kl = mempool_malloc_from_omt(
+ size_alloc,
+ &maybe_free
+ );
+ uint32_t size_freed = old_le_size + keylen + sizeof(keylen);
+ toku_mempool_mfree(&m_buffer_mempool, nullptr, size_freed); // Must pass nullptr, since le is no good any more.
+ new_kl->keylen = keylen;
+ memcpy(new_kl->key_le, keyp, keylen);
+ m_buffer.set_at(new_kl, idx);
+ *new_le_space = get_le_from_klpair(new_kl);
+ // free at end, so that the keyp and keylen
+ // passed in is still valid
+ if (maybe_free) {
+ toku_free(maybe_free);
+ }
}
+//TODO: probably not free the "maybe_free" right away?
void bn_data::get_space_for_insert(
uint32_t idx,
const void* keyp,
uint32_t keylen,
size_t size,
- LEAFENTRY* new_le_space,
- void **const maybe_free
+ LEAFENTRY* new_le_space
)
{
- add_key(keylen);
-
- *maybe_free = nullptr;
- LEAFENTRY new_le = mempool_malloc_and_update_dmt(size, maybe_free);
- size_t new_le_offset = toku_mempool_get_offset_from_pointer_and_base(&this->m_buffer_mempool, new_le);
-
- klpair_dmtwriter kl(keylen, new_le_offset, keyp);
- m_buffer.insert_at(kl, idx);
-
- *new_le_space = new_le;
-}
-
-class split_klpairs_extra {
- bn_data *const m_left_bn;
- bn_data *const m_right_bn;
- klpair_dmt_t::builder *const m_left_builder;
- klpair_dmt_t::builder *const m_right_builder;
- struct mempool *const m_left_dest_mp;
- uint32_t m_split_at;
-
- struct mempool *left_dest_mp(void) const { return m_left_dest_mp; }
- struct mempool *right_dest_mp(void) const { return &m_right_bn->m_buffer_mempool; }
-
- void copy_klpair(const uint32_t klpair_len, const klpair_struct &klpair,
- klpair_dmt_t::builder *const builder,
- struct mempool *const dest_mp,
- bn_data *const bn) {
- LEAFENTRY old_le = m_left_bn->get_le_from_klpair(&klpair);
- size_t le_size = leafentry_memsize(old_le);
-
- void *new_le = toku_mempool_malloc(dest_mp, le_size, 1);
- paranoid_invariant_notnull(new_le);
- memcpy(new_le, old_le, le_size);
- size_t le_offset = toku_mempool_get_offset_from_pointer_and_base(dest_mp, new_le);
- size_t keylen = keylen_from_klpair_len(klpair_len);
- builder->append(klpair_dmtwriter(keylen, le_offset, klpair.key));
-
- bn->add_key(keylen);
- }
-
- int move_leafentry(const uint32_t klpair_len, const klpair_struct &klpair, const uint32_t idx) {
- m_left_bn->remove_key(keylen_from_klpair_len(klpair_len));
-
- if (idx < m_split_at) {
- copy_klpair(klpair_len, klpair, m_left_builder, left_dest_mp(), m_left_bn);
- } else {
- copy_klpair(klpair_len, klpair, m_right_builder, right_dest_mp(), m_right_bn);
- }
- return 0;
- }
-
- public:
- split_klpairs_extra(bn_data *const left_bn, bn_data *const right_bn,
- klpair_dmt_t::builder *const left_builder,
- klpair_dmt_t::builder *const right_builder,
- struct mempool *const left_new_mp,
- uint32_t split_at)
- : m_left_bn(left_bn),
- m_right_bn(right_bn),
- m_left_builder(left_builder),
- m_right_builder(right_builder),
- m_left_dest_mp(left_new_mp),
- m_split_at(split_at) {}
- static int cb(const uint32_t klpair_len, const klpair_struct &klpair, const uint32_t idx, split_klpairs_extra *const thisp) {
- return thisp->move_leafentry(klpair_len, klpair, idx);
+ void* maybe_free = nullptr;
+ uint32_t size_alloc = size + keylen + sizeof(keylen);
+ KLPAIR new_kl = mempool_malloc_from_omt(
+ size_alloc,
+ &maybe_free
+ );
+ new_kl->keylen = keylen;
+ memcpy(new_kl->key_le, keyp, keylen);
+ m_buffer.insert_at(new_kl, idx);
+ *new_le_space = get_le_from_klpair(new_kl);
+ // free at end, so that the keyp and keylen
+ // passed in is still valid (you never know if
+ // it was part of the old mempool, this is just
+ // safer).
+ if (maybe_free) {
+ toku_free(maybe_free);
}
-};
+}
-void bn_data::split_klpairs(
- bn_data* right_bd,
- uint32_t split_at //lower bound inclusive for right_bd
+void bn_data::move_leafentries_to(
+ BN_DATA dest_bd,
+ uint32_t lbi, //lower bound inclusive
+ uint32_t ube //upper bound exclusive
)
+//Effect: move leafentries in the range [lbi, ube) from this to src_omt to newly created dest_omt
{
- // We use move_leafentries_to during a split, and the split algorithm should never call this
- // if it's splitting on a boundary, so there must be some leafentries in the range to move.
- paranoid_invariant(split_at < num_klpairs());
-
- right_bd->init_zero();
-
- size_t mpsize = toku_mempool_get_used_size(&m_buffer_mempool); // overkill, but safe
-
- struct mempool new_left_mp;
- toku_mempool_construct(&new_left_mp, mpsize);
-
- struct mempool *right_mp = &right_bd->m_buffer_mempool;
- toku_mempool_construct(right_mp, mpsize);
-
- klpair_dmt_t::builder left_dmt_builder;
- left_dmt_builder.create(split_at, m_disksize_of_keys); // overkill, but safe (builder will realloc at the end)
-
- klpair_dmt_t::builder right_dmt_builder;
- right_dmt_builder.create(num_klpairs() - split_at, m_disksize_of_keys); // overkill, but safe (builder will realloc at the end)
-
- split_klpairs_extra extra(this, right_bd, &left_dmt_builder, &right_dmt_builder, &new_left_mp, split_at);
-
- int r = m_buffer.iterate<split_klpairs_extra, split_klpairs_extra::cb>(&extra);
- invariant_zero(r);
-
- m_buffer.destroy();
- toku_mempool_destroy(&m_buffer_mempool);
-
- m_buffer_mempool = new_left_mp;
-
- left_dmt_builder.build(&m_buffer);
- right_dmt_builder.build(&right_bd->m_buffer);
+ paranoid_invariant(lbi < ube);
+ paranoid_invariant(ube <= omt_size());
+ KLPAIR *XMALLOC_N(ube-lbi, newklpointers); // create new omt
+
+ size_t mpsize = toku_mempool_get_used_space(&m_buffer_mempool); // overkill, but safe
+ struct mempool *dest_mp = &dest_bd->m_buffer_mempool;
+ struct mempool *src_mp = &m_buffer_mempool;
+ toku_mempool_construct(dest_mp, mpsize);
+
+ uint32_t i = 0;
+ for (i = lbi; i < ube; i++) {
+ KLPAIR curr_kl= 0;
+ m_buffer.fetch(i, &curr_kl);
+
+ size_t kl_size = klpair_size(curr_kl);
+ KLPAIR new_kl = NULL;
+ CAST_FROM_VOIDP(new_kl, toku_mempool_malloc(dest_mp, kl_size, 1));
+ memcpy(new_kl, curr_kl, kl_size);
+ newklpointers[i-lbi] = new_kl;
+ toku_mempool_mfree(src_mp, curr_kl, kl_size);
+ }
- // Potentially shrink memory pool for destination.
- // We overallocated ("overkill") above
- struct mempool *const left_mp = &m_buffer_mempool;
- paranoid_invariant_zero(toku_mempool_get_frag_size(left_mp));
- toku_mempool_realloc_larger(left_mp, toku_mempool_get_used_size(left_mp));
- paranoid_invariant_zero(toku_mempool_get_frag_size(right_mp));
- toku_mempool_realloc_larger(right_mp, toku_mempool_get_used_size(right_mp));
+ dest_bd->m_buffer.create_steal_sorted_array(&newklpointers, ube-lbi, ube-lbi);
+ // now remove the elements from src_omt
+ for (i=ube-1; i >= lbi; i--) {
+ m_buffer.delete_at(i);
+ }
}
uint64_t bn_data::get_disk_size() {
- return m_disksize_of_keys +
- toku_mempool_get_used_size(&m_buffer_mempool);
-}
-
-struct verify_le_in_mempool_state {
- size_t offset_limit;
- class bn_data *bd;
-};
-
-static int verify_le_in_mempool (const uint32_t, klpair_struct *klpair, const uint32_t idx UU(), struct verify_le_in_mempool_state * const state) {
- invariant(klpair->le_offset < state->offset_limit);
-
- LEAFENTRY le = state->bd->get_le_from_klpair(klpair);
- uint32_t size = leafentry_memsize(le);
-
- size_t end_offset = klpair->le_offset+size;
-
- invariant(end_offset <= state->offset_limit);
- return 0;
+ return toku_mempool_get_used_space(&m_buffer_mempool);
}
-//This is a debug-only (paranoid) verification.
-//Verifies the dmt is valid, and all leafentries are entirely in the mempool's memory.
void bn_data::verify_mempool(void) {
- //Verify the dmt itself <- paranoid and slow
- m_buffer.verify();
-
- verify_le_in_mempool_state state = { .offset_limit = toku_mempool_get_offset_limit(&m_buffer_mempool), .bd = this };
- //Verify every leafentry pointed to by the keys in the dmt are fully inside the mempool
- m_buffer.iterate_ptr< decltype(state), verify_le_in_mempool >(&state);
+ // TODO: implement something
}
-uint32_t bn_data::num_klpairs(void) const {
+uint32_t bn_data::omt_size(void) const {
return m_buffer.size();
}
@@ -631,54 +375,40 @@ void bn_data::destroy(void) {
// The buffer may have been freed already, in some cases.
m_buffer.destroy();
toku_mempool_destroy(&m_buffer_mempool);
- m_disksize_of_keys = 0;
}
-void bn_data::set_contents_as_clone_of_sorted_array(
+//TODO: Splitting key/val requires changing this
+void bn_data::replace_contents_with_clone_of_sorted_array(
uint32_t num_les,
const void** old_key_ptrs,
uint32_t* old_keylens,
- LEAFENTRY* old_les,
- size_t *le_sizes,
- size_t total_key_size,
- size_t total_le_size
- )
+ LEAFENTRY* old_les,
+ size_t *le_sizes,
+ size_t mempool_size
+ )
{
- //Enforce "just created" invariant.
- paranoid_invariant_zero(m_disksize_of_keys);
- paranoid_invariant_zero(num_klpairs());
- paranoid_invariant_null(toku_mempool_get_base(&m_buffer_mempool));
- paranoid_invariant_zero(toku_mempool_get_size(&m_buffer_mempool));
-
- toku_mempool_construct(&m_buffer_mempool, total_le_size);
- m_buffer.destroy();
- m_disksize_of_keys = 0;
-
- klpair_dmt_t::builder dmt_builder;
- dmt_builder.create(num_les, total_key_size);
-
+ toku_mempool_construct(&m_buffer_mempool, mempool_size);
+ KLPAIR *XMALLOC_N(num_les, le_array);
for (uint32_t idx = 0; idx < num_les; idx++) {
- void* new_le = toku_mempool_malloc(&m_buffer_mempool, le_sizes[idx], 1);
- paranoid_invariant_notnull(new_le);
- memcpy(new_le, old_les[idx], le_sizes[idx]);
- size_t le_offset = toku_mempool_get_offset_from_pointer_and_base(&m_buffer_mempool, new_le);
- dmt_builder.append(klpair_dmtwriter(old_keylens[idx], le_offset, old_key_ptrs[idx]));
- add_key(old_keylens[idx]);
+ KLPAIR new_kl = (KLPAIR)toku_mempool_malloc(
+ &m_buffer_mempool,
+ le_sizes[idx] + old_keylens[idx] + sizeof(uint32_t),
+ 1); // point to new location
+ new_kl->keylen = old_keylens[idx];
+ memcpy(new_kl->key_le, old_key_ptrs[idx], new_kl->keylen);
+ memcpy(get_le_from_klpair(new_kl), old_les[idx], le_sizes[idx]);
+ CAST_FROM_VOIDP(le_array[idx], new_kl);
}
- dmt_builder.build(&this->m_buffer);
-}
-
-LEAFENTRY bn_data::get_le_from_klpair(const klpair_struct *klpair) const {
- void * ptr = toku_mempool_get_pointer_from_base_and_offset(&this->m_buffer_mempool, klpair->le_offset);
- LEAFENTRY CAST_FROM_VOIDP(le, ptr);
- return le;
+ //TODO: Splitting key/val requires changing this; keys are stored in old omt.. cannot delete it yet?
+ m_buffer.destroy();
+ m_buffer.create_steal_sorted_array(&le_array, num_les, num_les);
}
// get info about a single leafentry by index
int bn_data::fetch_le(uint32_t idx, LEAFENTRY *le) {
- klpair_struct* klpair = nullptr;
- int r = m_buffer.fetch(idx, nullptr, &klpair);
+ KLPAIR klpair = NULL;
+ int r = m_buffer.fetch(idx, &klpair);
if (r == 0) {
*le = get_le_from_klpair(klpair);
}
@@ -686,41 +416,59 @@ int bn_data::fetch_le(uint32_t idx, LEAFENTRY *le) {
}
int bn_data::fetch_klpair(uint32_t idx, LEAFENTRY *le, uint32_t *len, void** key) {
- klpair_struct* klpair = nullptr;
- uint32_t klpair_len;
- int r = m_buffer.fetch(idx, &klpair_len, &klpair);
+ KLPAIR klpair = NULL;
+ int r = m_buffer.fetch(idx, &klpair);
if (r == 0) {
- *len = keylen_from_klpair_len(klpair_len);
- *key = klpair->key;
+ *len = klpair->keylen;
+ *key = klpair->key_le;
*le = get_le_from_klpair(klpair);
}
return r;
}
int bn_data::fetch_klpair_disksize(uint32_t idx, size_t *size) {
- klpair_struct* klpair = nullptr;
- uint32_t klpair_len;
- int r = m_buffer.fetch(idx, &klpair_len, &klpair);
+ KLPAIR klpair = NULL;
+ int r = m_buffer.fetch(idx, &klpair);
if (r == 0) {
- *size = klpair_disksize(klpair_len, klpair);
+ *size = klpair_disksize(klpair);
}
return r;
}
-int bn_data::fetch_key_and_len(uint32_t idx, uint32_t *len, void** key) {
- klpair_struct* klpair = nullptr;
- uint32_t klpair_len;
- int r = m_buffer.fetch(idx, &klpair_len, &klpair);
+int bn_data::fetch_le_key_and_len(uint32_t idx, uint32_t *len, void** key) {
+ KLPAIR klpair = NULL;
+ int r = m_buffer.fetch(idx, &klpair);
if (r == 0) {
- *len = keylen_from_klpair_len(klpair_len);
- *key = klpair->key;
+ *len = klpair->keylen;
+ *key = klpair->key_le;
}
return r;
}
+
+struct mp_pair {
+ void* orig_base;
+ void* new_base;
+ klpair_omt_t* omt;
+};
+
+static int fix_mp_offset(const KLPAIR &klpair, const uint32_t idx, struct mp_pair * const p) {
+ char* old_value = (char *) klpair;
+ char *new_value = old_value - (char *)p->orig_base + (char *)p->new_base;
+ p->omt->set_at((KLPAIR)new_value, idx);
+ return 0;
+}
+
void bn_data::clone(bn_data* orig_bn_data) {
toku_mempool_clone(&orig_bn_data->m_buffer_mempool, &m_buffer_mempool);
m_buffer.clone(orig_bn_data->m_buffer);
- this->m_disksize_of_keys = orig_bn_data->m_disksize_of_keys;
+ struct mp_pair p;
+ p.orig_base = toku_mempool_get_base(&orig_bn_data->m_buffer_mempool);
+ p.new_base = toku_mempool_get_base(&m_buffer_mempool);
+ p.omt = &m_buffer;
+
+ int r = m_buffer.iterate_on_range<decltype(p), fix_mp_offset>(0, omt_size(), &p);
+ invariant_zero(r);
}
+
diff --git a/storage/tokudb/ft-index/ft/bndata.h b/storage/tokudb/ft-index/ft/bndata.h
index 79daf1e5bf0..37e80c32967 100644
--- a/storage/tokudb/ft-index/ft/bndata.h
+++ b/storage/tokudb/ft-index/ft/bndata.h
@@ -91,296 +91,166 @@ PATENT RIGHTS GRANT:
#pragma once
-#include <util/mempool.h>
-#include "wbuf.h"
-#include <util/dmt.h>
+#include <util/omt.h>
#include "leafentry.h"
+#include <util/mempool.h>
+
+#if 0 //for implementation
+static int
+UU() verify_in_mempool(OMTVALUE lev, uint32_t UU(idx), void *mpv)
+{
+ LEAFENTRY CAST_FROM_VOIDP(le, lev);
+ struct mempool *CAST_FROM_VOIDP(mp, mpv);
+ int r = toku_mempool_inrange(mp, le, leafentry_memsize(le));
+ lazy_assert(r);
+ return 0;
+}
+ toku_omt_iterate(bn->buffer, verify_in_mempool, &bn->buffer_mempool);
+
+#endif
-// Key/leafentry pair stored in a dmt. The key is inlined, the offset (in leafentry mempool) is stored for the leafentry.
struct klpair_struct {
- uint32_t le_offset; //Offset of leafentry (in leafentry mempool)
- uint8_t key[0]; // key, followed by le
+ uint32_t keylen;
+ uint8_t key_le[0]; // key, followed by le
};
-static constexpr uint32_t keylen_from_klpair_len(const uint32_t klpair_len) {
- return klpair_len - __builtin_offsetof(klpair_struct, key);
-}
-
+typedef struct klpair_struct *KLPAIR;
-static_assert(__builtin_offsetof(klpair_struct, key) == 1*sizeof(uint32_t), "klpair alignment issues");
-static_assert(__builtin_offsetof(klpair_struct, key) == sizeof(klpair_struct), "klpair size issues");
+static inline LEAFENTRY get_le_from_klpair(KLPAIR klpair){
+ uint32_t keylen = klpair->keylen;
+ LEAFENTRY le = (LEAFENTRY)(klpair->key_le + keylen);
+ return le;
+}
-// A wrapper for the heaviside function provided to dmt->find*.
-// Needed because the heaviside functions provided to bndata do not know about the internal types.
-// Alternative to this wrapper is to expose accessor functions and rewrite all the external heaviside functions.
-template<typename dmtcmp_t,
- int (*h)(const DBT &, const dmtcmp_t &)>
-static int klpair_find_wrapper(const uint32_t klpair_len, const klpair_struct &klpair, const dmtcmp_t &extra) {
+template<typename omtcmp_t,
+ int (*h)(const DBT &, const omtcmp_t &)>
+static int wrappy_fun_find(const KLPAIR &klpair, const omtcmp_t &extra) {
+ //TODO: kill this function when we split, and/or use toku_fill_dbt
DBT kdbt;
- kdbt.data = const_cast<void*>(reinterpret_cast<const void*>(klpair.key));
- kdbt.size = keylen_from_klpair_len(klpair_len);
+ kdbt.data = klpair->key_le;
+ kdbt.size = klpair->keylen;
return h(kdbt, extra);
}
-template<typename inner_iterate_extra_t>
-struct klpair_iterate_extra {
- public:
- inner_iterate_extra_t *inner;
- const class bn_data * bd;
-};
-
-// A wrapper for the high-order function provided to dmt->iterate*
-// Needed because the heaviside functions provided to bndata do not know about the internal types.
-// Alternative to this wrapper is to expose accessor functions and rewrite all the external heaviside functions.
template<typename iterate_extra_t,
- int (*f)(const void * key, const uint32_t keylen, const LEAFENTRY &, const uint32_t idx, iterate_extra_t *const)>
-static int klpair_iterate_wrapper(const uint32_t klpair_len, const klpair_struct &klpair, const uint32_t idx, klpair_iterate_extra<iterate_extra_t> *const extra) {
- const void* key = &klpair.key;
- LEAFENTRY le = extra->bd->get_le_from_klpair(&klpair);
- return f(key, keylen_from_klpair_len(klpair_len), le, idx, extra->inner);
-}
-
-
-namespace toku {
-// dmt writer for klpair_struct
-class klpair_dmtwriter {
- public:
- // Return the size needed for the klpair_struct that this dmtwriter represents
- size_t get_size(void) const {
- return sizeof(klpair_struct) + this->keylen;
- }
- // Write the klpair_struct this dmtwriter represents to a destination
- void write_to(klpair_struct *const dest) const {
- dest->le_offset = this->le_offset;
- memcpy(dest->key, this->keyp, this->keylen);
- }
-
- klpair_dmtwriter(uint32_t _keylen, uint32_t _le_offset, const void* _keyp)
- : keylen(_keylen), le_offset(_le_offset), keyp(_keyp) {}
- klpair_dmtwriter(const uint32_t klpair_len, klpair_struct *const src)
- : keylen(keylen_from_klpair_len(klpair_len)), le_offset(src->le_offset), keyp(src->key) {}
- private:
- const uint32_t keylen;
- const uint32_t le_offset;
- const void* keyp;
-};
+ int (*h)(const void * key, const uint32_t keylen, const LEAFENTRY &, const uint32_t idx, iterate_extra_t *const)>
+static int wrappy_fun_iterate(const KLPAIR &klpair, const uint32_t idx, iterate_extra_t *const extra) {
+ uint32_t keylen = klpair->keylen;
+ void* key = klpair->key_le;
+ LEAFENTRY le = get_le_from_klpair(klpair);
+ return h(key, keylen, le, idx, extra);
}
-typedef toku::dmt<klpair_struct, klpair_struct*, toku::klpair_dmtwriter> klpair_dmt_t;
+typedef toku::omt<KLPAIR> klpair_omt_t;
// This class stores the data associated with a basement node
class bn_data {
public:
- // Initialize an empty bn_data _without_ a dmt backing.
- // Externally only used for deserialization.
void init_zero(void);
-
- // Initialize an empty bn_data _with_ a dmt
void initialize_empty(void);
-
- // Deserialize a bn_data from rbuf.
- // This is the entry point for deserialization.
- void deserialize_from_rbuf(uint32_t num_entries, struct rbuf *rb, uint32_t data_size, uint32_t version);
-
- // Retrieve the memory footprint of this basement node.
- // May over or under count: see Tokutek/ft-index#136
- // Also see dmt's implementation.
+ void initialize_from_data(uint32_t num_entries, unsigned char *buf, uint32_t data_size);
+ // globals
uint64_t get_memory_size(void);
-
- // Get the serialized size of this basement node.
uint64_t get_disk_size(void);
-
- // Perform (paranoid) verification that all leafentries are fully contained within the mempool
void verify_mempool(void);
- // size() of key dmt
- uint32_t num_klpairs(void) const;
+ // Interact with "omt"
+ uint32_t omt_size(void) const;
- // iterate() on key dmt (and associated leafentries)
template<typename iterate_extra_t,
int (*f)(const void * key, const uint32_t keylen, const LEAFENTRY &, const uint32_t, iterate_extra_t *const)>
- int iterate(iterate_extra_t *const iterate_extra) const {
- return iterate_on_range<iterate_extra_t, f>(0, num_klpairs(), iterate_extra);
+ int omt_iterate(iterate_extra_t *const iterate_extra) const {
+ return omt_iterate_on_range<iterate_extra_t, f>(0, omt_size(), iterate_extra);
}
- // iterate_on_range() on key dmt (and associated leafentries)
template<typename iterate_extra_t,
int (*f)(const void * key, const uint32_t keylen, const LEAFENTRY &, const uint32_t, iterate_extra_t *const)>
- int iterate_on_range(const uint32_t left, const uint32_t right, iterate_extra_t *const iterate_extra) const {
- klpair_iterate_extra<iterate_extra_t> klpair_extra = { iterate_extra, this };
- return m_buffer.iterate_on_range< klpair_iterate_extra<iterate_extra_t>, klpair_iterate_wrapper<iterate_extra_t, f> >(left, right, &klpair_extra);
+ int omt_iterate_on_range(const uint32_t left, const uint32_t right, iterate_extra_t *const iterate_extra) const {
+ return m_buffer.iterate_on_range< iterate_extra_t, wrappy_fun_iterate<iterate_extra_t, f> >(left, right, iterate_extra);
}
- // find_zero() on key dmt
- template<typename dmtcmp_t,
- int (*h)(const DBT &, const dmtcmp_t &)>
- int find_zero(const dmtcmp_t &extra, LEAFENTRY *const value, void** key, uint32_t* keylen, uint32_t *const idxp) const {
- klpair_struct* klpair = nullptr;
- uint32_t klpair_len;
- int r = m_buffer.find_zero< dmtcmp_t, klpair_find_wrapper<dmtcmp_t, h> >(extra, &klpair_len, &klpair, idxp);
+ template<typename omtcmp_t,
+ int (*h)(const DBT &, const omtcmp_t &)>
+ int find_zero(const omtcmp_t &extra, LEAFENTRY *const value, void** key, uint32_t* keylen, uint32_t *const idxp) const {
+ KLPAIR klpair = NULL;
+ int r = m_buffer.find_zero< omtcmp_t, wrappy_fun_find<omtcmp_t, h> >(extra, &klpair, idxp);
if (r == 0) {
if (value) {
*value = get_le_from_klpair(klpair);
}
if (key) {
- paranoid_invariant_notnull(keylen);
- *key = klpair->key;
- *keylen = keylen_from_klpair_len(klpair_len);
+ paranoid_invariant(keylen != NULL);
+ *key = klpair->key_le;
+ *keylen = klpair->keylen;
}
else {
- paranoid_invariant_null(keylen);
+ paranoid_invariant(keylen == NULL);
}
}
return r;
}
- // find() on key dmt (and associated leafentries)
- template<typename dmtcmp_t,
- int (*h)(const DBT &, const dmtcmp_t &)>
- int find(const dmtcmp_t &extra, int direction, LEAFENTRY *const value, void** key, uint32_t* keylen, uint32_t *const idxp) const {
- klpair_struct* klpair = nullptr;
- uint32_t klpair_len;
- int r = m_buffer.find< dmtcmp_t, klpair_find_wrapper<dmtcmp_t, h> >(extra, direction, &klpair_len, &klpair, idxp);
+ template<typename omtcmp_t,
+ int (*h)(const DBT &, const omtcmp_t &)>
+ int find(const omtcmp_t &extra, int direction, LEAFENTRY *const value, void** key, uint32_t* keylen, uint32_t *const idxp) const {
+ KLPAIR klpair = NULL;
+ int r = m_buffer.find< omtcmp_t, wrappy_fun_find<omtcmp_t, h> >(extra, direction, &klpair, idxp);
if (r == 0) {
if (value) {
*value = get_le_from_klpair(klpair);
}
if (key) {
- paranoid_invariant_notnull(keylen);
- *key = klpair->key;
- *keylen = keylen_from_klpair_len(klpair_len);
+ paranoid_invariant(keylen != NULL);
+ *key = klpair->key_le;
+ *keylen = klpair->keylen;
}
else {
- paranoid_invariant_null(keylen);
+ paranoid_invariant(keylen == NULL);
}
}
return r;
}
- // Fetch leafentry by index
- __attribute__((__nonnull__))
+ // get info about a single leafentry by index
int fetch_le(uint32_t idx, LEAFENTRY *le);
- // Fetch (leafentry, key, keylen) by index
- __attribute__((__nonnull__))
int fetch_klpair(uint32_t idx, LEAFENTRY *le, uint32_t *len, void** key);
- // Fetch (serialized size of leafentry, key, and keylen) by index
- __attribute__((__nonnull__))
int fetch_klpair_disksize(uint32_t idx, size_t *size);
- // Fetch (key, keylen) by index
- __attribute__((__nonnull__))
- int fetch_key_and_len(uint32_t idx, uint32_t *len, void** key);
+ int fetch_le_key_and_len(uint32_t idx, uint32_t *len, void** key);
- // Move leafentries (and associated key/keylens) from this basement node to dest_bd
- // Moves indexes [lbi-ube)
- __attribute__((__nonnull__))
- void split_klpairs(bn_data* dest_bd, uint32_t first_index_for_dest);
+ // Interact with another bn_data
+ void move_leafentries_to(BN_DATA dest_bd,
+ uint32_t lbi, //lower bound inclusive
+ uint32_t ube //upper bound exclusive
+ );
- // Destroy this basement node and free memory.
void destroy(void);
- // Uses sorted array as input for this basement node.
- // Expects this to be a basement node just initialized with initialize_empty()
- void set_contents_as_clone_of_sorted_array(
+ // Replaces contents, into brand new mempool.
+ // Returns old mempool base, expects caller to free it.
+ void replace_contents_with_clone_of_sorted_array(
uint32_t num_les,
const void** old_key_ptrs,
uint32_t* old_keylens,
LEAFENTRY* old_les,
size_t *le_sizes,
- size_t total_key_size,
- size_t total_le_size
+ size_t mempool_size
);
- // Make this basement node a clone of orig_bn_data.
- // orig_bn_data still owns all its memory (dmt, mempool)
- // this basement node will have a new dmt, mempool containing same data.
void clone(bn_data* orig_bn_data);
-
- // Delete klpair index idx with provided keylen and old leafentry with size old_le_size
void delete_leafentry (
uint32_t idx,
uint32_t keylen,
uint32_t old_le_size
);
-
- // Allocates space in the mempool to store a new leafentry.
- // This may require reorganizing the mempool and updating the dmt.
- __attribute__((__nonnull__))
- void get_space_for_overwrite(uint32_t idx, const void* keyp, uint32_t keylen, uint32_t old_size, uint32_t new_size, LEAFENTRY* new_le_space, void **const maybe_free);
-
- // Allocates space in the mempool to store a new leafentry
- // and inserts a new key into the dmt
- // This may require reorganizing the mempool and updating the dmt.
- __attribute__((__nonnull__))
- void get_space_for_insert(uint32_t idx, const void* keyp, uint32_t keylen, size_t size, LEAFENTRY* new_le_space, void **const maybe_free);
-
- // Gets a leafentry given a klpair from this basement node.
- LEAFENTRY get_le_from_klpair(const klpair_struct *klpair) const;
-
- void serialize_to_wbuf(struct wbuf *const wb);
-
- // Prepares this basement node for serialization.
- // Must be called before serializing this basement node.
- // Between calling prepare_to_serialize and actually serializing, the basement node may not be modified
- void prepare_to_serialize(void);
-
- // Serialize the basement node header to a wbuf
- // Requires prepare_to_serialize() to have been called first.
- void serialize_header(struct wbuf *wb) const;
-
- // Serialize all keys and leafentries to a wbuf
- // Requires prepare_to_serialize() (and serialize_header()) has been called first.
- // Currently only supported when all keys are fixed-length.
- void serialize_rest(struct wbuf *wb) const;
-
- static const uint32_t HEADER_LENGTH = 0
- + sizeof(uint32_t) // key_data_size
- + sizeof(uint32_t) // val_data_size
- + sizeof(uint32_t) // fixed_key_length
- + sizeof(uint8_t) // all_keys_same_length
- + sizeof(uint8_t) // keys_vals_separate
- + 0;
+ void get_space_for_overwrite(uint32_t idx, const void* keyp, uint32_t keylen, uint32_t old_size, uint32_t new_size, LEAFENTRY* new_le_space);
+ void get_space_for_insert(uint32_t idx, const void* keyp, uint32_t keylen, size_t size, LEAFENTRY* new_le_space);
private:
+ // Private functions
+ KLPAIR mempool_malloc_from_omt(size_t size, void **maybe_free);
+ void omt_compress_kvspace(size_t added_size, void **maybe_free);
- // split_klpairs_extra should be a local class in split_klpairs, but
- // the dmt template parameter for iterate needs linkage, so it has to be a
- // separate class, but we want it to be able to call e.g. add_key
- friend class split_klpairs_extra;
-
- // Allocates space in the mempool.
- // If there is insufficient space, the mempool is enlarged and leafentries may be shuffled to reduce fragmentation.
- // If shuffling happens, the offsets stored in the dmt are updated.
- LEAFENTRY mempool_malloc_and_update_dmt(size_t size, void **maybe_free);
-
- // Change the size of the mempool to support what is already in it, plus added_size.
- // possibly "compress" by shuffling leafentries around to reduce fragmentation to 0.
- // If fragmentation is already 0 and force_compress is not true, shuffling may be skipped.
- // If shuffling happens, leafentries will be stored in the mempool in sorted order.
- void dmt_compress_kvspace(size_t added_size, void **maybe_free, bool force_compress);
-
- // Note that a key was added (for maintaining disk-size of this basement node)
- void add_key(uint32_t keylen);
-
- // Note that multiple keys were added (for maintaining disk-size of this basement node)
- void add_keys(uint32_t n_keys, uint32_t combined_klpair_len);
-
- // Note that a key was removed (for maintaining disk-size of this basement node)
- void remove_key(uint32_t keylen);
-
- klpair_dmt_t m_buffer; // pointers to individual leaf entries
+ klpair_omt_t m_buffer; // pointers to individual leaf entries
struct mempool m_buffer_mempool; // storage for all leaf entries
friend class bndata_bugfix_test;
-
- // Get the serialized size of a klpair.
- // As of Jan 14, 2014, serialized size of a klpair is independent of whether this basement node has fixed-length keys.
- uint32_t klpair_disksize(const uint32_t klpair_len, const klpair_struct *klpair) const;
-
- // The disk/memory size of all keys. (Note that the size of memory for the leafentries is maintained by m_buffer_mempool)
- size_t m_disksize_of_keys;
-
- // Deserialize this basement node from rbuf
- // all keys will be first followed by all leafentries (both in sorted order)
- void initialize_from_separate_keys_and_vals(uint32_t num_entries, struct rbuf *rb, uint32_t data_size, uint32_t version,
- uint32_t key_data_size, uint32_t val_data_size, bool all_keys_same_length,
- uint32_t fixed_klpair_length);
};
diff --git a/storage/tokudb/ft-index/ft/cachetable.cc b/storage/tokudb/ft-index/ft/cachetable.cc
index d7c734cc5fd..b489c9525f1 100644
--- a/storage/tokudb/ft-index/ft/cachetable.cc
+++ b/storage/tokudb/ft-index/ft/cachetable.cc
@@ -370,7 +370,7 @@ toku_cachetable_set_env_dir(CACHETABLE ct, const char *env_dir) {
// What cachefile goes with particular iname (iname relative to env)?
// The transaction that is adding the reference might not have a reference
-// to the ft, therefore the cachefile might be closing.
+// to the brt, therefore the cachefile might be closing.
// If closing, we want to return that it is not there, but must wait till after
// the close has finished.
// Once the close has finished, there must not be a cachefile with that name
@@ -380,7 +380,7 @@ int toku_cachefile_of_iname_in_env (CACHETABLE ct, const char *iname_in_env, CAC
}
// What cachefile goes with particular fd?
-// This function can only be called if the ft is still open, so file must
+// This function can only be called if the brt is still open, so file must
// still be open
int toku_cachefile_of_filenum (CACHETABLE ct, FILENUM filenum, CACHEFILE *cf) {
return ct->cf_list.cachefile_of_filenum(filenum, cf);
@@ -642,7 +642,7 @@ static void cachetable_free_pair(PAIR p) {
cachetable_evictions++;
PAIR_ATTR new_attr = p->attr;
// Note that flush_callback is called with write_me false, so the only purpose of this
- // call is to tell the ft layer to evict the node (keep_me is false).
+ // call is to tell the brt layer to evict the node (keep_me is false).
// Also, because we have already removed the PAIR from the cachetable in
// cachetable_remove_pair, we cannot pass in p->cachefile and p->cachefile->fd
// for the first two parameters, as these may be invalid (#5171), so, we
@@ -1302,6 +1302,8 @@ void toku_cachetable_pf_pinned_pair(
pair_unlock(p);
}
+
+// NOW A TEST ONLY FUNCTION!!!
int toku_cachetable_get_and_pin (
CACHEFILE cachefile,
CACHEKEY key,
@@ -1571,7 +1573,7 @@ exit:
return try_again;
}
-int toku_cachetable_get_and_pin_with_dep_pairs (
+int toku_cachetable_get_and_pin_with_dep_pairs_batched (
CACHEFILE cachefile,
CACHEKEY key,
uint32_t fullhash,
@@ -1764,6 +1766,43 @@ got_value:
return 0;
}
+int toku_cachetable_get_and_pin_with_dep_pairs (
+ CACHEFILE cachefile,
+ CACHEKEY key,
+ uint32_t fullhash,
+ void**value,
+ long *sizep,
+ CACHETABLE_WRITE_CALLBACK write_callback,
+ CACHETABLE_FETCH_CALLBACK fetch_callback,
+ CACHETABLE_PARTIAL_FETCH_REQUIRED_CALLBACK pf_req_callback,
+ CACHETABLE_PARTIAL_FETCH_CALLBACK pf_callback,
+ pair_lock_type lock_type,
+ void* read_extraargs, // parameter for fetch_callback, pf_req_callback, and pf_callback
+ uint32_t num_dependent_pairs, // number of dependent pairs that we may need to checkpoint
+ PAIR* dependent_pairs,
+ enum cachetable_dirty* dependent_dirty // array stating dirty/cleanness of dependent pairs
+ )
+// See cachetable.h
+{
+ int r = toku_cachetable_get_and_pin_with_dep_pairs_batched(
+ cachefile,
+ key,
+ fullhash,
+ value,
+ sizep,
+ write_callback,
+ fetch_callback,
+ pf_req_callback,
+ pf_callback,
+ lock_type,
+ read_extraargs,
+ num_dependent_pairs,
+ dependent_pairs,
+ dependent_dirty
+ );
+ return r;
+}
+
// Lookup a key in the cachetable. If it is found and it is not being written, then
// acquire a read lock on the pair, update the LRU list, and return sucess.
//
@@ -2009,7 +2048,7 @@ maybe_pin_pair(
return retval;
}
-int toku_cachetable_get_and_pin_nonblocking(
+int toku_cachetable_get_and_pin_nonblocking_batched(
CACHEFILE cf,
CACHEKEY key,
uint32_t fullhash,
@@ -2161,6 +2200,40 @@ try_again:
abort();
}
+int toku_cachetable_get_and_pin_nonblocking (
+ CACHEFILE cf,
+ CACHEKEY key,
+ uint32_t fullhash,
+ void**value,
+ long* sizep,
+ CACHETABLE_WRITE_CALLBACK write_callback,
+ CACHETABLE_FETCH_CALLBACK fetch_callback,
+ CACHETABLE_PARTIAL_FETCH_REQUIRED_CALLBACK pf_req_callback,
+ CACHETABLE_PARTIAL_FETCH_CALLBACK pf_callback,
+ pair_lock_type lock_type,
+ void *read_extraargs,
+ UNLOCKERS unlockers
+ )
+// See cachetable.h.
+{
+ int r = 0;
+ r = toku_cachetable_get_and_pin_nonblocking_batched(
+ cf,
+ key,
+ fullhash,
+ value,
+ sizep,
+ write_callback,
+ fetch_callback,
+ pf_req_callback,
+ pf_callback,
+ lock_type,
+ read_extraargs,
+ unlockers
+ );
+ return r;
+}
+
struct cachefile_prefetch_args {
PAIR p;
CACHETABLE_FETCH_CALLBACK fetch_callback;
diff --git a/storage/tokudb/ft-index/ft/cachetable.h b/storage/tokudb/ft-index/ft/cachetable.h
index 9c11db02e00..c654927aa21 100644
--- a/storage/tokudb/ft-index/ft/cachetable.h
+++ b/storage/tokudb/ft-index/ft/cachetable.h
@@ -344,6 +344,28 @@ void toku_cachetable_put(CACHEFILE cf, CACHEKEY key, uint32_t fullhash,
// then the required PAIRs are written to disk for checkpoint.
// KEY PROPERTY OF DEPENDENT PAIRS: They are already locked by the client
// Returns: 0 if the memory object is in memory, otherwise an error number.
+// Rationale:
+// begin_batched_pin and end_batched_pin take and release a read lock on the pair list.
+// Normally, that would be done within this get_and_pin, but we want to pin multiple nodes with a single acquisition of the read lock.
+int toku_cachetable_get_and_pin_with_dep_pairs_batched (
+ CACHEFILE cachefile,
+ CACHEKEY key,
+ uint32_t fullhash,
+ void**value,
+ long *sizep,
+ CACHETABLE_WRITE_CALLBACK write_callback,
+ CACHETABLE_FETCH_CALLBACK fetch_callback,
+ CACHETABLE_PARTIAL_FETCH_REQUIRED_CALLBACK pf_req_callback,
+ CACHETABLE_PARTIAL_FETCH_CALLBACK pf_callback,
+ pair_lock_type lock_type,
+ void* read_extraargs, // parameter for fetch_callback, pf_req_callback, and pf_callback
+ uint32_t num_dependent_pairs, // number of dependent pairs that we may need to checkpoint
+ PAIR* dependent_pairs,
+ enum cachetable_dirty* dependent_dirty // array stating dirty/cleanness of dependent pairs
+ );
+
+// Effect: call toku_cachetable_get_and_pin_with_dep_pairs_batched once,
+// wrapped in begin_batched_pin and end_batched_pin calls.
int toku_cachetable_get_and_pin_with_dep_pairs (
CACHEFILE cachefile,
CACHEKEY key,
@@ -361,6 +383,7 @@ int toku_cachetable_get_and_pin_with_dep_pairs (
enum cachetable_dirty* dependent_dirty // array stating dirty/cleanness of dependent pairs
);
+
// Get and pin a memory object.
// Effects: If the memory object is in the cachetable acquire the PAIR lock on it.
// Otherwise, fetch it from storage by calling the fetch callback. If the fetch
@@ -399,7 +422,10 @@ struct unlockers {
// Effect: If the block is in the cachetable, then return it.
// Otherwise call the functions in unlockers, fetch the data (but don't pin it, since we'll just end up pinning it again later), and return TOKUDB_TRY_AGAIN.
-int toku_cachetable_get_and_pin_nonblocking (
+// Rationale:
+// begin_batched_pin and end_batched_pin take and release a read lock on the pair list.
+// Normally, that would be done within this get_and_pin, but we want to pin multiple nodes with a single acquisition of the read lock.
+int toku_cachetable_get_and_pin_nonblocking_batched (
CACHEFILE cf,
CACHEKEY key,
uint32_t fullhash,
@@ -414,6 +440,23 @@ int toku_cachetable_get_and_pin_nonblocking (
UNLOCKERS unlockers
);
+// Effect: call toku_cachetable_get_and_pin_nonblocking_batched once,
+// wrapped in begin_batched_pin and end_batched_pin calls.
+int toku_cachetable_get_and_pin_nonblocking (
+ CACHEFILE cf,
+ CACHEKEY key,
+ uint32_t fullhash,
+ void**value,
+ long *sizep,
+ CACHETABLE_WRITE_CALLBACK write_callback,
+ CACHETABLE_FETCH_CALLBACK fetch_callback,
+ CACHETABLE_PARTIAL_FETCH_REQUIRED_CALLBACK pf_req_callback __attribute__((unused)),
+ CACHETABLE_PARTIAL_FETCH_CALLBACK pf_callback __attribute__((unused)),
+ pair_lock_type lock_type,
+ void *read_extraargs, // parameter for fetch_callback, pf_req_callback, and pf_callback
+ UNLOCKERS unlockers
+ );
+
int toku_cachetable_maybe_get_and_pin (CACHEFILE, CACHEKEY, uint32_t /*fullhash*/, pair_lock_type, void**);
// Effect: Maybe get and pin a memory object.
// This function is similar to the get_and_pin function except that it
diff --git a/storage/tokudb/ft-index/ft/checksum-benchmarks/adler32.cc b/storage/tokudb/ft-index/ft/checksum-benchmarks/adler32.cc
new file mode 100644
index 00000000000..e151cb9c680
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/checksum-benchmarks/adler32.cc
@@ -0,0 +1,236 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include <toku_assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <zlib.h>
+#include <openssl/md2.h>
+#include <openssl/md4.h>
+#include <openssl/md5.h>
+
+const unsigned int prime = 2000000011;
+
+unsigned int karprabin (unsigned char *datac, int N) {
+ assert(N%4==0);
+ unsigned int *data=(unsigned int*)datac;
+ N=N/4;
+ int i;
+ unsigned int result=0;
+ for (i=0; i<N; i++) {
+ result=(result*prime)+data[i];
+ }
+ return result;
+}
+
+// According to
+// P. L'Ecuyer, "Tables of Linear Congruential Generators of
+// Different Sizes and Good Lattice Structure", Mathematics of
+// Computation 68:225, 249--260 (1999).
+// m=2^{32}-5 a=1588635695 is good.
+
+const unsigned int mkr = 4294967291U;
+const unsigned int akr = 1588635695U;
+
+
+// But this is slower
+unsigned int karprabinP (unsigned char *datac, int N) {
+ assert(N%4==0);
+ unsigned int *data=(unsigned int*)datac;
+ N=N/4;
+ int i;
+ unsigned long long result=0;
+ for (i=0; i<N; i++) {
+ result=((result*akr)+data[i])%mkr;
+ }
+ return result;
+}
+
+float tdiff (struct timeval *start, struct timeval *end) {
+ return (end->tv_sec-start->tv_sec) +1e-6*(end->tv_usec - start->tv_usec);
+}
+
+int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+ struct timeval start, end;
+ const int N=2<<20;
+ unsigned char *data=malloc(N);
+ int i;
+ assert(data);
+ for (i=0; i<N; i++) data[i]=random();
+
+ // adler32
+ {
+ uLong a32 = adler32(0L, Z_NULL, 0);
+ for (i=0; i<3; i++) {
+ gettimeofday(&start, 0);
+ a32 = adler32(a32, data, N);
+ gettimeofday(&end, 0);
+ float tm = tdiff(&start, &end);
+ printf("adler32=%lu, time=%9.6fs %9.6fns/b\n", a32, tm, 1e9*tm/N);
+ }
+ }
+
+ // crc32
+ {
+ uLong c32 = crc32(0L, Z_NULL, 0);
+ for (i=0; i<3; i++) {
+ gettimeofday(&start, 0);
+ c32 = crc32(c32, data, N);
+ gettimeofday(&end, 0);
+ float tm = tdiff(&start, &end);
+ printf("crc32=%lu, time=%9.6fs %9.6fns/b\n", c32, tm, 1e9*tm/N);
+ }
+ }
+
+ // MD2
+ {
+ unsigned char buf[MD2_DIGEST_LENGTH];
+ int j;
+ for (i=0; i<3; i++) {
+ gettimeofday(&start, 0);
+ MD2(data, N, buf);
+ gettimeofday(&end, 0);
+ float tm = tdiff(&start, &end);
+ printf("md2=");
+ for (j=0; j<MD2_DIGEST_LENGTH; j++) {
+ printf("%02x", buf[j]);
+ }
+ printf(" time=%9.6fs %9.6fns/b\n", tm, 1e9*tm/N);
+ }
+ }
+
+ // MD4
+ {
+ unsigned char buf[MD4_DIGEST_LENGTH];
+ int j;
+ for (i=0; i<3; i++) {
+ gettimeofday(&start, 0);
+ MD4(data, N, buf);
+ gettimeofday(&end, 0);
+ float tm = tdiff(&start, &end);
+ printf("md4=");
+ for (j=0; j<MD4_DIGEST_LENGTH; j++) {
+ printf("%02x", buf[j]);
+ }
+ printf(" time=%9.6fs %9.6fns/b\n", tm, 1e9*tm/N);
+ }
+ }
+
+ // MD5
+ {
+ unsigned char buf[MD5_DIGEST_LENGTH];
+ int j;
+ for (i=0; i<3; i++) {
+ gettimeofday(&start, 0);
+ MD5(data, N, buf);
+ gettimeofday(&end, 0);
+ float tm = tdiff(&start, &end);
+ printf("md5=");
+ for (j=0; j<MD5_DIGEST_LENGTH; j++) {
+ printf("%02x", buf[j]);
+ }
+ printf(" time=%9.6fs %9.6fns/b\n", tm, 1e9*tm/N);
+ }
+ }
+
+ // karp rabin
+ {
+ for (i=0; i<3; i++) {
+ gettimeofday(&start, 0);
+ unsigned int kr = karprabin(data, N);
+ gettimeofday(&end, 0);
+ float tm = tdiff(&start, &end);
+ printf("kr=%ud time=%9.6fs %9.6fns/b\n", kr, tm, 1e9*tm/N);
+ }
+ }
+ free(data);
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/compression-ratio/cratio.cc b/storage/tokudb/ft-index/ft/compression-ratio/cratio.cc
new file mode 100644
index 00000000000..395504d3b92
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/compression-ratio/cratio.cc
@@ -0,0 +1,195 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+/* Measure the extent to which we can compress a file.
+ * Works on version 8. */
+
+#define _XOPEN_SOURCE 500
+#include <arpa/inet.h>
+#include <toku_assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <zlib.h>
+#include <toku_portability.h>
+
+
+toku_off_t fd_size (int fd) {
+ int64_t file_size;
+ int r = toku_os_get_file_size(fd, &file_size);
+ assert(r==0);
+ return file_size;
+}
+
+#define NSIZE (1<<20)
+unsigned char fbuf[NSIZE];
+unsigned char cbuf[NSIZE+500];
+
+void
+measure_header (int fd, toku_off_t off, // read header from this offset
+ toku_off_t *usize, // size uncompressed (but not including any padding)
+ toku_off_t *csize) // compressed size
+{
+ int r;
+ r=pread(fd, fbuf, 12, off);
+ assert(r==12);
+ assert(memcmp(fbuf,"tokudata",8)==0);
+ int bsize = toku_dtoh32(*(uint32_t*)(fbuf+8));
+ //printf("Bsize=%d\n", bsize);
+ (*usize)+=bsize;
+ assert(bsize<=NSIZE);
+ r=pread(fd, fbuf, bsize, off);
+ assert(r==bsize);
+ uLongf destLen=sizeof(cbuf);
+ r=compress2(cbuf, &destLen,
+ fbuf+20, bsize-=20, // skip magic nodesize and version
+ 1);
+ assert(r==Z_OK);
+ destLen+=16; // account for the size and magic and version
+ //printf("Csize=%ld\n", destLen);
+ (*csize)+=destLen;
+}
+
+void
+measure_node (int fd, toku_off_t off, // read header from this offset
+ toku_off_t *usize, // size uncompressed (but not including any padding)
+ toku_off_t *csize) // compressed size
+{
+ int r;
+ r=pread(fd, fbuf, 24, off);
+ assert(r==24);
+ //printf("fbuf[0..7]=%c%c%c%c%c%c%c%c\n", fbuf[0], fbuf[1], fbuf[2], fbuf[3], fbuf[4], fbuf[5], fbuf[6], fbuf[7]);
+ assert(memcmp(fbuf,"tokuleaf",8)==0 || memcmp(fbuf, "tokunode", 8)==0);
+ assert(8==toku_dtoh32(*(uint32_t*)(fbuf+8))); // check file version
+ int bsize = toku_dtoh32(*(uint32_t*)(fbuf+20));
+ //printf("Bsize=%d\n", bsize);
+ (*usize)+=bsize;
+
+ assert(bsize<=NSIZE);
+ r=pread(fd, fbuf, bsize, off);
+ assert(r==bsize);
+ uLongf destLen=sizeof(cbuf);
+ r=compress2(cbuf, &destLen,
+ fbuf+28, bsize-=28, // skip constant header stuff
+ 1);
+ destLen += 24; // add in magic (8), version(4), lsn (8), and size (4). Actually lsn will be compressed, but ignore that for now.
+ assert(r==Z_OK);
+ //printf("Csize=%ld\n", destLen);
+ (*csize)+=destLen;
+
+}
+
+
+
+/* The single argument is the filename to measure. */
+int main (int argc, const char *argv[]) {
+ assert(argc==2);
+ const char *fname=argv[1];
+ int fd = open(fname, O_RDONLY);
+ assert(fd>=0);
+ toku_off_t fsize = fd_size(fd);
+ printf("fsize (uncompressed with padding)=%lld\n", (long long)fsize);
+
+ toku_off_t usize=0, csize=0;
+ measure_header(fd, 0, &usize, &csize);
+
+ toku_off_t i;
+ for (i=NSIZE; i+24<fsize; i+=NSIZE) {
+ measure_node(fd, i, &usize, &csize);
+ }
+
+ printf("usize (uncompressed with no padding)=%10lld (ratio=%5.2f)\n", (long long)usize, (double)fsize/(double)usize);
+ printf("csize (compressed) =%10lld (ratio=%5.2f)\n", (long long)csize, (double)fsize/(double)csize);
+
+ close(fd);
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/fifo.cc b/storage/tokudb/ft-index/ft/fifo.cc
index 07d7baec2a1..7f6e1778df6 100644
--- a/storage/tokudb/ft-index/ft/fifo.cc
+++ b/storage/tokudb/ft-index/ft/fifo.cc
@@ -102,6 +102,7 @@ struct fifo {
int memory_used; // How many bytes are in use?
};
+const int fifo_initial_size = 4096;
static void fifo_init(struct fifo *fifo) {
fifo->n_items_in_fifo = 0;
fifo->memory = 0;
@@ -117,12 +118,12 @@ static int fifo_entry_size(struct fifo_entry *entry) {
}
__attribute__((const,nonnull))
-size_t toku_ft_msg_memsize_in_fifo(FT_MSG msg) {
+size_t toku_ft_msg_memsize_in_fifo(FT_MSG cmd) {
// This must stay in sync with fifo_entry_size because that's what we
// really trust. But sometimes we only have an in-memory FT_MSG, not
// a serialized fifo_entry so we have to fake it.
- return sizeof (struct fifo_entry) + msg->u.id.key->size + msg->u.id.val->size
- + xids_get_size(msg->xids)
+ return sizeof (struct fifo_entry) + cmd->u.id.key->size + cmd->u.id.val->size
+ + xids_get_size(cmd->xids)
- sizeof(XIDS_S);
}
diff --git a/storage/tokudb/ft-index/ft/fifo.h b/storage/tokudb/ft-index/ft/fifo.h
index e9f53248b98..e178ec6de24 100644
--- a/storage/tokudb/ft-index/ft/fifo.h
+++ b/storage/tokudb/ft-index/ft/fifo.h
@@ -97,6 +97,10 @@ PATENT RIGHTS GRANT:
// If the fifo_entry is unpacked, the compiler aligns the xids array and we waste a lot of space
+#if TOKU_WINDOWS
+#pragma pack(push, 1)
+#endif
+
struct __attribute__((__packed__)) fifo_entry {
unsigned int keylen;
unsigned int vallen;
@@ -106,7 +110,7 @@ struct __attribute__((__packed__)) fifo_entry {
XIDS_S xids_s;
};
-// get and set the ft message type for a fifo entry.
+// get and set the brt message type for a fifo entry.
// it is internally stored as a single unsigned char.
static inline enum ft_msg_type
fifo_entry_get_msg_type(const struct fifo_entry * entry)
@@ -124,6 +128,10 @@ fifo_entry_set_msg_type(struct fifo_entry * entry,
entry->type = type;
}
+#if TOKU_WINDOWS
+#pragma pack(pop)
+#endif
+
typedef struct fifo *FIFO;
int toku_fifo_create(FIFO *);
@@ -141,6 +149,9 @@ unsigned long toku_fifo_memory_size_in_use(FIFO fifo); // return how much memor
unsigned long toku_fifo_memory_footprint(FIFO fifo); // return how much memory the fifo occupies
+//These two are problematic, since I don't want to malloc() the bytevecs, but dequeueing the fifo frees the memory.
+//int toku_fifo_peek_deq (FIFO, bytevec *key, ITEMLEN *keylen, bytevec *data, ITEMLEN *datalen, uint32_t *type, TXNID *xid);
+//int toku_fifo_peek_deq_cmdstruct (FIFO, FT_MSG, DBT*, DBT*); // fill in the FT_MSG, using the two DBTs for the DBT part.
void toku_fifo_iterate(FIFO, void(*f)(bytevec key,ITEMLEN keylen,bytevec data,ITEMLEN datalen, enum ft_msg_type type, MSN msn, XIDS xids, bool is_fresh, void*), void*);
#define FIFO_ITERATE(fifo,keyvar,keylenvar,datavar,datalenvar,typevar,msnvar,xidsvar,is_freshvar,body) ({ \
@@ -167,7 +178,7 @@ int toku_fifo_iterate_internal_has_more(FIFO fifo, int off);
int toku_fifo_iterate_internal_next(FIFO fifo, int off);
struct fifo_entry * toku_fifo_iterate_internal_get_entry(FIFO fifo, int off);
size_t toku_fifo_internal_entry_memsize(struct fifo_entry *e) __attribute__((const,nonnull));
-size_t toku_ft_msg_memsize_in_fifo(FT_MSG msg) __attribute__((const,nonnull));
+size_t toku_ft_msg_memsize_in_fifo(FT_MSG cmd) __attribute__((const,nonnull));
DBT *fill_dbt_for_fifo_entry(DBT *dbt, const struct fifo_entry *entry);
struct fifo_entry *toku_fifo_get_entry(FIFO fifo, int off);
diff --git a/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc b/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc
index 91a0040b02e..16edf068d4d 100644
--- a/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc
+++ b/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc
@@ -201,8 +201,8 @@ toku_create_new_ftnode (
// then a PL_WRITE_CHEAP lock is grabbed
//
int
-toku_pin_ftnode_for_query(
- FT_HANDLE ft_handle,
+toku_pin_ftnode_batched(
+ FT_HANDLE brt,
BLOCKNUM blocknum,
uint32_t fullhash,
UNLOCKERS unlockers,
@@ -225,13 +225,13 @@ toku_pin_ftnode_for_query(
paranoid_invariant(bfe->type == ftnode_fetch_subset);
}
- int r = toku_cachetable_get_and_pin_nonblocking(
- ft_handle->ft->cf,
+ int r = toku_cachetable_get_and_pin_nonblocking_batched(
+ brt->ft->cf,
blocknum,
fullhash,
&node_v,
NULL,
- get_write_callbacks_for_node(ft_handle->ft),
+ get_write_callbacks_for_node(brt->ft),
toku_ftnode_fetch_callback,
toku_ftnode_pf_req_callback,
toku_ftnode_pf_callback,
@@ -245,7 +245,7 @@ toku_pin_ftnode_for_query(
node = static_cast<FTNODE>(node_v);
if (apply_ancestor_messages && node->height == 0) {
needs_ancestors_messages = toku_ft_leaf_needs_ancestors_messages(
- ft_handle->ft,
+ brt->ft,
node,
ancestors,
bounds,
@@ -255,20 +255,20 @@ toku_pin_ftnode_for_query(
if (needs_ancestors_messages) {
toku::context apply_messages_ctx(CTX_MESSAGE_APPLICATION);
- toku_unpin_ftnode_read_only(ft_handle->ft, node);
- int rr = toku_cachetable_get_and_pin_nonblocking(
- ft_handle->ft->cf,
- blocknum,
- fullhash,
- &node_v,
- NULL,
- get_write_callbacks_for_node(ft_handle->ft),
- toku_ftnode_fetch_callback,
- toku_ftnode_pf_req_callback,
- toku_ftnode_pf_callback,
- PL_WRITE_CHEAP,
- bfe, //read_extraargs
- unlockers);
+ toku_unpin_ftnode_read_only(brt->ft, node);
+ int rr = toku_cachetable_get_and_pin_nonblocking_batched(
+ brt->ft->cf,
+ blocknum,
+ fullhash,
+ &node_v,
+ NULL,
+ get_write_callbacks_for_node(brt->ft),
+ toku_ftnode_fetch_callback,
+ toku_ftnode_pf_req_callback,
+ toku_ftnode_pf_callback,
+ PL_WRITE_CHEAP,
+ bfe, //read_extraargs
+ unlockers);
if (rr != 0) {
assert(rr == TOKUDB_TRY_AGAIN); // Any other error and we should bomb out ASAP.
r = TOKUDB_TRY_AGAIN;
@@ -276,7 +276,7 @@ toku_pin_ftnode_for_query(
}
node = static_cast<FTNODE>(node_v);
toku_apply_ancestors_messages_to_node(
- ft_handle,
+ brt,
node,
ancestors,
bounds,
@@ -317,14 +317,54 @@ exit:
}
void
-toku_pin_ftnode_with_dep_nodes(
+toku_pin_ftnode_off_client_thread_and_maybe_move_messages(
FT h,
BLOCKNUM blocknum,
uint32_t fullhash,
FTNODE_FETCH_EXTRA bfe,
pair_lock_type lock_type,
uint32_t num_dependent_nodes,
- FTNODE *dependent_nodes,
+ FTNODE* dependent_nodes,
+ FTNODE *node_p,
+ bool move_messages)
+{
+ toku_pin_ftnode_off_client_thread_batched_and_maybe_move_messages(
+ h,
+ blocknum,
+ fullhash,
+ bfe,
+ lock_type,
+ num_dependent_nodes,
+ dependent_nodes,
+ node_p,
+ move_messages
+ );
+}
+
+void
+toku_pin_ftnode_off_client_thread(
+ FT h,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ FTNODE_FETCH_EXTRA bfe,
+ pair_lock_type lock_type,
+ uint32_t num_dependent_nodes,
+ FTNODE* dependent_nodes,
+ FTNODE *node_p)
+{
+ toku_pin_ftnode_off_client_thread_and_maybe_move_messages(
+ h, blocknum, fullhash, bfe, lock_type, num_dependent_nodes, dependent_nodes, node_p, true);
+}
+
+void
+toku_pin_ftnode_off_client_thread_batched_and_maybe_move_messages(
+ FT h,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ FTNODE_FETCH_EXTRA bfe,
+ pair_lock_type lock_type,
+ uint32_t num_dependent_nodes,
+ FTNODE* dependent_nodes,
FTNODE *node_p,
bool move_messages)
{
@@ -336,7 +376,7 @@ toku_pin_ftnode_with_dep_nodes(
dependent_dirty_bits[i] = (enum cachetable_dirty) dependent_nodes[i]->dirty;
}
- int r = toku_cachetable_get_and_pin_with_dep_pairs(
+ int r = toku_cachetable_get_and_pin_with_dep_pairs_batched(
h->cf,
blocknum,
fullhash,
@@ -352,22 +392,27 @@ toku_pin_ftnode_with_dep_nodes(
dependent_pairs,
dependent_dirty_bits
);
- invariant_zero(r);
+ assert(r==0);
FTNODE node = (FTNODE) node_v;
- if (lock_type != PL_READ && node->height > 0 && move_messages) {
+ if ((lock_type != PL_READ) && node->height > 0 && move_messages) {
toku_move_ftnode_messages_to_stale(h, node);
}
*node_p = node;
}
-void toku_pin_ftnode(FT ft,
- BLOCKNUM blocknum,
- uint32_t fullhash,
- FTNODE_FETCH_EXTRA bfe,
- pair_lock_type lock_type,
- FTNODE *node_p,
- bool move_messages) {
- toku_pin_ftnode_with_dep_nodes(ft, blocknum, fullhash, bfe, lock_type, 0, nullptr, node_p, move_messages);
+void
+toku_pin_ftnode_off_client_thread_batched(
+ FT h,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ FTNODE_FETCH_EXTRA bfe,
+ pair_lock_type lock_type,
+ uint32_t num_dependent_nodes,
+ FTNODE* dependent_nodes,
+ FTNODE *node_p)
+{
+ toku_pin_ftnode_off_client_thread_batched_and_maybe_move_messages(
+ h, blocknum, fullhash, bfe, lock_type, num_dependent_nodes, dependent_nodes, node_p, true);
}
int toku_maybe_pin_ftnode_clean(FT ft, BLOCKNUM blocknum, uint32_t fullhash, pair_lock_type lock_type, FTNODE *nodep) {
@@ -384,12 +429,24 @@ cleanup:
return r;
}
-void toku_unpin_ftnode(FT ft, FTNODE node) {
- int r = toku_cachetable_unpin(ft->cf,
- node->ct_pair,
- static_cast<enum cachetable_dirty>(node->dirty),
- make_ftnode_pair_attr(node));
- invariant_zero(r);
+void
+toku_unpin_ftnode_off_client_thread(FT ft, FTNODE node)
+{
+ int r = toku_cachetable_unpin(
+ ft->cf,
+ node->ct_pair,
+ (enum cachetable_dirty) node->dirty,
+ make_ftnode_pair_attr(node)
+ );
+ assert(r==0);
+}
+
+void
+toku_unpin_ftnode(FT ft, FTNODE node)
+{
+ // printf("%*sUnpin %ld\n", 8-node->height, "", node->thisnodename.b);
+ //VERIFY_NODE(brt,node);
+ toku_unpin_ftnode_off_client_thread(ft, node);
}
void
@@ -403,25 +460,3 @@ toku_unpin_ftnode_read_only(FT ft, FTNODE node)
);
assert(r==0);
}
-
-void toku_ftnode_swap_pair_values(FTNODE a, FTNODE b)
-// Effect: Swap the blocknum, fullhash, and PAIR for for a and b
-// Requires: Both nodes are pinned
-{
- BLOCKNUM tmp_blocknum = a->thisnodename;
- uint32_t tmp_fullhash = a->fullhash;
- PAIR tmp_pair = a->ct_pair;
-
- a->thisnodename = b->thisnodename;
- a->fullhash = b->fullhash;
- a->ct_pair = b->ct_pair;
-
- b->thisnodename = tmp_blocknum;
- b->fullhash = tmp_fullhash;
- b->ct_pair = tmp_pair;
-
- // A and B swapped pair pointers, but we still have to swap
- // the actual pair values (ie: the FTNODEs they represent)
- // in the cachetable.
- toku_cachetable_swap_pair_values(a->ct_pair, b->ct_pair);
-}
diff --git a/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.h b/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.h
index dc84d7f006b..dd43d0ec033 100644
--- a/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.h
+++ b/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.h
@@ -138,10 +138,13 @@ toku_create_new_ftnode (
int n_children
);
-// This function returns a pinned ftnode to the caller.
+/**
+ * Batched version of toku_pin_ftnode, see cachetable batched API for more
+ * details.
+ */
int
-toku_pin_ftnode_for_query(
- FT_HANDLE ft_h,
+toku_pin_ftnode_batched(
+ FT_HANDLE brt,
BLOCKNUM blocknum,
uint32_t fullhash,
UNLOCKERS unlockers,
@@ -153,27 +156,34 @@ toku_pin_ftnode_for_query(
bool* msgs_applied
);
-// Pins an ftnode without dependent pairs
-void toku_pin_ftnode(
+/**
+ * Unfortunately, this function is poorly named
+ * as over time, client threads have also started
+ * calling this function.
+ * This function returns a pinned ftnode to the caller.
+ * Unlike toku_pin_ftnode, this function blocks until the node is pinned.
+ */
+void
+toku_pin_ftnode_off_client_thread(
FT h,
BLOCKNUM blocknum,
uint32_t fullhash,
FTNODE_FETCH_EXTRA bfe,
pair_lock_type lock_type,
- FTNODE *node_p,
- bool move_messages
+ uint32_t num_dependent_nodes,
+ FTNODE* dependent_nodes,
+ FTNODE *node_p
);
-// Pins an ftnode with dependent pairs
-// Unlike toku_pin_ftnode_for_query, this function blocks until the node is pinned.
-void toku_pin_ftnode_with_dep_nodes(
+void
+toku_pin_ftnode_off_client_thread_and_maybe_move_messages(
FT h,
BLOCKNUM blocknum,
uint32_t fullhash,
FTNODE_FETCH_EXTRA bfe,
pair_lock_type lock_type,
uint32_t num_dependent_nodes,
- FTNODE *dependent_nodes,
+ FTNODE* dependent_nodes,
FTNODE *node_p,
bool move_messages
);
@@ -185,12 +195,53 @@ void toku_pin_ftnode_with_dep_nodes(
int toku_maybe_pin_ftnode_clean(FT ft, BLOCKNUM blocknum, uint32_t fullhash, pair_lock_type lock_type, FTNODE *nodep);
/**
- * Effect: Unpin an ftnode.
+ * Batched version of toku_pin_ftnode_off_client_thread, see cachetable
+ * batched API for more details.
*/
-void toku_unpin_ftnode(FT h, FTNODE node);
-void toku_unpin_ftnode_read_only(FT ft, FTNODE node);
+void
+toku_pin_ftnode_off_client_thread_batched_and_maybe_move_messages(
+ FT h,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ FTNODE_FETCH_EXTRA bfe,
+ pair_lock_type lock_type,
+ uint32_t num_dependent_nodes,
+ FTNODE* dependent_nodes,
+ FTNODE *node_p,
+ bool move_messages
+ );
-// Effect: Swaps pair values of two pinned nodes
-void toku_ftnode_swap_pair_values(FTNODE nodea, FTNODE nodeb);
+/**
+ * Batched version of toku_pin_ftnode_off_client_thread, see cachetable
+ * batched API for more details.
+ */
+void
+toku_pin_ftnode_off_client_thread_batched(
+ FT h,
+ BLOCKNUM blocknum,
+ uint32_t fullhash,
+ FTNODE_FETCH_EXTRA bfe,
+ pair_lock_type lock_type,
+ uint32_t num_dependent_nodes,
+ FTNODE* dependent_nodes,
+ FTNODE *node_p
+ );
+
+/**
+ * Effect: Unpin a brt node. Used for
+ * nodes that were pinned off client thread.
+ */
+void
+toku_unpin_ftnode_off_client_thread(FT h, FTNODE node);
+
+/**
+ * Effect: Unpin a brt node.
+ * Used for nodes pinned on a client thread
+ */
+void
+toku_unpin_ftnode(FT h, FTNODE node);
+
+void
+toku_unpin_ftnode_read_only(FT ft, FTNODE node);
#endif
diff --git a/storage/tokudb/ft-index/ft/ft-flusher.cc b/storage/tokudb/ft-index/ft/ft-flusher.cc
index dc4096a7993..20975c7aa01 100644
--- a/storage/tokudb/ft-index/ft/ft-flusher.cc
+++ b/storage/tokudb/ft-index/ft/ft-flusher.cc
@@ -104,7 +104,7 @@ PATENT RIGHTS GRANT:
*/
static FT_FLUSHER_STATUS_S ft_flusher_status;
-#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(ft_flusher_status, k, c, t, "ft flusher: " l, inc)
+#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(ft_flusher_status, k, c, t, "brt flusher: " l, inc)
#define STATUS_VALUE(x) ft_flusher_status.status[x].value.num
void toku_ft_flusher_status_init(void) {
@@ -334,7 +334,7 @@ default_merge_child(struct flusher_advice *fa,
// we are just going to unpin child and
// let ft_merge_child pin it again
//
- toku_unpin_ftnode(h, child);
+ toku_unpin_ftnode_off_client_thread(h, child);
//
//
// it is responsibility of ft_merge_child to unlock parent
@@ -486,8 +486,8 @@ ct_maybe_merge_child(struct flusher_advice *fa,
default_pick_child_after_split,
&ctme);
- toku_unpin_ftnode(h, parent);
- toku_unpin_ftnode(h, child);
+ toku_unpin_ftnode_off_client_thread(h, parent);
+ toku_unpin_ftnode_off_client_thread(h, child);
FTNODE root_node = NULL;
{
@@ -496,7 +496,7 @@ ct_maybe_merge_child(struct flusher_advice *fa,
toku_calculate_root_offset_pointer(h, &root, &fullhash);
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, h);
- toku_pin_ftnode(h, root, fullhash, &bfe, PL_WRITE_EXPENSIVE, &root_node, true);
+ toku_pin_ftnode_off_client_thread(h, root, fullhash, &bfe, PL_WRITE_EXPENSIVE, 0, NULL, &root_node);
toku_assert_entire_node_in_memory(root_node);
}
@@ -565,7 +565,6 @@ static bool may_node_be_reactive(FT ft, FTNODE node)
*/
static void
handle_split_of_child(
- FT ft,
FTNODE node,
int childnum,
FTNODE childa,
@@ -608,20 +607,8 @@ handle_split_of_child(
paranoid_invariant(BP_BLOCKNUM(node, childnum).b==childa->thisnodename.b); // use the same child
- // We never set the rightmost blocknum to be the root.
- // Instead, we wait for the root to split and let promotion initialize the rightmost
- // blocknum to be the first non-root leaf node on the right extreme to recieve an insert.
- invariant(ft->h->root_blocknum.b != ft->rightmost_blocknum.b);
- if (childa->thisnodename.b == ft->rightmost_blocknum.b) {
- // The rightmost leaf (a) split into (a) and (b). We want (b) to swap pair values
- // with (a), now that it is the new rightmost leaf. This keeps the rightmost blocknum
- // constant, the same the way we keep the root blocknum constant.
- toku_ftnode_swap_pair_values(childa, childb);
- BP_BLOCKNUM(node, childnum) = childa->thisnodename;
- }
-
BP_BLOCKNUM(node, childnum+1) = childb->thisnodename;
- BP_WORKDONE(node, childnum+1) = 0;
+ BP_WORKDONE(node, childnum+1) = 0;
BP_STATE(node,childnum+1) = PT_AVAIL;
NONLEAF_CHILDINFO new_bnc = toku_create_empty_nl();
@@ -702,16 +689,16 @@ ftleaf_get_split_loc(
switch (split_mode) {
case SPLIT_LEFT_HEAVY: {
*num_left_bns = node->n_children;
- *num_left_les = BLB_DATA(node, *num_left_bns - 1)->num_klpairs();
+ *num_left_les = BLB_DATA(node, *num_left_bns - 1)->omt_size();
if (*num_left_les == 0) {
*num_left_bns = node->n_children - 1;
- *num_left_les = BLB_DATA(node, *num_left_bns - 1)->num_klpairs();
+ *num_left_les = BLB_DATA(node, *num_left_bns - 1)->omt_size();
}
goto exit;
}
case SPLIT_RIGHT_HEAVY: {
*num_left_bns = 1;
- *num_left_les = BLB_DATA(node, 0)->num_klpairs() ? 1 : 0;
+ *num_left_les = BLB_DATA(node, 0)->omt_size() ? 1 : 0;
goto exit;
}
case SPLIT_EVENLY: {
@@ -720,8 +707,8 @@ ftleaf_get_split_loc(
uint64_t sumlesizes = ftleaf_disk_size(node);
uint32_t size_so_far = 0;
for (int i = 0; i < node->n_children; i++) {
- bn_data* bd = BLB_DATA(node, i);
- uint32_t n_leafentries = bd->num_klpairs();
+ BN_DATA bd = BLB_DATA(node, i);
+ uint32_t n_leafentries = bd->omt_size();
for (uint32_t j=0; j < n_leafentries; j++) {
size_t size_this_le;
int rr = bd->fetch_klpair_disksize(j, &size_this_le);
@@ -738,7 +725,7 @@ ftleaf_get_split_loc(
(*num_left_les)--;
} else if (*num_left_bns > 1) {
(*num_left_bns)--;
- *num_left_les = BLB_DATA(node, *num_left_bns - 1)->num_klpairs();
+ *num_left_les = BLB_DATA(node, *num_left_bns - 1)->omt_size();
} else {
// we are trying to split a leaf with only one
// leafentry in it
@@ -756,6 +743,8 @@ exit:
return;
}
+// TODO: (Zardosht) possibly get rid of this function and use toku_omt_split_at in
+// ftleaf_split
static void
move_leafentries(
BASEMENTNODE dest_bn,
@@ -765,8 +754,7 @@ move_leafentries(
)
//Effect: move leafentries in the range [lbi, upe) from src_omt to newly created dest_omt
{
- invariant(ube == src_bn->data_buffer.num_klpairs());
- src_bn->data_buffer.split_klpairs(&dest_bn->data_buffer, lbi);
+ src_bn->data_buffer.move_leafentries_to(&dest_bn->data_buffer, lbi, ube);
}
static void ftnode_finalize_split(FTNODE node, FTNODE B, MSN max_msn_applied_to_node) {
@@ -863,7 +851,7 @@ ftleaf_split(
ftleaf_get_split_loc(node, split_mode, &num_left_bns, &num_left_les);
{
// did we split right on the boundary between basement nodes?
- const bool split_on_boundary = (num_left_les == 0) || (num_left_les == (int) BLB_DATA(node, num_left_bns - 1)->num_klpairs());
+ const bool split_on_boundary = (num_left_les == 0) || (num_left_les == (int) BLB_DATA(node, num_left_bns - 1)->omt_size());
// Now we know where we are going to break it
// the two nodes will have a total of n_children+1 basement nodes
// and n_children-1 pivots
@@ -924,7 +912,7 @@ ftleaf_split(
move_leafentries(BLB(B, curr_dest_bn_index),
BLB(node, curr_src_bn_index),
num_left_les, // first row to be moved to B
- BLB_DATA(node, curr_src_bn_index)->num_klpairs() // number of rows in basement to be split
+ BLB_DATA(node, curr_src_bn_index)->omt_size() // number of rows in basement to be split
);
BLB_MAX_MSN_APPLIED(B, curr_dest_bn_index) = BLB_MAX_MSN_APPLIED(node, curr_src_bn_index);
curr_dest_bn_index++;
@@ -966,10 +954,10 @@ ftleaf_split(
toku_destroy_dbt(&node->childkeys[num_left_bns - 1]);
}
} else if (splitk) {
- bn_data* bd = BLB_DATA(node, num_left_bns - 1);
+ BN_DATA bd = BLB_DATA(node, num_left_bns - 1);
uint32_t keylen;
void *key;
- int rr = bd->fetch_key_and_len(bd->num_klpairs() - 1, &keylen, &key);
+ int rr = bd->fetch_le_key_and_len(bd->omt_size() - 1, &keylen, &key);
invariant_zero(rr);
toku_memdup_dbt(splitk, key, keylen);
}
@@ -1084,7 +1072,7 @@ ft_split_child(
ft_nonleaf_split(h, child, &nodea, &nodeb, &splitk, 2, dep_nodes);
}
// printf("%s:%d child did split\n", __FILE__, __LINE__);
- handle_split_of_child (h, node, childnum, nodea, nodeb, &splitk);
+ handle_split_of_child (node, childnum, nodea, nodeb, &splitk);
// for test
call_flusher_thread_callback(flt_flush_during_split);
@@ -1094,20 +1082,20 @@ ft_split_child(
// and possibly continue
// flushing one of the children
int picked_child = fa->pick_child_after_split(h, node, childnum, childnum + 1, fa->extra);
- toku_unpin_ftnode(h, node);
+ toku_unpin_ftnode_off_client_thread(h, node);
if (picked_child == childnum ||
(picked_child < 0 && nodea->height > 0 && fa->should_recursively_flush(nodea, fa->extra))) {
- toku_unpin_ftnode(h, nodeb);
+ toku_unpin_ftnode_off_client_thread(h, nodeb);
toku_ft_flush_some_child(h, nodea, fa);
}
else if (picked_child == childnum + 1 ||
(picked_child < 0 && nodeb->height > 0 && fa->should_recursively_flush(nodeb, fa->extra))) {
- toku_unpin_ftnode(h, nodea);
+ toku_unpin_ftnode_off_client_thread(h, nodea);
toku_ft_flush_some_child(h, nodeb, fa);
}
else {
- toku_unpin_ftnode(h, nodea);
- toku_unpin_ftnode(h, nodeb);
+ toku_unpin_ftnode_off_client_thread(h, nodea);
+ toku_unpin_ftnode_off_client_thread(h, nodeb);
}
}
@@ -1180,11 +1168,11 @@ merge_leaf_nodes(FTNODE a, FTNODE b)
a->dirty = 1;
b->dirty = 1;
- bn_data* a_last_bd = BLB_DATA(a, a->n_children-1);
+ BN_DATA a_last_bd = BLB_DATA(a, a->n_children-1);
// this bool states if the last basement node in a has any items or not
// If it does, then it stays in the merge. If it does not, the last basement node
// of a gets eliminated because we do not have a pivot to store for it (because it has no elements)
- const bool a_has_tail = a_last_bd->num_klpairs() > 0;
+ const bool a_has_tail = a_last_bd->omt_size() > 0;
// move each basement node from b to a
// move the pivots, adding one of what used to be max(a)
@@ -1211,7 +1199,7 @@ merge_leaf_nodes(FTNODE a, FTNODE b)
if (a_has_tail) {
uint32_t keylen;
void *key;
- int rr = a_last_bd->fetch_key_and_len(a_last_bd->num_klpairs() - 1, &keylen, &key);
+ int rr = a_last_bd->fetch_le_key_and_len(a_last_bd->omt_size() - 1, &keylen, &key);
invariant_zero(rr);
toku_memdup_dbt(&a->childkeys[a->n_children-1], key, keylen);
a->totalchildkeylens += keylen;
@@ -1355,7 +1343,7 @@ maybe_merge_pinned_nodes(
// For nonleaf nodes, we distribute the children evenly. That may leave one or both of the nodes overfull, but that's OK.
// If we distribute, we set *splitk to a malloced pivot key.
// Parameters:
-// t The FT.
+// t The BRT.
// parent The parent of the two nodes to be split.
// parent_splitk The pivot key between a and b. This is either free()'d or returned in *splitk.
// a The first node to merge.
@@ -1438,7 +1426,7 @@ ft_merge_child(
uint32_t childfullhash = compute_child_fullhash(h->cf, node, childnuma);
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, h);
- toku_pin_ftnode_with_dep_nodes(h, BP_BLOCKNUM(node, childnuma), childfullhash, &bfe, PL_WRITE_EXPENSIVE, 1, &node, &childa, true);
+ toku_pin_ftnode_off_client_thread(h, BP_BLOCKNUM(node, childnuma), childfullhash, &bfe, PL_WRITE_EXPENSIVE, 1, &node, &childa);
}
// for test
call_flusher_thread_callback(flt_flush_before_pin_second_node_for_merge);
@@ -1449,7 +1437,7 @@ ft_merge_child(
uint32_t childfullhash = compute_child_fullhash(h->cf, node, childnumb);
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, h);
- toku_pin_ftnode_with_dep_nodes(h, BP_BLOCKNUM(node, childnumb), childfullhash, &bfe, PL_WRITE_EXPENSIVE, 2, dep_nodes, &childb, true);
+ toku_pin_ftnode_off_client_thread(h, BP_BLOCKNUM(node, childnumb), childfullhash, &bfe, PL_WRITE_EXPENSIVE, 2, dep_nodes, &childb);
}
if (toku_bnc_n_entries(BNC(node,childnuma))>0) {
@@ -1502,14 +1490,6 @@ ft_merge_child(
&node->childkeys[childnuma+1],
(node->n_children-childnumb)*sizeof(node->childkeys[0]));
REALLOC_N(node->n_children-1, node->childkeys);
-
- // Handle a merge of the rightmost leaf node.
- if (did_merge && childb->thisnodename.b == h->rightmost_blocknum.b) {
- invariant(childb->thisnodename.b != h->h->root_blocknum.b);
- toku_ftnode_swap_pair_values(childa, childb);
- BP_BLOCKNUM(node, childnuma) = childa->thisnodename;
- }
-
paranoid_invariant(BP_BLOCKNUM(node, childnuma).b == childa->thisnodename.b);
childa->dirty = 1; // just to make sure
childb->dirty = 1; // just to make sure
@@ -1545,7 +1525,7 @@ ft_merge_child(
// unlock the parent
paranoid_invariant(node->dirty);
- toku_unpin_ftnode(h, node);
+ toku_unpin_ftnode_off_client_thread(h, node);
}
else {
// for test
@@ -1553,14 +1533,14 @@ ft_merge_child(
// unlock the parent
paranoid_invariant(node->dirty);
- toku_unpin_ftnode(h, node);
- toku_unpin_ftnode(h, childb);
+ toku_unpin_ftnode_off_client_thread(h, node);
+ toku_unpin_ftnode_off_client_thread(h, childb);
}
if (childa->height > 0 && fa->should_recursively_flush(childa, fa->extra)) {
toku_ft_flush_some_child(h, childa, fa);
}
else {
- toku_unpin_ftnode(h, childa);
+ toku_unpin_ftnode_off_client_thread(h, childa);
}
}
@@ -1595,7 +1575,7 @@ void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa)
// Note that we don't read the entire node into memory yet.
// The idea is let's try to do the minimum work before releasing the parent lock
fill_bfe_for_min_read(&bfe, ft);
- toku_pin_ftnode_with_dep_nodes(ft, targetchild, childfullhash, &bfe, PL_WRITE_EXPENSIVE, 1, &parent, &child, true);
+ toku_pin_ftnode_off_client_thread(ft, targetchild, childfullhash, &bfe, PL_WRITE_EXPENSIVE, 1, &parent, &child);
// for test
call_flusher_thread_callback(ft_flush_aflter_child_pin);
@@ -1611,6 +1591,7 @@ void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa)
bool may_child_be_reactive = may_node_be_reactive(ft, child);
paranoid_invariant(child->thisnodename.b!=0);
+ //VERIFY_NODE(brt, child);
// only do the following work if there is a flush to perform
if (toku_bnc_n_entries(BNC(parent, childnum)) > 0 || parent->height == 1) {
@@ -1633,7 +1614,7 @@ void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa)
// reactive, we can unpin the parent
//
if (!may_child_be_reactive) {
- toku_unpin_ftnode(ft, parent);
+ toku_unpin_ftnode_off_client_thread(ft, parent);
parent = NULL;
}
@@ -1651,7 +1632,7 @@ void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa)
// for the root with a fresh one
enum reactivity child_re = get_node_reactivity(ft, child);
if (parent && child_re == RE_STABLE) {
- toku_unpin_ftnode(ft, parent);
+ toku_unpin_ftnode_off_client_thread(ft, parent);
parent = NULL;
}
@@ -1690,7 +1671,7 @@ void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa)
)
{
if (parent) {
- toku_unpin_ftnode(ft, parent);
+ toku_unpin_ftnode_off_client_thread(ft, parent);
parent = NULL;
}
//
@@ -1700,7 +1681,7 @@ void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa)
toku_ft_flush_some_child(ft, child, fa);
}
else {
- toku_unpin_ftnode(ft, child);
+ toku_unpin_ftnode_off_client_thread(ft, child);
}
}
else if (child_re == RE_FISSIBLE) {
@@ -1856,7 +1837,7 @@ toku_ftnode_cleaner_callback(
ct_flusher_advice_init(&fa, &fste, h->h->nodesize);
toku_ft_flush_some_child(h, node, &fa);
} else {
- toku_unpin_ftnode(h, node);
+ toku_unpin_ftnode_off_client_thread(h, node);
}
return 0;
}
@@ -1916,7 +1897,7 @@ static void flush_node_fun(void *fe_v)
toku_ft_flush_some_child(fe->h, fe->node, &fa);
}
else {
- toku_unpin_ftnode(fe->h,fe->node);
+ toku_unpin_ftnode_off_client_thread(fe->h,fe->node);
}
}
else {
diff --git a/storage/tokudb/ft-index/ft/ft-flusher.h b/storage/tokudb/ft-index/ft/ft-flusher.h
index 0788bf665d3..35371af99e8 100644
--- a/storage/tokudb/ft-index/ft/ft-flusher.h
+++ b/storage/tokudb/ft-index/ft/ft-flusher.h
@@ -124,7 +124,7 @@ typedef enum {
FT_FLUSHER_SPLIT_NONLEAF, // number of nonleaf nodes split
FT_FLUSHER_MERGE_LEAF, // number of times leaf nodes are merged
FT_FLUSHER_MERGE_NONLEAF, // number of times nonleaf nodes are merged
- FT_FLUSHER_BALANCE_LEAF, // number of times a leaf node is balanced
+ FT_FLUSHER_BALANCE_LEAF, // number of times a leaf node is balanced inside brt
FT_FLUSHER_STATUS_NUM_ROWS
} ft_flusher_status_entry;
@@ -230,7 +230,7 @@ void toku_ft_hot_get_status(FT_HOT_STATUS);
* we go until the end of the FT.
*/
int
-toku_ft_hot_optimize(FT_HANDLE ft_h, DBT* left, DBT* right,
+toku_ft_hot_optimize(FT_HANDLE brt, DBT* left, DBT* right,
int (*progress_callback)(void *extra, float progress),
void *progress_extra, uint64_t* loops_run);
diff --git a/storage/tokudb/ft-index/ft/ft-hot-flusher.cc b/storage/tokudb/ft-index/ft/ft-hot-flusher.cc
index 066e075ee0e..0c9691b1e4d 100644
--- a/storage/tokudb/ft-index/ft/ft-hot-flusher.cc
+++ b/storage/tokudb/ft-index/ft/ft-hot-flusher.cc
@@ -298,9 +298,9 @@ hot_flusher_destroy(struct hot_flusher_extra *flusher)
// Entry point for Hot Optimize Table (HOT). Note, this function is
// not recursive. It iterates over root-to-leaf paths.
int
-toku_ft_hot_optimize(FT_HANDLE ft_handle, DBT* left, DBT* right,
- int (*progress_callback)(void *extra, float progress),
- void *progress_extra, uint64_t* loops_run)
+toku_ft_hot_optimize(FT_HANDLE brt, DBT* left, DBT* right,
+ int (*progress_callback)(void *extra, float progress),
+ void *progress_extra, uint64_t* loops_run)
{
toku::context flush_ctx(CTX_FLUSH);
@@ -316,7 +316,7 @@ toku_ft_hot_optimize(FT_HANDLE ft_handle, DBT* left, DBT* right,
// start of HOT operation
(void) toku_sync_fetch_and_add(&STATUS_VALUE(FT_HOT_NUM_STARTED), 1);
- toku_ft_note_hot_begin(ft_handle);
+ toku_ft_note_hot_begin(brt);
// Higher level logic prevents a dictionary from being deleted or
// truncated during a hot optimize operation. Doing so would violate
@@ -329,16 +329,17 @@ toku_ft_hot_optimize(FT_HANDLE ft_handle, DBT* left, DBT* right,
{
// Get root node (the first parent of each successive HOT
// call.)
- toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &fullhash);
+ toku_calculate_root_offset_pointer(brt->ft, &root_key, &fullhash);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_handle->ft);
- toku_pin_ftnode(ft_handle->ft,
- (BLOCKNUM) root_key,
- fullhash,
- &bfe,
- PL_WRITE_EXPENSIVE,
- &root,
- true);
+ fill_bfe_for_full_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(brt->ft,
+ (BLOCKNUM) root_key,
+ fullhash,
+ &bfe,
+ PL_WRITE_EXPENSIVE,
+ 0,
+ NULL,
+ &root);
toku_assert_entire_node_in_memory(root);
}
@@ -364,12 +365,12 @@ toku_ft_hot_optimize(FT_HANDLE ft_handle, DBT* left, DBT* right,
// This should recurse to the bottom of the tree and then
// return.
if (root->height > 0) {
- toku_ft_flush_some_child(ft_handle->ft, root, &advice);
+ toku_ft_flush_some_child(brt->ft, root, &advice);
} else {
// Since there are no children to flush, we should abort
// the HOT call.
flusher.rightmost_leaf_seen = 1;
- toku_unpin_ftnode(ft_handle->ft, root);
+ toku_unpin_ftnode_off_client_thread(brt->ft, root);
}
// Set the highest pivot key seen here, since the parent may
@@ -385,8 +386,8 @@ toku_ft_hot_optimize(FT_HANDLE ft_handle, DBT* left, DBT* right,
else if (right) {
// if we have flushed past the bounds set for us,
// set rightmost_leaf_seen so we exit
- FAKE_DB(db, &ft_handle->ft->cmp_descriptor);
- int cmp = ft_handle->ft->compare_fun(&db, &flusher.max_current_key, right);
+ FAKE_DB(db, &brt->ft->cmp_descriptor);
+ int cmp = brt->ft->compare_fun(&db, &flusher.max_current_key, right);
if (cmp > 0) {
flusher.rightmost_leaf_seen = 1;
}
@@ -416,7 +417,7 @@ toku_ft_hot_optimize(FT_HANDLE ft_handle, DBT* left, DBT* right,
if (r == 0) { success = true; }
{
- toku_ft_note_hot_complete(ft_handle, success, msn_at_start_of_hot);
+ toku_ft_note_hot_complete(brt, success, msn_at_start_of_hot);
}
if (success) {
diff --git a/storage/tokudb/ft-index/ft/ft-internal.h b/storage/tokudb/ft-index/ft/ft-internal.h
index 378e8921328..730bf1e1547 100644
--- a/storage/tokudb/ft-index/ft/ft-internal.h
+++ b/storage/tokudb/ft-index/ft/ft-internal.h
@@ -92,7 +92,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <toku_race_tools.h>
// Symbol TOKUDB_REVISION is not defined by fractal-tree makefiles, so
@@ -118,15 +118,11 @@ PATENT RIGHTS GRANT:
#include "bndata.h"
enum { KEY_VALUE_OVERHEAD = 8 }; /* Must store the two lengths. */
-enum { FT_MSG_OVERHEAD = (2 + sizeof(MSN)) }; // the type plus freshness plus MSN
+enum { FT_CMD_OVERHEAD = (2 + sizeof(MSN)) }; // the type plus freshness plus MSN
enum { FT_DEFAULT_FANOUT = 16 };
enum { FT_DEFAULT_NODE_SIZE = 4 * 1024 * 1024 };
enum { FT_DEFAULT_BASEMENT_NODE_SIZE = 128 * 1024 };
-// We optimize for a sequential insert pattern if 100 consecutive injections
-// happen into the rightmost leaf node due to promotion.
-enum { FT_SEQINSERT_SCORE_THRESHOLD = 100 };
-
//
// Field in ftnode_fetch_extra that tells the
// partial fetch callback what piece of the node
@@ -458,7 +454,7 @@ enum {
uint32_t compute_child_fullhash (CACHEFILE cf, FTNODE node, int childnum);
-// The ft_header is not managed by the cachetable. Instead, it hangs off the cachefile as userdata.
+// The brt_header is not managed by the cachetable. Instead, it hangs off the cachefile as userdata.
enum ft_type {FT_CURRENT=1, FT_CHECKPOINT_INPROGRESS};
@@ -474,7 +470,7 @@ struct ft_header {
// LSN of creation of "checkpoint-begin" record in log.
LSN checkpoint_lsn;
- // see ft_layout_version.h. maybe don't need this if we assume
+ // see brt_layout_version.h. maybe don't need this if we assume
// it's always the current version after deserializing
const int layout_version;
// different (<) from layout_version if upgraded from a previous
@@ -508,7 +504,7 @@ struct ft_header {
enum toku_compression_method compression_method;
unsigned int fanout;
- // Current Minimum MSN to be used when upgrading pre-MSN FT's.
+ // Current Minimum MSN to be used when upgrading pre-MSN BRT's.
// This is decremented from our currnt MIN_MSN so as not to clash
// with any existing 'normal' MSN's.
MSN highest_unused_msn_for_upgrade;
@@ -530,7 +526,7 @@ struct ft_header {
STAT64INFO_S on_disk_stats;
};
-// ft_header is always the current version.
+// brt_header is always the current version.
struct ft {
FT_HEADER h;
FT_HEADER checkpoint_header;
@@ -576,22 +572,6 @@ struct ft {
// is this ft a blackhole? if so, all messages are dropped.
bool blackhole;
-
- // The blocknum of the rightmost leaf node in the tree. Stays constant through splits
- // and merges using pair-swapping (like the root node, see toku_ftnode_swap_pair_values())
- //
- // This field only transitions from RESERVED_BLOCKNUM_NULL to non-null, never back.
- // We initialize it when promotion inserts into a non-root leaf node on the right extreme.
- // We use the blocktable lock to protect the initialize transition, though it's not really
- // necessary since all threads should be setting it to the same value. We maintain that invariant
- // on first initialization, see ft_set_or_verify_rightmost_blocknum()
- BLOCKNUM rightmost_blocknum;
-
- // sequential access pattern heuristic
- // - when promotion pushes a message directly into the rightmost leaf, the score goes up.
- // - if the score is high enough, we optimistically attempt to insert directly into the rightmost leaf
- // - if our attempt fails because the key was not in range of the rightmost leaf, we reset the score back to 0
- uint32_t seqinsert_score;
};
// Allocate a DB struct off the stack and only set its comparison
@@ -728,7 +708,7 @@ void toku_assert_entire_node_in_memory(FTNODE node);
// append a child node to a parent node
void toku_ft_nonleaf_append_child(FTNODE node, FTNODE child, const DBT *pivotkey);
-// append a message to a nonleaf node child buffer
+// append a cmd to a nonleaf node child buffer
void toku_ft_append_to_child_buffer(ft_compare_func compare_fun, DESCRIPTOR desc, FTNODE node, int childnum, enum ft_msg_type type, MSN msn, XIDS xids, bool is_fresh, const DBT *key, const DBT *val);
STAT64INFO_S toku_get_and_clear_basement_stats(FTNODE leafnode);
@@ -788,7 +768,7 @@ static inline CACHETABLE_WRITE_CALLBACK get_write_callbacks_for_node(FT h) {
static const FTNODE null_ftnode=0;
-/* an ft cursor is represented as a kv pair in a tree */
+/* a brt cursor is represented as a kv pair in a tree */
struct ft_cursor {
struct toku_list cursors_link;
FT_HANDLE ft_handle;
@@ -989,7 +969,7 @@ __attribute__((nonnull))
void toku_ft_bn_update_max_msn(FTNODE node, MSN max_msn_applied, int child_to_read);
__attribute__((const,nonnull))
-size_t toku_ft_msg_memsize_in_fifo(FT_MSG msg);
+size_t toku_ft_msg_memsize_in_fifo(FT_MSG cmd);
int
toku_ft_search_which_child(
@@ -1038,25 +1018,26 @@ int toku_ftnode_hot_next_child(FTNODE node,
/* Stuff for testing */
// toku_testsetup_initialize() must be called before any other test_setup_xxx() functions are called.
void toku_testsetup_initialize(void);
-int toku_testsetup_leaf(FT_HANDLE ft_h, BLOCKNUM *blocknum, int n_children, char **keys, int *keylens);
-int toku_testsetup_nonleaf (FT_HANDLE ft_h, int height, BLOCKNUM *diskoff, int n_children, BLOCKNUM *children, char **keys, int *keylens);
-int toku_testsetup_root(FT_HANDLE ft_h, BLOCKNUM);
-int toku_testsetup_get_sersize(FT_HANDLE ft_h, BLOCKNUM); // Return the size on disk.
-int toku_testsetup_insert_to_leaf (FT_HANDLE ft_h, BLOCKNUM, const char *key, int keylen, const char *val, int vallen);
-int toku_testsetup_insert_to_nonleaf (FT_HANDLE ft_h, BLOCKNUM, enum ft_msg_type, const char *key, int keylen, const char *val, int vallen);
+int toku_testsetup_leaf(FT_HANDLE brt, BLOCKNUM *blocknum, int n_children, char **keys, int *keylens);
+int toku_testsetup_nonleaf (FT_HANDLE brt, int height, BLOCKNUM *diskoff, int n_children, BLOCKNUM *children, char **keys, int *keylens);
+int toku_testsetup_root(FT_HANDLE brt, BLOCKNUM);
+int toku_testsetup_get_sersize(FT_HANDLE brt, BLOCKNUM); // Return the size on disk.
+int toku_testsetup_insert_to_leaf (FT_HANDLE brt, BLOCKNUM, const char *key, int keylen, const char *val, int vallen);
+int toku_testsetup_insert_to_nonleaf (FT_HANDLE brt, BLOCKNUM, enum ft_msg_type, const char *key, int keylen, const char *val, int vallen);
void toku_pin_node_with_min_bfe(FTNODE* node, BLOCKNUM b, FT_HANDLE t);
-void toku_ft_root_put_msg(FT h, FT_MSG msg, txn_gc_info *gc_info);
+// toku_ft_root_put_cmd() accepts non-constant cmd because this is where we set the msn
+void toku_ft_root_put_cmd(FT h, FT_MSG_S * cmd, txn_gc_info *gc_info);
void
toku_get_node_for_verify(
BLOCKNUM blocknum,
- FT_HANDLE ft_h,
+ FT_HANDLE brt,
FTNODE* nodep
);
int
-toku_verify_ftnode (FT_HANDLE ft_h,
+toku_verify_ftnode (FT_HANDLE brt,
MSN rootmsn, MSN parentmsn_with_messages, bool messages_exist_above,
FTNODE node, int height,
const DBT *lesser_pivot, // Everything in the subtree should be > lesser_pivot. (lesser_pivot==NULL if there is no lesser pivot.)
@@ -1204,11 +1185,6 @@ typedef enum {
FT_PRO_NUM_STOP_LOCK_CHILD,
FT_PRO_NUM_STOP_CHILD_INMEM,
FT_PRO_NUM_DIDNT_WANT_PROMOTE,
- FT_BASEMENT_DESERIALIZE_FIXED_KEYSIZE, // how many basement nodes were deserialized with a fixed keysize
- FT_BASEMENT_DESERIALIZE_VARIABLE_KEYSIZE, // how many basement nodes were deserialized with a variable keysize
- FT_PRO_RIGHTMOST_LEAF_SHORTCUT_SUCCESS,
- FT_PRO_RIGHTMOST_LEAF_SHORTCUT_FAIL_POS,
- FT_PRO_RIGHTMOST_LEAF_SHORTCUT_FAIL_REACTIVE,
FT_STATUS_NUM_ROWS
} ft_status_entry;
@@ -1220,9 +1196,9 @@ typedef struct {
void toku_ft_get_status(FT_STATUS);
void
-toku_ft_bn_apply_msg_once(
+toku_ft_bn_apply_cmd_once (
BASEMENTNODE bn,
- const FT_MSG msg,
+ const FT_MSG cmd,
uint32_t idx,
LEAFENTRY le,
txn_gc_info *gc_info,
@@ -1231,38 +1207,38 @@ toku_ft_bn_apply_msg_once(
);
void
-toku_ft_bn_apply_msg(
+toku_ft_bn_apply_cmd (
ft_compare_func compare_fun,
ft_update_func update_fun,
DESCRIPTOR desc,
BASEMENTNODE bn,
- FT_MSG msg,
+ FT_MSG cmd,
txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
);
void
-toku_ft_leaf_apply_msg(
+toku_ft_leaf_apply_cmd (
ft_compare_func compare_fun,
ft_update_func update_fun,
DESCRIPTOR desc,
FTNODE node,
int target_childnum,
- FT_MSG msg,
+ FT_MSG cmd,
txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
);
void
-toku_ft_node_put_msg(
+toku_ft_node_put_cmd (
ft_compare_func compare_fun,
ft_update_func update_fun,
DESCRIPTOR desc,
FTNODE node,
int target_childnum,
- FT_MSG msg,
+ FT_MSG cmd,
bool is_fresh,
txn_gc_info *gc_info,
size_t flow_deltas[],
diff --git a/storage/tokudb/ft-index/ft/ft-node-deserialize.cc b/storage/tokudb/ft-index/ft/ft-node-deserialize.cc
index f309a32b44a..4f869419266 100644
--- a/storage/tokudb/ft-index/ft/ft-node-deserialize.cc
+++ b/storage/tokudb/ft-index/ft/ft-node-deserialize.cc
@@ -193,7 +193,7 @@ check_node_info_checksum(struct rbuf *rb)
{
int r = 0;
// Verify checksum of header stored.
- uint32_t checksum = toku_x1764_memory(rb->buf, rb->ndone);
+ uint32_t checksum = x1764_memory(rb->buf, rb->ndone);
uint32_t stored_checksum = rbuf_int(rb);
if (stored_checksum != checksum) {
@@ -229,7 +229,7 @@ check_legacy_end_checksum(struct rbuf *rb)
{
int r = 0;
uint32_t expected_xsum = rbuf_int(rb);
- uint32_t actual_xsum = toku_x1764_memory(rb->buf, rb->size - 4);
+ uint32_t actual_xsum = x1764_memory(rb->buf, rb->size - 4);
if (expected_xsum != actual_xsum) {
r = TOKUDB_BAD_CHECKSUM;
}
diff --git a/storage/tokudb/ft-index/ft/ft-ops.cc b/storage/tokudb/ft-index/ft/ft-ops.cc
index f9701ec34b1..d61af8716e3 100644
--- a/storage/tokudb/ft-index/ft/ft-ops.cc
+++ b/storage/tokudb/ft-index/ft/ft-ops.cc
@@ -228,12 +228,14 @@ basement nodes, bulk fetch, and partial fetch:
#include <stdint.h>
+static const uint32_t this_version = FT_LAYOUT_VERSION;
+
/* Status is intended for display to humans to help understand system behavior.
* It does not need to be perfectly thread-safe.
*/
static FT_STATUS_S ft_status;
-#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(ft_status, k, c, t, "ft: " l, inc)
+#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(ft_status, k, c, t, "brt: " l, inc)
static toku_mutex_t ft_open_close_lock;
@@ -365,11 +367,6 @@ status_init(void)
STATUS_INIT(FT_PRO_NUM_STOP_LOCK_CHILD, PROMOTION_STOPPED_CHILD_LOCKED_OR_NOT_IN_MEMORY, PARCOUNT, "promotion: stopped because the child was locked or not at all in memory", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(FT_PRO_NUM_STOP_CHILD_INMEM, PROMOTION_STOPPED_CHILD_NOT_FULLY_IN_MEMORY, PARCOUNT, "promotion: stopped because the child was not fully in memory", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(FT_PRO_NUM_DIDNT_WANT_PROMOTE, PROMOTION_STOPPED_AFTER_LOCKING_CHILD, PARCOUNT, "promotion: stopped anyway, after locking the child", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
- STATUS_INIT(FT_BASEMENT_DESERIALIZE_FIXED_KEYSIZE, BASEMENT_DESERIALIZATION_FIXED_KEY, PARCOUNT, "basement nodes deserialized with fixed-keysize", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
- STATUS_INIT(FT_BASEMENT_DESERIALIZE_VARIABLE_KEYSIZE, BASEMENT_DESERIALIZATION_VARIABLE_KEY, PARCOUNT, "basement nodes deserialized with variable-keysize", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
- STATUS_INIT(FT_PRO_RIGHTMOST_LEAF_SHORTCUT_SUCCESS, nullptr, PARCOUNT, "promotion: succeeded in using the rightmost leaf shortcut", TOKU_ENGINE_STATUS);
- STATUS_INIT(FT_PRO_RIGHTMOST_LEAF_SHORTCUT_FAIL_POS, nullptr, PARCOUNT, "promotion: tried the rightmost leaf shorcut but failed (out-of-bounds)", TOKU_ENGINE_STATUS);
- STATUS_INIT(FT_PRO_RIGHTMOST_LEAF_SHORTCUT_FAIL_REACTIVE,nullptr, PARCOUNT, "promotion: tried the rightmost leaf shorcut but failed (child reactive)", TOKU_ENGINE_STATUS);
ft_status.initialized = true;
}
@@ -422,14 +419,6 @@ toku_ft_get_status(FT_STATUS s) {
} \
} while (0)
-void toku_note_deserialized_basement_node(bool fixed_key_size) {
- if (fixed_key_size) {
- STATUS_INC(FT_BASEMENT_DESERIALIZE_FIXED_KEYSIZE, 1);
- } else {
- STATUS_INC(FT_BASEMENT_DESERIALIZE_VARIABLE_KEYSIZE, 1);
- }
-}
-
bool is_entire_node_in_memory(FTNODE node) {
for (int i = 0; i < node->n_children; i++) {
if(BP_STATE(node,i) != PT_AVAIL) {
@@ -450,7 +439,7 @@ get_leaf_num_entries(FTNODE node) {
int i;
toku_assert_entire_node_in_memory(node);
for ( i = 0; i < node->n_children; i++) {
- result += BLB_DATA(node, i)->num_klpairs();
+ result += BLB_DATA(node, i)->omt_size();
}
return result;
}
@@ -636,7 +625,6 @@ ftnode_memory_size (FTNODE node)
int n_children = node->n_children;
retval += sizeof(*node);
retval += (n_children)*(sizeof(node->bp[0]));
- retval += (n_children > 0 ? n_children-1 : 0)*(sizeof(node->childkeys[0]));
retval += node->totalchildkeylens;
// now calculate the sizes of the partitions
@@ -743,14 +731,14 @@ toku_bfe_rightmost_child_wanted(struct ftnode_fetch_extra *bfe, FTNODE node)
}
static int
-ft_cursor_rightmost_child_wanted(FT_CURSOR cursor, FT_HANDLE ft_handle, FTNODE node)
+ft_cursor_rightmost_child_wanted(FT_CURSOR cursor, FT_HANDLE brt, FTNODE node)
{
if (cursor->right_is_pos_infty) {
return node->n_children - 1;
} else if (cursor->range_lock_right_key.data == nullptr) {
return -1;
} else {
- return toku_ftnode_which_child(node, &cursor->range_lock_right_key, &ft_handle->ft->cmp_descriptor, ft_handle->ft->compare_fun);
+ return toku_ftnode_which_child(node, &cursor->range_lock_right_key, &brt->ft->cmp_descriptor, brt->ft->compare_fun);
}
}
@@ -893,11 +881,6 @@ void toku_ftnode_clone_callback(
for (int i = 0; i < node->n_children-1; i++) {
toku_clone_dbt(&cloned_node->childkeys[i], node->childkeys[i]);
}
- if (node->height > 0) {
- // need to move messages here so that we don't serialize stale
- // messages to the fresh tree - ft verify code complains otherwise.
- toku_move_ftnode_messages_to_stale(ft, node);
- }
// clone partition
ftnode_clone_partitions(node, cloned_node);
@@ -940,14 +923,11 @@ void toku_ftnode_flush_callback(
int height = ftnode->height;
if (write_me) {
toku_assert_entire_node_in_memory(ftnode);
- if (height > 0 && !is_clone) {
- // cloned nodes already had their stale messages moved, see toku_ftnode_clone_callback()
- toku_move_ftnode_messages_to_stale(h, ftnode);
- } else if (height == 0) {
+ if (height == 0) {
ft_leaf_run_gc(h, ftnode);
- if (!is_clone) {
- ftnode_update_disk_stats(ftnode, h, for_checkpoint);
- }
+ }
+ if (height == 0 && !is_clone) {
+ ftnode_update_disk_stats(ftnode, h, for_checkpoint);
}
int r = toku_serialize_ftnode_to(fd, ftnode->thisnodename, ftnode, ndd, !is_clone, h, for_checkpoint);
assert_zero(r);
@@ -1090,10 +1070,9 @@ exit:
return;
}
-static void ft_bnc_move_messages_to_stale(FT ft, NONLEAF_CHILDINFO bnc);
-
// replace the child buffer with a compressed version of itself.
-static void
+// @return the old child buffer
+static NONLEAF_CHILDINFO
compress_internal_node_partition(FTNODE node, int i, enum toku_compression_method compression_method)
{
// if we should evict, compress the
@@ -1104,9 +1083,11 @@ compress_internal_node_partition(FTNODE node, int i, enum toku_compression_metho
sub_block_init(sb);
toku_create_compressed_partition_from_available(node, i, compression_method, sb);
- // now set the state to compressed
+ // now set the state to compressed and return the old, available partition
+ NONLEAF_CHILDINFO bnc = BNC(node, i);
set_BSB(node, i, sb);
BP_STATE(node,i) = PT_COMPRESSED;
+ return bnc;
}
void toku_evict_bn_from_memory(FTNODE node, int childnum, FT h) {
@@ -1159,27 +1140,18 @@ int toku_ftnode_pe_callback(void *ftnode_pv, PAIR_ATTR old_attr, void *write_ext
for (int i = 0; i < node->n_children; i++) {
if (BP_STATE(node,i) == PT_AVAIL) {
if (BP_SHOULD_EVICT(node,i)) {
- NONLEAF_CHILDINFO bnc = BNC(node, i);
- if (ft_compress_buffers_before_eviction &&
- // We may not serialize and compress a partition in memory if its
- // in memory layout version is different than what's on disk (and
- // therefore requires upgrade).
- //
- // Auto-upgrade code assumes that if a node's layout version read
- // from disk is not current, it MUST require upgrade. Breaking
- // this rule would cause upgrade code to upgrade this partition
- // again after we serialize it as the current version, which is bad.
- node->layout_version == node->layout_version_read_from_disk) {
- ft_bnc_move_messages_to_stale(ft, bnc);
- compress_internal_node_partition(
+ NONLEAF_CHILDINFO bnc;
+ if (ft_compress_buffers_before_eviction) {
+ // When partially evicting, always compress with quicklz
+ bnc = compress_internal_node_partition(
node,
i,
- // Always compress with quicklz
TOKU_QUICKLZ_METHOD
);
} else {
// We're not compressing buffers before eviction. Simply
// detach the buffer and set the child's state to on-disk.
+ bnc = BNC(node, i);
set_BNULL(node, i);
BP_STATE(node, i) = PT_ON_DISK;
}
@@ -1289,7 +1261,7 @@ bool toku_ftnode_pf_req_callback(void* ftnode_pv, void* read_extraargs) {
FTNODE node = (FTNODE) ftnode_pv;
struct ftnode_fetch_extra *bfe = (struct ftnode_fetch_extra *) read_extraargs;
//
- // The three types of fetches that the ft layer may request are:
+ // The three types of fetches that the brt layer may request are:
// - ftnode_fetch_none: no partitions are necessary (example use: stat64)
// - ftnode_fetch_subset: some subset is necessary (example use: toku_ft_search)
// - ftnode_fetch_all: entire node is necessary (example use: flush, split, merge)
@@ -1521,7 +1493,7 @@ int toku_ftnode_pf_callback(void* ftnode_pv, void* disk_data, void* read_extraar
return 0;
}
-struct msg_leafval_heaviside_extra {
+struct cmd_leafval_heaviside_extra {
ft_compare_func compare_fun;
DESCRIPTOR desc;
DBT const * const key;
@@ -1529,7 +1501,7 @@ struct msg_leafval_heaviside_extra {
//TODO: #1125 optimize
static int
-toku_msg_leafval_heaviside(DBT const &kdbt, const struct msg_leafval_heaviside_extra &be) {
+toku_cmd_leafval_heaviside(DBT const &kdbt, const struct cmd_leafval_heaviside_extra &be) {
FAKE_DB(db, be.desc);
DBT const * const key = be.key;
return be.compare_fun(&db, &kdbt, key);
@@ -1645,10 +1617,12 @@ ft_init_new_root(FT ft, FTNODE oldroot, FTNODE *newrootp)
BLOCKNUM old_blocknum = oldroot->thisnodename;
uint32_t old_fullhash = oldroot->fullhash;
+ PAIR old_pair = oldroot->ct_pair;
int new_height = oldroot->height+1;
uint32_t new_fullhash;
BLOCKNUM new_blocknum;
+ PAIR new_pair = NULL;
cachetable_put_empty_node_with_dep_nodes(
ft,
@@ -1658,6 +1632,7 @@ ft_init_new_root(FT ft, FTNODE oldroot, FTNODE *newrootp)
&new_fullhash,
&newroot
);
+ new_pair = newroot->ct_pair;
assert(newroot);
assert(new_height > 0);
@@ -1669,18 +1644,22 @@ ft_init_new_root(FT ft, FTNODE oldroot, FTNODE *newrootp)
ft->h->layout_version,
ft->h->flags
);
- newroot->fullhash = new_fullhash;
MSN msna = oldroot->max_msn_applied_to_node_on_disk;
newroot->max_msn_applied_to_node_on_disk = msna;
BP_STATE(newroot,0) = PT_AVAIL;
newroot->dirty = 1;
- // Set the first child to have the new blocknum,
- // and then swap newroot with oldroot. The new root
- // will inherit the hash/blocknum/pair from oldroot,
- // keeping the root blocknum constant.
- BP_BLOCKNUM(newroot, 0) = new_blocknum;
- toku_ftnode_swap_pair_values(newroot, oldroot);
+ // now do the "switcheroo"
+ BP_BLOCKNUM(newroot,0) = new_blocknum;
+ newroot->thisnodename = old_blocknum;
+ newroot->fullhash = old_fullhash;
+ newroot->ct_pair = old_pair;
+
+ oldroot->thisnodename = new_blocknum;
+ oldroot->fullhash = new_fullhash;
+ oldroot->ct_pair = new_pair;
+
+ toku_cachetable_swap_pair_values(old_pair, new_pair);
toku_ft_split_child(
ft,
@@ -1695,14 +1674,15 @@ ft_init_new_root(FT ft, FTNODE oldroot, FTNODE *newrootp)
// return to caller
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
ft,
old_blocknum,
old_fullhash,
&bfe,
PL_WRITE_EXPENSIVE, // may_modify_node
- newrootp,
- true
+ 0,
+ NULL,
+ newrootp
);
}
@@ -1736,16 +1716,16 @@ toku_ft_nonleaf_append_child(FTNODE node, FTNODE child, const DBT *pivotkey) {
}
void
-toku_ft_bn_apply_msg_once (
+toku_ft_bn_apply_cmd_once (
BASEMENTNODE bn,
- const FT_MSG msg,
+ const FT_MSG cmd,
uint32_t idx,
LEAFENTRY le,
txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
)
-// Effect: Apply msg to leafentry (msn is ignored)
+// Effect: Apply cmd to leafentry (msn is ignored)
// Calculate work done by message on leafentry and add it to caller's workdone counter.
// idx is the location where it goes
// le is old leafentry
@@ -1754,16 +1734,16 @@ toku_ft_bn_apply_msg_once (
LEAFENTRY new_le=0;
int64_t numbytes_delta = 0; // how many bytes of user data (not including overhead) were added or deleted from this row
int64_t numrows_delta = 0; // will be +1 or -1 or 0 (if row was added or deleted or not)
- uint32_t key_storage_size = ft_msg_get_keylen(msg) + sizeof(uint32_t);
+ uint32_t key_storage_size = ft_msg_get_keylen(cmd) + sizeof(uint32_t);
if (le) {
oldsize = leafentry_memsize(le) + key_storage_size;
}
-
- // toku_le_apply_msg() may call bn_data::mempool_malloc_and_update_dmt() to allocate more space.
+
+ // toku_le_apply_msg() may call mempool_malloc_from_omt() to allocate more space.
// That means le is guaranteed to not cause a sigsegv but it may point to a mempool that is
// no longer in use. We'll have to release the old mempool later.
toku_le_apply_msg(
- msg,
+ cmd,
le,
&bn->data_buffer,
idx,
@@ -1771,8 +1751,6 @@ toku_ft_bn_apply_msg_once (
&new_le,
&numbytes_delta
);
- // at this point, we cannot trust cmd->u.id.key to be valid.
- // The dmt may have realloced its mempool and freed the one containing key.
newsize = new_le ? (leafentry_memsize(new_le) + + key_storage_size) : 0;
if (le && new_le) {
@@ -1810,7 +1788,7 @@ struct setval_extra_s {
uint32_t tag;
bool did_set_val;
int setval_r; // any error code that setval_fun wants to return goes here.
- // need arguments for toku_ft_bn_apply_msg_once
+ // need arguments for toku_ft_bn_apply_cmd_once
BASEMENTNODE bn;
MSN msn; // captured from original message, not currently used
XIDS xids;
@@ -1818,7 +1796,7 @@ struct setval_extra_s {
uint32_t idx;
LEAFENTRY le;
txn_gc_info *gc_info;
- uint64_t * workdone; // set by toku_ft_bn_apply_msg_once()
+ uint64_t * workdone; // set by toku_ft_bn_apply_cmd_once()
STAT64INFO stats_to_update;
};
@@ -1826,7 +1804,7 @@ struct setval_extra_s {
* If new_val == NULL, we send a delete message instead of an insert.
* This happens here instead of in do_delete() for consistency.
* setval_fun() is called from handlerton, passing in svextra_v
- * from setval_extra_s input arg to ft->update_fun().
+ * from setval_extra_s input arg to brt->update_fun().
*/
static void setval_fun (const DBT *new_val, void *svextra_v) {
struct setval_extra_s *CAST_FROM_VOIDP(svextra, svextra_v);
@@ -1835,7 +1813,7 @@ static void setval_fun (const DBT *new_val, void *svextra_v) {
svextra->did_set_val = true;
{
- // can't leave scope until toku_ft_bn_apply_msg_once if
+ // can't leave scope until toku_ft_bn_apply_cmd_once if
// this is a delete
DBT val;
FT_MSG_S msg = { FT_NONE, svextra->msn, svextra->xids,
@@ -1848,7 +1826,7 @@ static void setval_fun (const DBT *new_val, void *svextra_v) {
toku_init_dbt(&val);
msg.u.id.val = &val;
}
- toku_ft_bn_apply_msg_once(svextra->bn, &msg,
+ toku_ft_bn_apply_cmd_once(svextra->bn, &msg,
svextra->idx, svextra->le,
svextra->gc_info,
svextra->workdone, svextra->stats_to_update);
@@ -1856,11 +1834,11 @@ static void setval_fun (const DBT *new_val, void *svextra_v) {
}
}
-// We are already past the msn filter (in toku_ft_bn_apply_msg(), which calls do_update()),
+// We are already past the msn filter (in toku_ft_bn_apply_cmd(), which calls do_update()),
// so capturing the msn in the setval_extra_s is not strictly required. The alternative
// would be to put a dummy msn in the messages created by setval_fun(), but preserving
// the original msn seems cleaner and it preserves accountability at a lower layer.
-static int do_update(ft_update_func update_fun, DESCRIPTOR desc, BASEMENTNODE bn, FT_MSG msg, uint32_t idx,
+static int do_update(ft_update_func update_fun, DESCRIPTOR desc, BASEMENTNODE bn, FT_MSG cmd, uint32_t idx,
LEAFENTRY le,
void* keydata,
uint32_t keylen,
@@ -1876,23 +1854,23 @@ static int do_update(ft_update_func update_fun, DESCRIPTOR desc, BASEMENTNODE bn
// the location of data depends whether this is a regular or
// broadcast update
- if (msg->type == FT_UPDATE) {
+ if (cmd->type == FT_UPDATE) {
// key is passed in with command (should be same as from le)
// update function extra is passed in with command
STATUS_INC(FT_UPDATES, 1);
- keyp = msg->u.id.key;
- update_function_extra = msg->u.id.val;
- } else if (msg->type == FT_UPDATE_BROADCAST_ALL) {
+ keyp = cmd->u.id.key;
+ update_function_extra = cmd->u.id.val;
+ } else if (cmd->type == FT_UPDATE_BROADCAST_ALL) {
// key is not passed in with broadcast, it comes from le
// update function extra is passed in with command
paranoid_invariant(le); // for broadcast updates, we just hit all leafentries
// so this cannot be null
paranoid_invariant(keydata);
paranoid_invariant(keylen);
- paranoid_invariant(msg->u.id.key->size == 0);
+ paranoid_invariant(cmd->u.id.key->size == 0);
STATUS_INC(FT_UPDATES_BROADCAST, 1);
keyp = toku_fill_dbt(&key, keydata, keylen);
- update_function_extra = msg->u.id.val;
+ update_function_extra = cmd->u.id.val;
} else {
abort();
}
@@ -1908,10 +1886,10 @@ static int do_update(ft_update_func update_fun, DESCRIPTOR desc, BASEMENTNODE bn
}
le_for_update = le;
- struct setval_extra_s setval_extra = {setval_tag, false, 0, bn, msg->msn, msg->xids,
+ struct setval_extra_s setval_extra = {setval_tag, false, 0, bn, cmd->msn, cmd->xids,
keyp, idx, le_for_update, gc_info,
workdone, stats_to_update};
- // call handlerton's ft->update_fun(), which passes setval_extra to setval_fun()
+ // call handlerton's brt->update_fun(), which passes setval_extra to setval_fun()
FAKE_DB(db, desc);
int r = update_fun(
&db,
@@ -1925,20 +1903,20 @@ static int do_update(ft_update_func update_fun, DESCRIPTOR desc, BASEMENTNODE bn
return r;
}
-// Should be renamed as something like "apply_msg_to_basement()."
+// Should be renamed as something like "apply_cmd_to_basement()."
void
-toku_ft_bn_apply_msg (
+toku_ft_bn_apply_cmd (
ft_compare_func compare_fun,
ft_update_func update_fun,
DESCRIPTOR desc,
BASEMENTNODE bn,
- FT_MSG msg,
+ FT_MSG cmd,
txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
)
// Effect:
-// Put a msg into a leaf.
+// Put a cmd into a leaf.
// Calculate work done by message on leafnode and add it to caller's workdone counter.
// The leaf could end up "too big" or "too small". The caller must fix that up.
{
@@ -1946,28 +1924,28 @@ toku_ft_bn_apply_msg (
void* key = NULL;
uint32_t keylen = 0;
- uint32_t num_klpairs;
+ uint32_t omt_size;
int r;
- struct msg_leafval_heaviside_extra be = {compare_fun, desc, msg->u.id.key};
+ struct cmd_leafval_heaviside_extra be = {compare_fun, desc, cmd->u.id.key};
unsigned int doing_seqinsert = bn->seqinsert;
bn->seqinsert = 0;
- switch (msg->type) {
+ switch (cmd->type) {
case FT_INSERT_NO_OVERWRITE:
case FT_INSERT: {
uint32_t idx;
if (doing_seqinsert) {
- idx = bn->data_buffer.num_klpairs();
+ idx = bn->data_buffer.omt_size();
DBT kdbt;
- r = bn->data_buffer.fetch_key_and_len(idx-1, &kdbt.size, &kdbt.data);
+ r = bn->data_buffer.fetch_le_key_and_len(idx-1, &kdbt.size, &kdbt.data);
if (r != 0) goto fz;
- int cmp = toku_msg_leafval_heaviside(kdbt, be);
+ int cmp = toku_cmd_leafval_heaviside(kdbt, be);
if (cmp >= 0) goto fz;
r = DB_NOTFOUND;
} else {
fz:
- r = bn->data_buffer.find_zero<decltype(be), toku_msg_leafval_heaviside>(
+ r = bn->data_buffer.find_zero<decltype(be), toku_cmd_leafval_heaviside>(
be,
&storeddata,
&key,
@@ -1980,13 +1958,13 @@ toku_ft_bn_apply_msg (
} else {
assert_zero(r);
}
- toku_ft_bn_apply_msg_once(bn, msg, idx, storeddata, gc_info, workdone, stats_to_update);
+ toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, gc_info, workdone, stats_to_update);
// if the insertion point is within a window of the right edge of
// the leaf then it is sequential
// window = min(32, number of leaf entries/16)
{
- uint32_t s = bn->data_buffer.num_klpairs();
+ uint32_t s = bn->data_buffer.omt_size();
uint32_t w = s / 16;
if (w == 0) w = 1;
if (w > 32) w = 32;
@@ -2003,7 +1981,7 @@ toku_ft_bn_apply_msg (
uint32_t idx;
// Apply to all the matches
- r = bn->data_buffer.find_zero<decltype(be), toku_msg_leafval_heaviside>(
+ r = bn->data_buffer.find_zero<decltype(be), toku_cmd_leafval_heaviside>(
be,
&storeddata,
&key,
@@ -2012,7 +1990,7 @@ toku_ft_bn_apply_msg (
);
if (r == DB_NOTFOUND) break;
assert_zero(r);
- toku_ft_bn_apply_msg_once(bn, msg, idx, storeddata, gc_info, workdone, stats_to_update);
+ toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, gc_info, workdone, stats_to_update);
break;
}
@@ -2021,8 +1999,8 @@ toku_ft_bn_apply_msg (
case FT_COMMIT_BROADCAST_ALL:
case FT_OPTIMIZE:
// Apply to all leafentries
- num_klpairs = bn->data_buffer.num_klpairs();
- for (uint32_t idx = 0; idx < num_klpairs; ) {
+ omt_size = bn->data_buffer.omt_size();
+ for (uint32_t idx = 0; idx < omt_size; ) {
DBT curr_keydbt;
void* curr_keyp = NULL;
uint32_t curr_keylen = 0;
@@ -2030,32 +2008,31 @@ toku_ft_bn_apply_msg (
assert_zero(r);
toku_fill_dbt(&curr_keydbt, curr_keyp, curr_keylen);
// because this is a broadcast message, we need
- // to fill the key in the message that we pass into toku_ft_bn_apply_msg_once
- msg->u.id.key = &curr_keydbt;
+ // to fill the key in the msg that we pass into toku_ft_bn_apply_cmd_once
+ cmd->u.id.key = &curr_keydbt;
int deleted = 0;
if (!le_is_clean(storeddata)) { //If already clean, nothing to do.
- toku_ft_bn_apply_msg_once(bn, msg, idx, storeddata, gc_info, workdone, stats_to_update);
- // at this point, we cannot trust msg->u.id.key to be valid.
- uint32_t new_dmt_size = bn->data_buffer.num_klpairs();
- if (new_dmt_size != num_klpairs) {
- paranoid_invariant(new_dmt_size + 1 == num_klpairs);
+ toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, gc_info, workdone, stats_to_update);
+ uint32_t new_omt_size = bn->data_buffer.omt_size();
+ if (new_omt_size != omt_size) {
+ paranoid_invariant(new_omt_size+1 == omt_size);
//Item was deleted.
deleted = 1;
}
}
if (deleted)
- num_klpairs--;
+ omt_size--;
else
idx++;
}
- paranoid_invariant(bn->data_buffer.num_klpairs() == num_klpairs);
+ paranoid_invariant(bn->data_buffer.omt_size() == omt_size);
break;
case FT_COMMIT_BROADCAST_TXN:
case FT_ABORT_BROADCAST_TXN:
// Apply to all leafentries if txn is represented
- num_klpairs = bn->data_buffer.num_klpairs();
- for (uint32_t idx = 0; idx < num_klpairs; ) {
+ omt_size = bn->data_buffer.omt_size();
+ for (uint32_t idx = 0; idx < omt_size; ) {
DBT curr_keydbt;
void* curr_keyp = NULL;
uint32_t curr_keylen = 0;
@@ -2063,29 +2040,29 @@ toku_ft_bn_apply_msg (
assert_zero(r);
toku_fill_dbt(&curr_keydbt, curr_keyp, curr_keylen);
// because this is a broadcast message, we need
- // to fill the key in the message that we pass into toku_ft_bn_apply_msg_once
- msg->u.id.key = &curr_keydbt;
+ // to fill the key in the msg that we pass into toku_ft_bn_apply_cmd_once
+ cmd->u.id.key = &curr_keydbt;
int deleted = 0;
- if (le_has_xids(storeddata, msg->xids)) {
- toku_ft_bn_apply_msg_once(bn, msg, idx, storeddata, gc_info, workdone, stats_to_update);
- uint32_t new_dmt_size = bn->data_buffer.num_klpairs();
- if (new_dmt_size != num_klpairs) {
- paranoid_invariant(new_dmt_size + 1 == num_klpairs);
+ if (le_has_xids(storeddata, cmd->xids)) {
+ toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, gc_info, workdone, stats_to_update);
+ uint32_t new_omt_size = bn->data_buffer.omt_size();
+ if (new_omt_size != omt_size) {
+ paranoid_invariant(new_omt_size+1 == omt_size);
//Item was deleted.
deleted = 1;
}
}
if (deleted)
- num_klpairs--;
+ omt_size--;
else
idx++;
}
- paranoid_invariant(bn->data_buffer.num_klpairs() == num_klpairs);
+ paranoid_invariant(bn->data_buffer.omt_size() == omt_size);
break;
case FT_UPDATE: {
uint32_t idx;
- r = bn->data_buffer.find_zero<decltype(be), toku_msg_leafval_heaviside>(
+ r = bn->data_buffer.find_zero<decltype(be), toku_cmd_leafval_heaviside>(
be,
&storeddata,
&key,
@@ -2096,12 +2073,12 @@ toku_ft_bn_apply_msg (
{
//Point to msg's copy of the key so we don't worry about le being freed
//TODO: 46 MAYBE Get rid of this when le_apply message memory is better handled
- key = msg->u.id.key->data;
- keylen = msg->u.id.key->size;
+ key = cmd->u.id.key->data;
+ keylen = cmd->u.id.key->size;
}
- r = do_update(update_fun, desc, bn, msg, idx, NULL, NULL, 0, gc_info, workdone, stats_to_update);
+ r = do_update(update_fun, desc, bn, cmd, idx, NULL, NULL, 0, gc_info, workdone, stats_to_update);
} else if (r==0) {
- r = do_update(update_fun, desc, bn, msg, idx, storeddata, key, keylen, gc_info, workdone, stats_to_update);
+ r = do_update(update_fun, desc, bn, cmd, idx, storeddata, key, keylen, gc_info, workdone, stats_to_update);
} // otherwise, a worse error, just return it
break;
}
@@ -2109,7 +2086,7 @@ toku_ft_bn_apply_msg (
// apply to all leafentries.
uint32_t idx = 0;
uint32_t num_leafentries_before;
- while (idx < (num_leafentries_before = bn->data_buffer.num_klpairs())) {
+ while (idx < (num_leafentries_before = bn->data_buffer.omt_size())) {
void* curr_key = nullptr;
uint32_t curr_keylen = 0;
r = bn->data_buffer.fetch_klpair(idx, &storeddata, &curr_keylen, &curr_key);
@@ -2124,10 +2101,10 @@ toku_ft_bn_apply_msg (
// This is broken below. Have a compilation error checked
// in as a reminder
- r = do_update(update_fun, desc, bn, msg, idx, storeddata, curr_key, curr_keylen, gc_info, workdone, stats_to_update);
+ r = do_update(update_fun, desc, bn, cmd, idx, storeddata, curr_key, curr_keylen, gc_info, workdone, stats_to_update);
assert_zero(r);
- if (num_leafentries_before == bn->data_buffer.num_klpairs()) {
+ if (num_leafentries_before == bn->data_buffer.omt_size()) {
// we didn't delete something, so increment the index.
idx++;
}
@@ -2209,7 +2186,7 @@ void toku_bnc_insert_msg(NONLEAF_CHILDINFO bnc, const void *key, ITEMLEN keylen,
}
}
-// append a msg to a nonleaf node's child buffer
+// append a cmd to a nonleaf node's child buffer
// should be static, but used by test programs
void toku_ft_append_to_child_buffer(ft_compare_func compare_fun, DESCRIPTOR desc, FTNODE node, int childnum, enum ft_msg_type type, MSN msn, XIDS xids, bool is_fresh, const DBT *key, const DBT *val) {
paranoid_invariant(BP_STATE(node,childnum) == PT_AVAIL);
@@ -2217,14 +2194,14 @@ void toku_ft_append_to_child_buffer(ft_compare_func compare_fun, DESCRIPTOR desc
node->dirty = 1;
}
-static void ft_nonleaf_msg_once_to_child(ft_compare_func compare_fun, DESCRIPTOR desc, FTNODE node, int target_childnum, FT_MSG msg, bool is_fresh, size_t flow_deltas[])
+static void ft_nonleaf_cmd_once_to_child(ft_compare_func compare_fun, DESCRIPTOR desc, FTNODE node, int target_childnum, FT_MSG cmd, bool is_fresh, size_t flow_deltas[])
// Previously we had passive aggressive promotion, but that causes a lot of I/O a the checkpoint. So now we are just putting it in the buffer here.
// Also we don't worry about the node getting overfull here. It's the caller's problem.
{
unsigned int childnum = (target_childnum >= 0
? target_childnum
- : toku_ftnode_which_child(node, msg->u.id.key, desc, compare_fun));
- toku_ft_append_to_child_buffer(compare_fun, desc, node, childnum, msg->type, msg->msn, msg->xids, is_fresh, msg->u.id.key, msg->u.id.val);
+ : toku_ftnode_which_child(node, cmd->u.id.key, desc, compare_fun));
+ toku_ft_append_to_child_buffer(compare_fun, desc, node, childnum, cmd->type, cmd->msn, cmd->xids, is_fresh, cmd->u.id.key, cmd->u.id.val);
NONLEAF_CHILDINFO bnc = BNC(node, childnum);
bnc->flow[0] += flow_deltas[0];
bnc->flow[1] += flow_deltas[1];
@@ -2296,62 +2273,62 @@ static uint64_t
ft_msg_size(FT_MSG msg) {
size_t keyval_size = msg->u.id.key->size + msg->u.id.val->size;
size_t xids_size = xids_get_serialize_size(msg->xids);
- return keyval_size + KEY_VALUE_OVERHEAD + FT_MSG_OVERHEAD + xids_size;
+ return keyval_size + KEY_VALUE_OVERHEAD + FT_CMD_OVERHEAD + xids_size;
}
static void
-ft_nonleaf_msg_all(ft_compare_func compare_fun, DESCRIPTOR desc, FTNODE node, FT_MSG msg, bool is_fresh, size_t flow_deltas[])
-// Effect: Put the message into a nonleaf node. We put it into all children, possibly causing the children to become reactive.
+ft_nonleaf_cmd_all (ft_compare_func compare_fun, DESCRIPTOR desc, FTNODE node, FT_MSG cmd, bool is_fresh, size_t flow_deltas[])
+// Effect: Put the cmd into a nonleaf node. We put it into all children, possibly causing the children to become reactive.
// We don't do the splitting and merging. That's up to the caller after doing all the puts it wants to do.
// The re_array[i] gets set to the reactivity of any modified child i. (And there may be several such children.)
{
for (int i = 0; i < node->n_children; i++) {
- ft_nonleaf_msg_once_to_child(compare_fun, desc, node, i, msg, is_fresh, flow_deltas);
+ ft_nonleaf_cmd_once_to_child(compare_fun, desc, node, i, cmd, is_fresh, flow_deltas);
}
}
static bool
-ft_msg_applies_once(FT_MSG msg)
+ft_msg_applies_once(FT_MSG cmd)
{
- return ft_msg_type_applies_once(msg->type);
+ return ft_msg_type_applies_once(cmd->type);
}
static bool
-ft_msg_applies_all(FT_MSG msg)
+ft_msg_applies_all(FT_MSG cmd)
{
- return ft_msg_type_applies_all(msg->type);
+ return ft_msg_type_applies_all(cmd->type);
}
static bool
-ft_msg_does_nothing(FT_MSG msg)
+ft_msg_does_nothing(FT_MSG cmd)
{
- return ft_msg_type_does_nothing(msg->type);
+ return ft_msg_type_does_nothing(cmd->type);
}
static void
-ft_nonleaf_put_msg(ft_compare_func compare_fun, DESCRIPTOR desc, FTNODE node, int target_childnum, FT_MSG msg, bool is_fresh, size_t flow_deltas[])
-// Effect: Put the message into a nonleaf node. We may put it into a child, possibly causing the child to become reactive.
+ft_nonleaf_put_cmd (ft_compare_func compare_fun, DESCRIPTOR desc, FTNODE node, int target_childnum, FT_MSG cmd, bool is_fresh, size_t flow_deltas[])
+// Effect: Put the cmd into a nonleaf node. We may put it into a child, possibly causing the child to become reactive.
// We don't do the splitting and merging. That's up to the caller after doing all the puts it wants to do.
// The re_array[i] gets set to the reactivity of any modified child i. (And there may be several such children.)
//
{
//
- // see comments in toku_ft_leaf_apply_msg
+ // see comments in toku_ft_leaf_apply_cmd
// to understand why we handle setting
// node->max_msn_applied_to_node_on_disk here,
- // and don't do it in toku_ft_node_put_msg
+ // and don't do it in toku_ft_node_put_cmd
//
- MSN msg_msn = msg->msn;
- invariant(msg_msn.msn > node->max_msn_applied_to_node_on_disk.msn);
- node->max_msn_applied_to_node_on_disk = msg_msn;
-
- if (ft_msg_applies_once(msg)) {
- ft_nonleaf_msg_once_to_child(compare_fun, desc, node, target_childnum, msg, is_fresh, flow_deltas);
- } else if (ft_msg_applies_all(msg)) {
- ft_nonleaf_msg_all(compare_fun, desc, node, msg, is_fresh, flow_deltas);
+ MSN cmd_msn = cmd->msn;
+ invariant(cmd_msn.msn > node->max_msn_applied_to_node_on_disk.msn);
+ node->max_msn_applied_to_node_on_disk = cmd_msn;
+
+ if (ft_msg_applies_once(cmd)) {
+ ft_nonleaf_cmd_once_to_child(compare_fun, desc, node, target_childnum, cmd, is_fresh, flow_deltas);
+ } else if (ft_msg_applies_all(cmd)) {
+ ft_nonleaf_cmd_all(compare_fun, desc, node, cmd, is_fresh, flow_deltas);
} else {
- paranoid_invariant(ft_msg_does_nothing(msg));
+ paranoid_invariant(ft_msg_does_nothing(cmd));
}
}
@@ -2431,7 +2408,7 @@ basement_node_gc_all_les(BASEMENTNODE bn,
int r = 0;
uint32_t index = 0;
uint32_t num_leafentries_before;
- while (index < (num_leafentries_before = bn->data_buffer.num_klpairs())) {
+ while (index < (num_leafentries_before = bn->data_buffer.omt_size())) {
void* keyp = NULL;
uint32_t keylen = 0;
LEAFENTRY leaf_entry;
@@ -2447,7 +2424,7 @@ basement_node_gc_all_les(BASEMENTNODE bn,
delta
);
// Check if the leaf entry was deleted or not.
- if (num_leafentries_before == bn->data_buffer.num_klpairs()) {
+ if (num_leafentries_before == bn->data_buffer.omt_size()) {
++index;
}
}
@@ -2532,7 +2509,7 @@ void toku_bnc_flush_to_child(
bnc->buffer, key, keylen, val, vallen, type, msn, xids, is_fresh,
({
DBT hk,hv;
- FT_MSG_S ftmsg = { type, msn, xids, .u = { .id = { toku_fill_dbt(&hk, key, keylen),
+ FT_MSG_S ftcmd = { type, msn, xids, .u = { .id = { toku_fill_dbt(&hk, key, keylen),
toku_fill_dbt(&hv, val, vallen) } } };
size_t flow_deltas[] = { 0, 0 };
if (remaining_memsize <= bnc->flow[0]) {
@@ -2544,13 +2521,13 @@ void toku_bnc_flush_to_child(
// end of the fifo
flow_deltas[1] = FIFO_CURRENT_ENTRY_MEMSIZE;
}
- toku_ft_node_put_msg(
+ toku_ft_node_put_cmd(
ft->compare_fun,
ft->update_fun,
&ft->cmp_descriptor,
child,
-1,
- &ftmsg,
+ &ftcmd,
is_fresh,
&gc_info,
flow_deltas,
@@ -2579,35 +2556,35 @@ bool toku_bnc_should_promote(FT ft, NONLEAF_CHILDINFO bnc) {
}
void
-toku_ft_node_put_msg (
+toku_ft_node_put_cmd (
ft_compare_func compare_fun,
ft_update_func update_fun,
DESCRIPTOR desc,
FTNODE node,
int target_childnum,
- FT_MSG msg,
+ FT_MSG cmd,
bool is_fresh,
txn_gc_info *gc_info,
size_t flow_deltas[],
STAT64INFO stats_to_update
)
-// Effect: Push message into the subtree rooted at NODE.
+// Effect: Push CMD into the subtree rooted at NODE.
// If NODE is a leaf, then
-// put message into leaf, applying it to the leafentries
-// If NODE is a nonleaf, then push the message into the FIFO(s) of the relevent child(ren).
+// put CMD into leaf, applying it to the leafentries
+// If NODE is a nonleaf, then push the cmd into the FIFO(s) of the relevent child(ren).
// The node may become overfull. That's not our problem.
{
toku_assert_entire_node_in_memory(node);
//
- // see comments in toku_ft_leaf_apply_msg
+ // see comments in toku_ft_leaf_apply_cmd
// to understand why we don't handle setting
// node->max_msn_applied_to_node_on_disk here,
// and instead defer to these functions
//
if (node->height==0) {
- toku_ft_leaf_apply_msg(compare_fun, update_fun, desc, node, target_childnum, msg, gc_info, nullptr, stats_to_update);
+ toku_ft_leaf_apply_cmd(compare_fun, update_fun, desc, node, target_childnum, cmd, gc_info, nullptr, stats_to_update);
} else {
- ft_nonleaf_put_msg(compare_fun, desc, node, target_childnum, msg, is_fresh, flow_deltas);
+ ft_nonleaf_put_cmd(compare_fun, desc, node, target_childnum, cmd, is_fresh, flow_deltas);
}
}
@@ -2615,16 +2592,16 @@ static const struct pivot_bounds infinite_bounds = {.lower_bound_exclusive=NULL,
.upper_bound_inclusive=NULL};
-// Effect: applies the message to the leaf if the appropriate basement node is in memory.
+// Effect: applies the cmd to the leaf if the appropriate basement node is in memory.
// This function is called during message injection and/or flushing, so the entire
// node MUST be in memory.
-void toku_ft_leaf_apply_msg(
+void toku_ft_leaf_apply_cmd(
ft_compare_func compare_fun,
ft_update_func update_fun,
DESCRIPTOR desc,
FTNODE node,
int target_childnum, // which child to inject to, or -1 if unknown
- FT_MSG msg,
+ FT_MSG cmd,
txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
@@ -2634,7 +2611,7 @@ void toku_ft_leaf_apply_msg(
toku_assert_entire_node_in_memory(node);
//
- // Because toku_ft_leaf_apply_msg is called with the intent of permanently
+ // Because toku_ft_leaf_apply_cmd is called with the intent of permanently
// applying a message to a leaf node (meaning the message is permanently applied
// and will be purged from the system after this call, as opposed to
// toku_apply_ancestors_messages_to_node, which applies a message
@@ -2647,29 +2624,29 @@ void toku_ft_leaf_apply_msg(
//
// we cannot blindly update node->max_msn_applied_to_node_on_disk,
// we must check to see if the msn is greater that the one already stored,
- // because the message may have already been applied earlier (via
+ // because the cmd may have already been applied earlier (via
// toku_apply_ancestors_messages_to_node) to answer a query
//
// This is why we handle node->max_msn_applied_to_node_on_disk both here
- // and in ft_nonleaf_put_msg, as opposed to in one location, toku_ft_node_put_msg.
+ // and in ft_nonleaf_put_cmd, as opposed to in one location, toku_ft_node_put_cmd.
//
- MSN msg_msn = msg->msn;
- if (msg_msn.msn > node->max_msn_applied_to_node_on_disk.msn) {
- node->max_msn_applied_to_node_on_disk = msg_msn;
+ MSN cmd_msn = cmd->msn;
+ if (cmd_msn.msn > node->max_msn_applied_to_node_on_disk.msn) {
+ node->max_msn_applied_to_node_on_disk = cmd_msn;
}
- if (ft_msg_applies_once(msg)) {
+ if (ft_msg_applies_once(cmd)) {
unsigned int childnum = (target_childnum >= 0
? target_childnum
- : toku_ftnode_which_child(node, msg->u.id.key, desc, compare_fun));
+ : toku_ftnode_which_child(node, cmd->u.id.key, desc, compare_fun));
BASEMENTNODE bn = BLB(node, childnum);
- if (msg->msn.msn > bn->max_msn_applied.msn) {
- bn->max_msn_applied = msg->msn;
- toku_ft_bn_apply_msg(compare_fun,
+ if (cmd->msn.msn > bn->max_msn_applied.msn) {
+ bn->max_msn_applied = cmd->msn;
+ toku_ft_bn_apply_cmd(compare_fun,
update_fun,
desc,
bn,
- msg,
+ cmd,
gc_info,
workdone,
stats_to_update);
@@ -2677,15 +2654,15 @@ void toku_ft_leaf_apply_msg(
STATUS_INC(FT_MSN_DISCARDS, 1);
}
}
- else if (ft_msg_applies_all(msg)) {
+ else if (ft_msg_applies_all(cmd)) {
for (int childnum=0; childnum<node->n_children; childnum++) {
- if (msg->msn.msn > BLB(node, childnum)->max_msn_applied.msn) {
- BLB(node, childnum)->max_msn_applied = msg->msn;
- toku_ft_bn_apply_msg(compare_fun,
+ if (cmd->msn.msn > BLB(node, childnum)->max_msn_applied.msn) {
+ BLB(node, childnum)->max_msn_applied = cmd->msn;
+ toku_ft_bn_apply_cmd(compare_fun,
update_fun,
desc,
BLB(node, childnum),
- msg,
+ cmd,
gc_info,
workdone,
stats_to_update);
@@ -2694,7 +2671,7 @@ void toku_ft_leaf_apply_msg(
}
}
}
- else if (!ft_msg_does_nothing(msg)) {
+ else if (!ft_msg_does_nothing(cmd)) {
abort();
}
VERIFY_NODE(t, node);
@@ -2704,7 +2681,7 @@ static void inject_message_in_locked_node(
FT ft,
FTNODE node,
int childnum,
- FT_MSG_S *msg,
+ FT_MSG_S *cmd,
size_t flow_deltas[],
txn_gc_info *gc_info
)
@@ -2729,16 +2706,16 @@ static void inject_message_in_locked_node(
// Get the MSN from the header. Now that we have a write lock on the
// node we're injecting into, we know no other thread will get an MSN
// after us and get that message into our subtree before us.
- msg->msn.msn = toku_sync_add_and_fetch(&ft->h->max_msn_in_ft.msn, 1);
- paranoid_invariant(msg->msn.msn > node->max_msn_applied_to_node_on_disk.msn);
+ cmd->msn.msn = toku_sync_add_and_fetch(&ft->h->max_msn_in_ft.msn, 1);
+ paranoid_invariant(cmd->msn.msn > node->max_msn_applied_to_node_on_disk.msn);
STAT64INFO_S stats_delta = {0,0};
- toku_ft_node_put_msg(
+ toku_ft_node_put_cmd(
ft->compare_fun,
ft->update_fun,
&ft->cmp_descriptor,
node,
childnum,
- msg,
+ cmd,
true,
gc_info,
flow_deltas,
@@ -2748,7 +2725,7 @@ static void inject_message_in_locked_node(
toku_ft_update_stats(&ft->in_memory_stats, stats_delta);
}
//
- // assumption is that toku_ft_node_put_msg will
+ // assumption is that toku_ft_node_put_cmd will
// mark the node as dirty.
// enforcing invariant here.
//
@@ -2757,27 +2734,17 @@ static void inject_message_in_locked_node(
// TODO: Why not at height 0?
// update some status variables
if (node->height != 0) {
- uint64_t msgsize = ft_msg_size(msg);
+ uint64_t msgsize = ft_msg_size(cmd);
STATUS_INC(FT_MSG_BYTES_IN, msgsize);
STATUS_INC(FT_MSG_BYTES_CURR, msgsize);
STATUS_INC(FT_MSG_NUM, 1);
- if (ft_msg_applies_all(msg)) {
+ if (ft_msg_applies_all(cmd)) {
STATUS_INC(FT_MSG_NUM_BROADCAST, 1);
}
}
// verify that msn of latest message was captured in root node
- paranoid_invariant(msg->msn.msn == node->max_msn_applied_to_node_on_disk.msn);
-
- if (node->thisnodename.b == ft->rightmost_blocknum.b) {
- if (ft->seqinsert_score < FT_SEQINSERT_SCORE_THRESHOLD) {
- // we promoted to the rightmost leaf node and the seqinsert score has not yet saturated.
- toku_sync_fetch_and_add(&ft->seqinsert_score, 1);
- }
- } else if (ft->seqinsert_score != 0) {
- // we promoted to something other than the rightmost leaf node and the score should reset
- ft->seqinsert_score = 0;
- }
+ paranoid_invariant(cmd->msn.msn == node->max_msn_applied_to_node_on_disk.msn);
// if we call toku_ft_flush_some_child, then that function unpins the root
// otherwise, we unpin ourselves
@@ -2801,6 +2768,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
// Effect:
// If child needs to be split or merged, do that.
// parent and child will be unlocked if this happens
+// also, the batched pin will have ended if this happens
// Requires: parent and child are read locked
// Returns:
// true if relocking is needed
@@ -2825,7 +2793,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, ft);
FTNODE newparent, newchild;
- toku_pin_ftnode(ft, parent_blocknum, parent_fullhash, &bfe, PL_WRITE_CHEAP, &newparent, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, parent_blocknum, parent_fullhash, &bfe, PL_WRITE_CHEAP, 0, nullptr, &newparent);
if (newparent->height != parent_height || newparent->n_children != parent_n_children ||
childnum >= newparent->n_children || toku_bnc_n_entries(BNC(newparent, childnum))) {
// If the height changed or childnum is now off the end, something clearly got split or merged out from under us.
@@ -2839,7 +2807,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
// and split it.
child_blocknum = BP_BLOCKNUM(newparent, childnum);
child_fullhash = compute_child_fullhash(ft->cf, newparent, childnum);
- toku_pin_ftnode_with_dep_nodes(ft, child_blocknum, child_fullhash, &bfe, PL_WRITE_CHEAP, 1, &newparent, &newchild, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, child_blocknum, child_fullhash, &bfe, PL_WRITE_CHEAP, 1, &newparent, &newchild);
newre = get_node_reactivity(ft, newchild);
if (newre == RE_FISSIBLE) {
enum split_mode split_mode;
@@ -2877,7 +2845,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, ft);
FTNODE newparent, newchild;
- toku_pin_ftnode(ft, parent_blocknum, parent_fullhash, &bfe, PL_WRITE_CHEAP, &newparent, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, parent_blocknum, parent_fullhash, &bfe, PL_WRITE_CHEAP, 0, nullptr, &newparent);
if (newparent->height != parent_height || childnum >= newparent->n_children) {
// looks like this is the root and it got merged, let's just start over (like in the split case above)
toku_unpin_ftnode_read_only(ft, newparent);
@@ -2885,7 +2853,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
}
child_blocknum = BP_BLOCKNUM(newparent, childnum);
child_fullhash = compute_child_fullhash(ft->cf, newparent, childnum);
- toku_pin_ftnode_with_dep_nodes(ft, child_blocknum, child_fullhash, &bfe, PL_READ, 1, &newparent, &newchild, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, child_blocknum, child_fullhash, &bfe, PL_READ, 1, &newparent, &newchild);
newre = get_node_reactivity(ft, newchild);
if (newre == RE_FUSIBLE && newparent->n_children >= 2) {
toku_unpin_ftnode_read_only(ft, newchild);
@@ -2909,20 +2877,20 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
abort();
}
-static void inject_message_at_this_blocknum(FT ft, CACHEKEY cachekey, uint32_t fullhash, FT_MSG_S *msg, size_t flow_deltas[], txn_gc_info *gc_info)
+static void inject_message_at_this_blocknum(FT ft, CACHEKEY cachekey, uint32_t fullhash, FT_MSG_S *cmd, size_t flow_deltas[], txn_gc_info *gc_info)
// Effect:
-// Inject message into the node at this blocknum (cachekey).
+// Inject cmd into the node at this blocknum (cachekey).
// Gets a write lock on the node for you.
{
toku::context inject_ctx(CTX_MESSAGE_INJECTION);
FTNODE node;
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, ft);
- toku_pin_ftnode(ft, cachekey, fullhash, &bfe, PL_WRITE_CHEAP, &node, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, cachekey, fullhash, &bfe, PL_WRITE_CHEAP, 0, NULL, &node);
toku_assert_entire_node_in_memory(node);
paranoid_invariant(node->fullhash==fullhash);
ft_verify_flags(ft, node);
- inject_message_in_locked_node(ft, node, -1, msg, flow_deltas, gc_info);
+ inject_message_in_locked_node(ft, node, -1, cmd, flow_deltas, gc_info);
}
__attribute__((const))
@@ -2935,26 +2903,11 @@ static inline bool should_inject_in_node(seqinsert_loc loc, int height, int dept
return (height == 0 || (loc == NEITHER_EXTREME && (height <= 1 || depth >= 2)));
}
-static void ft_set_or_verify_rightmost_blocknum(FT ft, BLOCKNUM b)
-// Given: 'b', the _definitive_ and constant rightmost blocknum of 'ft'
-{
- if (ft->rightmost_blocknum.b == RESERVED_BLOCKNUM_NULL) {
- toku_ft_lock(ft);
- if (ft->rightmost_blocknum.b == RESERVED_BLOCKNUM_NULL) {
- ft->rightmost_blocknum = b;
- }
- toku_ft_unlock(ft);
- }
- // The rightmost blocknum only transitions from RESERVED_BLOCKNUM_NULL to non-null.
- // If it's already set, verify that the stored value is consistent with 'b'
- invariant(ft->rightmost_blocknum.b == b.b);
-}
-
static void push_something_in_subtree(
FT ft,
FTNODE subtree_root,
int target_childnum,
- FT_MSG_S *msg,
+ FT_MSG_S *cmd,
size_t flow_deltas[],
txn_gc_info *gc_info,
int depth,
@@ -2962,8 +2915,8 @@ static void push_something_in_subtree(
bool just_did_split_or_merge
)
// Effects:
-// Assign message an MSN from ft->h.
-// Put message in the subtree rooted at node. Due to promotion the message may not be injected directly in this node.
+// Assign cmd an MSN from ft->h.
+// Put cmd in the subtree rooted at node. Due to promotion the message may not be injected directly in this node.
// Unlock node or schedule it to be unlocked (after a background flush).
// Either way, the caller is not responsible for unlocking node.
// Requires:
@@ -2997,25 +2950,17 @@ static void push_something_in_subtree(
default:
STATUS_INC(FT_PRO_NUM_INJECT_DEPTH_GT3, 1); break;
}
- // If the target node is a non-root leaf node on the right extreme,
- // set the rightmost blocknum. We know there are no messages above us
- // because promotion would not chose to inject directly into this leaf
- // otherwise. We explicitly skip the root node because then we don't have
- // to worry about changing the rightmost blocknum when the root splits.
- if (subtree_root->height == 0 && loc == RIGHT_EXTREME && subtree_root->thisnodename.b != ft->h->root_blocknum.b) {
- ft_set_or_verify_rightmost_blocknum(ft, subtree_root->thisnodename);
- }
- inject_message_in_locked_node(ft, subtree_root, target_childnum, msg, flow_deltas, gc_info);
+ inject_message_in_locked_node(ft, subtree_root, target_childnum, cmd, flow_deltas, gc_info);
} else {
int r;
int childnum;
NONLEAF_CHILDINFO bnc;
- // toku_ft_root_put_msg should not have called us otherwise.
- paranoid_invariant(ft_msg_applies_once(msg));
+ // toku_ft_root_put_cmd should not have called us otherwise.
+ paranoid_invariant(ft_msg_applies_once(cmd));
childnum = (target_childnum >= 0 ? target_childnum
- : toku_ftnode_which_child(subtree_root, msg->u.id.key, &ft->cmp_descriptor, ft->compare_fun));
+ : toku_ftnode_which_child(subtree_root, cmd->u.id.key, &ft->cmp_descriptor, ft->compare_fun));
bnc = BNC(subtree_root, childnum);
if (toku_bnc_n_entries(bnc) > 0) {
@@ -3064,11 +3009,11 @@ static void push_something_in_subtree(
if (lock_type == PL_WRITE_CHEAP) {
// We intend to take the write lock for message injection
toku::context inject_ctx(CTX_MESSAGE_INJECTION);
- toku_pin_ftnode(ft, child_blocknum, child_fullhash, &bfe, lock_type, &child, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, child_blocknum, child_fullhash, &bfe, lock_type, 0, nullptr, &child);
} else {
// We're going to keep promoting
toku::context promo_ctx(CTX_PROMO);
- toku_pin_ftnode(ft, child_blocknum, child_fullhash, &bfe, lock_type, &child, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, child_blocknum, child_fullhash, &bfe, lock_type, 0, nullptr, &child);
}
} else {
r = toku_maybe_pin_ftnode_clean(ft, child_blocknum, child_fullhash, lock_type, &child);
@@ -3101,14 +3046,14 @@ static void push_something_in_subtree(
FTNODE newparent;
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, ft); // should be fully in memory, we just split it
- toku_pin_ftnode(ft, subtree_root_blocknum, subtree_root_fullhash, &bfe, PL_READ, &newparent, true);
- push_something_in_subtree(ft, newparent, -1, msg, flow_deltas, gc_info, depth, loc, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, subtree_root_blocknum, subtree_root_fullhash, &bfe, PL_READ, 0, nullptr, &newparent);
+ push_something_in_subtree(ft, newparent, -1, cmd, flow_deltas, gc_info, depth, loc, true);
return;
}
}
if (next_loc != NEITHER_EXTREME || child->dirty || toku_bnc_should_promote(ft, bnc)) {
- push_something_in_subtree(ft, child, -1, msg, flow_deltas, gc_info, depth + 1, next_loc, false);
+ push_something_in_subtree(ft, child, -1, cmd, flow_deltas, gc_info, depth + 1, next_loc, false);
toku_sync_fetch_and_add(&bnc->flow[0], flow_deltas[0]);
// The recursive call unpinned the child, but
// we're responsible for unpinning subtree_root.
@@ -3144,19 +3089,19 @@ static void push_something_in_subtree(
default:
STATUS_INC(FT_PRO_NUM_INJECT_DEPTH_GT3, 1); break;
}
- inject_message_at_this_blocknum(ft, subtree_root_blocknum, subtree_root_fullhash, msg, flow_deltas, gc_info);
+ inject_message_at_this_blocknum(ft, subtree_root_blocknum, subtree_root_fullhash, cmd, flow_deltas, gc_info);
}
}
}
-void toku_ft_root_put_msg(
+void toku_ft_root_put_cmd(
FT ft,
- FT_MSG_S *msg,
+ FT_MSG_S *cmd,
txn_gc_info *gc_info
)
// Effect:
-// - assign msn to message and update msn in the header
-// - push the message into the ft
+// - assign msn to cmd and update msn in the header
+// - push the cmd into the ft
// As of Clayface, the root blocknum is a constant, so preventing a
// race between message injection and the split of a root is the job
@@ -3189,7 +3134,7 @@ void toku_ft_root_put_msg(
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, ft);
- size_t flow_deltas[] = { toku_ft_msg_memsize_in_fifo(msg), 0 };
+ size_t flow_deltas[] = { toku_ft_msg_memsize_in_fifo(cmd), 0 };
pair_lock_type lock_type;
lock_type = PL_READ; // try first for a read lock
@@ -3198,7 +3143,7 @@ void toku_ft_root_put_msg(
// and jump back to here.
change_lock_type:
// get the root node
- toku_pin_ftnode(ft, root_key, fullhash, &bfe, lock_type, &node, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, root_key, fullhash, &bfe, lock_type, 0, NULL, &node);
toku_assert_entire_node_in_memory(node);
paranoid_invariant(node->fullhash==fullhash);
ft_verify_flags(ft, node);
@@ -3235,7 +3180,7 @@ void toku_ft_root_put_msg(
ft_init_new_root(ft, node, &node);
// Then downgrade back to a read lock, and we can finally
// do the injection.
- toku_unpin_ftnode(ft, node);
+ toku_unpin_ftnode_off_client_thread(ft, node);
lock_type = PL_READ;
STATUS_INC(FT_PRO_NUM_ROOT_SPLIT, 1);
goto change_lock_type;
@@ -3251,286 +3196,33 @@ void toku_ft_root_put_msg(
// anyway.
// Now, either inject here or promote. We decide based on a heuristic:
- if (node->height == 0 || !ft_msg_applies_once(msg)) {
+ if (node->height == 0 || !ft_msg_applies_once(cmd)) {
// If the root's a leaf or we're injecting a broadcast, drop the read lock and inject here.
toku_unpin_ftnode_read_only(ft, node);
STATUS_INC(FT_PRO_NUM_ROOT_H0_INJECT, 1);
- inject_message_at_this_blocknum(ft, root_key, fullhash, msg, flow_deltas, gc_info);
+ inject_message_at_this_blocknum(ft, root_key, fullhash, cmd, flow_deltas, gc_info);
} else if (node->height > 1) {
// If the root's above height 1, we are definitely eligible for promotion.
- push_something_in_subtree(ft, node, -1, msg, flow_deltas, gc_info, 0, LEFT_EXTREME | RIGHT_EXTREME, false);
+ push_something_in_subtree(ft, node, -1, cmd, flow_deltas, gc_info, 0, LEFT_EXTREME | RIGHT_EXTREME, false);
} else {
// The root's height 1. We may be eligible for promotion here.
// On the extremes, we want to promote, in the middle, we don't.
- int childnum = toku_ftnode_which_child(node, msg->u.id.key, &ft->cmp_descriptor, ft->compare_fun);
+ int childnum = toku_ftnode_which_child(node, cmd->u.id.key, &ft->cmp_descriptor, ft->compare_fun);
if (childnum == 0 || childnum == node->n_children - 1) {
// On the extremes, promote. We know which childnum we're going to, so pass that down too.
- push_something_in_subtree(ft, node, childnum, msg, flow_deltas, gc_info, 0, LEFT_EXTREME | RIGHT_EXTREME, false);
+ push_something_in_subtree(ft, node, childnum, cmd, flow_deltas, gc_info, 0, LEFT_EXTREME | RIGHT_EXTREME, false);
} else {
// At height 1 in the middle, don't promote, drop the read lock and inject here.
toku_unpin_ftnode_read_only(ft, node);
STATUS_INC(FT_PRO_NUM_ROOT_H1_INJECT, 1);
- inject_message_at_this_blocknum(ft, root_key, fullhash, msg, flow_deltas, gc_info);
- }
- }
-}
-
-static int ft_compare_keys(FT ft, const DBT *a, const DBT *b)
-// Effect: Compare two keys using the given fractal tree's comparator/descriptor
-{
- FAKE_DB(db, &ft->cmp_descriptor);
- return ft->compare_fun(&db, a, b);
-}
-
-static LEAFENTRY bn_get_le_and_key(BASEMENTNODE bn, int idx, DBT *key)
-// Effect: Gets the i'th leafentry from the given basement node and
-// fill its key in *key
-// Requires: The i'th leafentry exists.
-{
- LEAFENTRY le;
- uint32_t le_len;
- void *le_key;
- int r = bn->data_buffer.fetch_klpair(idx, &le, &le_len, &le_key);
- invariant_zero(r);
- toku_fill_dbt(key, le_key, le_len);
- return le;
-}
-
-static LEAFENTRY ft_leaf_leftmost_le_and_key(FTNODE leaf, DBT *leftmost_key)
-// Effect: If a leftmost key exists in the given leaf, toku_fill_dbt()
-// the key into *leftmost_key
-// Requires: Leaf is fully in memory and pinned for read or write.
-// Return: leafentry if it exists, nullptr otherwise
-{
- for (int i = 0; i < leaf->n_children; i++) {
- BASEMENTNODE bn = BLB(leaf, i);
- if (bn->data_buffer.num_klpairs() > 0) {
- // Get the first (leftmost) leafentry and its key
- return bn_get_le_and_key(bn, 0, leftmost_key);
- }
- }
- return nullptr;
-}
-
-static LEAFENTRY ft_leaf_rightmost_le_and_key(FTNODE leaf, DBT *rightmost_key)
-// Effect: If a rightmost key exists in the given leaf, toku_fill_dbt()
-// the key into *rightmost_key
-// Requires: Leaf is fully in memory and pinned for read or write.
-// Return: leafentry if it exists, nullptr otherwise
-{
- for (int i = leaf->n_children - 1; i >= 0; i--) {
- BASEMENTNODE bn = BLB(leaf, i);
- size_t num_les = bn->data_buffer.num_klpairs();
- if (num_les > 0) {
- // Get the last (rightmost) leafentry and its key
- return bn_get_le_and_key(bn, num_les - 1, rightmost_key);
- }
- }
- return nullptr;
-}
-
-static int ft_leaf_get_relative_key_pos(FT ft, FTNODE leaf, const DBT *key, bool *nondeleted_key_found, int *target_childnum)
-// Effect: Determines what the relative position of the given key is with
-// respect to a leaf node, and if it exists.
-// Requires: Leaf is fully in memory and pinned for read or write.
-// Requires: target_childnum is non-null
-// Return: < 0 if key is less than the leftmost key in the leaf OR the relative position is unknown, for any reason.
-// 0 if key is in the bounds [leftmost_key, rightmost_key] for this leaf or the leaf is empty
-// > 0 if key is greater than the rightmost key in the leaf
-// *nondeleted_key_found is set (if non-null) if the target key was found and is not deleted, unmodified otherwise
-// *target_childnum is set to the child that (does or would) contain the key, if calculated, unmodified otherwise
-{
- DBT rightmost_key;
- LEAFENTRY rightmost_le = ft_leaf_rightmost_le_and_key(leaf, &rightmost_key);
- if (rightmost_le == nullptr) {
- // If we can't get a rightmost key then the leaf is empty.
- // In such a case, we don't have any information about what keys would be in this leaf.
- // We have to assume the leaf node that would contain this key is to the left.
- return -1;
- }
- // We have a rightmost leafentry, so it must exist in some child node
- invariant(leaf->n_children > 0);
-
- int relative_pos = 0;
- int c = ft_compare_keys(ft, key, &rightmost_key);
- if (c > 0) {
- relative_pos = 1;
- *target_childnum = leaf->n_children - 1;
- } else if (c == 0) {
- if (nondeleted_key_found != nullptr && !le_latest_is_del(rightmost_le)) {
- *nondeleted_key_found = true;
- }
- relative_pos = 0;
- *target_childnum = leaf->n_children - 1;
- } else {
- // The key is less than the rightmost. It may still be in bounds if it's >= the leftmost.
- DBT leftmost_key;
- LEAFENTRY leftmost_le = ft_leaf_leftmost_le_and_key(leaf, &leftmost_key);
- invariant_notnull(leftmost_le); // Must exist because a rightmost exists
- c = ft_compare_keys(ft, key, &leftmost_key);
- if (c > 0) {
- if (nondeleted_key_found != nullptr) {
- // The caller wants to know if a nondeleted key can be found.
- LEAFENTRY target_le;
- int childnum = toku_ftnode_which_child(leaf, key, &ft->cmp_descriptor, ft->compare_fun);
- BASEMENTNODE bn = BLB(leaf, childnum);
- struct msg_leafval_heaviside_extra extra = { ft->compare_fun, &ft->cmp_descriptor, key };
- int r = bn->data_buffer.find_zero<decltype(extra), toku_msg_leafval_heaviside>(
- extra,
- &target_le,
- nullptr, nullptr, nullptr
- );
- *target_childnum = childnum;
- if (r == 0 && !le_latest_is_del(leftmost_le)) {
- *nondeleted_key_found = true;
- }
- }
- relative_pos = 0;
- } else if (c == 0) {
- if (nondeleted_key_found != nullptr && !le_latest_is_del(leftmost_le)) {
- *nondeleted_key_found = true;
- }
- relative_pos = 0;
- *target_childnum = 0;
- } else {
- relative_pos = -1;
- }
- }
-
- return relative_pos;
-}
-
-static void ft_insert_directly_into_leaf(FT ft, FTNODE leaf, int target_childnum, DBT *key, DBT *val,
- XIDS message_xids, enum ft_msg_type type, txn_gc_info *gc_info);
-static int getf_nothing(ITEMLEN, bytevec, ITEMLEN, bytevec, void *, bool);
-
-static int ft_maybe_insert_into_rightmost_leaf(FT ft, DBT *key, DBT *val, XIDS message_xids, enum ft_msg_type type,
- txn_gc_info *gc_info, bool unique)
-// Effect: Pins the rightmost leaf node and attempts to do an insert.
-// There are three reasons why we may not succeed.
-// - The rightmost leaf is too full and needs a split.
-// - The key to insert is not within the provable bounds of this leaf node.
-// - The key is within bounds, but it already exists.
-// Return: 0 if this function did insert, DB_KEYEXIST if a unique key constraint exists and
-// some nondeleted leafentry with the same key exists
-// < 0 if this function did not insert, for a reason other than DB_KEYEXIST.
-// Note: Treat this function as a possible, but not necessary, optimization for insert.
-// Rationale: We want O(1) insertions down the rightmost path of the tree.
-{
- int r = -1;
-
- uint32_t rightmost_fullhash;
- BLOCKNUM rightmost_blocknum = ft->rightmost_blocknum;
- FTNODE rightmost_leaf = nullptr;
-
- // Don't do the optimization if our heurstic suggests that
- // insertion pattern is not sequential.
- if (ft->seqinsert_score < FT_SEQINSERT_SCORE_THRESHOLD) {
- goto cleanup;
- }
-
- // We know the seqinsert score is high enough that we should
- // attemp to directly insert into the right most leaf. Because
- // the score is non-zero, the rightmost blocknum must have been
- // set. See inject_message_in_locked_node(), which only increases
- // the score if the target node blocknum == rightmost_blocknum
- invariant(rightmost_blocknum.b != RESERVED_BLOCKNUM_NULL);
-
- // Pin the rightmost leaf with a write lock.
- rightmost_fullhash = toku_cachetable_hash(ft->cf, rightmost_blocknum);
- struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft);
- toku_pin_ftnode(ft, rightmost_blocknum, rightmost_fullhash, &bfe, PL_WRITE_CHEAP, &rightmost_leaf, true);
-
- // The rightmost blocknum never chances once it is initialized to something
- // other than null. Verify that the pinned node has the correct blocknum.
- invariant(rightmost_leaf->thisnodename.b == rightmost_blocknum.b);
-
- // If the rightmost leaf is reactive, bail out out and let the normal promotion pass
- // take care of it. This also ensures that if any of our ancestors are reactive,
- // they'll be taken care of too.
- if (get_leaf_reactivity(rightmost_leaf, ft->h->nodesize) != RE_STABLE) {
- STATUS_INC(FT_PRO_RIGHTMOST_LEAF_SHORTCUT_FAIL_REACTIVE, 1);
- goto cleanup;
- }
-
- // The groundwork has been laid for an insertion directly into the rightmost
- // leaf node. We know that it is pinned for write, fully in memory, has
- // no messages above it, and is not reactive.
- //
- // Now, two more things must be true for this insertion to actually happen:
- // 1. The key to insert is within the bounds of this leafnode, or to the right.
- // 2. If there is a uniqueness constraint, it passes.
- bool nondeleted_key_found;
- int relative_pos;
- int target_childnum;
-
- nondeleted_key_found = false;
- target_childnum = -1;
- relative_pos = ft_leaf_get_relative_key_pos(ft, rightmost_leaf, key,
- unique ? &nondeleted_key_found : nullptr,
- &target_childnum);
- if (relative_pos >= 0) {
- STATUS_INC(FT_PRO_RIGHTMOST_LEAF_SHORTCUT_SUCCESS, 1);
- if (unique && nondeleted_key_found) {
- r = DB_KEYEXIST;
- } else {
- ft_insert_directly_into_leaf(ft, rightmost_leaf, target_childnum,
- key, val, message_xids, type, gc_info);
- r = 0;
+ inject_message_at_this_blocknum(ft, root_key, fullhash, cmd, flow_deltas, gc_info);
}
- } else {
- STATUS_INC(FT_PRO_RIGHTMOST_LEAF_SHORTCUT_FAIL_POS, 1);
- r = -1;
- }
-
-cleanup:
- // If we did the insert, the rightmost leaf was unpinned for us.
- if (r != 0 && rightmost_leaf != nullptr) {
- toku_unpin_ftnode(ft, rightmost_leaf);
}
-
- return r;
}
-
-static void ft_txn_log_insert(FT ft, DBT *key, DBT *val, TOKUTXN txn, bool do_logging, enum ft_msg_type type);
-
-int toku_ft_insert_unique(FT_HANDLE ft_h, DBT *key, DBT *val, TOKUTXN txn, bool do_logging) {
-// Effect: Insert a unique key-val pair into the fractal tree.
-// Return: 0 on success, DB_KEYEXIST if the overwrite constraint failed
- XIDS message_xids = txn != nullptr ? toku_txn_get_xids(txn) : xids_get_root_xids();
- TXN_MANAGER txn_manager = toku_ft_get_txn_manager(ft_h);
- txn_manager_state txn_state_for_gc(txn_manager);
-
- TXNID oldest_referenced_xid_estimate = toku_ft_get_oldest_referenced_xid_estimate(ft_h);
- txn_gc_info gc_info(&txn_state_for_gc,
- oldest_referenced_xid_estimate,
- // no messages above us, we can implicitly promote uxrs based on this xid
- oldest_referenced_xid_estimate,
- true);
- int r = ft_maybe_insert_into_rightmost_leaf(ft_h->ft, key, val, message_xids, FT_INSERT, &gc_info, true);
- if (r != 0 && r != DB_KEYEXIST) {
- // Default to a regular unique check + insert algorithm if we couldn't
- // do it based on the rightmost leaf alone.
- int lookup_r = toku_ft_lookup(ft_h, key, getf_nothing, nullptr);
- if (lookup_r == DB_NOTFOUND) {
- toku_ft_send_insert(ft_h, key, val, message_xids, FT_INSERT, &gc_info);
- r = 0;
- } else {
- r = DB_KEYEXIST;
- }
- }
-
- if (r == 0) {
- ft_txn_log_insert(ft_h->ft, key, val, txn, do_logging, FT_INSERT);
- }
- return r;
-}
-
-// Effect: Insert the key-val pair into an ft.
-void toku_ft_insert (FT_HANDLE ft_handle, DBT *key, DBT *val, TOKUTXN txn) {
- toku_ft_maybe_insert(ft_handle, key, val, txn, false, ZERO_LSN, true, FT_INSERT);
+// Effect: Insert the key-val pair into brt.
+void toku_ft_insert (FT_HANDLE brt, DBT *key, DBT *val, TOKUTXN txn) {
+ toku_ft_maybe_insert(brt, key, val, txn, false, ZERO_LSN, true, FT_INSERT);
}
void toku_ft_load_recovery(TOKUTXN txn, FILENUM old_filenum, char const * new_iname, int do_fsync, int do_log, LSN *load_lsn) {
@@ -3585,7 +3277,7 @@ void toku_ft_optimize (FT_HANDLE ft_h) {
DBT val;
toku_init_dbt(&key);
toku_init_dbt(&val);
- FT_MSG_S ftmsg = { FT_OPTIMIZE, ZERO_MSN, message_xids, .u = { .id = {&key,&val} } };
+ FT_MSG_S ftcmd = { FT_OPTIMIZE, ZERO_MSN, message_xids, .u = { .id = {&key,&val} } };
TXN_MANAGER txn_manager = toku_ft_get_txn_manager(ft_h);
txn_manager_state txn_state_for_gc(txn_manager);
@@ -3596,36 +3288,36 @@ void toku_ft_optimize (FT_HANDLE ft_h) {
// no messages above us, we can implicitly promote uxrs based on this xid
oldest_referenced_xid_estimate,
true);
- toku_ft_root_put_msg(ft_h->ft, &ftmsg, &gc_info);
+ toku_ft_root_put_cmd(ft_h->ft, &ftcmd, &gc_info);
xids_destroy(&message_xids);
}
}
-void toku_ft_load(FT_HANDLE ft_handle, TOKUTXN txn, char const * new_iname, int do_fsync, LSN *load_lsn) {
- FILENUM old_filenum = toku_cachefile_filenum(ft_handle->ft->cf);
+void toku_ft_load(FT_HANDLE brt, TOKUTXN txn, char const * new_iname, int do_fsync, LSN *load_lsn) {
+ FILENUM old_filenum = toku_cachefile_filenum(brt->ft->cf);
int do_log = 1;
toku_ft_load_recovery(txn, old_filenum, new_iname, do_fsync, do_log, load_lsn);
}
// ft actions for logging hot index filenums
-void toku_ft_hot_index(FT_HANDLE ft_handle __attribute__ ((unused)), TOKUTXN txn, FILENUMS filenums, int do_fsync, LSN *lsn) {
+void toku_ft_hot_index(FT_HANDLE brt __attribute__ ((unused)), TOKUTXN txn, FILENUMS filenums, int do_fsync, LSN *lsn) {
int do_log = 1;
toku_ft_hot_index_recovery(txn, filenums, do_fsync, do_log, lsn);
}
void
-toku_ft_log_put (TOKUTXN txn, FT_HANDLE ft_handle, const DBT *key, const DBT *val) {
+toku_ft_log_put (TOKUTXN txn, FT_HANDLE brt, const DBT *key, const DBT *val) {
TOKULOGGER logger = toku_txn_logger(txn);
if (logger) {
BYTESTRING keybs = {.len=key->size, .data=(char *) key->data};
BYTESTRING valbs = {.len=val->size, .data=(char *) val->data};
TXNID_PAIR xid = toku_txn_get_txnid(txn);
- toku_log_enq_insert(logger, (LSN*)0, 0, txn, toku_cachefile_filenum(ft_handle->ft->cf), xid, keybs, valbs);
+ toku_log_enq_insert(logger, (LSN*)0, 0, txn, toku_cachefile_filenum(brt->ft->cf), xid, keybs, valbs);
}
}
void
-toku_ft_log_put_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *fts, uint32_t num_fts, const DBT *key, const DBT *val) {
+toku_ft_log_put_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *brts, uint32_t num_fts, const DBT *key, const DBT *val) {
assert(txn);
assert(num_fts > 0);
TOKULOGGER logger = toku_txn_logger(txn);
@@ -3633,7 +3325,7 @@ toku_ft_log_put_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *fts, uint32_
FILENUM fnums[num_fts];
uint32_t i;
for (i = 0; i < num_fts; i++) {
- fnums[i] = toku_cachefile_filenum(fts[i]->ft->cf);
+ fnums[i] = toku_cachefile_filenum(brts[i]->ft->cf);
}
FILENUMS filenums = {.num = num_fts, .filenums = fnums};
BYTESTRING keybs = {.len=key->size, .data=(char *) key->data};
@@ -3654,38 +3346,32 @@ TXNID toku_ft_get_oldest_referenced_xid_estimate(FT_HANDLE ft_h) {
return txn_manager != nullptr ? toku_txn_manager_get_oldest_referenced_xid_estimate(txn_manager) : TXNID_NONE;
}
-static void ft_txn_log_insert(FT ft, DBT *key, DBT *val, TOKUTXN txn, bool do_logging, enum ft_msg_type type) {
- paranoid_invariant(type == FT_INSERT || type == FT_INSERT_NO_OVERWRITE);
-
- //By default use committed messages
+void toku_ft_maybe_insert (FT_HANDLE ft_h, DBT *key, DBT *val, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging, enum ft_msg_type type) {
+ paranoid_invariant(type==FT_INSERT || type==FT_INSERT_NO_OVERWRITE);
+ XIDS message_xids = xids_get_root_xids(); //By default use committed messages
TXNID_PAIR xid = toku_txn_get_txnid(txn);
if (txn) {
BYTESTRING keybs = {key->size, (char *) key->data};
- toku_logger_save_rollback_cmdinsert(txn, toku_cachefile_filenum(ft->cf), &keybs);
- toku_txn_maybe_note_ft(txn, ft);
+ toku_logger_save_rollback_cmdinsert(txn, toku_cachefile_filenum(ft_h->ft->cf), &keybs);
+ toku_txn_maybe_note_ft(txn, ft_h->ft);
+ message_xids = toku_txn_get_xids(txn);
}
TOKULOGGER logger = toku_txn_logger(txn);
if (do_logging && logger) {
BYTESTRING keybs = {.len=key->size, .data=(char *) key->data};
BYTESTRING valbs = {.len=val->size, .data=(char *) val->data};
if (type == FT_INSERT) {
- toku_log_enq_insert(logger, (LSN*)0, 0, txn, toku_cachefile_filenum(ft->cf), xid, keybs, valbs);
+ toku_log_enq_insert(logger, (LSN*)0, 0, txn, toku_cachefile_filenum(ft_h->ft->cf), xid, keybs, valbs);
}
else {
- toku_log_enq_insert_no_overwrite(logger, (LSN*)0, 0, txn, toku_cachefile_filenum(ft->cf), xid, keybs, valbs);
+ toku_log_enq_insert_no_overwrite(logger, (LSN*)0, 0, txn, toku_cachefile_filenum(ft_h->ft->cf), xid, keybs, valbs);
}
}
-}
-
-void toku_ft_maybe_insert (FT_HANDLE ft_h, DBT *key, DBT *val, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging, enum ft_msg_type type) {
- ft_txn_log_insert(ft_h->ft, key, val, txn, do_logging, type);
LSN treelsn;
if (oplsn_valid && oplsn.lsn <= (treelsn = toku_ft_checkpoint_lsn(ft_h->ft)).lsn) {
// do nothing
} else {
- XIDS message_xids = txn ? toku_txn_get_xids(txn) : xids_get_root_xids();
-
TXN_MANAGER txn_manager = toku_ft_get_txn_manager(ft_h);
txn_manager_state txn_state_for_gc(txn_manager);
@@ -3695,26 +3381,10 @@ void toku_ft_maybe_insert (FT_HANDLE ft_h, DBT *key, DBT *val, TOKUTXN txn, bool
// no messages above us, we can implicitly promote uxrs based on this xid
oldest_referenced_xid_estimate,
txn != nullptr ? !txn->for_recovery : false);
- int r = ft_maybe_insert_into_rightmost_leaf(ft_h->ft, key, val, message_xids, FT_INSERT, &gc_info, false);
- if (r != 0) {
- toku_ft_send_insert(ft_h, key, val, message_xids, type, &gc_info);
- }
+ toku_ft_send_insert(ft_h, key, val, message_xids, type, &gc_info);
}
}
-static void ft_insert_directly_into_leaf(FT ft, FTNODE leaf, int target_childnum, DBT *key, DBT *val,
- XIDS message_xids, enum ft_msg_type type, txn_gc_info *gc_info)
-// Effect: Insert directly into a leaf node a fractal tree. Does not do any logging.
-// Requires: Leaf is fully in memory and pinned for write.
-// Requires: If this insertion were to happen through the root node, the promotion
-// algorithm would have selected the given leaf node as the point of injection.
-// That means this function relies on the current implementation of promotion.
-{
- FT_MSG_S ftcmd = { type, ZERO_MSN, message_xids, .u = { .id = { key, val } } };
- size_t flow_deltas[] = { 0, 0 };
- inject_message_in_locked_node(ft, leaf, target_childnum, &ftcmd, flow_deltas, gc_info);
-}
-
static void
ft_send_update_msg(FT_HANDLE ft_h, FT_MSG_S *msg, TOKUTXN txn) {
msg->xids = (txn
@@ -3730,7 +3400,7 @@ ft_send_update_msg(FT_HANDLE ft_h, FT_MSG_S *msg, TOKUTXN txn) {
// no messages above us, we can implicitly promote uxrs based on this xid
oldest_referenced_xid_estimate,
txn != nullptr ? !txn->for_recovery : false);
- toku_ft_root_put_msg(ft_h->ft, msg, &gc_info);
+ toku_ft_root_put_cmd(ft_h->ft, msg, &gc_info);
}
void toku_ft_maybe_update(FT_HANDLE ft_h, const DBT *key, const DBT *update_function_extra,
@@ -3799,33 +3469,33 @@ void toku_ft_maybe_update_broadcast(FT_HANDLE ft_h, const DBT *update_function_e
}
}
-void toku_ft_send_insert(FT_HANDLE ft_handle, DBT *key, DBT *val, XIDS xids, enum ft_msg_type type, txn_gc_info *gc_info) {
- FT_MSG_S ftmsg = { type, ZERO_MSN, xids, .u = { .id = { key, val } } };
- toku_ft_root_put_msg(ft_handle->ft, &ftmsg, gc_info);
+void toku_ft_send_insert(FT_HANDLE brt, DBT *key, DBT *val, XIDS xids, enum ft_msg_type type, txn_gc_info *gc_info) {
+ FT_MSG_S ftcmd = { type, ZERO_MSN, xids, .u = { .id = { key, val } } };
+ toku_ft_root_put_cmd(brt->ft, &ftcmd, gc_info);
}
-void toku_ft_send_commit_any(FT_HANDLE ft_handle, DBT *key, XIDS xids, txn_gc_info *gc_info) {
+void toku_ft_send_commit_any(FT_HANDLE brt, DBT *key, XIDS xids, txn_gc_info *gc_info) {
DBT val;
- FT_MSG_S ftmsg = { FT_COMMIT_ANY, ZERO_MSN, xids, .u = { .id = { key, toku_init_dbt(&val) } } };
- toku_ft_root_put_msg(ft_handle->ft, &ftmsg, gc_info);
+ FT_MSG_S ftcmd = { FT_COMMIT_ANY, ZERO_MSN, xids, .u = { .id = { key, toku_init_dbt(&val) } } };
+ toku_ft_root_put_cmd(brt->ft, &ftcmd, gc_info);
}
-void toku_ft_delete(FT_HANDLE ft_handle, DBT *key, TOKUTXN txn) {
- toku_ft_maybe_delete(ft_handle, key, txn, false, ZERO_LSN, true);
+void toku_ft_delete(FT_HANDLE brt, DBT *key, TOKUTXN txn) {
+ toku_ft_maybe_delete(brt, key, txn, false, ZERO_LSN, true);
}
void
-toku_ft_log_del(TOKUTXN txn, FT_HANDLE ft_handle, const DBT *key) {
+toku_ft_log_del(TOKUTXN txn, FT_HANDLE brt, const DBT *key) {
TOKULOGGER logger = toku_txn_logger(txn);
if (logger) {
BYTESTRING keybs = {.len=key->size, .data=(char *) key->data};
TXNID_PAIR xid = toku_txn_get_txnid(txn);
- toku_log_enq_delete_any(logger, (LSN*)0, 0, txn, toku_cachefile_filenum(ft_handle->ft->cf), xid, keybs);
+ toku_log_enq_delete_any(logger, (LSN*)0, 0, txn, toku_cachefile_filenum(brt->ft->cf), xid, keybs);
}
}
void
-toku_ft_log_del_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *fts, uint32_t num_fts, const DBT *key, const DBT *val) {
+toku_ft_log_del_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *brts, uint32_t num_fts, const DBT *key, const DBT *val) {
assert(txn);
assert(num_fts > 0);
TOKULOGGER logger = toku_txn_logger(txn);
@@ -3833,7 +3503,7 @@ toku_ft_log_del_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *fts, uint32_
FILENUM fnums[num_fts];
uint32_t i;
for (i = 0; i < num_fts; i++) {
- fnums[i] = toku_cachefile_filenum(fts[i]->ft->cf);
+ fnums[i] = toku_cachefile_filenum(brts[i]->ft->cf);
}
FILENUMS filenums = {.num = num_fts, .filenums = fnums};
BYTESTRING keybs = {.len=key->size, .data=(char *) key->data};
@@ -3876,10 +3546,10 @@ void toku_ft_maybe_delete(FT_HANDLE ft_h, DBT *key, TOKUTXN txn, bool oplsn_vali
}
}
-void toku_ft_send_delete(FT_HANDLE ft_handle, DBT *key, XIDS xids, txn_gc_info *gc_info) {
+void toku_ft_send_delete(FT_HANDLE brt, DBT *key, XIDS xids, txn_gc_info *gc_info) {
DBT val; toku_init_dbt(&val);
- FT_MSG_S ftmsg = { FT_DELETE_ANY, ZERO_MSN, xids, .u = { .id = { key, &val } } };
- toku_ft_root_put_msg(ft_handle->ft, &ftmsg, gc_info);
+ FT_MSG_S ftcmd = { FT_DELETE_ANY, ZERO_MSN, xids, .u = { .id = { key, &val } } };
+ toku_ft_root_put_cmd(brt->ft, &ftcmd, gc_info);
}
/* ******************** open,close and create ********************** */
@@ -3890,22 +3560,22 @@ int toku_open_ft_handle (const char *fname, int is_create, FT_HANDLE *ft_handle_
enum toku_compression_method compression_method,
CACHETABLE cachetable, TOKUTXN txn,
int (*compare_fun)(DB *, const DBT*,const DBT*)) {
- FT_HANDLE ft_handle;
+ FT_HANDLE brt;
const int only_create = 0;
- toku_ft_handle_create(&ft_handle);
- toku_ft_handle_set_nodesize(ft_handle, nodesize);
- toku_ft_handle_set_basementnodesize(ft_handle, basementnodesize);
- toku_ft_handle_set_compression_method(ft_handle, compression_method);
- toku_ft_handle_set_fanout(ft_handle, 16);
- toku_ft_set_bt_compare(ft_handle, compare_fun);
+ toku_ft_handle_create(&brt);
+ toku_ft_handle_set_nodesize(brt, nodesize);
+ toku_ft_handle_set_basementnodesize(brt, basementnodesize);
+ toku_ft_handle_set_compression_method(brt, compression_method);
+ toku_ft_handle_set_fanout(brt, 16);
+ toku_ft_set_bt_compare(brt, compare_fun);
- int r = toku_ft_handle_open(ft_handle, fname, is_create, only_create, cachetable, txn);
+ int r = toku_ft_handle_open(brt, fname, is_create, only_create, cachetable, txn);
if (r != 0) {
return r;
}
- *ft_handle_p = ft_handle;
+ *ft_handle_p = brt;
return r;
}
@@ -3923,19 +3593,20 @@ static inline int ft_open_maybe_direct(const char *filename, int oflag, int mode
}
}
-// open a file for use by the ft
+static const mode_t file_mode = S_IRUSR+S_IWUSR+S_IRGRP+S_IWGRP+S_IROTH+S_IWOTH;
+
+// open a file for use by the brt
// Requires: File does not exist.
-static int ft_create_file(FT_HANDLE UU(ft_handle), const char *fname, int *fdp) {
- mode_t mode = S_IRWXU|S_IRWXG|S_IRWXO;
+static int ft_create_file(FT_HANDLE UU(brt), const char *fname, int *fdp) {
int r;
int fd;
int er;
- fd = ft_open_maybe_direct(fname, O_RDWR | O_BINARY, mode);
+ fd = ft_open_maybe_direct(fname, O_RDWR | O_BINARY, file_mode);
assert(fd==-1);
if ((er = get_maybe_error_errno()) != ENOENT) {
return er;
}
- fd = ft_open_maybe_direct(fname, O_RDWR | O_CREAT | O_BINARY, mode);
+ fd = ft_open_maybe_direct(fname, O_RDWR | O_CREAT | O_BINARY, file_mode);
if (fd==-1) {
r = get_error_errno();
return r;
@@ -3951,11 +3622,10 @@ static int ft_create_file(FT_HANDLE UU(ft_handle), const char *fname, int *fdp)
return r;
}
-// open a file for use by the ft. if the file does not exist, error
+// open a file for use by the brt. if the file does not exist, error
static int ft_open_file(const char *fname, int *fdp) {
- mode_t mode = S_IRWXU|S_IRWXG|S_IRWXO;
int fd;
- fd = ft_open_maybe_direct(fname, O_RDWR | O_BINARY, mode);
+ fd = ft_open_maybe_direct(fname, O_RDWR | O_BINARY, file_mode);
if (fd==-1) {
return get_error_errno();
}
@@ -4113,13 +3783,12 @@ ft_handle_open(FT_HANDLE ft_h, const char *fname_in_env, int is_create, int only
}
if (r==ENOENT && is_create) {
did_create = true;
- mode_t mode = S_IRWXU|S_IRWXG|S_IRWXO;
if (txn) {
BYTESTRING bs = { .len=(uint32_t) strlen(fname_in_env), .data = (char*)fname_in_env };
toku_logger_save_rollback_fcreate(txn, reserved_filenum, &bs); // bs is a copy of the fname relative to the environment
}
txn_created = (bool)(txn!=NULL);
- toku_logger_log_fcreate(txn, fname_in_env, reserved_filenum, mode, ft_h->options.flags, ft_h->options.nodesize, ft_h->options.basementnodesize, ft_h->options.compression_method);
+ toku_logger_log_fcreate(txn, fname_in_env, reserved_filenum, file_mode, ft_h->options.flags, ft_h->options.nodesize, ft_h->options.basementnodesize, ft_h->options.compression_method);
r = ft_create_file(ft_h, fname_in_cwd, &fd);
if (r) { goto exit; }
}
@@ -4186,7 +3855,7 @@ ft_handle_open(FT_HANDLE ft_h, const char *fname_in_env, int is_create, int only
// important note here,
// after this point, where we associate the header
- // with the ft_handle, the function is not allowed to fail
+ // with the brt, the function is not allowed to fail
// Code that handles failure (located below "exit"),
// depends on this
toku_ft_note_ft_handle_open(ft, ft_h);
@@ -4195,7 +3864,7 @@ ft_handle_open(FT_HANDLE ft_h, const char *fname_in_env, int is_create, int only
toku_txn_maybe_note_ft(txn, ft);
}
- //Opening an ft may restore to previous checkpoint. Truncate if necessary.
+ //Opening a brt may restore to previous checkpoint. Truncate if necessary.
{
int fd = toku_cachefile_get_fd (ft->cf);
toku_maybe_truncate_file_on_open(ft->blocktable, fd);
@@ -4211,9 +3880,9 @@ exit:
// we only call toku_ft_note_ft_handle_open
// when the function succeeds, so if we are here,
// then that means we have a reference to the header
- // but we have not linked it to this ft. So,
+ // but we have not linked it to this brt. So,
// we can simply try to remove the header.
- // We don't need to unlink this ft from the header
+ // We don't need to unlink this brt from the header
toku_ft_grab_reflock(ft);
bool needed = toku_ft_needed_unlocked(ft);
toku_ft_release_reflock(ft);
@@ -4230,7 +3899,7 @@ exit:
return r;
}
-// Open an ft for the purpose of recovery, which requires that the ft be open to a pre-determined FILENUM
+// Open a brt for the purpose of recovery, which requires that the brt be open to a pre-determined FILENUM
// and may require a specific checkpointed version of the file.
// (dict_id is assigned by the ft_handle_open() function.)
int
@@ -4242,7 +3911,7 @@ toku_ft_handle_open_recovery(FT_HANDLE t, const char *fname_in_env, int is_creat
return r;
}
-// Open an ft in normal use. The FILENUM and dict_id are assigned by the ft_handle_open() function.
+// Open a brt in normal use. The FILENUM and dict_id are assigned by the ft_handle_open() function.
// Requires: The multi-operation client lock must be held to prevent a checkpoint from occuring.
int
toku_ft_handle_open(FT_HANDLE t, const char *fname_in_env, int is_create, int only_create, CACHETABLE cachetable, TOKUTXN txn) {
@@ -4277,7 +3946,7 @@ toku_ft_handle_clone(FT_HANDLE *cloned_ft_handle, FT_HANDLE ft_handle, TOKUTXN t
return r;
}
-// Open an ft in normal use. The FILENUM and dict_id are assigned by the ft_handle_open() function.
+// Open a brt in normal use. The FILENUM and dict_id are assigned by the ft_handle_open() function.
int
toku_ft_handle_open_with_dict_id(
FT_HANDLE t,
@@ -4305,8 +3974,8 @@ toku_ft_handle_open_with_dict_id(
}
DICTIONARY_ID
-toku_ft_get_dictionary_id(FT_HANDLE ft_handle) {
- FT h = ft_handle->ft;
+toku_ft_get_dictionary_id(FT_HANDLE brt) {
+ FT h = brt->ft;
DICTIONARY_ID dict_id = h->dict_id;
return dict_id;
}
@@ -4321,7 +3990,7 @@ void toku_ft_get_flags(FT_HANDLE ft_handle, unsigned int *flags) {
}
void toku_ft_get_maximum_advised_key_value_lengths (unsigned int *max_key_len, unsigned int *max_val_len)
-// return the maximum advisable key value lengths. The ft doesn't enforce these.
+// return the maximum advisable key value lengths. The brt doesn't enforce these.
{
*max_key_len = 32*1024;
*max_val_len = 32*1024*1024;
@@ -4364,21 +4033,21 @@ void toku_ft_handle_get_basementnodesize(FT_HANDLE ft_handle, unsigned int *base
}
}
-void toku_ft_set_bt_compare(FT_HANDLE ft_handle, int (*bt_compare)(DB*, const DBT*, const DBT*)) {
- ft_handle->options.compare_fun = bt_compare;
+void toku_ft_set_bt_compare(FT_HANDLE brt, int (*bt_compare)(DB*, const DBT*, const DBT*)) {
+ brt->options.compare_fun = bt_compare;
}
-void toku_ft_set_redirect_callback(FT_HANDLE ft_handle, on_redirect_callback redir_cb, void* extra) {
- ft_handle->redirect_callback = redir_cb;
- ft_handle->redirect_callback_extra = extra;
+void toku_ft_set_redirect_callback(FT_HANDLE brt, on_redirect_callback redir_cb, void* extra) {
+ brt->redirect_callback = redir_cb;
+ brt->redirect_callback_extra = extra;
}
-void toku_ft_set_update(FT_HANDLE ft_handle, ft_update_func update_fun) {
- ft_handle->options.update_fun = update_fun;
+void toku_ft_set_update(FT_HANDLE brt, ft_update_func update_fun) {
+ brt->options.update_fun = update_fun;
}
-ft_compare_func toku_ft_get_bt_compare (FT_HANDLE ft_handle) {
- return ft_handle->options.compare_fun;
+ft_compare_func toku_ft_get_bt_compare (FT_HANDLE brt) {
+ return brt->options.compare_fun;
}
static void
@@ -4420,18 +4089,18 @@ toku_close_ft_handle_nolsn (FT_HANDLE ft_handle, char** UU(error_string)) {
}
void toku_ft_handle_create(FT_HANDLE *ft_handle_ptr) {
- FT_HANDLE XMALLOC(ft_handle);
- memset(ft_handle, 0, sizeof *ft_handle);
- toku_list_init(&ft_handle->live_ft_handle_link);
- ft_handle->options.flags = 0;
- ft_handle->did_set_flags = false;
- ft_handle->options.nodesize = FT_DEFAULT_NODE_SIZE;
- ft_handle->options.basementnodesize = FT_DEFAULT_BASEMENT_NODE_SIZE;
- ft_handle->options.compression_method = TOKU_DEFAULT_COMPRESSION_METHOD;
- ft_handle->options.fanout = FT_DEFAULT_FANOUT;
- ft_handle->options.compare_fun = toku_builtin_compare_fun;
- ft_handle->options.update_fun = NULL;
- *ft_handle_ptr = ft_handle;
+ FT_HANDLE XMALLOC(brt);
+ memset(brt, 0, sizeof *brt);
+ toku_list_init(&brt->live_ft_handle_link);
+ brt->options.flags = 0;
+ brt->did_set_flags = false;
+ brt->options.nodesize = FT_DEFAULT_NODE_SIZE;
+ brt->options.basementnodesize = FT_DEFAULT_BASEMENT_NODE_SIZE;
+ brt->options.compression_method = TOKU_DEFAULT_COMPRESSION_METHOD;
+ brt->options.fanout = FT_DEFAULT_FANOUT;
+ brt->options.compare_fun = toku_builtin_compare_fun;
+ brt->options.update_fun = NULL;
+ *ft_handle_ptr = brt;
}
/* ************* CURSORS ********************* */
@@ -4495,7 +4164,7 @@ ft_cursor_extract_val(LEAFENTRY le,
}
int toku_ft_cursor (
- FT_HANDLE ft_handle,
+ FT_HANDLE brt,
FT_CURSOR *cursorptr,
TOKUTXN ttxn,
bool is_snapshot_read,
@@ -4504,14 +4173,14 @@ int toku_ft_cursor (
{
if (is_snapshot_read) {
invariant(ttxn != NULL);
- int accepted = does_txn_read_entry(ft_handle->ft->h->root_xid_that_created, ttxn);
+ int accepted = does_txn_read_entry(brt->ft->h->root_xid_that_created, ttxn);
if (accepted!=TOKUDB_ACCEPT) {
invariant(accepted==0);
return TOKUDB_MVCC_DICTIONARY_TOO_NEW;
}
}
FT_CURSOR XCALLOC(cursor);
- cursor->ft_handle = ft_handle;
+ cursor->ft_handle = brt;
cursor->prefetching = false;
toku_init_dbt(&cursor->range_lock_left_key);
toku_init_dbt(&cursor->range_lock_right_key);
@@ -4687,11 +4356,11 @@ int fifo_offset_msn_cmp(FIFO &fifo, const int32_t &ao, const int32_t &bo)
/**
* Given a fifo_entry, either decompose it into its parameters and call
- * toku_ft_bn_apply_msg, or discard it, based on its MSN and the MSN of the
+ * toku_ft_bn_apply_cmd, or discard it, based on its MSN and the MSN of the
* basement node.
*/
static void
-do_bn_apply_msg(FT_HANDLE t, BASEMENTNODE bn, struct fifo_entry *entry, txn_gc_info *gc_info, uint64_t *workdone, STAT64INFO stats_to_update)
+do_bn_apply_cmd(FT_HANDLE t, BASEMENTNODE bn, struct fifo_entry *entry, txn_gc_info *gc_info, uint64_t *workdone, STAT64INFO stats_to_update)
{
// The messages are being iterated over in (key,msn) order or just in
// msn order, so all the messages for one key, from one buffer, are in
@@ -4709,13 +4378,13 @@ do_bn_apply_msg(FT_HANDLE t, BASEMENTNODE bn, struct fifo_entry *entry, txn_gc_i
DBT hk;
toku_fill_dbt(&hk, key, keylen);
DBT hv;
- FT_MSG_S ftmsg = { type, msn, xids, .u = { .id = { &hk, toku_fill_dbt(&hv, val, vallen) } } };
- toku_ft_bn_apply_msg(
+ FT_MSG_S ftcmd = { type, msn, xids, .u = { .id = { &hk, toku_fill_dbt(&hv, val, vallen) } } };
+ toku_ft_bn_apply_cmd(
t->ft->compare_fun,
t->ft->update_fun,
&t->ft->cmp_descriptor,
bn,
- &ftmsg,
+ &ftcmd,
gc_info,
workdone,
stats_to_update
@@ -4725,12 +4394,12 @@ do_bn_apply_msg(FT_HANDLE t, BASEMENTNODE bn, struct fifo_entry *entry, txn_gc_i
}
// We must always mark entry as stale since it has been marked
// (using omt::iterate_and_mark_range)
- // It is possible to call do_bn_apply_msg even when it won't apply the message because
+ // It is possible to call do_bn_apply_cmd even when it won't apply the message because
// the node containing it could have been evicted and brought back in.
entry->is_fresh = false;
}
-struct iterate_do_bn_apply_msg_extra {
+struct iterate_do_bn_apply_cmd_extra {
FT_HANDLE t;
BASEMENTNODE bn;
NONLEAF_CHILDINFO bnc;
@@ -4739,11 +4408,11 @@ struct iterate_do_bn_apply_msg_extra {
STAT64INFO stats_to_update;
};
-int iterate_do_bn_apply_msg(const int32_t &offset, const uint32_t UU(idx), struct iterate_do_bn_apply_msg_extra *const e) __attribute__((nonnull(3)));
-int iterate_do_bn_apply_msg(const int32_t &offset, const uint32_t UU(idx), struct iterate_do_bn_apply_msg_extra *const e)
+int iterate_do_bn_apply_cmd(const int32_t &offset, const uint32_t UU(idx), struct iterate_do_bn_apply_cmd_extra *const e) __attribute__((nonnull(3)));
+int iterate_do_bn_apply_cmd(const int32_t &offset, const uint32_t UU(idx), struct iterate_do_bn_apply_cmd_extra *const e)
{
struct fifo_entry *entry = toku_fifo_get_entry(e->bnc->buffer, offset);
- do_bn_apply_msg(e->t, e->bn, entry, e->gc_info, e->workdone, e->stats_to_update);
+ do_bn_apply_cmd(e->t, e->bn, entry, e->gc_info, e->workdone, e->stats_to_update);
return 0;
}
@@ -4756,7 +4425,7 @@ int iterate_do_bn_apply_msg(const int32_t &offset, const uint32_t UU(idx), struc
* found. The pivot_bounds are the lower bound exclusive and upper bound
* inclusive, because they come from pivot keys in the tree. We want OMT
* indices, which must have the lower bound be inclusive and the upper
- * bound exclusive. We will get these by telling omt::find to look
+ * bound exclusive. We will get these by telling toku_omt_find to look
* for something strictly bigger than each of our pivot bounds.
*
* Outputs the OMT indices in lbi (lower bound inclusive) and ube (upper
@@ -4829,7 +4498,7 @@ find_bounds_within_message_tree(
// Again, we use an msn of MAX_MSN and a direction of +1 to get
// the first thing bigger than the upper_bound_inclusive key.
// This is therefore the smallest thing we don't want to apply,
- // and omt::iterate_on_range will not examine it.
+ // and toku_omt_iterate_on_range will not examine it.
struct toku_fifo_entry_key_msn_heaviside_extra ube_extra;
ZERO_STRUCT(ube_extra);
ube_extra.desc = desc;
@@ -4925,22 +4594,22 @@ bnc_apply_messages_to_basement_node(
for (int i = 0; i < buffer_size; ++i) {
*msgs_applied = true;
struct fifo_entry *entry = toku_fifo_get_entry(bnc->buffer, offsets[i]);
- do_bn_apply_msg(t, bn, entry, gc_info, &workdone_this_ancestor, &stats_delta);
+ do_bn_apply_cmd(t, bn, entry, gc_info, &workdone_this_ancestor, &stats_delta);
}
} else if (stale_lbi == stale_ube) {
// No stale messages to apply, we just apply fresh messages, and mark them to be moved to stale later.
- struct iterate_do_bn_apply_msg_extra iter_extra = { .t = t, .bn = bn, .bnc = bnc, .gc_info = gc_info, .workdone = &workdone_this_ancestor, .stats_to_update = &stats_delta };
+ struct iterate_do_bn_apply_cmd_extra iter_extra = { .t = t, .bn = bn, .bnc = bnc, .gc_info = gc_info, .workdone = &workdone_this_ancestor, .stats_to_update = &stats_delta };
if (fresh_ube - fresh_lbi > 0) *msgs_applied = true;
- r = bnc->fresh_message_tree.iterate_and_mark_range<struct iterate_do_bn_apply_msg_extra, iterate_do_bn_apply_msg>(fresh_lbi, fresh_ube, &iter_extra);
+ r = bnc->fresh_message_tree.iterate_and_mark_range<struct iterate_do_bn_apply_cmd_extra, iterate_do_bn_apply_cmd>(fresh_lbi, fresh_ube, &iter_extra);
assert_zero(r);
} else {
invariant(fresh_lbi == fresh_ube);
// No fresh messages to apply, we just apply stale messages.
if (stale_ube - stale_lbi > 0) *msgs_applied = true;
- struct iterate_do_bn_apply_msg_extra iter_extra = { .t = t, .bn = bn, .bnc = bnc, .gc_info = gc_info, .workdone = &workdone_this_ancestor, .stats_to_update = &stats_delta };
+ struct iterate_do_bn_apply_cmd_extra iter_extra = { .t = t, .bn = bn, .bnc = bnc, .gc_info = gc_info, .workdone = &workdone_this_ancestor, .stats_to_update = &stats_delta };
- r = bnc->stale_message_tree.iterate_on_range<struct iterate_do_bn_apply_msg_extra, iterate_do_bn_apply_msg>(stale_lbi, stale_ube, &iter_extra);
+ r = bnc->stale_message_tree.iterate_on_range<struct iterate_do_bn_apply_cmd_extra, iterate_do_bn_apply_cmd>(stale_lbi, stale_ube, &iter_extra);
assert_zero(r);
}
//
@@ -5214,13 +4883,6 @@ int copy_to_stale(const int32_t &offset, const uint32_t UU(idx), struct copy_to_
return 0;
}
-static void ft_bnc_move_messages_to_stale(FT ft, NONLEAF_CHILDINFO bnc) {
- struct copy_to_stale_extra cts_extra = { .ft = ft, .bnc = bnc };
- int r = bnc->fresh_message_tree.iterate_over_marked<struct copy_to_stale_extra, copy_to_stale>(&cts_extra);
- invariant_zero(r);
- bnc->fresh_message_tree.delete_all_marked();
-}
-
__attribute__((nonnull))
void
toku_move_ftnode_messages_to_stale(FT ft, FTNODE node) {
@@ -5233,7 +4895,10 @@ toku_move_ftnode_messages_to_stale(FT ft, FTNODE node) {
// We can't delete things out of the fresh tree inside the above
// procedures because we're still looking at the fresh tree. Instead
// we have to move messages after we're done looking at it.
- ft_bnc_move_messages_to_stale(ft, bnc);
+ struct copy_to_stale_extra cts_extra = { .ft = ft, .bnc = bnc };
+ int r = bnc->fresh_message_tree.iterate_over_marked<struct copy_to_stale_extra, copy_to_stale>(&cts_extra);
+ invariant_zero(r);
+ bnc->fresh_message_tree.delete_all_marked();
}
}
@@ -5327,7 +4992,7 @@ ok: ;
switch (search->direction) {
case FT_SEARCH_LEFT:
idx++;
- if (idx >= bn->data_buffer.num_klpairs() ||
+ if (idx >= bn->data_buffer.omt_size() ||
((n_deleted % 64) == 0 && !search_continue(search, key, keylen))) {
if (ftcursor->interrupt_cb && ftcursor->interrupt_cb(ftcursor->interrupt_cb_extra)) {
return TOKUDB_INTERRUPTED;
@@ -5402,7 +5067,7 @@ got_a_good_value:
static int
ft_search_node (
- FT_HANDLE ft_handle,
+ FT_HANDLE brt,
FTNODE node,
ft_search_t *search,
int child_to_search,
@@ -5437,25 +5102,25 @@ ftnode_pf_callback_and_free_bfe(void *ftnode_pv, void* disk_data, void *read_ext
}
static void
-ft_node_maybe_prefetch(FT_HANDLE ft_handle, FTNODE node, int childnum, FT_CURSOR ftcursor, bool *doprefetch) {
+ft_node_maybe_prefetch(FT_HANDLE brt, FTNODE node, int childnum, FT_CURSOR ftcursor, bool *doprefetch) {
// the number of nodes to prefetch
const int num_nodes_to_prefetch = 1;
// if we want to prefetch in the tree
// then prefetch the next children if there are any
if (*doprefetch && ft_cursor_prefetching(ftcursor) && !ftcursor->disable_prefetching) {
- int rc = ft_cursor_rightmost_child_wanted(ftcursor, ft_handle, node);
+ int rc = ft_cursor_rightmost_child_wanted(ftcursor, brt, node);
for (int i = childnum + 1; (i <= childnum + num_nodes_to_prefetch) && (i <= rc); i++) {
BLOCKNUM nextchildblocknum = BP_BLOCKNUM(node, i);
- uint32_t nextfullhash = compute_child_fullhash(ft_handle->ft->cf, node, i);
+ uint32_t nextfullhash = compute_child_fullhash(brt->ft->cf, node, i);
struct ftnode_fetch_extra *MALLOC(bfe);
- fill_bfe_for_prefetch(bfe, ft_handle->ft, ftcursor);
+ fill_bfe_for_prefetch(bfe, brt->ft, ftcursor);
bool doing_prefetch = false;
toku_cachefile_prefetch(
- ft_handle->ft->cf,
+ brt->ft->cf,
nextchildblocknum,
nextfullhash,
- get_write_callbacks_for_node(ft_handle->ft),
+ get_write_callbacks_for_node(brt->ft),
ftnode_fetch_callback_and_free_bfe,
toku_ftnode_pf_req_callback,
ftnode_pf_callback_and_free_bfe,
@@ -5481,11 +5146,11 @@ static void
unlock_ftnode_fun (void *v) {
struct unlock_ftnode_extra *x = NULL;
CAST_FROM_VOIDP(x, v);
- FT_HANDLE ft_handle = x->ft_handle;
+ FT_HANDLE brt = x->ft_handle;
FTNODE node = x->node;
// CT lock is held
int r = toku_cachetable_unpin_ct_prelocked_no_flush(
- ft_handle->ft->cf,
+ brt->ft->cf,
node->ct_pair,
(enum cachetable_dirty) node->dirty,
x->msgs_applied ? make_ftnode_pair_attr(node) : make_invalid_pair_attr()
@@ -5495,14 +5160,14 @@ unlock_ftnode_fun (void *v) {
/* search in a node's child */
static int
-ft_search_child(FT_HANDLE ft_handle, FTNODE node, int childnum, ft_search_t *search, FT_GET_CALLBACK_FUNCTION getf, void *getf_v, bool *doprefetch, FT_CURSOR ftcursor, UNLOCKERS unlockers,
+ft_search_child(FT_HANDLE brt, FTNODE node, int childnum, ft_search_t *search, FT_GET_CALLBACK_FUNCTION getf, void *getf_v, bool *doprefetch, FT_CURSOR ftcursor, UNLOCKERS unlockers,
ANCESTORS ancestors, struct pivot_bounds const * const bounds, bool can_bulk_fetch)
// Effect: Search in a node's child. Searches are read-only now (at least as far as the hardcopy is concerned).
{
struct ancestors next_ancestors = {node, childnum, ancestors};
BLOCKNUM childblocknum = BP_BLOCKNUM(node,childnum);
- uint32_t fullhash = compute_child_fullhash(ft_handle->ft->cf, node, childnum);
+ uint32_t fullhash = compute_child_fullhash(brt->ft->cf, node, childnum);
FTNODE childnode = nullptr;
// If the current node's height is greater than 1, then its child is an internal node.
@@ -5511,7 +5176,7 @@ ft_search_child(FT_HANDLE ft_handle, FTNODE node, int childnum, ft_search_t *sea
struct ftnode_fetch_extra bfe;
fill_bfe_for_subset_read(
&bfe,
- ft_handle->ft,
+ brt->ft,
search,
&ftcursor->range_lock_left_key,
&ftcursor->range_lock_right_key,
@@ -5522,7 +5187,7 @@ ft_search_child(FT_HANDLE ft_handle, FTNODE node, int childnum, ft_search_t *sea
);
bool msgs_applied = false;
{
- int rr = toku_pin_ftnode_for_query(ft_handle, childblocknum, fullhash,
+ int rr = toku_pin_ftnode_batched(brt, childblocknum, fullhash,
unlockers,
&next_ancestors, bounds,
&bfe,
@@ -5532,24 +5197,27 @@ ft_search_child(FT_HANDLE ft_handle, FTNODE node, int childnum, ft_search_t *sea
if (rr==TOKUDB_TRY_AGAIN) {
return rr;
}
+ // We end the batch before applying ancestor messages if we get
+ // all the way to a leaf.
invariant_zero(rr);
}
- struct unlock_ftnode_extra unlock_extra = { ft_handle, childnode, msgs_applied };
- struct unlockers next_unlockers = { true, unlock_ftnode_fun, (void *) &unlock_extra, unlockers };
- int r = ft_search_node(ft_handle, childnode, search, bfe.child_to_read, getf, getf_v, doprefetch, ftcursor, &next_unlockers, &next_ancestors, bounds, can_bulk_fetch);
+ struct unlock_ftnode_extra unlock_extra = {brt,childnode,msgs_applied};
+ struct unlockers next_unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, unlockers};
+
+ int r = ft_search_node(brt, childnode, search, bfe.child_to_read, getf, getf_v, doprefetch, ftcursor, &next_unlockers, &next_ancestors, bounds, can_bulk_fetch);
if (r!=TOKUDB_TRY_AGAIN) {
// maybe prefetch the next child
if (r == 0 && node->height == 1) {
- ft_node_maybe_prefetch(ft_handle, node, childnum, ftcursor, doprefetch);
+ ft_node_maybe_prefetch(brt, node, childnum, ftcursor, doprefetch);
}
assert(next_unlockers.locked);
if (msgs_applied) {
- toku_unpin_ftnode(ft_handle->ft, childnode);
+ toku_unpin_ftnode(brt->ft, childnode);
}
else {
- toku_unpin_ftnode_read_only(ft_handle->ft, childnode);
+ toku_unpin_ftnode_read_only(brt->ft, childnode);
}
} else {
// try again.
@@ -5562,10 +5230,10 @@ ft_search_child(FT_HANDLE ft_handle, FTNODE node, int childnum, ft_search_t *sea
// the node was not unpinned, so we unpin it here
if (next_unlockers.locked) {
if (msgs_applied) {
- toku_unpin_ftnode(ft_handle->ft, childnode);
+ toku_unpin_ftnode(brt->ft, childnode);
}
else {
- toku_unpin_ftnode_read_only(ft_handle->ft, childnode);
+ toku_unpin_ftnode_read_only(brt->ft, childnode);
}
}
}
@@ -5679,7 +5347,7 @@ static bool search_try_again(FTNODE node, int child_to_search, ft_search_t *sear
static int
ft_search_node(
- FT_HANDLE ft_handle,
+ FT_HANDLE brt,
FTNODE node,
ft_search_t *search,
int child_to_search,
@@ -5704,7 +5372,7 @@ ft_search_node(
const struct pivot_bounds next_bounds = next_pivot_keys(node, child_to_search, bounds);
if (node->height > 0) {
r = ft_search_child(
- ft_handle,
+ brt,
node,
child_to_search,
search,
@@ -5777,13 +5445,13 @@ ft_search_node(
}
static int
-toku_ft_search (FT_HANDLE ft_handle, ft_search_t *search, FT_GET_CALLBACK_FUNCTION getf, void *getf_v, FT_CURSOR ftcursor, bool can_bulk_fetch)
+toku_ft_search (FT_HANDLE brt, ft_search_t *search, FT_GET_CALLBACK_FUNCTION getf, void *getf_v, FT_CURSOR ftcursor, bool can_bulk_fetch)
// Effect: Perform a search. Associate cursor with a leaf if possible.
// All searches are performed through this function.
{
int r;
uint trycount = 0; // How many tries did it take to get the result?
- FT ft = ft_handle->ft;
+ FT ft = brt->ft;
toku::context search_ctx(CTX_SEARCH);
@@ -5802,8 +5470,8 @@ try_again:
// the appropriate partition of the child we are using is in memory.
// So, here are the steps for a search (and this applies to this function
// as well as ft_search_child:
- // - Take the search parameter, and create a ftnode_fetch_extra, that will be used by toku_pin_ftnode
- // - Call toku_pin_ftnode with the bfe as the extra for the fetch callback (in case the node is not at all in memory)
+ // - Take the search parameter, and create a ftnode_fetch_extra, that will be used by toku_pin_ftnode(_holding_lock)
+ // - Call toku_pin_ftnode(_holding_lock) with the bfe as the extra for the fetch callback (in case the node is not at all in memory)
// and the partial fetch callback (in case the node is perhaps partially in memory) to the fetch the node
// - This eventually calls either toku_ftnode_fetch_callback or toku_ftnode_pf_req_callback depending on whether the node is in
// memory at all or not.
@@ -5834,27 +5502,28 @@ try_again:
uint32_t fullhash;
CACHEKEY root_key;
toku_calculate_root_offset_pointer(ft, &root_key, &fullhash);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread_batched(
ft,
root_key,
fullhash,
&bfe,
PL_READ, // may_modify_node set to false, because root cannot change during search
- &node,
- true
+ 0,
+ NULL,
+ &node
);
}
uint tree_height = node->height + 1; // How high is the tree? This is the height of the root node plus one (leaf is at height 0).
- struct unlock_ftnode_extra unlock_extra = {ft_handle,node,false};
+ struct unlock_ftnode_extra unlock_extra = {brt,node,false};
struct unlockers unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, (UNLOCKERS)NULL};
{
bool doprefetch = false;
//static int counter = 0; counter++;
- r = ft_search_node(ft_handle, node, search, bfe.child_to_read, getf, getf_v, &doprefetch, ftcursor, &unlockers, (ANCESTORS)NULL, &infinite_bounds, can_bulk_fetch);
+ r = ft_search_node(brt, node, search, bfe.child_to_read, getf, getf_v, &doprefetch, ftcursor, &unlockers, (ANCESTORS)NULL, &infinite_bounds, can_bulk_fetch);
if (r==TOKUDB_TRY_AGAIN) {
// there are two cases where we get TOKUDB_TRY_AGAIN
// case 1 is when some later call to toku_pin_ftnode returned
@@ -5863,7 +5532,7 @@ try_again:
// some piece of a node that it needed was not in memory.
// In this case, the node was not unpinned, so we unpin it here
if (unlockers.locked) {
- toku_unpin_ftnode_read_only(ft_handle->ft, node);
+ toku_unpin_ftnode_read_only(brt->ft, node);
}
goto try_again;
} else {
@@ -5872,7 +5541,7 @@ try_again:
}
assert(unlockers.locked);
- toku_unpin_ftnode_read_only(ft_handle->ft, node);
+ toku_unpin_ftnode_read_only(brt->ft, node);
//Heaviside function (+direction) queries define only a lower or upper
@@ -5923,9 +5592,9 @@ ft_cursor_search(FT_CURSOR cursor, ft_search_t *search, FT_GET_CALLBACK_FUNCTION
return r;
}
-static inline int compare_k_x(FT_HANDLE ft_handle, const DBT *k, const DBT *x) {
- FAKE_DB(db, &ft_handle->ft->cmp_descriptor);
- return ft_handle->ft->compare_fun(&db, k, x);
+static inline int compare_k_x(FT_HANDLE brt, const DBT *k, const DBT *x) {
+ FAKE_DB(db, &brt->ft->cmp_descriptor);
+ return brt->ft->compare_fun(&db, k, x);
}
static int
@@ -5935,8 +5604,8 @@ ft_cursor_compare_one(const ft_search_t &search __attribute__((__unused__)), con
}
static int ft_cursor_compare_set(const ft_search_t &search, const DBT *x) {
- FT_HANDLE CAST_FROM_VOIDP(ft_handle, search.context);
- return compare_k_x(ft_handle, search.k, x) <= 0; /* return min xy: kv <= xy */
+ FT_HANDLE CAST_FROM_VOIDP(brt, search.context);
+ return compare_k_x(brt, search.k, x) <= 0; /* return min xy: kv <= xy */
}
static int
@@ -6001,8 +5670,8 @@ toku_ft_cursor_last(FT_CURSOR cursor, FT_GET_CALLBACK_FUNCTION getf, void *getf_
}
static int ft_cursor_compare_next(const ft_search_t &search, const DBT *x) {
- FT_HANDLE CAST_FROM_VOIDP(ft_handle, search.context);
- return compare_k_x(ft_handle, search.k, x) < 0; /* return min xy: kv < xy */
+ FT_HANDLE CAST_FROM_VOIDP(brt, search.context);
+ return compare_k_x(brt, search.k, x) < 0; /* return min xy: kv < xy */
}
static int
@@ -6022,7 +5691,7 @@ ft_cursor_shortcut (
int r = 0;
// if we are searching towards the end, limit is last element
// if we are searching towards the beginning, limit is the first element
- uint32_t limit = (direction > 0) ? (bd->num_klpairs() - 1) : 0;
+ uint32_t limit = (direction > 0) ? (bd->omt_size() - 1) : 0;
//Starting with the prev, find the first real (non-provdel) leafentry.
while (index != limit) {
@@ -6110,8 +5779,8 @@ ft_cursor_search_eq_k_x(FT_CURSOR cursor, ft_search_t *search, FT_GET_CALLBACK_F
}
static int ft_cursor_compare_prev(const ft_search_t &search, const DBT *x) {
- FT_HANDLE CAST_FROM_VOIDP(ft_handle, search.context);
- return compare_k_x(ft_handle, search.k, x) > 0; /* return max xy: kv > xy */
+ FT_HANDLE CAST_FROM_VOIDP(brt, search.context);
+ return compare_k_x(brt, search.k, x) > 0; /* return max xy: kv > xy */
}
int
@@ -6126,8 +5795,8 @@ toku_ft_cursor_prev(FT_CURSOR cursor, FT_GET_CALLBACK_FUNCTION getf, void *getf_
}
static int ft_cursor_compare_set_range(const ft_search_t &search, const DBT *x) {
- FT_HANDLE CAST_FROM_VOIDP(ft_handle, search.context);
- return compare_k_x(ft_handle, search.k, x) <= 0; /* return kv <= xy */
+ FT_HANDLE CAST_FROM_VOIDP(brt, search.context);
+ return compare_k_x(brt, search.k, x) <= 0; /* return kv <= xy */
}
int
@@ -6153,8 +5822,8 @@ toku_ft_cursor_set_range(FT_CURSOR cursor, DBT *key, DBT *key_bound, FT_GET_CALL
}
static int ft_cursor_compare_set_range_reverse(const ft_search_t &search, const DBT *x) {
- FT_HANDLE CAST_FROM_VOIDP(ft_handle, search.context);
- return compare_k_x(ft_handle, search.k, x) >= 0; /* return kv >= xy */
+ FT_HANDLE CAST_FROM_VOIDP(brt, search.context);
+ return compare_k_x(brt, search.k, x) >= 0; /* return kv >= xy */
}
int
@@ -6218,6 +5887,14 @@ toku_ft_cursor_peek(FT_CURSOR cursor, const DBT **pkey, const DBT **pval)
*pval = &cursor->val;
}
+//We pass in toku_dbt_fake to the search functions, since it will not pass the
+//key(or val) to the heaviside function if key(or val) is NULL.
+//It is not used for anything else,
+//the actual 'extra' information for the heaviside function is inside the
+//wrapper.
+static const DBT __toku_dbt_fake = {};
+static const DBT* const toku_dbt_fake = &__toku_dbt_fake;
+
bool toku_ft_cursor_uninitialized(FT_CURSOR c) {
return ft_cursor_not_set(c);
}
@@ -6226,12 +5903,12 @@ bool toku_ft_cursor_uninitialized(FT_CURSOR c) {
/* ********************************* lookup **************************************/
int
-toku_ft_lookup (FT_HANDLE ft_handle, DBT *k, FT_GET_CALLBACK_FUNCTION getf, void *getf_v)
+toku_ft_lookup (FT_HANDLE brt, DBT *k, FT_GET_CALLBACK_FUNCTION getf, void *getf_v)
{
int r, rr;
FT_CURSOR cursor;
- rr = toku_ft_cursor(ft_handle, &cursor, NULL, false, false);
+ rr = toku_ft_cursor(brt, &cursor, NULL, false, false);
if (rr != 0) return rr;
int op = DB_SET;
@@ -6285,7 +5962,7 @@ keyrange_compare (DBT const &kdbt, const struct keyrange_compare_s &s) {
}
static void
-keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node,
+keysrange_in_leaf_partition (FT_HANDLE brt, FTNODE node,
DBT* key_left, DBT* key_right,
int left_child_number, int right_child_number, uint64_t estimated_num_rows,
uint64_t *less, uint64_t* equal_left, uint64_t* middle,
@@ -6302,7 +5979,7 @@ keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node,
if (BP_STATE(node, left_child_number) == PT_AVAIL) {
int r;
// The partition is in main memory then get an exact count.
- struct keyrange_compare_s s_left = {ft_handle->ft, key_left};
+ struct keyrange_compare_s s_left = {brt->ft, key_left};
BASEMENTNODE bn = BLB(node, left_child_number);
uint32_t idx_left = 0;
// if key_left is NULL then set r==-1 and idx==0.
@@ -6310,11 +5987,11 @@ keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node,
*less = idx_left;
*equal_left = (r==0) ? 1 : 0;
- uint32_t size = bn->data_buffer.num_klpairs();
+ uint32_t size = bn->data_buffer.omt_size();
uint32_t idx_right = size;
r = -1;
if (single_basement && key_right) {
- struct keyrange_compare_s s_right = {ft_handle->ft, key_right};
+ struct keyrange_compare_s s_right = {brt->ft, key_right};
r = bn->data_buffer.find_zero<decltype(s_right), keyrange_compare>(s_right, nullptr, nullptr, nullptr, &idx_right);
}
*middle = idx_right - idx_left - *equal_left;
@@ -6339,7 +6016,7 @@ keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node,
}
static int
-toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node,
+toku_ft_keysrange_internal (FT_HANDLE brt, FTNODE node,
DBT* key_left, DBT* key_right, bool may_find_right,
uint64_t* less, uint64_t* equal_left, uint64_t* middle,
uint64_t* equal_right, uint64_t* greater, bool* single_basement_node,
@@ -6351,15 +6028,15 @@ toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node,
{
int r = 0;
// if KEY is NULL then use the leftmost key.
- int left_child_number = key_left ? toku_ftnode_which_child (node, key_left, &ft_handle->ft->cmp_descriptor, ft_handle->ft->compare_fun) : 0;
+ int left_child_number = key_left ? toku_ftnode_which_child (node, key_left, &brt->ft->cmp_descriptor, brt->ft->compare_fun) : 0;
int right_child_number = node->n_children; // Sentinel that does not equal left_child_number.
if (may_find_right) {
- right_child_number = key_right ? toku_ftnode_which_child (node, key_right, &ft_handle->ft->cmp_descriptor, ft_handle->ft->compare_fun) : node->n_children - 1;
+ right_child_number = key_right ? toku_ftnode_which_child (node, key_right, &brt->ft->cmp_descriptor, brt->ft->compare_fun) : node->n_children - 1;
}
uint64_t rows_per_child = estimated_num_rows / node->n_children;
if (node->height == 0) {
- keysrange_in_leaf_partition(ft_handle, node, key_left, key_right, left_child_number, right_child_number,
+ keysrange_in_leaf_partition(brt, node, key_left, key_right, left_child_number, right_child_number,
rows_per_child, less, equal_left, middle, equal_right, greater, single_basement_node);
*less += rows_per_child * left_child_number;
@@ -6372,12 +6049,12 @@ toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node,
// do the child.
struct ancestors next_ancestors = {node, left_child_number, ancestors};
BLOCKNUM childblocknum = BP_BLOCKNUM(node, left_child_number);
- uint32_t fullhash = compute_child_fullhash(ft_handle->ft->cf, node, left_child_number);
+ uint32_t fullhash = compute_child_fullhash(brt->ft->cf, node, left_child_number);
FTNODE childnode;
bool msgs_applied = false;
bool child_may_find_right = may_find_right && left_child_number == right_child_number;
- r = toku_pin_ftnode_for_query(
- ft_handle,
+ r = toku_pin_ftnode_batched(
+ brt,
childblocknum,
fullhash,
unlockers,
@@ -6392,11 +6069,11 @@ toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node,
if (r != TOKUDB_TRY_AGAIN) {
assert_zero(r);
- struct unlock_ftnode_extra unlock_extra = {ft_handle,childnode,false};
+ struct unlock_ftnode_extra unlock_extra = {brt,childnode,false};
struct unlockers next_unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, unlockers};
const struct pivot_bounds next_bounds = next_pivot_keys(node, left_child_number, bounds);
- r = toku_ft_keysrange_internal(ft_handle, childnode, key_left, key_right, child_may_find_right,
+ r = toku_ft_keysrange_internal(brt, childnode, key_left, key_right, child_may_find_right,
less, equal_left, middle, equal_right, greater, single_basement_node,
rows_per_child, min_bfe, match_bfe, &next_unlockers, &next_ancestors, &next_bounds);
if (r != TOKUDB_TRY_AGAIN) {
@@ -6410,14 +6087,14 @@ toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node,
}
assert(unlockers->locked);
- toku_unpin_ftnode_read_only(ft_handle->ft, childnode);
+ toku_unpin_ftnode_read_only(brt->ft, childnode);
}
}
}
return r;
}
-void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint64_t *less_p, uint64_t* equal_left_p, uint64_t* middle_p, uint64_t* equal_right_p, uint64_t* greater_p, bool* middle_3_exact_p)
+void toku_ft_keysrange(FT_HANDLE brt, DBT* key_left, DBT* key_right, uint64_t *less_p, uint64_t* equal_left_p, uint64_t* middle_p, uint64_t* equal_right_p, uint64_t* greater_p, bool* middle_3_exact_p)
// Effect: Return an estimate of the number of keys to the left, the number equal (to left key), number between keys, number equal to right key, and the number to the right of both keys.
// The values are an estimate.
// If you perform a keyrange on two keys that are in the same basement, equal_less, middle, and equal_right will be exact.
@@ -6431,7 +6108,7 @@ void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint6
// Simplify internals by only supporting key_right != null when key_left != null
// If key_right != null and key_left == null, then swap them and fix up numbers.
uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, greater = 0;
- toku_ft_keysrange(ft_handle, key_right, nullptr, &less, &equal_left, &middle, &equal_right, &greater, middle_3_exact_p);
+ toku_ft_keysrange(brt, key_right, nullptr, &less, &equal_left, &middle, &equal_right, &greater, middle_3_exact_p);
*less_p = 0;
*equal_left_p = 0;
*middle_p = less;
@@ -6444,8 +6121,8 @@ void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint6
paranoid_invariant(!(!key_left && key_right));
struct ftnode_fetch_extra min_bfe;
struct ftnode_fetch_extra match_bfe;
- fill_bfe_for_min_read(&min_bfe, ft_handle->ft); // read pivot keys but not message buffers
- fill_bfe_for_keymatch(&match_bfe, ft_handle->ft, key_left, key_right, false, false); // read basement node only if both keys in it.
+ fill_bfe_for_min_read(&min_bfe, brt->ft); // read pivot keys but not message buffers
+ fill_bfe_for_keymatch(&match_bfe, brt->ft, key_left, key_right, false, false); // read basement node only if both keys in it.
try_again:
{
uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, greater = 0;
@@ -6454,27 +6131,28 @@ try_again:
{
uint32_t fullhash;
CACHEKEY root_key;
- toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &fullhash);
- toku_pin_ftnode(
- ft_handle->ft,
+ toku_calculate_root_offset_pointer(brt->ft, &root_key, &fullhash);
+ toku_pin_ftnode_off_client_thread_batched(
+ brt->ft,
root_key,
fullhash,
&match_bfe,
PL_READ, // may_modify_node, cannot change root during keyrange
- &node,
- true
+ 0,
+ NULL,
+ &node
);
}
- struct unlock_ftnode_extra unlock_extra = {ft_handle,node,false};
+ struct unlock_ftnode_extra unlock_extra = {brt,node,false};
struct unlockers unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, (UNLOCKERS)NULL};
{
int r;
- int64_t numrows = ft_handle->ft->in_memory_stats.numrows;
+ int64_t numrows = brt->ft->in_memory_stats.numrows;
if (numrows < 0)
numrows = 0; // prevent appearance of a negative number
- r = toku_ft_keysrange_internal (ft_handle, node, key_left, key_right, true,
+ r = toku_ft_keysrange_internal (brt, node, key_left, key_right, true,
&less, &equal_left, &middle, &equal_right, &greater,
&single_basement_node, numrows,
&min_bfe, &match_bfe, &unlockers, (ANCESTORS)NULL, &infinite_bounds);
@@ -6490,7 +6168,7 @@ try_again:
invariant_zero(greater);
uint64_t less2 = 0, equal_left2 = 0, middle2 = 0, equal_right2 = 0, greater2 = 0;
bool ignore;
- r = toku_ft_keysrange_internal (ft_handle, node, key_right, nullptr, false,
+ r = toku_ft_keysrange_internal (brt, node, key_right, nullptr, false,
&less2, &equal_left2, &middle2, &equal_right2, &greater2,
&ignore, numrows,
&min_bfe, &match_bfe, &unlockers, (ANCESTORS)nullptr, &infinite_bounds);
@@ -6520,7 +6198,7 @@ try_again:
}
}
assert(unlockers.locked);
- toku_unpin_ftnode_read_only(ft_handle->ft, node);
+ toku_unpin_ftnode_read_only(brt->ft, node);
if (!key_right) {
paranoid_invariant_zero(equal_right);
paranoid_invariant_zero(greater);
@@ -6569,7 +6247,7 @@ static int get_key_after_bytes_in_basementnode(FT ft, BASEMENTNODE bn, const DBT
assert(r == 0 || r == DB_NOTFOUND);
}
struct get_key_after_bytes_iterate_extra iter_extra = {skip_len, skipped, callback, cb_extra};
- r = bn->data_buffer.iterate_on_range<get_key_after_bytes_iterate_extra, get_key_after_bytes_iterate>(idx_left, bn->data_buffer.num_klpairs(), &iter_extra);
+ r = bn->data_buffer.omt_iterate_on_range<get_key_after_bytes_iterate_extra, get_key_after_bytes_iterate>(idx_left, bn->data_buffer.omt_size(), &iter_extra);
// Invert the sense of r == 0 (meaning the iterate finished, which means we didn't find what we wanted)
if (r == 1) {
@@ -6589,7 +6267,7 @@ static int get_key_after_bytes_in_child(FT_HANDLE ft_h, FT ft, FTNODE node, UNLO
uint32_t fullhash = compute_child_fullhash(ft->cf, node, childnum);
FTNODE child;
bool msgs_applied = false;
- r = toku_pin_ftnode_for_query(ft_h, childblocknum, fullhash, unlockers, &next_ancestors, bounds, bfe, false, &child, &msgs_applied);
+ r = toku_pin_ftnode_batched(ft_h, childblocknum, fullhash, unlockers, &next_ancestors, bounds, bfe, false, &child, &msgs_applied);
paranoid_invariant(!msgs_applied);
if (r == TOKUDB_TRY_AGAIN) {
return r;
@@ -6672,7 +6350,7 @@ int toku_ft_get_key_after_bytes(FT_HANDLE ft_h, const DBT *start_key, uint64_t s
uint32_t fullhash;
CACHEKEY root_key;
toku_calculate_root_offset_pointer(ft, &root_key, &fullhash);
- toku_pin_ftnode(ft, root_key, fullhash, &bfe, PL_READ, &root, true);
+ toku_pin_ftnode_off_client_thread_batched(ft, root_key, fullhash, &bfe, PL_READ, 0, nullptr, &root);
}
struct unlock_ftnode_extra unlock_extra = {ft_h, root, false};
struct unlockers unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, (UNLOCKERS) nullptr};
@@ -6700,16 +6378,16 @@ int toku_ft_get_key_after_bytes(FT_HANDLE ft_h, const DBT *start_key, uint64_t s
}
//Test-only wrapper for the old one-key range function
-void toku_ft_keyrange(FT_HANDLE ft_handle, DBT *key, uint64_t *less, uint64_t *equal, uint64_t *greater) {
+void toku_ft_keyrange(FT_HANDLE brt, DBT *key, uint64_t *less, uint64_t *equal, uint64_t *greater) {
uint64_t zero_equal_right, zero_greater;
bool ignore;
- toku_ft_keysrange(ft_handle, key, nullptr, less, equal, greater, &zero_equal_right, &zero_greater, &ignore);
+ toku_ft_keysrange(brt, key, nullptr, less, equal, greater, &zero_equal_right, &zero_greater, &ignore);
invariant_zero(zero_equal_right);
invariant_zero(zero_greater);
}
-void toku_ft_handle_stat64 (FT_HANDLE ft_handle, TOKUTXN UU(txn), struct ftstat64_s *s) {
- toku_ft_stat64(ft_handle->ft, s);
+void toku_ft_handle_stat64 (FT_HANDLE brt, TOKUTXN UU(txn), struct ftstat64_s *s) {
+ toku_ft_stat64(brt->ft, s);
}
void toku_ft_handle_get_fractal_tree_info64(FT_HANDLE ft_h, struct ftinfo64 *s) {
@@ -6722,22 +6400,23 @@ int toku_ft_handle_iterate_fractal_tree_block_map(FT_HANDLE ft_h, int (*iter)(ui
/* ********************* debugging dump ************************ */
static int
-toku_dump_ftnode (FILE *file, FT_HANDLE ft_handle, BLOCKNUM blocknum, int depth, const DBT *lorange, const DBT *hirange) {
+toku_dump_ftnode (FILE *file, FT_HANDLE brt, BLOCKNUM blocknum, int depth, const DBT *lorange, const DBT *hirange) {
int result=0;
FTNODE node;
- toku_get_node_for_verify(blocknum, ft_handle, &node);
- result=toku_verify_ftnode(ft_handle, ft_handle->ft->h->max_msn_in_ft, ft_handle->ft->h->max_msn_in_ft, false, node, -1, lorange, hirange, NULL, NULL, 0, 1, 0);
- uint32_t fullhash = toku_cachetable_hash(ft_handle->ft->cf, blocknum);
+ toku_get_node_for_verify(blocknum, brt, &node);
+ result=toku_verify_ftnode(brt, brt->ft->h->max_msn_in_ft, brt->ft->h->max_msn_in_ft, false, node, -1, lorange, hirange, NULL, NULL, 0, 1, 0);
+ uint32_t fullhash = toku_cachetable_hash(brt->ft->cf, blocknum);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_handle->ft);
- toku_pin_ftnode(
- ft_handle->ft,
+ fill_bfe_for_full_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
blocknum,
fullhash,
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->fullhash==fullhash);
fprintf(file, "%*sNode=%p\n", depth, "", node);
@@ -6764,7 +6443,7 @@ toku_dump_ftnode (FILE *file, FT_HANDLE ft_handle, BLOCKNUM blocknum, int depth,
});
}
else {
- int size = BLB_DATA(node, i)->num_klpairs();
+ int size = BLB_DATA(node, i)->omt_size();
if (0)
for (int j=0; j<size; j++) {
LEAFENTRY le;
@@ -6786,25 +6465,25 @@ toku_dump_ftnode (FILE *file, FT_HANDLE ft_handle, BLOCKNUM blocknum, int depth,
char *CAST_FROM_VOIDP(key, node->childkeys[i-1].data);
fprintf(file, "%*spivot %d len=%u %u\n", depth+1, "", i-1, node->childkeys[i-1].size, (unsigned)toku_dtoh32(*(int*)key));
}
- toku_dump_ftnode(file, ft_handle, BP_BLOCKNUM(node, i), depth+4,
+ toku_dump_ftnode(file, brt, BP_BLOCKNUM(node, i), depth+4,
(i==0) ? lorange : &node->childkeys[i-1],
(i==node->n_children-1) ? hirange : &node->childkeys[i]);
}
}
}
- toku_unpin_ftnode(ft_handle->ft, node);
+ toku_unpin_ftnode_off_client_thread(brt->ft, node);
return result;
}
-int toku_dump_ft (FILE *f, FT_HANDLE ft_handle) {
+int toku_dump_ft (FILE *f, FT_HANDLE brt) {
int r;
- assert(ft_handle->ft);
- toku_dump_translation_table(f, ft_handle->ft->blocktable);
+ assert(brt->ft);
+ toku_dump_translation_table(f, brt->ft->blocktable);
{
uint32_t fullhash = 0;
CACHEKEY root_key;
- toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &fullhash);
- r = toku_dump_ftnode(f, ft_handle, root_key, 0, 0, 0);
+ toku_calculate_root_offset_pointer(brt->ft, &root_key, &fullhash);
+ r = toku_dump_ftnode(f, brt, root_key, 0, 0, 0);
}
return r;
}
@@ -6899,23 +6578,23 @@ void toku_ft_unlink(FT_HANDLE handle) {
}
int
-toku_ft_get_fragmentation(FT_HANDLE ft_handle, TOKU_DB_FRAGMENTATION report) {
+toku_ft_get_fragmentation(FT_HANDLE brt, TOKU_DB_FRAGMENTATION report) {
int r;
- int fd = toku_cachefile_get_fd(ft_handle->ft->cf);
- toku_ft_lock(ft_handle->ft);
+ int fd = toku_cachefile_get_fd(brt->ft->cf);
+ toku_ft_lock(brt->ft);
int64_t file_size;
r = toku_os_get_file_size(fd, &file_size);
if (r==0) {
report->file_size_bytes = file_size;
- toku_block_table_get_fragmentation_unlocked(ft_handle->ft->blocktable, report);
+ toku_block_table_get_fragmentation_unlocked(brt->ft->blocktable, report);
}
- toku_ft_unlock(ft_handle->ft);
+ toku_ft_unlock(brt->ft);
return r;
}
-static bool is_empty_fast_iter (FT_HANDLE ft_handle, FTNODE node) {
+static bool is_empty_fast_iter (FT_HANDLE brt, FTNODE node) {
if (node->height > 0) {
for (int childnum=0; childnum<node->n_children; childnum++) {
if (toku_bnc_nbytesinbuf(BNC(node, childnum)) != 0) {
@@ -6924,30 +6603,31 @@ static bool is_empty_fast_iter (FT_HANDLE ft_handle, FTNODE node) {
FTNODE childnode;
{
BLOCKNUM childblocknum = BP_BLOCKNUM(node,childnum);
- uint32_t fullhash = compute_child_fullhash(ft_handle->ft->cf, node, childnum);
+ uint32_t fullhash = compute_child_fullhash(brt->ft->cf, node, childnum);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_handle->ft);
+ fill_bfe_for_full_read(&bfe, brt->ft);
// don't need to pass in dependent nodes as we are not
// modifying nodes we are pinning
- toku_pin_ftnode(
- ft_handle->ft,
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
childblocknum,
fullhash,
&bfe,
PL_READ, // may_modify_node set to false, as nodes not modified
- &childnode,
- true
+ 0,
+ NULL,
+ &childnode
);
}
- int child_is_empty = is_empty_fast_iter(ft_handle, childnode);
- toku_unpin_ftnode(ft_handle->ft, childnode);
+ int child_is_empty = is_empty_fast_iter(brt, childnode);
+ toku_unpin_ftnode(brt->ft, childnode);
if (!child_is_empty) return 0;
}
return 1;
} else {
- // leaf: If the dmt is empty, we are happy.
+ // leaf: If the omt is empty, we are happy.
for (int i = 0; i < node->n_children; i++) {
- if (BLB_DATA(node, i)->num_klpairs()) {
+ if (BLB_DATA(node, i)->omt_size()) {
return false;
}
}
@@ -6955,7 +6635,7 @@ static bool is_empty_fast_iter (FT_HANDLE ft_handle, FTNODE node) {
}
}
-bool toku_ft_is_empty_fast (FT_HANDLE ft_handle)
+bool toku_ft_is_empty_fast (FT_HANDLE brt)
// A fast check to see if the tree is empty. If there are any messages or leafentries, we consider the tree to be nonempty. It's possible that those
// messages and leafentries would all optimize away and that the tree is empty, but we'll say it is nonempty.
{
@@ -6963,21 +6643,22 @@ bool toku_ft_is_empty_fast (FT_HANDLE ft_handle)
FTNODE node;
{
CACHEKEY root_key;
- toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &fullhash);
+ toku_calculate_root_offset_pointer(brt->ft, &root_key, &fullhash);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_handle->ft);
- toku_pin_ftnode(
- ft_handle->ft,
+ fill_bfe_for_full_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
root_key,
fullhash,
&bfe,
PL_READ, // may_modify_node set to false, node does not change
- &node,
- true
+ 0,
+ NULL,
+ &node
);
}
- bool r = is_empty_fast_iter(ft_handle, node);
- toku_unpin_ftnode(ft_handle->ft, node);
+ bool r = is_empty_fast_iter(brt, node);
+ toku_unpin_ftnode(brt->ft, node);
return r;
}
diff --git a/storage/tokudb/ft-index/ft/ft-ops.h b/storage/tokudb/ft-index/ft/ft-ops.h
index cfa6ba20f6f..a98923e9924 100644
--- a/storage/tokudb/ft-index/ft/ft-ops.h
+++ b/storage/tokudb/ft-index/ft/ft-ops.h
@@ -103,7 +103,7 @@ PATENT RIGHTS GRANT:
// A callback function is invoked with the key, and the data.
// The pointers (to the bytevecs) must not be modified. The data must be copied out before the callback function returns.
-// Note: In the thread-safe version, the ftnode remains locked while the callback function runs. So return soon, and don't call the ft code from the callback function.
+// Note: In the thread-safe version, the brt node remains locked while the callback function runs. So return soon, and don't call the BRT code from the callback function.
// If the callback function returns a nonzero value (an error code), then that error code is returned from the get function itself.
// The cursor object will have been updated (so that if result==0 the current value is the value being passed)
// (If r!=0 then the cursor won't have been updated.)
@@ -141,9 +141,9 @@ void toku_ft_handle_set_fanout(FT_HANDLE, unsigned int fanout);
void toku_ft_handle_get_fanout(FT_HANDLE, unsigned int *fanout);
void toku_ft_set_bt_compare(FT_HANDLE, ft_compare_func);
-ft_compare_func toku_ft_get_bt_compare (FT_HANDLE ft_h);
+ft_compare_func toku_ft_get_bt_compare (FT_HANDLE brt);
-void toku_ft_set_redirect_callback(FT_HANDLE ft_h, on_redirect_callback redir_cb, void* extra);
+void toku_ft_set_redirect_callback(FT_HANDLE brt, on_redirect_callback redir_cb, void* extra);
// How updates (update/insert/deletes) work:
// There are two flavers of upsertdels: Singleton and broadcast.
@@ -181,7 +181,7 @@ void toku_ft_set_redirect_callback(FT_HANDLE ft_h, on_redirect_callback redir_cb
// Implementation note: Acquires a write lock on the entire database.
// This function works by sending an BROADCAST-UPDATE message containing
// the key and the extra.
-void toku_ft_set_update(FT_HANDLE ft_h, ft_update_func update_fun);
+void toku_ft_set_update(FT_HANDLE brt, ft_update_func update_fun);
int toku_ft_handle_open(FT_HANDLE, const char *fname_in_env,
int is_create, int only_create, CACHETABLE ct, TOKUTXN txn) __attribute__ ((warn_unused_result));
@@ -208,63 +208,60 @@ toku_ft_handle_open_with_dict_id(
DICTIONARY_ID use_dictionary_id
) __attribute__ ((warn_unused_result));
-int toku_ft_lookup (FT_HANDLE ft_h, DBT *k, FT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
+int toku_ft_lookup (FT_HANDLE brt, DBT *k, FT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
-// Effect: Insert a key and data pair into an ft
-void toku_ft_insert (FT_HANDLE ft_h, DBT *k, DBT *v, TOKUTXN txn);
-
-// Returns: 0 if the key was inserted, DB_KEYEXIST if the key already exists
-int toku_ft_insert_unique(FT_HANDLE ft, DBT *k, DBT *v, TOKUTXN txn, bool do_logging);
+// Effect: Insert a key and data pair into a brt
+void toku_ft_insert (FT_HANDLE brt, DBT *k, DBT *v, TOKUTXN txn);
// Effect: Optimize the ft
-void toku_ft_optimize (FT_HANDLE ft_h);
+void toku_ft_optimize (FT_HANDLE brt);
-// Effect: Insert a key and data pair into an ft if the oplsn is newer than the ft's lsn. This function is called during recovery.
-void toku_ft_maybe_insert (FT_HANDLE ft_h, DBT *k, DBT *v, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging, enum ft_msg_type type);
+// Effect: Insert a key and data pair into a brt if the oplsn is newer than the brt lsn. This function is called during recovery.
+void toku_ft_maybe_insert (FT_HANDLE brt, DBT *k, DBT *v, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging, enum ft_msg_type type);
-// Effect: Send an update message into an ft. This function is called
+// Effect: Send an update message into a brt. This function is called
// during recovery.
-void toku_ft_maybe_update(FT_HANDLE ft_h, const DBT *key, const DBT *update_function_extra, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging);
+void toku_ft_maybe_update(FT_HANDLE brt, const DBT *key, const DBT *update_function_extra, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging);
-// Effect: Send a broadcasting update message into an ft. This function
+// Effect: Send a broadcasting update message into a brt. This function
// is called during recovery.
-void toku_ft_maybe_update_broadcast(FT_HANDLE ft_h, const DBT *update_function_extra, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging, bool is_resetting_op);
+void toku_ft_maybe_update_broadcast(FT_HANDLE brt, const DBT *update_function_extra, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging, bool is_resetting_op);
void toku_ft_load_recovery(TOKUTXN txn, FILENUM old_filenum, char const * new_iname, int do_fsync, int do_log, LSN *load_lsn);
-void toku_ft_load(FT_HANDLE ft_h, TOKUTXN txn, char const * new_iname, int do_fsync, LSN *get_lsn);
+void toku_ft_load(FT_HANDLE brt, TOKUTXN txn, char const * new_iname, int do_fsync, LSN *get_lsn);
void toku_ft_hot_index_recovery(TOKUTXN txn, FILENUMS filenums, int do_fsync, int do_log, LSN *hot_index_lsn);
-void toku_ft_hot_index(FT_HANDLE ft_h, TOKUTXN txn, FILENUMS filenums, int do_fsync, LSN *lsn);
+void toku_ft_hot_index(FT_HANDLE brt, TOKUTXN txn, FILENUMS filenums, int do_fsync, LSN *lsn);
-void toku_ft_log_put_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *fts, uint32_t num_fts, const DBT *key, const DBT *val);
-void toku_ft_log_put (TOKUTXN txn, FT_HANDLE ft_h, const DBT *key, const DBT *val);
-void toku_ft_log_del_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *fts, uint32_t num_fts, const DBT *key, const DBT *val);
-void toku_ft_log_del (TOKUTXN txn, FT_HANDLE ft_h, const DBT *key);
+void toku_ft_log_put_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *brts, uint32_t num_fts, const DBT *key, const DBT *val);
+void toku_ft_log_put (TOKUTXN txn, FT_HANDLE brt, const DBT *key, const DBT *val);
+void toku_ft_log_del_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *brts, uint32_t num_fts, const DBT *key, const DBT *val);
+void toku_ft_log_del (TOKUTXN txn, FT_HANDLE brt, const DBT *key);
-// Effect: Delete a key from an ft
-void toku_ft_delete (FT_HANDLE ft_h, DBT *k, TOKUTXN txn);
+// Effect: Delete a key from a brt
+void toku_ft_delete (FT_HANDLE brt, DBT *k, TOKUTXN txn);
-// Effect: Delete a key from an ft if the oplsn is newer than the ft lsn. This function is called during recovery.
-void toku_ft_maybe_delete (FT_HANDLE ft_h, DBT *k, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging);
+// Effect: Delete a key from a brt if the oplsn is newer than the brt lsn. This function is called during recovery.
+void toku_ft_maybe_delete (FT_HANDLE brt, DBT *k, TOKUTXN txn, bool oplsn_valid, LSN oplsn, bool do_logging);
TXNID toku_ft_get_oldest_referenced_xid_estimate(FT_HANDLE ft_h);
TXN_MANAGER toku_ft_get_txn_manager(FT_HANDLE ft_h);
-void toku_ft_send_insert(FT_HANDLE ft_h, DBT *key, DBT *val, XIDS xids, enum ft_msg_type type, txn_gc_info *gc_info);
-void toku_ft_send_delete(FT_HANDLE ft_h, DBT *key, XIDS xids, txn_gc_info *gc_info);
-void toku_ft_send_commit_any(FT_HANDLE ft_h, DBT *key, XIDS xids, txn_gc_info *gc_info);
+void toku_ft_send_insert(FT_HANDLE brt, DBT *key, DBT *val, XIDS xids, enum ft_msg_type type, txn_gc_info *gc_info);
+void toku_ft_send_delete(FT_HANDLE brt, DBT *key, XIDS xids, txn_gc_info *gc_info);
+void toku_ft_send_commit_any(FT_HANDLE brt, DBT *key, XIDS xids, txn_gc_info *gc_info);
int toku_close_ft_handle_nolsn (FT_HANDLE, char **error_string) __attribute__ ((warn_unused_result));
-int toku_dump_ft (FILE *,FT_HANDLE ft_h) __attribute__ ((warn_unused_result));
+int toku_dump_ft (FILE *,FT_HANDLE brt) __attribute__ ((warn_unused_result));
extern int toku_ft_debug_mode;
-int toku_verify_ft (FT_HANDLE ft_h) __attribute__ ((warn_unused_result));
-int toku_verify_ft_with_progress (FT_HANDLE ft_h, int (*progress_callback)(void *extra, float progress), void *extra, int verbose, int keep_going) __attribute__ ((warn_unused_result));
+int toku_verify_ft (FT_HANDLE brt) __attribute__ ((warn_unused_result));
+int toku_verify_ft_with_progress (FT_HANDLE brt, int (*progress_callback)(void *extra, float progress), void *extra, int verbose, int keep_going) __attribute__ ((warn_unused_result));
typedef struct ft_cursor *FT_CURSOR;
int toku_ft_cursor (FT_HANDLE, FT_CURSOR*, TOKUTXN, bool, bool) __attribute__ ((warn_unused_result));
void toku_ft_cursor_set_leaf_mode(FT_CURSOR);
-// Sets a boolean on the ft cursor that prevents uncessary copying of
+// Sets a boolean on the brt cursor that prevents uncessary copying of
// the cursor duing a one query.
void toku_ft_cursor_set_temporary(FT_CURSOR);
void toku_ft_cursor_remove_restriction(FT_CURSOR);
@@ -301,8 +298,8 @@ enum ft_flags {
TOKU_DB_VALCMP_BUILTIN_13 = (1<<3),
};
-void toku_ft_keyrange(FT_HANDLE ft_h, DBT *key, uint64_t *less, uint64_t *equal, uint64_t *greater);
-void toku_ft_keysrange(FT_HANDLE ft_h, DBT* key_left, DBT* key_right, uint64_t *less_p, uint64_t* equal_left_p, uint64_t* middle_p, uint64_t* equal_right_p, uint64_t* greater_p, bool* middle_3_exact_p);
+void toku_ft_keyrange(FT_HANDLE brt, DBT *key, uint64_t *less, uint64_t *equal, uint64_t *greater);
+void toku_ft_keysrange(FT_HANDLE brt, DBT* key_left, DBT* key_right, uint64_t *less_p, uint64_t* equal_left_p, uint64_t* middle_p, uint64_t* equal_right_p, uint64_t* greater_p, bool* middle_3_exact_p);
int toku_ft_get_key_after_bytes(FT_HANDLE ft_h, const DBT *start_key, uint64_t skip_len, void (*callback)(const DBT *end_key, uint64_t actually_skipped, void *extra), void *cb_extra);
@@ -344,9 +341,9 @@ void toku_maybe_preallocate_in_file (int fd, int64_t size, int64_t expected_size
// Effect: make the file bigger by either doubling it or growing by 16MiB whichever is less, until it is at least size
// Return 0 on success, otherwise an error number.
-int toku_ft_get_fragmentation(FT_HANDLE ft_h, TOKU_DB_FRAGMENTATION report) __attribute__ ((warn_unused_result));
+int toku_ft_get_fragmentation(FT_HANDLE brt, TOKU_DB_FRAGMENTATION report) __attribute__ ((warn_unused_result));
-bool toku_ft_is_empty_fast (FT_HANDLE ft_h) __attribute__ ((warn_unused_result));
+bool toku_ft_is_empty_fast (FT_HANDLE brt) __attribute__ ((warn_unused_result));
// Effect: Return true if there are no messages or leaf entries in the tree. If so, it's empty. If there are messages or leaf entries, we say it's not empty
// even though if we were to optimize the tree it might turn out that they are empty.
@@ -361,6 +358,4 @@ extern bool garbage_collection_debug;
void toku_ft_set_direct_io(bool direct_io_on);
void toku_ft_set_compress_buffers_before_eviction(bool compress_buffers);
-void toku_note_deserialized_basement_node(bool fixed_key_size);
-
#endif
diff --git a/storage/tokudb/ft-index/ft/ft-serialize.cc b/storage/tokudb/ft-index/ft/ft-serialize.cc
index 1879561f20a..e6fbe0a2ce4 100644
--- a/storage/tokudb/ft-index/ft/ft-serialize.cc
+++ b/storage/tokudb/ft-index/ft/ft-serialize.cc
@@ -132,7 +132,7 @@ toku_serialize_descriptor_contents_to_fd(int fd, const DESCRIPTOR desc, DISKOFF
toku_serialize_descriptor_contents_to_wbuf(&w, desc);
{
//Add checksum
- uint32_t checksum = toku_x1764_finish(&w.checksum);
+ uint32_t checksum = x1764_finish(&w.checksum);
wbuf_int(&w, checksum);
}
lazy_assert(w.ndone==w.size);
@@ -185,7 +185,7 @@ deserialize_descriptor_from(int fd, BLOCK_TABLE bt, DESCRIPTOR desc, int layout_
}
{
// check the checksum
- uint32_t x1764 = toku_x1764_memory(dbuf, size-4);
+ uint32_t x1764 = x1764_memory(dbuf, size-4);
//printf("%s:%d read from %ld (x1764 offset=%ld) size=%ld\n", __FILE__, __LINE__, block_translation_address_on_disk, offset, block_translation_size_on_disk);
uint32_t stored_x1764 = toku_dtoh32(*(int*)(dbuf + size-4));
if (x1764 != stored_x1764) {
@@ -210,7 +210,7 @@ exit:
int deserialize_ft_versioned(int fd, struct rbuf *rb, FT *ftp, uint32_t version)
// Effect: Deserialize the ft header.
-// We deserialize ft_header only once and then share everything with all the FTs.
+// We deserialize brt header only once and then share everything with all the brts.
{
int r;
FT ft = NULL;
@@ -462,8 +462,6 @@ serialize_ft_min_size (uint32_t version) {
size_t size = 0;
switch(version) {
- case FT_LAYOUT_VERSION_27:
- case FT_LAYOUT_VERSION_26:
case FT_LAYOUT_VERSION_25:
case FT_LAYOUT_VERSION_24:
case FT_LAYOUT_VERSION_23:
@@ -625,7 +623,7 @@ int deserialize_ft_from_fd_into_rbuf(int fd,
//Verify checksum (FT_LAYOUT_VERSION_13 or later, when checksum function changed)
uint32_t calculated_x1764;
- calculated_x1764 = toku_x1764_memory(rb->buf, rb->size-4);
+ calculated_x1764 = x1764_memory(rb->buf, rb->size-4);
uint32_t stored_x1764;
stored_x1764 = toku_dtoh32(*(int*)(rb->buf+rb->size-4));
if (calculated_x1764 != stored_x1764) {
@@ -805,7 +803,7 @@ void toku_serialize_ft_to_wbuf (
wbuf_char(wbuf, (unsigned char) h->compression_method);
wbuf_MSN(wbuf, h->highest_unused_msn_for_upgrade);
wbuf_MSN(wbuf, h->max_msn_in_ft);
- uint32_t checksum = toku_x1764_finish(&wbuf->checksum);
+ uint32_t checksum = x1764_finish(&wbuf->checksum);
wbuf_int(wbuf, checksum);
lazy_assert(wbuf->ndone == wbuf->size);
}
diff --git a/storage/tokudb/ft-index/ft/ft-test-helpers.cc b/storage/tokudb/ft-index/ft/ft-test-helpers.cc
index 575bd69ab7e..135603147d9 100644
--- a/storage/tokudb/ft-index/ft/ft-test-helpers.cc
+++ b/storage/tokudb/ft-index/ft/ft-test-helpers.cc
@@ -96,7 +96,7 @@ PATENT RIGHTS GRANT:
#include "fttypes.h"
#include "ule.h"
-// dummymsn needed to simulate msn because messages are injected at a lower level than toku_ft_root_put_msg()
+// dummymsn needed to simulate msn because messages are injected at a lower level than toku_ft_root_put_cmd()
#define MIN_DUMMYMSN ((MSN) {(uint64_t)1 << 62})
static MSN dummymsn;
static int testsetup_initialized = 0;
@@ -119,10 +119,10 @@ next_dummymsn(void) {
bool ignore_if_was_already_open;
-int toku_testsetup_leaf(FT_HANDLE ft_handle, BLOCKNUM *blocknum, int n_children, char **keys, int *keylens) {
+int toku_testsetup_leaf(FT_HANDLE brt, BLOCKNUM *blocknum, int n_children, char **keys, int *keylens) {
FTNODE node;
assert(testsetup_initialized);
- toku_create_new_ftnode(ft_handle, &node, 0, n_children);
+ toku_create_new_ftnode(brt, &node, 0, n_children);
int i;
for (i=0; i<n_children; i++) {
BP_STATE(node,i) = PT_AVAIL;
@@ -134,15 +134,15 @@ int toku_testsetup_leaf(FT_HANDLE ft_handle, BLOCKNUM *blocknum, int n_children,
}
*blocknum = node->thisnodename;
- toku_unpin_ftnode(ft_handle->ft, node);
+ toku_unpin_ftnode(brt->ft, node);
return 0;
}
// Don't bother to clean up carefully if something goes wrong. (E.g., it's OK to have malloced stuff that hasn't been freed.)
-int toku_testsetup_nonleaf (FT_HANDLE ft_handle, int height, BLOCKNUM *blocknum, int n_children, BLOCKNUM *children, char **keys, int *keylens) {
+int toku_testsetup_nonleaf (FT_HANDLE brt, int height, BLOCKNUM *blocknum, int n_children, BLOCKNUM *children, char **keys, int *keylens) {
FTNODE node;
assert(testsetup_initialized);
- toku_create_new_ftnode(ft_handle, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
int i;
for (i=0; i<n_children; i++) {
BP_BLOCKNUM(node, i) = children[i];
@@ -153,28 +153,28 @@ int toku_testsetup_nonleaf (FT_HANDLE ft_handle, int height, BLOCKNUM *blocknum,
node->totalchildkeylens += keylens[i];
}
*blocknum = node->thisnodename;
- toku_unpin_ftnode(ft_handle->ft, node);
+ toku_unpin_ftnode(brt->ft, node);
return 0;
}
-int toku_testsetup_root(FT_HANDLE ft_handle, BLOCKNUM blocknum) {
+int toku_testsetup_root(FT_HANDLE brt, BLOCKNUM blocknum) {
assert(testsetup_initialized);
- ft_handle->ft->h->root_blocknum = blocknum;
+ brt->ft->h->root_blocknum = blocknum;
return 0;
}
-int toku_testsetup_get_sersize(FT_HANDLE ft_handle, BLOCKNUM diskoff) // Return the size on disk
+int toku_testsetup_get_sersize(FT_HANDLE brt, BLOCKNUM diskoff) // Return the size on disk
{
assert(testsetup_initialized);
void *node_v;
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_handle->ft);
+ fill_bfe_for_full_read(&bfe, brt->ft);
int r = toku_cachetable_get_and_pin(
- ft_handle->ft->cf, diskoff,
- toku_cachetable_hash(ft_handle->ft->cf, diskoff),
+ brt->ft->cf, diskoff,
+ toku_cachetable_hash(brt->ft->cf, diskoff),
&node_v,
NULL,
- get_write_callbacks_for_node(ft_handle->ft),
+ get_write_callbacks_for_node(brt->ft),
toku_ftnode_fetch_callback,
toku_ftnode_pf_req_callback,
toku_ftnode_pf_callback,
@@ -184,25 +184,25 @@ int toku_testsetup_get_sersize(FT_HANDLE ft_handle, BLOCKNUM diskoff) // Return
assert(r==0);
FTNODE CAST_FROM_VOIDP(node, node_v);
int size = toku_serialize_ftnode_size(node);
- toku_unpin_ftnode(ft_handle->ft, node);
+ toku_unpin_ftnode(brt->ft, node);
return size;
}
-int toku_testsetup_insert_to_leaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, const char *key, int keylen, const char *val, int vallen) {
+int toku_testsetup_insert_to_leaf (FT_HANDLE brt, BLOCKNUM blocknum, const char *key, int keylen, const char *val, int vallen) {
void *node_v;
int r;
assert(testsetup_initialized);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_handle->ft);
+ fill_bfe_for_full_read(&bfe, brt->ft);
r = toku_cachetable_get_and_pin(
- ft_handle->ft->cf,
+ brt->ft->cf,
blocknum,
- toku_cachetable_hash(ft_handle->ft->cf, blocknum),
+ toku_cachetable_hash(brt->ft->cf, blocknum),
&node_v,
NULL,
- get_write_callbacks_for_node(ft_handle->ft),
+ get_write_callbacks_for_node(brt->ft),
toku_ftnode_fetch_callback,
toku_ftnode_pf_req_callback,
toku_ftnode_pf_callback,
@@ -216,19 +216,19 @@ int toku_testsetup_insert_to_leaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, const
DBT keydbt,valdbt;
MSN msn = next_dummymsn();
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(),
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(),
.u = { .id = { toku_fill_dbt(&keydbt, key, keylen),
toku_fill_dbt(&valdbt, val, vallen) } } };
static size_t zero_flow_deltas[] = { 0, 0 };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, true);
- toku_ft_node_put_msg (
- ft_handle->ft->compare_fun,
- ft_handle->ft->update_fun,
- &ft_handle->ft->cmp_descriptor,
+ toku_ft_node_put_cmd (
+ brt->ft->compare_fun,
+ brt->ft->update_fun,
+ &brt->ft->cmp_descriptor,
node,
-1,
- &msg,
+ &cmd,
true,
&gc_info,
zero_flow_deltas,
@@ -237,7 +237,7 @@ int toku_testsetup_insert_to_leaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, const
toku_verify_or_set_counts(node);
- toku_unpin_ftnode(ft_handle->ft, node);
+ toku_unpin_ftnode(brt->ft, node);
return 0;
}
@@ -254,32 +254,33 @@ toku_pin_node_with_min_bfe(FTNODE* node, BLOCKNUM b, FT_HANDLE t)
{
struct ftnode_fetch_extra bfe;
fill_bfe_for_min_read(&bfe, t->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
b,
toku_cachetable_hash(t->ft->cf, b),
&bfe,
PL_WRITE_EXPENSIVE,
- node,
- true
+ 0,
+ NULL,
+ node
);
}
-int toku_testsetup_insert_to_nonleaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, enum ft_msg_type msgtype, const char *key, int keylen, const char *val, int vallen) {
+int toku_testsetup_insert_to_nonleaf (FT_HANDLE brt, BLOCKNUM blocknum, enum ft_msg_type cmdtype, const char *key, int keylen, const char *val, int vallen) {
void *node_v;
int r;
assert(testsetup_initialized);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_handle->ft);
+ fill_bfe_for_full_read(&bfe, brt->ft);
r = toku_cachetable_get_and_pin(
- ft_handle->ft->cf,
+ brt->ft->cf,
blocknum,
- toku_cachetable_hash(ft_handle->ft->cf, blocknum),
+ toku_cachetable_hash(brt->ft->cf, blocknum),
&node_v,
NULL,
- get_write_callbacks_for_node(ft_handle->ft),
+ get_write_callbacks_for_node(brt->ft),
toku_ftnode_fetch_callback,
toku_ftnode_pf_req_callback,
toku_ftnode_pf_callback,
@@ -293,19 +294,19 @@ int toku_testsetup_insert_to_nonleaf (FT_HANDLE ft_handle, BLOCKNUM blocknum, en
DBT k;
int childnum = toku_ftnode_which_child(node,
toku_fill_dbt(&k, key, keylen),
- &ft_handle->ft->cmp_descriptor, ft_handle->ft->compare_fun);
+ &brt->ft->cmp_descriptor, brt->ft->compare_fun);
XIDS xids_0 = xids_get_root_xids();
MSN msn = next_dummymsn();
- toku_bnc_insert_msg(BNC(node, childnum), key, keylen, val, vallen, msgtype, msn, xids_0, true, NULL, testhelper_string_key_cmp);
+ toku_bnc_insert_msg(BNC(node, childnum), key, keylen, val, vallen, cmdtype, msn, xids_0, true, NULL, testhelper_string_key_cmp);
// Hack to get the test working. The problem is that this test
// is directly queueing something in a FIFO instead of
- // using ft APIs.
+ // using brt APIs.
node->max_msn_applied_to_node_on_disk = msn;
node->dirty = 1;
// Also hack max_msn_in_ft
- ft_handle->ft->h->max_msn_in_ft = msn;
+ brt->ft->h->max_msn_in_ft = msn;
- toku_unpin_ftnode(ft_handle->ft, node);
+ toku_unpin_ftnode(brt->ft, node);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/ft-verify.cc b/storage/tokudb/ft-index/ft/ft-verify.cc
index 7e8d241cce2..fd65c2711de 100644
--- a/storage/tokudb/ft-index/ft/ft-verify.cc
+++ b/storage/tokudb/ft-index/ft/ft-verify.cc
@@ -89,7 +89,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-/* Verify an FT. */
+/* Verify a BRT. */
/* Check:
* The tree is of uniform depth (and the height is correct at every node)
* For each pivot key: the max of the stuff to the left is <= the pivot key < the min of the stuff to the right.
@@ -102,26 +102,26 @@ PATENT RIGHTS GRANT:
#include "ft.h"
static int
-compare_pairs (FT_HANDLE ft_handle, const DBT *a, const DBT *b) {
- FAKE_DB(db, &ft_handle->ft->cmp_descriptor);
- int cmp = ft_handle->ft->compare_fun(&db, a, b);
+compare_pairs (FT_HANDLE brt, const DBT *a, const DBT *b) {
+ FAKE_DB(db, &brt->ft->cmp_descriptor);
+ int cmp = brt->ft->compare_fun(&db, a, b);
return cmp;
}
static int
-compare_pair_to_key (FT_HANDLE ft_handle, const DBT *a, bytevec key, ITEMLEN keylen) {
+compare_pair_to_key (FT_HANDLE brt, const DBT *a, bytevec key, ITEMLEN keylen) {
DBT y;
- FAKE_DB(db, &ft_handle->ft->cmp_descriptor);
- int cmp = ft_handle->ft->compare_fun(&db, a, toku_fill_dbt(&y, key, keylen));
+ FAKE_DB(db, &brt->ft->cmp_descriptor);
+ int cmp = brt->ft->compare_fun(&db, a, toku_fill_dbt(&y, key, keylen));
return cmp;
}
static int
-verify_msg_in_child_buffer(FT_HANDLE ft_handle, enum ft_msg_type type, MSN msn, bytevec key, ITEMLEN keylen, bytevec UU(data), ITEMLEN UU(datalen), XIDS UU(xids), const DBT *lesser_pivot, const DBT *greatereq_pivot)
+verify_msg_in_child_buffer(FT_HANDLE brt, enum ft_msg_type type, MSN msn, bytevec key, ITEMLEN keylen, bytevec UU(data), ITEMLEN UU(datalen), XIDS UU(xids), const DBT *lesser_pivot, const DBT *greatereq_pivot)
__attribute__((warn_unused_result));
static int
-verify_msg_in_child_buffer(FT_HANDLE ft_handle, enum ft_msg_type type, MSN msn, bytevec key, ITEMLEN keylen, bytevec UU(data), ITEMLEN UU(datalen), XIDS UU(xids), const DBT *lesser_pivot, const DBT *greatereq_pivot) {
+verify_msg_in_child_buffer(FT_HANDLE brt, enum ft_msg_type type, MSN msn, bytevec key, ITEMLEN keylen, bytevec UU(data), ITEMLEN UU(datalen), XIDS UU(xids), const DBT *lesser_pivot, const DBT *greatereq_pivot) {
int result = 0;
if (msn.msn == ZERO_MSN.msn)
result = EINVAL;
@@ -135,12 +135,12 @@ verify_msg_in_child_buffer(FT_HANDLE ft_handle, enum ft_msg_type type, MSN msn,
case FT_COMMIT_ANY:
// verify key in bounds
if (lesser_pivot) {
- int compare = compare_pair_to_key(ft_handle, lesser_pivot, key, keylen);
+ int compare = compare_pair_to_key(brt, lesser_pivot, key, keylen);
if (compare >= 0)
result = EINVAL;
}
if (result == 0 && greatereq_pivot) {
- int compare = compare_pair_to_key(ft_handle, greatereq_pivot, key, keylen);
+ int compare = compare_pair_to_key(brt, greatereq_pivot, key, keylen);
if (compare < 0)
result = EINVAL;
}
@@ -152,7 +152,7 @@ verify_msg_in_child_buffer(FT_HANDLE ft_handle, enum ft_msg_type type, MSN msn,
static DBT
get_ith_key_dbt (BASEMENTNODE bn, int i) {
DBT kdbt;
- int r = bn->data_buffer.fetch_key_and_len(i, &kdbt.size, &kdbt.data);
+ int r = bn->data_buffer.fetch_le_key_and_len(i, &kdbt.size, &kdbt.data);
invariant_zero(r); // this is a bad failure if it happens.
return kdbt;
}
@@ -243,7 +243,7 @@ int verify_marked_messages(const int32_t &offset, const uint32_t UU(idx), struct
template<typename verify_omt_t>
static int
-verify_sorted_by_key_msn(FT_HANDLE ft_handle, FIFO fifo, const verify_omt_t &mt) {
+verify_sorted_by_key_msn(FT_HANDLE brt, FIFO fifo, const verify_omt_t &mt) {
int result = 0;
size_t last_offset = 0;
for (uint32_t i = 0; i < mt.size(); i++) {
@@ -253,8 +253,8 @@ verify_sorted_by_key_msn(FT_HANDLE ft_handle, FIFO fifo, const verify_omt_t &mt)
if (i > 0) {
struct toku_fifo_entry_key_msn_cmp_extra extra;
ZERO_STRUCT(extra);
- extra.desc = &ft_handle->ft->cmp_descriptor;
- extra.cmp = ft_handle->ft->compare_fun;
+ extra.desc = &brt->ft->cmp_descriptor;
+ extra.cmp = brt->ft->compare_fun;
extra.fifo = fifo;
if (toku_fifo_entry_key_msn_cmp(extra, last_offset, offset) >= 0) {
result = TOKUDB_NEEDS_REPAIR;
@@ -268,11 +268,11 @@ verify_sorted_by_key_msn(FT_HANDLE ft_handle, FIFO fifo, const verify_omt_t &mt)
template<typename count_omt_t>
static int
-count_eq_key_msn(FT_HANDLE ft_handle, FIFO fifo, const count_omt_t &mt, const DBT *key, MSN msn) {
+count_eq_key_msn(FT_HANDLE brt, FIFO fifo, const count_omt_t &mt, const DBT *key, MSN msn) {
struct toku_fifo_entry_key_msn_heaviside_extra extra;
ZERO_STRUCT(extra);
- extra.desc = &ft_handle->ft->cmp_descriptor;
- extra.cmp = ft_handle->ft->compare_fun;
+ extra.desc = &brt->ft->cmp_descriptor;
+ extra.cmp = brt->ft->compare_fun;
extra.fifo = fifo;
extra.key = key;
extra.msn = msn;
@@ -290,26 +290,28 @@ count_eq_key_msn(FT_HANDLE ft_handle, FIFO fifo, const count_omt_t &mt, const DB
void
toku_get_node_for_verify(
BLOCKNUM blocknum,
- FT_HANDLE ft_handle,
+ FT_HANDLE brt,
FTNODE* nodep
)
{
- uint32_t fullhash = toku_cachetable_hash(ft_handle->ft->cf, blocknum);
+ uint32_t fullhash = toku_cachetable_hash(brt->ft->cf, blocknum);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_handle->ft);
- toku_pin_ftnode(
- ft_handle->ft,
+ fill_bfe_for_full_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread_and_maybe_move_messages(
+ brt->ft,
blocknum,
fullhash,
&bfe,
PL_WRITE_EXPENSIVE, // may_modify_node
+ 0,
+ NULL,
nodep,
false
);
}
static int
-toku_verify_ftnode_internal(FT_HANDLE ft_handle,
+toku_verify_ftnode_internal(FT_HANDLE brt,
MSN rootmsn, MSN parentmsn_with_messages, bool messages_exist_above,
FTNODE node, int height,
const DBT *lesser_pivot, // Everything in the subtree should be > lesser_pivot. (lesser_pivot==NULL if there is no lesser pivot.)
@@ -332,17 +334,17 @@ toku_verify_ftnode_internal(FT_HANDLE ft_handle,
}
// Verify that all the pivot keys are in order.
for (int i = 0; i < node->n_children-2; i++) {
- int compare = compare_pairs(ft_handle, &node->childkeys[i], &node->childkeys[i+1]);
+ int compare = compare_pairs(brt, &node->childkeys[i], &node->childkeys[i+1]);
VERIFY_ASSERTION(compare < 0, i, "Value is >= the next value");
}
// Verify that all the pivot keys are lesser_pivot < pivot <= greatereq_pivot
for (int i = 0; i < node->n_children-1; i++) {
if (lesser_pivot) {
- int compare = compare_pairs(ft_handle, lesser_pivot, &node->childkeys[i]);
+ int compare = compare_pairs(brt, lesser_pivot, &node->childkeys[i]);
VERIFY_ASSERTION(compare < 0, i, "Pivot is >= the lower-bound pivot");
}
if (greatereq_pivot) {
- int compare = compare_pairs(ft_handle, greatereq_pivot, &node->childkeys[i]);
+ int compare = compare_pairs(brt, greatereq_pivot, &node->childkeys[i]);
VERIFY_ASSERTION(compare >= 0, i, "Pivot is < the upper-bound pivot");
}
}
@@ -354,12 +356,12 @@ toku_verify_ftnode_internal(FT_HANDLE ft_handle,
MSN last_msn = ZERO_MSN;
// Verify that messages in the buffers are in the right place.
NONLEAF_CHILDINFO bnc = BNC(node, i);
- VERIFY_ASSERTION(verify_sorted_by_key_msn(ft_handle, bnc->buffer, bnc->fresh_message_tree) == 0, i, "fresh_message_tree");
- VERIFY_ASSERTION(verify_sorted_by_key_msn(ft_handle, bnc->buffer, bnc->stale_message_tree) == 0, i, "stale_message_tree");
+ VERIFY_ASSERTION(verify_sorted_by_key_msn(brt, bnc->buffer, bnc->fresh_message_tree) == 0, i, "fresh_message_tree");
+ VERIFY_ASSERTION(verify_sorted_by_key_msn(brt, bnc->buffer, bnc->stale_message_tree) == 0, i, "stale_message_tree");
FIFO_ITERATE(bnc->buffer, key, keylen, data, datalen, itype, msn, xid, is_fresh,
({
enum ft_msg_type type = (enum ft_msg_type) itype;
- int r = verify_msg_in_child_buffer(ft_handle, type, msn, key, keylen, data, datalen, xid,
+ int r = verify_msg_in_child_buffer(brt, type, msn, key, keylen, data, datalen, xid,
curr_less_pivot,
curr_geq_pivot);
VERIFY_ASSERTION(r==0, i, "A message in the buffer is out of place");
@@ -370,7 +372,7 @@ toku_verify_ftnode_internal(FT_HANDLE ft_handle,
DBT keydbt;
toku_fill_dbt(&keydbt, key, keylen);
int total_count = 0;
- count = count_eq_key_msn(ft_handle, bnc->buffer, bnc->fresh_message_tree, toku_fill_dbt(&keydbt, key, keylen), msn);
+ count = count_eq_key_msn(brt, bnc->buffer, bnc->fresh_message_tree, toku_fill_dbt(&keydbt, key, keylen), msn);
total_count += count;
if (is_fresh) {
VERIFY_ASSERTION(count == 1, i, "a fresh message was not found in the fresh message tree");
@@ -378,7 +380,7 @@ toku_verify_ftnode_internal(FT_HANDLE ft_handle,
VERIFY_ASSERTION(count == 0, i, "a stale message was found in the fresh message tree");
}
VERIFY_ASSERTION(count <= 1, i, "a message was found multiple times in the fresh message tree");
- count = count_eq_key_msn(ft_handle, bnc->buffer, bnc->stale_message_tree, &keydbt, msn);
+ count = count_eq_key_msn(brt, bnc->buffer, bnc->stale_message_tree, &keydbt, msn);
total_count += count;
if (is_fresh) {
@@ -422,20 +424,20 @@ toku_verify_ftnode_internal(FT_HANDLE ft_handle,
}
else {
BASEMENTNODE bn = BLB(node, i);
- for (uint32_t j = 0; j < bn->data_buffer.num_klpairs(); j++) {
+ for (uint32_t j = 0; j < bn->data_buffer.omt_size(); j++) {
VERIFY_ASSERTION((rootmsn.msn >= this_msn.msn), 0, "leaf may have latest msn, but cannot be greater than root msn");
DBT kdbt = get_ith_key_dbt(bn, j);
if (curr_less_pivot) {
- int compare = compare_pairs(ft_handle, curr_less_pivot, &kdbt);
+ int compare = compare_pairs(brt, curr_less_pivot, &kdbt);
VERIFY_ASSERTION(compare < 0, j, "The leafentry is >= the lower-bound pivot");
}
if (curr_geq_pivot) {
- int compare = compare_pairs(ft_handle, curr_geq_pivot, &kdbt);
+ int compare = compare_pairs(brt, curr_geq_pivot, &kdbt);
VERIFY_ASSERTION(compare >= 0, j, "The leafentry is < the upper-bound pivot");
}
if (0 < j) {
DBT prev_key_dbt = get_ith_key_dbt(bn, j-1);
- int compare = compare_pairs(ft_handle, &prev_key_dbt, &kdbt);
+ int compare = compare_pairs(brt, &prev_key_dbt, &kdbt);
VERIFY_ASSERTION(compare < 0, j, "Adjacent leafentries are out of order");
}
}
@@ -449,7 +451,7 @@ done:
// input is a pinned node, on exit, node is unpinned
int
-toku_verify_ftnode (FT_HANDLE ft_handle,
+toku_verify_ftnode (FT_HANDLE brt,
MSN rootmsn, MSN parentmsn_with_messages, bool messages_exist_above,
FTNODE node, int height,
const DBT *lesser_pivot, // Everything in the subtree should be > lesser_pivot. (lesser_pivot==NULL if there is no lesser pivot.)
@@ -469,15 +471,15 @@ toku_verify_ftnode (FT_HANDLE ft_handle,
// Otherwise we'll just do the next call
result = toku_verify_ftnode_internal(
- ft_handle, rootmsn, parentmsn_with_messages, messages_exist_above, node, height, lesser_pivot, greatereq_pivot,
+ brt, rootmsn, parentmsn_with_messages, messages_exist_above, node, height, lesser_pivot, greatereq_pivot,
verbose, keep_going_on_failure, false);
if (result != 0 && (!keep_going_on_failure || result != TOKUDB_NEEDS_REPAIR)) goto done;
}
if (node->height > 0) {
- toku_move_ftnode_messages_to_stale(ft_handle->ft, node);
+ toku_move_ftnode_messages_to_stale(brt->ft, node);
}
result2 = toku_verify_ftnode_internal(
- ft_handle, rootmsn, parentmsn_with_messages, messages_exist_above, node, height, lesser_pivot, greatereq_pivot,
+ brt, rootmsn, parentmsn_with_messages, messages_exist_above, node, height, lesser_pivot, greatereq_pivot,
verbose, keep_going_on_failure, true);
if (result == 0) {
result = result2;
@@ -488,8 +490,8 @@ toku_verify_ftnode (FT_HANDLE ft_handle,
if (recurse && node->height > 0) {
for (int i = 0; i < node->n_children; i++) {
FTNODE child_node;
- toku_get_node_for_verify(BP_BLOCKNUM(node, i), ft_handle, &child_node);
- int r = toku_verify_ftnode(ft_handle, rootmsn,
+ toku_get_node_for_verify(BP_BLOCKNUM(node, i), brt, &child_node);
+ int r = toku_verify_ftnode(brt, rootmsn,
(toku_bnc_n_entries(BNC(node, i)) > 0
? this_msn
: parentmsn_with_messages),
@@ -506,7 +508,7 @@ toku_verify_ftnode (FT_HANDLE ft_handle,
}
}
done:
- toku_unpin_ftnode(ft_handle->ft, node);
+ toku_unpin_ftnode(brt->ft, node);
if (result == 0 && progress_callback)
result = progress_callback(progress_extra, 0.0);
@@ -515,26 +517,26 @@ done:
}
int
-toku_verify_ft_with_progress (FT_HANDLE ft_handle, int (*progress_callback)(void *extra, float progress), void *progress_extra, int verbose, int keep_on_going) {
- assert(ft_handle->ft);
+toku_verify_ft_with_progress (FT_HANDLE brt, int (*progress_callback)(void *extra, float progress), void *progress_extra, int verbose, int keep_on_going) {
+ assert(brt->ft);
FTNODE root_node = NULL;
{
uint32_t root_hash;
CACHEKEY root_key;
- toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &root_hash);
- toku_get_node_for_verify(root_key, ft_handle, &root_node);
+ toku_calculate_root_offset_pointer(brt->ft, &root_key, &root_hash);
+ toku_get_node_for_verify(root_key, brt, &root_node);
}
- int r = toku_verify_ftnode(ft_handle, ft_handle->ft->h->max_msn_in_ft, ft_handle->ft->h->max_msn_in_ft, false, root_node, -1, NULL, NULL, progress_callback, progress_extra, 1, verbose, keep_on_going);
+ int r = toku_verify_ftnode(brt, brt->ft->h->max_msn_in_ft, brt->ft->h->max_msn_in_ft, false, root_node, -1, NULL, NULL, progress_callback, progress_extra, 1, verbose, keep_on_going);
if (r == 0) {
- toku_ft_lock(ft_handle->ft);
- ft_handle->ft->h->time_of_last_verification = time(NULL);
- ft_handle->ft->h->dirty = 1;
- toku_ft_unlock(ft_handle->ft);
+ toku_ft_lock(brt->ft);
+ brt->ft->h->time_of_last_verification = time(NULL);
+ brt->ft->h->dirty = 1;
+ toku_ft_unlock(brt->ft);
}
return r;
}
int
-toku_verify_ft (FT_HANDLE ft_handle) {
- return toku_verify_ft_with_progress(ft_handle, NULL, NULL, 0, 0);
+toku_verify_ft (FT_HANDLE brt) {
+ return toku_verify_ft_with_progress(brt, NULL, NULL, 0, 0);
}
diff --git a/storage/tokudb/ft-index/ft/ft.cc b/storage/tokudb/ft-index/ft/ft.cc
index 5c8e439e644..0fd43065f1a 100644
--- a/storage/tokudb/ft-index/ft/ft.cc
+++ b/storage/tokudb/ft-index/ft/ft.cc
@@ -309,14 +309,16 @@ static void ft_close(CACHEFILE cachefile, int fd, void *header_v, bool oplsn_val
}
}
if (ft->h->dirty) { // this is the only place this bit is tested (in currentheader)
- if (logger) { //Rollback cachefile MUST NOT BE CLOSED DIRTY
- //It can be checkpointed only via 'checkpoint'
- assert(logger->rollback_cachefile != cachefile);
+ bool do_checkpoint = true;
+ if (logger && logger->rollback_cachefile == cachefile) {
+ do_checkpoint = false;
+ }
+ if (do_checkpoint) {
+ ft_begin_checkpoint(lsn, header_v);
+ ft_checkpoint(cachefile, fd, ft);
+ ft_end_checkpoint(cachefile, fd, header_v);
+ assert(!ft->h->dirty); // dirty bit should be cleared by begin_checkpoint and never set again (because we're closing the dictionary)
}
- ft_begin_checkpoint(lsn, header_v);
- ft_checkpoint(cachefile, fd, ft);
- ft_end_checkpoint(cachefile, fd, header_v);
- assert(!ft->h->dirty); // dirty bit should be cleared by begin_checkpoint and never set again (because we're closing the dictionary)
}
}
@@ -465,8 +467,8 @@ void toku_ft_create(FT *ftp, FT_OPTIONS options, CACHEFILE cf, TOKUTXN txn) {
*ftp = ft;
}
-// TODO: (Zardosht) get rid of ft parameter
-int toku_read_ft_and_store_in_cachefile (FT_HANDLE ft_handle, CACHEFILE cf, LSN max_acceptable_lsn, FT *header)
+// TODO: (Zardosht) get rid of brt parameter
+int toku_read_ft_and_store_in_cachefile (FT_HANDLE brt, CACHEFILE cf, LSN max_acceptable_lsn, FT *header)
// If the cachefile already has the header, then just get it.
// If the cachefile has not been initialized, then don't modify anything.
// max_acceptable_lsn is the latest acceptable checkpointed version of the file.
@@ -475,8 +477,8 @@ int toku_read_ft_and_store_in_cachefile (FT_HANDLE ft_handle, CACHEFILE cf, LSN
FT h;
if ((h = (FT) toku_cachefile_get_userdata(cf))!=0) {
*header = h;
- assert(ft_handle->options.update_fun == h->update_fun);
- assert(ft_handle->options.compare_fun == h->compare_fun);
+ assert(brt->options.update_fun == h->update_fun);
+ assert(brt->options.compare_fun == h->compare_fun);
return 0;
}
}
@@ -494,8 +496,8 @@ int toku_read_ft_and_store_in_cachefile (FT_HANDLE ft_handle, CACHEFILE cf, LSN
// GCC 4.8 seems to get confused by the gotos in the deserialize code and think h is maybe uninitialized.
invariant_notnull(h);
h->cf = cf;
- h->compare_fun = ft_handle->options.compare_fun;
- h->update_fun = ft_handle->options.update_fun;
+ h->compare_fun = brt->options.compare_fun;
+ h->update_fun = brt->options.update_fun;
toku_cachefile_set_userdata(cf,
(void*)h,
ft_log_fassociate_during_checkpoint,
@@ -557,13 +559,13 @@ FT_HANDLE toku_ft_get_only_existing_ft_handle(FT h) {
return ft_handle_ret;
}
-// Purpose: set fields in ft_header to capture accountability info for start of HOT optimize.
+// Purpose: set fields in brt_header to capture accountability info for start of HOT optimize.
// Note: HOT accountability variables in header are modified only while holding header lock.
// (Header lock is really needed for touching the dirty bit, but it's useful and
// convenient here for keeping the HOT variables threadsafe.)
void
-toku_ft_note_hot_begin(FT_HANDLE ft_handle) {
- FT ft = ft_handle->ft;
+toku_ft_note_hot_begin(FT_HANDLE brt) {
+ FT ft = brt->ft;
time_t now = time(NULL);
// hold lock around setting and clearing of dirty bit
@@ -576,11 +578,11 @@ toku_ft_note_hot_begin(FT_HANDLE ft_handle) {
}
-// Purpose: set fields in ft_header to capture accountability info for end of HOT optimize.
+// Purpose: set fields in brt_header to capture accountability info for end of HOT optimize.
// Note: See note for toku_ft_note_hot_begin().
void
-toku_ft_note_hot_complete(FT_HANDLE ft_handle, bool success, MSN msn_at_start_of_hot) {
- FT ft = ft_handle->ft;
+toku_ft_note_hot_complete(FT_HANDLE brt, bool success, MSN msn_at_start_of_hot) {
+ FT ft = brt->ft;
time_t now = time(NULL);
toku_ft_lock(ft);
@@ -626,7 +628,7 @@ toku_ft_init(FT ft,
ft->h->checkpoint_lsn = checkpoint_lsn;
}
-// Open an ft for use by redirect. The new ft must have the same dict_id as the old_ft passed in. (FILENUM is assigned by the ft_handle_open() function.)
+// Open a brt for use by redirect. The new brt must have the same dict_id as the old_ft passed in. (FILENUM is assigned by the ft_handle_open() function.)
static int
ft_handle_open_for_redirect(FT_HANDLE *new_ftp, const char *fname_in_env, TOKUTXN txn, FT old_h) {
FT_HANDLE t;
@@ -664,9 +666,9 @@ dictionary_redirect_internal(const char *dst_fname_in_env, FT src_h, TOKUTXN txn
FT dst_h = NULL;
struct toku_list *list;
- // open a dummy ft based off of
+ // open a dummy brt based off of
// dst_fname_in_env to get the header
- // then we will change all the ft's to have
+ // then we will change all the brt's to have
// their headers point to dst_h instead of src_h
FT_HANDLE tmp_dst_ft = NULL;
r = ft_handle_open_for_redirect(&tmp_dst_ft, dst_fname_in_env, txn, src_h);
@@ -680,7 +682,7 @@ dictionary_redirect_internal(const char *dst_fname_in_env, FT src_h, TOKUTXN txn
assert(dst_filenum.fileid!=FILENUM_NONE.fileid);
assert(dst_filenum.fileid!=src_filenum.fileid); //Cannot be same file.
- // for each live ft_handle, ft_handle->ft is currently src_h
+ // for each live brt, brt->ft is currently src_h
// we want to change it to dummy_dst
toku_ft_grab_reflock(src_h);
while (!toku_list_empty(&src_h->live_ft_handles)) {
@@ -720,7 +722,7 @@ toku_dictionary_redirect_abort(FT old_h, FT new_h, TOKUTXN txn) {
FILENUM new_filenum = toku_cachefile_filenum(new_h->cf);
assert(old_filenum.fileid!=new_filenum.fileid); //Cannot be same file.
- //No living fts in old header.
+ //No living brts in old header.
toku_ft_grab_reflock(old_h);
assert(toku_list_empty(&old_h->live_ft_handles));
toku_ft_release_reflock(old_h);
@@ -738,13 +740,13 @@ toku_dictionary_redirect_abort(FT old_h, FT new_h, TOKUTXN txn) {
/****
* on redirect or abort:
* if redirect txn_note_doing_work(txn)
- * if redirect connect src ft to txn (txn modified this ft)
- * for each src ft
- * open ft to dst file (create new ft struct)
- * if redirect connect dst ft to txn
- * redirect db to new ft
- * redirect cursors to new ft
- * close all src fts
+ * if redirect connect src brt to txn (txn modified this brt)
+ * for each src brt
+ * open brt to dst file (create new brt struct)
+ * if redirect connect dst brt to txn
+ * redirect db to new brt
+ * redirect cursors to new brt
+ * close all src brts
* if redirect make rollback log entry
*
* on commit:
@@ -756,21 +758,21 @@ int
toku_dictionary_redirect (const char *dst_fname_in_env, FT_HANDLE old_ft_h, TOKUTXN txn) {
// Input args:
// new file name for dictionary (relative to env)
-// old_ft_h is a live ft of open handle ({DB, FT_HANDLE} pair) that currently refers to old dictionary file.
+// old_ft_h is a live brt of open handle ({DB, BRT} pair) that currently refers to old dictionary file.
// (old_ft_h may be one of many handles to the dictionary.)
// txn that created the loader
// Requires:
// multi operation lock is held.
-// The ft is open. (which implies there can be no zombies.)
+// The brt is open. (which implies there can be no zombies.)
// The new file must be a valid dictionary.
-// The block size and flags in the new file must match the existing FT.
+// The block size and flags in the new file must match the existing BRT.
// The new file must already have its descriptor in it (and it must match the existing descriptor).
// Effect:
// Open new FTs (and related header and cachefile) to the new dictionary file with a new FILENUM.
-// Redirect all DBs that point to fts that point to the old file to point to fts that point to the new file.
+// Redirect all DBs that point to brts that point to the old file to point to brts that point to the new file.
// Copy the dictionary id (dict_id) from the header of the original file to the header of the new file.
// Create a rollback log entry.
-// The original FT, header, cachefile and file remain unchanged. They will be cleaned up on commmit.
+// The original BRT, header, cachefile and file remain unchanged. They will be cleaned up on commmit.
// If the txn aborts, then this operation will be undone
int r;
@@ -1077,8 +1079,8 @@ garbage_helper(BLOCKNUM blocknum, int64_t UU(size), int64_t UU(address), void *e
goto exit;
}
for (int i = 0; i < node->n_children; ++i) {
- bn_data* bd = BLB_DATA(node, i);
- r = bd->iterate<struct garbage_helper_extra, garbage_leafentry_helper>(info);
+ BN_DATA bd = BLB_DATA(node, i);
+ r = bd->omt_iterate<struct garbage_helper_extra, garbage_leafentry_helper>(info);
if (r != 0) {
goto exit;
}
diff --git a/storage/tokudb/ft-index/ft/ft.h b/storage/tokudb/ft-index/ft/ft.h
index e536241722c..92d1ba0b5ea 100644
--- a/storage/tokudb/ft-index/ft/ft.h
+++ b/storage/tokudb/ft-index/ft/ft.h
@@ -113,7 +113,7 @@ void toku_ft_release_reflock(FT ft);
void toku_ft_create(FT *ftp, FT_OPTIONS options, CACHEFILE cf, TOKUTXN txn);
void toku_ft_free (FT h);
-int toku_read_ft_and_store_in_cachefile (FT_HANDLE ft_h, CACHEFILE cf, LSN max_acceptable_lsn, FT *header);
+int toku_read_ft_and_store_in_cachefile (FT_HANDLE brt, CACHEFILE cf, LSN max_acceptable_lsn, FT *header);
void toku_ft_note_ft_handle_open(FT ft, FT_HANDLE live);
bool toku_ft_needed_unlocked(FT ft);
@@ -125,8 +125,8 @@ void toku_ft_evict_from_memory(FT ft, bool oplsn_valid, LSN oplsn);
FT_HANDLE toku_ft_get_only_existing_ft_handle(FT h);
-void toku_ft_note_hot_begin(FT_HANDLE ft_h);
-void toku_ft_note_hot_complete(FT_HANDLE ft_h, bool success, MSN msn_at_start_of_hot);
+void toku_ft_note_hot_begin(FT_HANDLE brt);
+void toku_ft_note_hot_complete(FT_HANDLE brt, bool success, MSN msn_at_start_of_hot);
void
toku_ft_init(
diff --git a/storage/tokudb/ft-index/ft/ft_layout_version.h b/storage/tokudb/ft-index/ft/ft_layout_version.h
index 01c7363e98d..da401ea7c55 100644
--- a/storage/tokudb/ft-index/ft/ft_layout_version.h
+++ b/storage/tokudb/ft-index/ft/ft_layout_version.h
@@ -99,7 +99,7 @@ enum ft_layout_version_e {
FT_LAYOUT_VERSION_7 = 7, // Diff from 6 to 7: Add exact-bit to leafentry_estimate #818, add magic to header #22, add per-subdatase flags #333
FT_LAYOUT_VERSION_8 = 8, // Diff from 7 to 8: Use murmur instead of crc32. We are going to make a simplification and stop supporting version 7 and before. Current As of Beta 1.0.6
FT_LAYOUT_VERSION_9 = 9, // Diff from 8 to 9: Variable-sized blocks and compression.
- FT_LAYOUT_VERSION_10 = 10, // Diff from 9 to 10: Variable number of compressed sub-blocks per block, disk byte order == intel byte order, Subtree estimates instead of just leafentry estimates, translation table, dictionary descriptors, checksum in header, subdb support removed from ft layer
+ FT_LAYOUT_VERSION_10 = 10, // Diff from 9 to 10: Variable number of compressed sub-blocks per block, disk byte order == intel byte order, Subtree estimates instead of just leafentry estimates, translation table, dictionary descriptors, checksum in header, subdb support removed from brt layer
FT_LAYOUT_VERSION_11 = 11, // Diff from 10 to 11: Nested transaction leafentries (completely redesigned). FT_CMDs on disk now support XIDS (multiple txnids) instead of exactly one.
FT_LAYOUT_VERSION_12 = 12, // Diff from 11 to 12: Added FT_CMD 'FT_INSERT_NO_OVERWRITE', compressed block format, num old blocks
FT_LAYOUT_VERSION_13 = 13, // Diff from 12 to 13: Fixed loader pivot bug, added build_id to every node, timestamps to ft
@@ -107,8 +107,8 @@ enum ft_layout_version_e {
FT_LAYOUT_VERSION_15 = 15, // Diff from 14 to 15: basement nodes, last verification time
FT_LAYOUT_VERSION_16 = 16, // Dr. No: No subtree estimates, partition layout information represented more transparently.
// ALERT ALERT ALERT: version 16 never released to customers, internal and beta use only
- FT_LAYOUT_VERSION_17 = 17, // Dr. No: Add STAT64INFO_S to ft header
- FT_LAYOUT_VERSION_18 = 18, // Dr. No: Add HOT info to ft header
+ FT_LAYOUT_VERSION_17 = 17, // Dr. No: Add STAT64INFO_S to brt_header
+ FT_LAYOUT_VERSION_18 = 18, // Dr. No: Add HOT info to brt_header
FT_LAYOUT_VERSION_19 = 19, // Doofenshmirtz: Add compression method, highest_unused_msn_for_upgrade
FT_LAYOUT_VERSION_20 = 20, // Deadshot: Add compression method to log_fcreate,
// mgr_last_xid after begin checkpoint,
@@ -119,8 +119,6 @@ enum ft_layout_version_e {
FT_LAYOUT_VERSION_23 = 23, // Ming: Fix upgrade path #5902
FT_LAYOUT_VERSION_24 = 24, // Riddler: change logentries that log transactions to store TXNID_PAIRs instead of TXNIDs
FT_LAYOUT_VERSION_25 = 25, // SecretSquirrel: ROLLBACK_LOG_NODES (on disk and in memory) now just use blocknum (instead of blocknum + hash) to point to other log nodes. same for xstillopen log entry
- FT_LAYOUT_VERSION_26 = 26, // Hojo: basements store key/vals separately on disk for fixed klpair length BNs
- FT_LAYOUT_VERSION_27 = 27, // serialize message trees with nonleaf buffers to avoid key, msn sort on deserialize
FT_NEXT_VERSION, // the version after the current version
FT_LAYOUT_VERSION = FT_NEXT_VERSION-1, // A hack so I don't have to change this line.
FT_LAYOUT_MIN_SUPPORTED_VERSION = FT_LAYOUT_VERSION_13, // Minimum version supported
diff --git a/storage/tokudb/ft-index/ft/ft_node-serialize.cc b/storage/tokudb/ft-index/ft/ft_node-serialize.cc
index 91ea0890c30..6fb6774ee34 100644
--- a/storage/tokudb/ft-index/ft/ft_node-serialize.cc
+++ b/storage/tokudb/ft-index/ft/ft_node-serialize.cc
@@ -101,7 +101,7 @@ PATENT RIGHTS GRANT:
static FT_UPGRADE_STATUS_S ft_upgrade_status;
-#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(ft_upgrade_status, k, c, t, "ft upgrade: " l, inc)
+#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(ft_upgrade_status, k, c, t, "brt upgrade: " l, inc)
static void
status_init(void)
@@ -279,66 +279,59 @@ serialize_node_header(FTNODE node, FTNODE_DISK_DATA ndd, struct wbuf *wbuf) {
wbuf_nocrc_int(wbuf, BP_SIZE (ndd, i)); // and the size
}
// checksum the header
- uint32_t end_to_end_checksum = toku_x1764_memory(wbuf->buf, wbuf_get_woffset(wbuf));
+ uint32_t end_to_end_checksum = x1764_memory(wbuf->buf, wbuf_get_woffset(wbuf));
wbuf_nocrc_int(wbuf, end_to_end_checksum);
invariant(wbuf->ndone == wbuf->size);
}
-static uint32_t
+static int
+wbufwriteleafentry(const void* key, const uint32_t keylen, const LEAFENTRY &le, const uint32_t UU(idx), struct wbuf * const wb) {
+ // need to pack the leafentry as it was in versions
+ // where the key was integrated into it
+ uint32_t begin_spot UU() = wb->ndone;
+ uint32_t le_disk_size = leafentry_disksize(le);
+ wbuf_nocrc_uint8_t(wb, le->type);
+ wbuf_nocrc_uint32_t(wb, keylen);
+ if (le->type == LE_CLEAN) {
+ wbuf_nocrc_uint32_t(wb, le->u.clean.vallen);
+ wbuf_nocrc_literal_bytes(wb, key, keylen);
+ wbuf_nocrc_literal_bytes(wb, le->u.clean.val, le->u.clean.vallen);
+ }
+ else {
+ paranoid_invariant(le->type == LE_MVCC);
+ wbuf_nocrc_uint32_t(wb, le->u.mvcc.num_cxrs);
+ wbuf_nocrc_uint8_t(wb, le->u.mvcc.num_pxrs);
+ wbuf_nocrc_literal_bytes(wb, key, keylen);
+ wbuf_nocrc_literal_bytes(wb, le->u.mvcc.xrs, le_disk_size - (1 + 4 + 1));
+ }
+ uint32_t end_spot UU() = wb->ndone;
+ paranoid_invariant((end_spot - begin_spot) == keylen + sizeof(keylen) + le_disk_size);
+ return 0;
+}
+
+static uint32_t
serialize_ftnode_partition_size (FTNODE node, int i)
{
uint32_t result = 0;
paranoid_invariant(node->bp[i].state == PT_AVAIL);
result++; // Byte that states what the partition is
if (node->height > 0) {
- NONLEAF_CHILDINFO bnc = BNC(node, i);
- // number of messages (4 bytes) plus size of the buffer
- result += (4 + toku_bnc_nbytesinbuf(bnc));
- // number of offsets (4 bytes) plus an array of 4 byte offsets, for each message tree
- result += (4 + (4 * bnc->fresh_message_tree.size()));
- result += (4 + (4 * bnc->stale_message_tree.size()));
- result += (4 + (4 * bnc->broadcast_list.size()));
+ result += 4; // size of bytes in buffer table
+ result += toku_bnc_nbytesinbuf(BNC(node, i));
}
else {
- result += 4 + bn_data::HEADER_LENGTH; // n_entries in buffer table + basement header
+ result += 4; // n_entries in buffer table
result += BLB_NBYTESINDATA(node, i);
}
result += 4; // checksum
return result;
}
-#define FTNODE_PARTITION_DMT_LEAVES 0xaa
+#define FTNODE_PARTITION_OMT_LEAVES 0xaa
#define FTNODE_PARTITION_FIFO_MSG 0xbb
-UU() static int
-assert_fresh(const int32_t &offset, const uint32_t UU(idx), struct fifo *const f) {
- struct fifo_entry *entry = toku_fifo_get_entry(f, offset);
- assert(entry->is_fresh);
- return 0;
-}
-
-UU() static int
-assert_stale(const int32_t &offset, const uint32_t UU(idx), struct fifo *const f) {
- struct fifo_entry *entry = toku_fifo_get_entry(f, offset);
- assert(!entry->is_fresh);
- return 0;
-}
-
-static void bnc_verify_message_trees(NONLEAF_CHILDINFO UU(bnc)) {
-#ifdef TOKU_DEBUG_PARANOID
- bnc->fresh_message_tree.iterate<struct fifo, assert_fresh>(bnc->buffer);
- bnc->stale_message_tree.iterate<struct fifo, assert_stale>(bnc->buffer);
-#endif
-}
-
-static int
-wbuf_write_offset(const int32_t &offset, const uint32_t UU(idx), struct wbuf *const wb) {
- wbuf_nocrc_int(wb, offset);
- return 0;
-}
-
static void
-serialize_child_buffer(NONLEAF_CHILDINFO bnc, struct wbuf *wb)
+serialize_nonleaf_childinfo(NONLEAF_CHILDINFO bnc, struct wbuf *wb)
{
unsigned char ch = FTNODE_PARTITION_FIFO_MSG;
wbuf_nocrc_char(wb, ch);
@@ -347,27 +340,14 @@ serialize_child_buffer(NONLEAF_CHILDINFO bnc, struct wbuf *wb)
FIFO_ITERATE(
bnc->buffer, key, keylen, data, datalen, type, msn, xids, is_fresh,
{
- paranoid_invariant((int) type >= 0 && (int) type < 256);
- wbuf_nocrc_char(wb, (unsigned char) type);
- wbuf_nocrc_char(wb, (unsigned char) is_fresh);
+ paranoid_invariant((int)type>=0 && type<256);
+ wbuf_nocrc_char(wb, (unsigned char)type);
+ wbuf_nocrc_char(wb, (unsigned char)is_fresh);
wbuf_MSN(wb, msn);
wbuf_nocrc_xids(wb, xids);
wbuf_nocrc_bytes(wb, key, keylen);
wbuf_nocrc_bytes(wb, data, datalen);
});
-
- bnc_verify_message_trees(bnc);
-
- // serialize the message trees (num entries, offsets array):
- // fresh, stale, broadcast
- wbuf_nocrc_int(wb, bnc->fresh_message_tree.size());
- bnc->fresh_message_tree.iterate<struct wbuf, wbuf_write_offset>(wb);
-
- wbuf_nocrc_int(wb, bnc->stale_message_tree.size());
- bnc->stale_message_tree.iterate<struct wbuf, wbuf_write_offset>(wb);
-
- wbuf_nocrc_int(wb, bnc->broadcast_list.size());
- bnc->broadcast_list.iterate<struct wbuf, wbuf_write_offset>(wb);
}
//
@@ -391,18 +371,21 @@ serialize_ftnode_partition(FTNODE node, int i, struct sub_block *sb) {
wbuf_init(&wb, sb->uncompressed_ptr, sb->uncompressed_size);
if (node->height > 0) {
// TODO: (Zardosht) possibly exit early if there are no messages
- serialize_child_buffer(BNC(node, i), &wb);
+ serialize_nonleaf_childinfo(BNC(node, i), &wb);
}
else {
- unsigned char ch = FTNODE_PARTITION_DMT_LEAVES;
- bn_data* bd = BLB_DATA(node, i);
+ unsigned char ch = FTNODE_PARTITION_OMT_LEAVES;
+ BN_DATA bd = BLB_DATA(node, i);
wbuf_nocrc_char(&wb, ch);
- wbuf_nocrc_uint(&wb, bd->num_klpairs());
+ wbuf_nocrc_uint(&wb, bd->omt_size());
- bd->serialize_to_wbuf(&wb);
+ //
+ // iterate over leafentries and place them into the buffer
+ //
+ bd->omt_iterate<struct wbuf, wbufwriteleafentry>(&wb);
}
- uint32_t end_to_end_checksum = toku_x1764_memory(sb->uncompressed_ptr, wbuf_get_woffset(&wb));
+ uint32_t end_to_end_checksum = x1764_memory(sb->uncompressed_ptr, wbuf_get_woffset(&wb));
wbuf_nocrc_int(&wb, end_to_end_checksum);
invariant(wb.ndone == wb.size);
invariant(sb->uncompressed_size==wb.ndone);
@@ -446,7 +429,7 @@ compress_ftnode_sub_block(struct sub_block *sb, enum toku_compression_method met
extra[1] = toku_htod32(sb->uncompressed_size);
// now checksum the entire thing
sb->compressed_size += 8; // now add the eight bytes that we saved for the sizes
- sb->xsum = toku_x1764_memory(sb->compressed_ptr,sb->compressed_size);
+ sb->xsum = x1764_memory(sb->compressed_ptr,sb->compressed_size);
//
// This is the end result for Dr. No and forward. For ftnodes, sb->compressed_ptr contains
@@ -510,7 +493,7 @@ static void serialize_ftnode_info(FTNODE node,
}
}
- uint32_t end_to_end_checksum = toku_x1764_memory(sb->uncompressed_ptr, wbuf_get_woffset(&wb));
+ uint32_t end_to_end_checksum = x1764_memory(sb->uncompressed_ptr, wbuf_get_woffset(&wb));
wbuf_nocrc_int(&wb, end_to_end_checksum);
invariant(wb.ndone == wb.size);
invariant(sb->uncompressed_size==wb.ndone);
@@ -563,7 +546,7 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
// Count number of leaf entries in this leaf (num_le).
uint32_t num_le = 0;
for (uint32_t i = 0; i < num_orig_basements; i++) {
- num_le += BLB_DATA(node, i)->num_klpairs();
+ num_le += BLB_DATA(node, i)->omt_size();
}
uint32_t num_alloc = num_le ? num_le : 1; // simplify logic below by always having at least one entry per array
@@ -588,10 +571,10 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
uint32_t curr_le = 0;
for (uint32_t i = 0; i < num_orig_basements; i++) {
- bn_data* bd = BLB_DATA(node, i);
+ BN_DATA bd = BLB_DATA(node, i);
struct array_info ai {.offset = curr_le, .le_array = leafpointers, .key_sizes_array = key_sizes, .key_ptr_array = key_pointers };
- bd->iterate<array_info, array_item>(&ai);
- curr_le += bd->num_klpairs();
+ bd->omt_iterate<array_info, array_item>(&ai);
+ curr_le += bd->omt_size();
}
// Create an array that will store indexes of new pivots.
@@ -609,14 +592,9 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
// Create an array that will store the size of each basement.
// This is the sum of the leaf sizes of all the leaves in that basement.
// We don't know how many basements there will be, so we use num_le as the upper bound.
-
- // Sum of all le sizes in a single basement
- toku::scoped_calloc bn_le_sizes_buf(sizeof(size_t) * num_alloc);
- size_t *bn_le_sizes = reinterpret_cast<size_t *>(bn_le_sizes_buf.get());
-
- // Sum of all key sizes in a single basement
- toku::scoped_calloc bn_key_sizes_buf(sizeof(size_t) * num_alloc);
- size_t *bn_key_sizes = reinterpret_cast<size_t *>(bn_key_sizes_buf.get());
+ toku::scoped_malloc bn_sizes_buf(sizeof(size_t) * num_alloc);
+ size_t *bn_sizes = reinterpret_cast<size_t *>(bn_sizes_buf.get());
+ bn_sizes[0] = 0;
// TODO 4050: All these arrays should be combined into a single array of some bn_info struct (pivot, msize, num_les).
// Each entry is the number of leafentries in this basement. (Again, num_le is overkill upper baound.)
@@ -633,7 +611,7 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
for (uint32_t i = 0; i < num_le; i++) {
uint32_t curr_le_size = leafentry_disksize((LEAFENTRY) leafpointers[i]);
le_sizes[i] = curr_le_size;
- if ((bn_size_so_far + curr_le_size + sizeof(uint32_t) + key_sizes[i] > basementnodesize) && (num_le_in_curr_bn != 0)) {
+ if ((bn_size_so_far + curr_le_size > basementnodesize) && (num_le_in_curr_bn != 0)) {
// cap off the current basement node to end with the element before i
new_pivots[curr_pivot] = i-1;
curr_pivot++;
@@ -642,9 +620,8 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
}
num_le_in_curr_bn++;
num_les_this_bn[curr_pivot] = num_le_in_curr_bn;
- bn_le_sizes[curr_pivot] += curr_le_size;
- bn_key_sizes[curr_pivot] += sizeof(uint32_t) + key_sizes[i]; // uint32_t le_offset
bn_size_so_far += curr_le_size + sizeof(uint32_t) + key_sizes[i];
+ bn_sizes[curr_pivot] = bn_size_so_far;
}
// curr_pivot is now the total number of pivot keys in the leaf node
int num_pivots = curr_pivot;
@@ -711,15 +688,17 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
uint32_t num_les_to_copy = num_les_this_bn[i];
invariant(num_les_to_copy == num_in_bn);
- bn_data* bd = BLB_DATA(node, i);
- bd->set_contents_as_clone_of_sorted_array(
+ // construct mempool for this basement
+ size_t size_this_bn = bn_sizes[i];
+
+ BN_DATA bd = BLB_DATA(node, i);
+ bd->replace_contents_with_clone_of_sorted_array(
num_les_to_copy,
&key_pointers[baseindex_this_bn],
&key_sizes[baseindex_this_bn],
&leafpointers[baseindex_this_bn],
&le_sizes[baseindex_this_bn],
- bn_key_sizes[i], // Total key sizes
- bn_le_sizes[i] // total le sizes
+ size_this_bn
);
BP_STATE(node,i) = PT_AVAIL;
@@ -1069,8 +1048,8 @@ toku_serialize_ftnode_to (int fd, BLOCKNUM blocknum, FTNODE node, FTNODE_DISK_DA
}
static void
-deserialize_child_buffer_v26(NONLEAF_CHILDINFO bnc, struct rbuf *rbuf,
- DESCRIPTOR desc, ft_compare_func cmp) {
+deserialize_child_buffer(NONLEAF_CHILDINFO bnc, struct rbuf *rbuf,
+ DESCRIPTOR desc, ft_compare_func cmp) {
int r;
int n_in_this_buffer = rbuf_int(rbuf);
int32_t *fresh_offsets = NULL, *stale_offsets = NULL;
@@ -1135,68 +1114,6 @@ deserialize_child_buffer_v26(NONLEAF_CHILDINFO bnc, struct rbuf *rbuf,
}
}
-// effect: deserialize a single message from rbuf and enqueue the result into the given fifo
-static void
-fifo_deserialize_msg_from_rbuf(FIFO fifo, struct rbuf *rbuf) {
- bytevec key, val;
- ITEMLEN keylen, vallen;
- enum ft_msg_type type = (enum ft_msg_type) rbuf_char(rbuf);
- bool is_fresh = rbuf_char(rbuf);
- MSN msn = rbuf_msn(rbuf);
- XIDS xids;
- xids_create_from_buffer(rbuf, &xids);
- rbuf_bytes(rbuf, &key, &keylen); /* Returns a pointer into the rbuf. */
- rbuf_bytes(rbuf, &val, &vallen);
- int r = toku_fifo_enq(fifo, key, keylen, val, vallen, type, msn, xids, is_fresh, nullptr);
- lazy_assert_zero(r);
- xids_destroy(&xids);
-}
-
-static void
-deserialize_child_buffer(NONLEAF_CHILDINFO bnc, struct rbuf *rbuf) {
- int n_in_this_buffer = rbuf_int(rbuf);
- int nfresh = 0, nstale = 0, nbroadcast_offsets = 0;
- int32_t *XMALLOC_N(n_in_this_buffer, stale_offsets);
- int32_t *XMALLOC_N(n_in_this_buffer, fresh_offsets);
- int32_t *XMALLOC_N(n_in_this_buffer, broadcast_offsets);
-
- toku_fifo_resize(bnc->buffer, rbuf->size + 64);
- for (int i = 0; i < n_in_this_buffer; i++) {
- fifo_deserialize_msg_from_rbuf(bnc->buffer, rbuf);
- }
-
- // read in each message tree (fresh, stale, broadcast)
- nfresh = rbuf_int(rbuf);
- bytevec fresh_offsets_src_v;
- rbuf_literal_bytes(rbuf, &fresh_offsets_src_v, nfresh * (sizeof *fresh_offsets));
- const int32_t *fresh_offsets_src = (const int32_t *) fresh_offsets_src_v;
- for (int i = 0; i < nfresh; i++) {
- fresh_offsets[i] = toku_dtoh32(fresh_offsets_src[i]);
- }
- nstale = rbuf_int(rbuf);
- bytevec stale_offsets_src_v;
- rbuf_literal_bytes(rbuf, &stale_offsets_src_v, nstale * (sizeof *stale_offsets));
- const int32_t *stale_offsets_src = (const int32_t *) stale_offsets_src_v;
- for (int i = 0; i < nstale; i++) {
- stale_offsets[i] = toku_dtoh32(stale_offsets_src[i]);
- }
- nbroadcast_offsets = rbuf_int(rbuf);
- bytevec broadcast_offsets_src_v;
- rbuf_literal_bytes(rbuf, &broadcast_offsets_src_v, nbroadcast_offsets * (sizeof *broadcast_offsets));
- const int32_t *broadcast_offsets_src = (const int32_t *) broadcast_offsets_src_v;
- for (int i = 0; i < nbroadcast_offsets; i++) {
- broadcast_offsets[i] = toku_dtoh32(broadcast_offsets_src[i]);
- }
-
- // build OMTs out of each offset array
- bnc->fresh_message_tree.destroy();
- bnc->fresh_message_tree.create_steal_sorted_array(&fresh_offsets, nfresh, n_in_this_buffer);
- bnc->stale_message_tree.destroy();
- bnc->stale_message_tree.create_steal_sorted_array(&stale_offsets, nstale, n_in_this_buffer);
- bnc->broadcast_list.destroy();
- bnc->broadcast_list.create_steal_sorted_array(&broadcast_offsets, nbroadcast_offsets, n_in_this_buffer);
-}
-
// dump a buffer to stderr
// no locking around this for now
void
@@ -1268,16 +1185,13 @@ NONLEAF_CHILDINFO toku_create_empty_nl(void) {
return cn;
}
-// must clone the OMTs, since we serialize them along with the FIFO
+// does NOT create OMTs, just the FIFO
NONLEAF_CHILDINFO toku_clone_nl(NONLEAF_CHILDINFO orig_childinfo) {
NONLEAF_CHILDINFO XMALLOC(cn);
toku_fifo_clone(orig_childinfo->buffer, &cn->buffer);
cn->fresh_message_tree.create_no_array();
- cn->fresh_message_tree.clone(orig_childinfo->fresh_message_tree);
cn->stale_message_tree.create_no_array();
- cn->stale_message_tree.clone(orig_childinfo->stale_message_tree);
cn->broadcast_list.create_no_array();
- cn->broadcast_list.clone(orig_childinfo->broadcast_list);
memset(cn->flow, 0, sizeof cn->flow);
return cn;
}
@@ -1358,7 +1272,7 @@ read_compressed_sub_block(struct rbuf *rb, struct sub_block *sb)
rbuf_literal_bytes(rb, cp, sb->compressed_size);
sb->xsum = rbuf_int(rb);
// let's check the checksum
- uint32_t actual_xsum = toku_x1764_memory((char *)sb->compressed_ptr-8, 8+sb->compressed_size);
+ uint32_t actual_xsum = x1764_memory((char *)sb->compressed_ptr-8, 8+sb->compressed_size);
if (sb->xsum != actual_xsum) {
r = TOKUDB_BAD_CHECKSUM;
}
@@ -1403,7 +1317,7 @@ verify_ftnode_sub_block (struct sub_block *sb)
// first verify the checksum
uint32_t data_size = sb->uncompressed_size - 4; // checksum is 4 bytes at end
uint32_t stored_xsum = toku_dtoh32(*((uint32_t *)((char *)sb->uncompressed_ptr + data_size)));
- uint32_t actual_xsum = toku_x1764_memory(sb->uncompressed_ptr, data_size);
+ uint32_t actual_xsum = x1764_memory(sb->uncompressed_ptr, data_size);
if (stored_xsum != actual_xsum) {
dump_bad_block((Bytef *) sb->uncompressed_ptr, sb->uncompressed_size);
r = TOKUDB_BAD_CHECKSUM;
@@ -1498,7 +1412,7 @@ setup_available_ftnode_partition(FTNODE node, int i) {
}
}
-// Assign the child_to_read member of the bfe from the given ftnode
+// Assign the child_to_read member of the bfe from the given brt node
// that has been brought into memory.
static void
update_bfe_using_ftnode(FTNODE node, struct ftnode_fetch_extra *bfe)
@@ -1533,7 +1447,7 @@ update_bfe_using_ftnode(FTNODE node, struct ftnode_fetch_extra *bfe)
}
// Using the search parameters in the bfe, this function will
-// initialize all of the given ftnode's partitions.
+// initialize all of the given brt node's partitions.
static void
setup_partitions_using_bfe(FTNODE node,
struct ftnode_fetch_extra *bfe,
@@ -1623,24 +1537,19 @@ deserialize_ftnode_partition(
if (node->height > 0) {
assert(ch == FTNODE_PARTITION_FIFO_MSG);
- NONLEAF_CHILDINFO bnc = BNC(node, childnum);
- if (node->layout_version_read_from_disk <= FT_LAYOUT_VERSION_26) {
- // Layout version <= 26 did not serialize sorted message trees to disk.
- deserialize_child_buffer_v26(bnc, &rb, desc, cmp);
- } else {
- deserialize_child_buffer(bnc, &rb);
- }
+ deserialize_child_buffer(BNC(node, childnum), &rb, desc, cmp);
BP_WORKDONE(node, childnum) = 0;
}
else {
- assert(ch == FTNODE_PARTITION_DMT_LEAVES);
+ assert(ch == FTNODE_PARTITION_OMT_LEAVES);
BLB_SEQINSERT(node, childnum) = 0;
uint32_t num_entries = rbuf_int(&rb);
// we are now at the first byte of first leafentry
data_size -= rb.ndone; // remaining bytes of leafentry data
-
+
BASEMENTNODE bn = BLB(node, childnum);
- bn->data_buffer.deserialize_from_rbuf(num_entries, &rb, data_size, node->layout_version_read_from_disk);
+ bn->data_buffer.initialize_from_data(num_entries, &rb.buf[rb.ndone], data_size);
+ rb.ndone += data_size;
}
assert(rb.ndone == rb.size);
exit:
@@ -1772,7 +1681,7 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
}
uint32_t checksum;
- checksum = toku_x1764_memory(rb->buf, rb->ndone);
+ checksum = x1764_memory(rb->buf, rb->ndone);
uint32_t stored_checksum;
stored_checksum = rbuf_int(rb);
if (stored_checksum != checksum) {
@@ -1798,7 +1707,7 @@ deserialize_ftnode_header_from_rbuf_if_small_enough (FTNODE *ftnode,
sb_node_info.xsum = rbuf_int(rb);
// let's check the checksum
uint32_t actual_xsum;
- actual_xsum = toku_x1764_memory((char *)sb_node_info.compressed_ptr-8, 8+sb_node_info.compressed_size);
+ actual_xsum = x1764_memory((char *)sb_node_info.compressed_ptr-8, 8+sb_node_info.compressed_size);
if (sb_node_info.xsum != actual_xsum) {
r = TOKUDB_BAD_CHECKSUM;
goto cleanup;
@@ -1883,7 +1792,7 @@ cleanup:
// also creates MSN's for older messages created in older versions
// that did not generate MSN's for messages. These new MSN's are
// generated from the root downwards, counting backwards from MIN_MSN
-// and persisted in the ft header.
+// and persisted in the brt header.
static int
deserialize_and_upgrade_internal_node(FTNODE node,
struct rbuf *rb,
@@ -2069,7 +1978,7 @@ deserialize_and_upgrade_internal_node(FTNODE node,
// still have the pointer to the buffer).
if (version >= FT_FIRST_LAYOUT_VERSION_WITH_END_TO_END_CHECKSUM) {
uint32_t expected_xsum = toku_dtoh32(*(uint32_t*)(rb->buf+rb->size-4)); // 27. checksum
- uint32_t actual_xsum = toku_x1764_memory(rb->buf, rb->size-4);
+ uint32_t actual_xsum = x1764_memory(rb->buf, rb->size-4);
if (expected_xsum != actual_xsum) {
fprintf(stderr, "%s:%d: Bad checksum: expected = %" PRIx32 ", actual= %" PRIx32 "\n",
__FUNCTION__,
@@ -2141,7 +2050,7 @@ deserialize_and_upgrade_leaf_node(FTNODE node,
setup_partitions_using_bfe(node, &temp_bfe, true);
// 11. Deserialize the partition maps, though they are not used in the
- // newer versions of ftnodes.
+ // newer versions of brt nodes.
struct sub_block_map part_map[npartitions];
for (int i = 0; i < npartitions; ++i) {
sub_block_map_deserialize(&part_map[i], rb);
@@ -2177,18 +2086,13 @@ deserialize_and_upgrade_leaf_node(FTNODE node,
assert_zero(r);
// Copy the pointer value straight into the OMT
LEAFENTRY new_le_in_bn = nullptr;
- void *maybe_free;
bn->data_buffer.get_space_for_insert(
i,
key,
keylen,
new_le_size,
- &new_le_in_bn,
- &maybe_free
+ &new_le_in_bn
);
- if (maybe_free) {
- toku_free(maybe_free);
- }
memcpy(new_le_in_bn, new_le, new_le_size);
toku_free(new_le);
}
@@ -2197,7 +2101,8 @@ deserialize_and_upgrade_leaf_node(FTNODE node,
if (has_end_to_end_checksum) {
data_size -= sizeof(uint32_t);
}
- bn->data_buffer.deserialize_from_rbuf(n_in_buf, rb, data_size, node->layout_version_read_from_disk);
+ bn->data_buffer.initialize_from_data(n_in_buf, &rb->buf[rb->ndone], data_size);
+ rb->ndone += data_size;
}
// Whatever this is must be less than the MSNs of every message above
@@ -2209,7 +2114,7 @@ deserialize_and_upgrade_leaf_node(FTNODE node,
// Checksum (end to end) is only on version 14
if (has_end_to_end_checksum) {
uint32_t expected_xsum = rbuf_int(rb); // 17. checksum
- uint32_t actual_xsum = toku_x1764_memory(rb->buf, rb->size - 4);
+ uint32_t actual_xsum = x1764_memory(rb->buf, rb->size - 4);
if (expected_xsum != actual_xsum) {
fprintf(stderr, "%s:%d: Bad checksum: expected = %" PRIx32 ", actual= %" PRIx32 "\n",
__FUNCTION__,
@@ -2408,7 +2313,7 @@ deserialize_ftnode_from_rbuf(
}
// verify checksum of header stored
uint32_t checksum;
- checksum = toku_x1764_memory(rb->buf, rb->ndone);
+ checksum = x1764_memory(rb->buf, rb->ndone);
uint32_t stored_checksum;
stored_checksum = rbuf_int(rb);
if (stored_checksum != checksum) {
@@ -2515,7 +2420,7 @@ cleanup:
// NOTE: Right now, callers higher in the stack will assert on
// failure, so this is OK for production. However, if we
// create tools that use this function to search for errors in
- // the FT, then we will leak memory.
+ // the BRT, then we will leak memory.
if (node) {
toku_free(node);
}
@@ -2674,7 +2579,7 @@ deserialize_ftnode_from_fd(int fd,
return r;
}
-// Read ftnode from file into struct. Perform version upgrade if necessary.
+// Read brt node from file into struct. Perform version upgrade if necessary.
int
toku_deserialize_ftnode_from (int fd,
BLOCKNUM blocknum,
@@ -2723,7 +2628,7 @@ serialize_rollback_log_size(ROLLBACK_LOG_NODE log) {
+8 //blocknum
+8 //previous (blocknum)
+8 //resident_bytecount
- +8 //memarena size
+ +8 //memarena_size_needed_to_load
+log->rollentry_resident_bytecount;
return size;
}
@@ -2744,7 +2649,7 @@ serialize_rollback_log_node_to_buf(ROLLBACK_LOG_NODE log, char *buf, size_t calc
wbuf_nocrc_BLOCKNUM(&wb, log->previous);
wbuf_nocrc_ulonglong(&wb, log->rollentry_resident_bytecount);
//Write down memarena size needed to restore
- wbuf_nocrc_ulonglong(&wb, toku_memarena_total_size_in_use(log->rollentry_arena));
+ wbuf_nocrc_ulonglong(&wb, memarena_total_size_in_use(log->rollentry_arena));
{
//Store rollback logs
@@ -2800,7 +2705,7 @@ serialize_uncompressed_block_to_memory(char * uncompressed_buf,
// compute the header checksum and serialize it
uint32_t header_length = (char *)ptr - (char *)compressed_buf;
- uint32_t xsum = toku_x1764_memory(compressed_buf, header_length);
+ uint32_t xsum = x1764_memory(compressed_buf, header_length);
*ptr = toku_htod32(xsum);
uint32_t padded_len = roundup_to_multiple(512, header_len + compressed_len);
@@ -2908,8 +2813,8 @@ deserialize_rollback_log_from_rbuf (BLOCKNUM blocknum, ROLLBACK_LOG_NODE *log_p,
result->rollentry_resident_bytecount = rbuf_ulonglong(rb);
size_t arena_initial_size = rbuf_ulonglong(rb);
- result->rollentry_arena = toku_memarena_create_presized(arena_initial_size);
- if (0) { died1: toku_memarena_destroy(&result->rollentry_arena); goto died0; }
+ result->rollentry_arena = memarena_create_presized(arena_initial_size);
+ if (0) { died1: memarena_close(&result->rollentry_arena); goto died0; }
//Load rollback entries
lazy_assert(rb->size > 4);
@@ -2972,7 +2877,7 @@ decompress_from_raw_block_into_rbuf(uint8_t *raw_block, size_t raw_block_size, s
{ // verify the header checksum
uint32_t header_length = node_header_overhead + sub_block_header_size(n_sub_blocks);
invariant(header_length <= raw_block_size);
- uint32_t xsum = toku_x1764_memory(raw_block, header_length);
+ uint32_t xsum = x1764_memory(raw_block, header_length);
uint32_t stored_xsum = toku_dtoh32(*(uint32_t *)(raw_block + header_length));
if (xsum != stored_xsum) {
r = TOKUDB_BAD_CHECKSUM;
diff --git a/storage/tokudb/ft-index/ft/ftloader-internal.h b/storage/tokudb/ft-index/ft/ftloader-internal.h
index d60537490dd..8ceac6527e6 100644
--- a/storage/tokudb/ft-index/ft/ftloader-internal.h
+++ b/storage/tokudb/ft-index/ft/ftloader-internal.h
@@ -257,7 +257,7 @@ struct ft_loader_s {
int progress_callback_result; // initially zero, if any call to the poll function callback returns nonzero, we save the result here (and don't call the poll callback function again).
- LSN load_lsn; //LSN of the fsynced 'load' log entry. Write this LSN (as checkpoint_lsn) in ft headers made by this loader.
+ LSN load_lsn; //LSN of the fsynced 'load' log entry. Write this LSN (as checkpoint_lsn) in brt headers made by this loader.
TXNID load_root_xid; //(Root) transaction that performed the load.
QUEUE *fractal_queues; // an array of work queues, one for each secondary index.
@@ -280,7 +280,7 @@ uint64_t toku_ft_loader_get_n_rows(FTLOADER bl);
struct fractal_thread_args {
FTLOADER bl;
const DESCRIPTOR descriptor;
- int fd; // write the ft into fd.
+ int fd; // write the brt into tfd.
int progress_allocation;
QUEUE q;
uint64_t total_disksize_estimate;
@@ -312,17 +312,17 @@ int toku_merge_some_files_using_dbufio (const bool to_q, FIDX dest_data, QUEUE q
int ft_loader_sort_and_write_rows (struct rowset *rows, struct merge_fileset *fs, FTLOADER bl, int which_db, DB *dest_db, ft_compare_func);
// This is probably only for testing.
-int toku_loader_write_ft_from_q_in_C (FTLOADER bl,
- const DESCRIPTOR descriptor,
- int fd, // write to here
- int progress_allocation,
- QUEUE q,
- uint64_t total_disksize_estimate,
- int which_db,
- uint32_t target_nodesize,
- uint32_t target_basementnodesize,
- enum toku_compression_method target_compression_method,
- uint32_t fanout);
+int toku_loader_write_brt_from_q_in_C (FTLOADER bl,
+ const DESCRIPTOR descriptor,
+ int fd, // write to here
+ int progress_allocation,
+ QUEUE q,
+ uint64_t total_disksize_estimate,
+ int which_db,
+ uint32_t target_nodesize,
+ uint32_t target_basementnodesize,
+ enum toku_compression_method target_compression_method,
+ uint32_t fanout);
int ft_loader_mergesort_row_array (struct row rows[/*n*/], int n, int which_db, DB *dest_db, ft_compare_func, FTLOADER, struct rowset *);
@@ -339,7 +339,7 @@ int toku_ft_loader_internal_init (/* out */ FTLOADER *blp,
CACHETABLE cachetable,
generate_row_for_put_func g,
DB *src_db,
- int N, FT_HANDLE ft_hs[/*N*/], DB* dbs[/*N*/],
+ int N, FT_HANDLE brts[/*N*/], DB* dbs[/*N*/],
const char *new_fnames_in_env[/*N*/],
ft_compare_func bt_compare_functions[/*N*/],
const char *temp_file_template,
diff --git a/storage/tokudb/ft-index/ft/ftloader.cc b/storage/tokudb/ft-index/ft/ftloader.cc
index 67b3cf9905e..497f3138059 100644
--- a/storage/tokudb/ft-index/ft/ftloader.cc
+++ b/storage/tokudb/ft-index/ft/ftloader.cc
@@ -91,7 +91,9 @@ PATENT RIGHTS GRANT:
#include <toku_portability.h>
+#if !TOKU_WINDOWS
#include <arpa/inet.h>
+#endif
#include <stdio.h>
#include <memory.h>
@@ -99,9 +101,7 @@ PATENT RIGHTS GRANT:
#include <toku_assert.h>
#include <string.h>
#include <fcntl.h>
-
-#include <util/x1764.h>
-
+#include "x1764.h"
#include "ftloader-internal.h"
#include "ft-internal.h"
#include "sub_block.h"
@@ -541,7 +541,7 @@ int toku_ft_loader_internal_init (/* out */ FTLOADER *blp,
CACHETABLE cachetable,
generate_row_for_put_func g,
DB *src_db,
- int N, FT_HANDLE fts[/*N*/], DB* dbs[/*N*/],
+ int N, FT_HANDLE brts[/*N*/], DB* dbs[/*N*/],
const char *new_fnames_in_env[/*N*/],
ft_compare_func bt_compare_functions[/*N*/],
const char *temp_file_template,
@@ -585,11 +585,11 @@ int toku_ft_loader_internal_init (/* out */ FTLOADER *blp,
#define SET_TO_MY_STRDUP(lval, s) do { char *v = toku_strdup(s); if (!v) { int r = get_error_errno(); toku_ft_loader_internal_destroy(bl, true); return r; } lval = v; } while (0)
MY_CALLOC_N(N, bl->root_xids_that_created);
- for (int i=0; i<N; i++) if (fts[i]) bl->root_xids_that_created[i]=fts[i]->ft->h->root_xid_that_created;
+ for (int i=0; i<N; i++) if (brts[i]) bl->root_xids_that_created[i]=brts[i]->ft->h->root_xid_that_created;
MY_CALLOC_N(N, bl->dbs);
- for (int i=0; i<N; i++) if (fts[i]) bl->dbs[i]=dbs[i];
+ for (int i=0; i<N; i++) if (brts[i]) bl->dbs[i]=dbs[i];
MY_CALLOC_N(N, bl->descriptors);
- for (int i=0; i<N; i++) if (fts[i]) bl->descriptors[i]=&fts[i]->ft->descriptor;
+ for (int i=0; i<N; i++) if (brts[i]) bl->descriptors[i]=&brts[i]->ft->descriptor;
MY_CALLOC_N(N, bl->new_fnames_in_env);
for (int i=0; i<N; i++) SET_TO_MY_STRDUP(bl->new_fnames_in_env[i], new_fnames_in_env[i]);
MY_CALLOC_N(N, bl->extracted_datasizes); // the calloc_n zeroed everything, which is what we want
@@ -645,7 +645,7 @@ int toku_ft_loader_open (/* out */ FTLOADER *blp,
CACHETABLE cachetable,
generate_row_for_put_func g,
DB *src_db,
- int N, FT_HANDLE fts[/*N*/], DB* dbs[/*N*/],
+ int N, FT_HANDLE brts[/*N*/], DB* dbs[/*N*/],
const char *new_fnames_in_env[/*N*/],
ft_compare_func bt_compare_functions[/*N*/],
const char *temp_file_template,
@@ -672,7 +672,7 @@ int toku_ft_loader_open (/* out */ FTLOADER *blp,
int result = 0;
{
int r = toku_ft_loader_internal_init(blp, cachetable, g, src_db,
- N, fts, dbs,
+ N, brts, dbs,
new_fnames_in_env,
bt_compare_functions,
temp_file_template,
@@ -1378,7 +1378,7 @@ static int process_primary_rows (FTLOADER bl, struct rowset *primary_rowset) {
}
int toku_ft_loader_put (FTLOADER bl, DBT *key, DBT *val)
-/* Effect: Put a key-value pair into the ft loader. Called by DB_LOADER->put().
+/* Effect: Put a key-value pair into the brt loader. Called by DB_LOADER->put().
* Return value: 0 on success, an error number otherwise.
*/
{
@@ -2630,7 +2630,7 @@ static int toku_loader_write_ft_from_q (FTLOADER bl,
char *XMALLOC_N(desc_size, buf);
wbuf_init(&wbuf, buf, desc_size);
toku_serialize_descriptor_contents_to_wbuf(&wbuf, descriptor);
- uint32_t checksum = toku_x1764_finish(&wbuf.checksum);
+ uint32_t checksum = x1764_finish(&wbuf.checksum);
wbuf_int(&wbuf, checksum);
invariant(wbuf.ndone==desc_size);
r = toku_os_write(out.fd, wbuf.buf, wbuf.ndone);
@@ -2681,17 +2681,17 @@ static int toku_loader_write_ft_from_q (FTLOADER bl,
return result;
}
-int toku_loader_write_ft_from_q_in_C (FTLOADER bl,
- const DESCRIPTOR descriptor,
- int fd, // write to here
- int progress_allocation,
- QUEUE q,
- uint64_t total_disksize_estimate,
- int which_db,
- uint32_t target_nodesize,
- uint32_t target_basementnodesize,
- enum toku_compression_method target_compression_method,
- uint32_t target_fanout)
+int toku_loader_write_brt_from_q_in_C (FTLOADER bl,
+ const DESCRIPTOR descriptor,
+ int fd, // write to here
+ int progress_allocation,
+ QUEUE q,
+ uint64_t total_disksize_estimate,
+ int which_db,
+ uint32_t target_nodesize,
+ uint32_t target_basementnodesize,
+ enum toku_compression_method target_compression_method,
+ uint32_t target_fanout)
// This is probably only for testing.
{
target_nodesize = target_nodesize == 0 ? default_loader_nodesize : target_nodesize;
@@ -2727,7 +2727,7 @@ static int loader_do_i (FTLOADER bl,
if (r) goto error;
{
- mode_t mode = S_IRWXU|S_IRWXG|S_IRWXO;
+ mode_t mode = S_IRUSR+S_IWUSR + S_IRGRP+S_IWGRP;
int fd = toku_os_open(new_fname, O_RDWR| O_CREAT | O_BINARY, mode); // #2621
if (fd < 0) {
r = get_error_errno(); goto error;
@@ -2938,17 +2938,17 @@ static void add_pair_to_leafnode (struct leaf_buf *lbuf, unsigned char *key, int
// #3588 TODO just make a clean ule and append it to the omt
// #3588 TODO can do the rebalancing here and avoid a lot of work later
FTNODE leafnode = lbuf->node;
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
DBT thekey = { .data = key, .size = (uint32_t) keylen };
DBT theval = { .data = val, .size = (uint32_t) vallen };
- FT_MSG_S msg = { .type = FT_INSERT,
+ FT_MSG_S cmd = { .type = FT_INSERT,
.msn = ZERO_MSN,
.xids = lbuf->xids,
.u = { .id = { &thekey, &theval } } };
uint64_t workdone=0;
// there's no mvcc garbage in a bulk-loaded FT, so there's no need to pass useful gc info
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, true);
- toku_ft_bn_apply_msg_once(BLB(leafnode,0), &msg, idx, NULL, &gc_info, &workdone, stats_to_update);
+ toku_ft_bn_apply_cmd_once(BLB(leafnode,0), &cmd, idx, NULL, &gc_info, &workdone, stats_to_update);
}
static int write_literal(struct dbout *out, void*data, size_t len) {
@@ -3013,7 +3013,7 @@ static int write_translation_table (struct dbout *out, long long *off_of_transla
putbuf_int64(&ttable, out->translation[i].off);
putbuf_int64(&ttable, out->translation[i].size);
}
- unsigned int checksum = toku_x1764_memory(ttable.buf, ttable.off);
+ unsigned int checksum = x1764_memory(ttable.buf, ttable.off);
putbuf_int32(&ttable, checksum);
// pad it to 512 zeros
long long encoded_length = ttable.off;
diff --git a/storage/tokudb/ft-index/ft/ftloader.h b/storage/tokudb/ft-index/ft/ftloader.h
index c920b4c5362..2243ddd080c 100644
--- a/storage/tokudb/ft-index/ft/ftloader.h
+++ b/storage/tokudb/ft-index/ft/ftloader.h
@@ -102,13 +102,13 @@ typedef struct ft_loader_s *FTLOADER;
int toku_ft_loader_open (FTLOADER *bl,
CACHETABLE cachetable,
- generate_row_for_put_func g,
- DB *src_db,
- int N,
- FT_HANDLE ft_hs[/*N*/], DB* dbs[/*N*/],
- const char * new_fnames_in_env[/*N*/],
- ft_compare_func bt_compare_functions[/*N*/],
- const char *temp_file_template,
+ generate_row_for_put_func g,
+ DB *src_db,
+ int N,
+ FT_HANDLE brts[/*N*/], DB* dbs[/*N*/],
+ const char * new_fnames_in_env[/*N*/],
+ ft_compare_func bt_compare_functions[/*N*/],
+ const char *temp_file_template,
LSN load_lsn,
TOKUTXN txn,
bool reserve_memory,
diff --git a/storage/tokudb/ft-index/ft/fttypes.h b/storage/tokudb/ft-index/ft/fttypes.h
index 73e228cf6ff..052d6342883 100644
--- a/storage/tokudb/ft-index/ft/fttypes.h
+++ b/storage/tokudb/ft-index/ft/fttypes.h
@@ -198,7 +198,7 @@ typedef struct {
static const STAT64INFO_S ZEROSTATS = {0,0};
-/* At the ft layer, a FILENUM uniquely identifies an open file.
+/* At the brt layer, a FILENUM uniquely identifies an open file.
* At the ydb layer, a DICTIONARY_ID uniquely identifies an open dictionary.
* With the introduction of the loader (ticket 2216), it is possible for the file that holds
* an open dictionary to change, so these are now separate and independent unique identifiers.
@@ -230,7 +230,7 @@ typedef struct cachetable *CACHETABLE;
typedef struct cachefile *CACHEFILE;
typedef struct ctpair *PAIR;
typedef class checkpointer *CHECKPOINTER;
-class bn_data;
+typedef class bn_data *BN_DATA;
/* tree command types */
enum ft_msg_type {
@@ -323,14 +323,14 @@ struct ft_msg {
XIDS xids;
union {
/* insert or delete */
- struct ft_msg_insert_delete {
+ struct ft_cmd_insert_delete {
const DBT *key; // for insert, delete, upsertdel
const DBT *val; // for insert, delete, (and it is the "extra" for upsertdel, upsertdel_broadcast_all)
} id;
} u;
};
-
-// Message sent into the ft to implement insert, delete, update, etc
+// Message sent into brt to implement command (insert, delete, etc.)
+// This structure supports nested transactions, and obsoletes ft_msg.
typedef struct ft_msg FT_MSG_S;
typedef struct ft_msg *FT_MSG;
diff --git a/storage/tokudb/ft-index/ft/ftverify.cc b/storage/tokudb/ft-index/ft/ftverify.cc
index 1b103abd55a..fbac7399dc4 100644
--- a/storage/tokudb/ft-index/ft/ftverify.cc
+++ b/storage/tokudb/ft-index/ft/ftverify.cc
@@ -98,6 +98,7 @@ PATENT RIGHTS GRANT:
#include "ft-internal.h"
#include "ft_layout_version.h"
#include "block_table.h"
+#include "x1764.h"
#include "rbuf.h"
#include "sub_block.h"
diff --git a/storage/tokudb/ft-index/ft/hash-benchmarks/hash-benchmark-manually-open.cc b/storage/tokudb/ft-index/ft/hash-benchmarks/hash-benchmark-manually-open.cc
new file mode 100644
index 00000000000..308bb352482
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/hash-benchmarks/hash-benchmark-manually-open.cc
@@ -0,0 +1,378 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+/* Benchmark various hash functions. */
+
+#include <sys/time.h>
+#include <zlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <toku_assert.h>
+
+#define N 200000000
+char *buf;
+
+static double tdiff (struct timeval *a, struct timeval *b) {
+ return a->tv_sec - b->tv_sec + (1e-6)*(a->tv_usec - b->tv_usec);
+}
+
+#define measure_bandwidth(str, body) ({ \
+ int c; \
+ struct timeval start,end; \
+ gettimeofday(&start, 0); \
+ body; \
+ gettimeofday(&end, 0); \
+ double diff = tdiff(&end, &start); \
+ printf("%s=%08x %d bytes in %8.6fs for %8.3fMB/s\n", str, c, N, diff, N*(1e-6)/diff); \
+ })
+
+int sum32 (int start, void *buf, int bytecount) {
+ int *ibuf = buf;
+ assert(bytecount%4==0);
+ while (bytecount>0) {
+ start+=*ibuf;
+ ibuf++;
+ bytecount-=4;
+ }
+ return start;
+}
+
+static const uint32_t m = 0x5bd1e995;
+static const int r = 24;
+static const uint32_t seed = 0x3dd3b51a;
+
+#define USE_ZERO_CHECKSUM 0
+
+static uint32_t MurmurHash2 ( const void * key, int len)
+{
+ if (USE_ZERO_CHECKSUM) return 0;
+
+ // 'm' and 'r' are mixing constants generated offline.
+ // They're not really 'magic', they just happen to work well.
+
+
+ // Initialize the hash to a 'random' value
+
+ uint32_t h = seed;
+
+ // Mix 4 bytes at a time into the hash
+
+ const unsigned char * data = (const unsigned char *)key;
+
+ while(len >= 4)
+ {
+ uint32_t k = *(uint32_t *)data;
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
+ h ^= k;
+
+ data += 4;
+ len -= 4;
+ }
+
+ // Handle the last few bytes of the input array
+
+ switch(len)
+ {
+ case 3: h ^= data[2] << 16;
+ case 2: h ^= data[1] << 8;
+ case 1: h ^= data[0];
+ h *= m;
+ };
+
+ // Do a few final mixes of the hash to ensure the last few
+ // bytes are well-incorporated.
+
+ h ^= h >> 29;
+ h *= m;
+ h ^= h >> 31;
+
+ return h;
+}
+
+struct murmur {
+ int n_bytes_in_k; // How many bytes in k
+ uint32_t k; // These are the extra bytes. Bytes are shifted into the low-order bits.
+ uint32_t h; // The hash so far (up to the most recent 4-byte boundary)
+};
+
+void murmur_init (struct murmur *mm) {
+ mm->n_bytes_in_k=0;
+ mm->k =0;
+ mm->h = seed;
+}
+
+#define MIX() ({ k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; })
+#define LD1() data[0]
+#define LD2() ((data[0]<<8) | data[1])
+#define LD3() ((data[0]<<16) | (data[1]<<8) | data[2])
+#define ADD1_0() (mm->k = LD1())
+#define ADD1() (mm->k = (k<<8) | LD1())
+#define ADD2_0() (mm->k = LD2())
+#define ADD2() (mm->k = (k<<16) | LD2())
+#define ADD3_0() (mm->k = LD3())
+#define ADD3() (mm->k = (k<<24) | LD3())
+
+void murmur_add (struct murmur *mm, const void * key, unsigned int len) {
+ if (USE_ZERO_CHECKSUM) return;
+ if (len==0) return;
+ const int n_bytes_in_k = mm->n_bytes_in_k;
+ uint32_t k = mm->k;
+ const unsigned char *data = key;
+ uint32_t h = mm->h;
+ switch (n_bytes_in_k) {
+ case 0:
+ switch (len) {
+ case 1: ADD1_0(); mm->n_bytes_in_k = 1; mm->h=h; return;
+ case 2: ADD2_0(); mm->n_bytes_in_k = 2; mm->h=h; return;
+ case 3: ADD3_0(); mm->n_bytes_in_k = 3; mm->h=h; return;
+ default: break;
+ }
+ break;
+ case 1:
+ switch (len) {
+ case 1: ADD1(); mm->n_bytes_in_k = 2; mm->h=h; return;
+ case 2: ADD2(); mm->n_bytes_in_k = 3; mm->h=h; return;
+ case 3: ADD3(); mm->n_bytes_in_k = 0; MIX(); mm->h=h; return;
+ default: ADD3(); mm->n_bytes_in_k = 0; MIX(); len-=3; data+=3; break;
+ }
+ break;
+ case 2:
+ switch (len) {
+ case 1: ADD1(); mm->n_bytes_in_k = 3; mm->h=h; return;
+ case 2: ADD2(); mm->n_bytes_in_k = 0; MIX(); mm->h=h; return;
+ default: ADD2(); mm->n_bytes_in_k = 0; MIX(); len-=2; data+=2; break;
+ }
+ break;
+ case 3:
+ switch (len) {
+ case 1: ADD1(); mm->n_bytes_in_k = 0; MIX(); mm->h=h; return;
+ default: ADD1(); mm->n_bytes_in_k = 0; MIX(); len--; data++; break;
+ }
+ break;
+ default: assert(0);
+ }
+
+ // We've used up the partial bytes at the beginning of k.
+ assert(mm->n_bytes_in_k==0);
+ while (len >= 4) {
+ uint32_t k = toku_dtoh32(*(uint32_t *)data);
+ //printf(" oldh=%08x k=%08x", h, k);
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
+ h ^= k;
+
+ data += 4;
+ len -= 4;
+ //printf(" h=%08x\n", h);
+ }
+ mm->h=h;
+ //printf("%s:%d h=%08x\n", __FILE__, __LINE__, h);
+ {
+ uint32_t k=0;
+ switch (len) {
+ case 3: k = *data << 16; data++;
+ case 2: k |= *data << 8; data++;
+ case 1: k |= *data;
+ }
+ mm->k = k;
+ mm->n_bytes_in_k = len;
+ //printf("now extra=%08x (%d bytes) n_bytes=%d\n", mm->k, len, mm->n_bytes_in_k);
+
+ }
+}
+
+uint32_t murmur_finish (struct murmur *mm) {
+ if (USE_ZERO_CHECKSUM) return 0;
+ uint32_t h = mm->h;
+ if (mm->n_bytes_in_k>0) {
+ h ^= mm->k;
+ h *= m;
+ }
+ if (0) {
+ // The real murmur function does this extra mixing at the end. We don't need that for fingerprint.
+ h ^= h >> 29;
+ h *= m;
+ h ^= h >> 31;
+ }
+ return h;
+}
+
+struct sum84 {
+ uint32_t sum;
+ int i;
+};
+void sum84_init (struct sum84 *s) { s->sum=0; s->i=0; };
+void sum84_add (struct sum84 *s, char *buf, int count) {
+ while (s->i%4!=0 && count>0) {
+ char v = *buf;
+ s->sum ^= v << (s->i%4)*8;
+ buf++; count--; s->i++;
+ }
+ while (count>4) {
+ s->sum ^= *(int*)buf;
+ buf+=4; count-=4;
+ }
+ while (count>0) {
+ char v = *buf;
+ s->sum ^= v << (s->i%4)*8;
+ buf++; count--; s->i++;
+ }
+}
+int sum84_finish (struct sum84 *s) {
+ return s->sum;
+}
+
+uint32_t xor8_add (uint32_t x, char *buf, int count) {
+ while (count>4) {
+ x ^= *(int*)buf;
+ buf+=4; count-=4;
+ }
+ while (count>0) {
+ char v = *buf;
+ x ^= v;
+ buf++; count--;
+ }
+ return x;
+}
+uint32_t xor8_finish (uint32_t x) {
+ return (x ^ (x>>8) ^ (x>>16) ^ (x>>24))&0xff;
+}
+
+uint64_t xor8_64_add (uint64_t x, char *buf, int count) {
+ while (count>8) {
+ x ^= *(uint64_t*)buf;
+ buf+=8; count-=8;
+ }
+ while (count>0) {
+ char v = *buf;
+ x ^= v;
+ buf++; count--;
+ }
+ return x;
+}
+uint32_t xor8_64_finish (uint64_t x) {
+ return (x ^ (x>>8) ^ (x>>16) ^ (x>>24) ^ (x>>32) ^ (x>>40) ^ (x>>48) ^ (x>>56))&0xff;
+}
+
+static void measure_bandwidths (void) {
+ measure_bandwidth("crc32 ", c=crc32(0, buf, N));
+ measure_bandwidth("sum32 ", c=sum32(0, buf, N));
+ measure_bandwidth("murmur ", c=MurmurHash2(buf, N));
+ measure_bandwidth("murmurf ", ({ struct murmur mm; murmur_init(&mm); murmur_add(&mm, buf, N); c=murmur_finish(&mm); }));
+ measure_bandwidth("sum84 ", ({ struct sum84 s; sum84_init(&s); sum84_add(&s, buf, N); c=sum84_finish(&s); }));
+ measure_bandwidth("xor32 ", ({ c=0; int j; for(j=0; j<N/4; j++) c^=*(int*)buf+j*4; }));
+ measure_bandwidth("xor8 ", c=xor8_finish(xor8_add(0, buf, N)));
+ measure_bandwidth("xor8_64 ", c=xor8_64_finish(xor8_64_add(0, buf, N)));
+ measure_bandwidth("crc32by1 ", ({ c=0; int j; for(j=0; j<N; j++) c=crc32(c, buf+j, 1); }));
+ measure_bandwidth("crc32by2 ", ({ c=0; int j; for(j=0; j<N; j+=2) c=crc32(c, buf+j, 2); }));
+ measure_bandwidth("sum8by1 ", ({ c=0; int j; for(j=0; j<N; j++) c+=buf[j]; }));
+ measure_bandwidth("murmurby1", ({ struct murmur mm; murmur_init(&mm); int j; for(j=0; j<N; j++) murmur_add(&mm, buf+j, 1); c=murmur_finish(&mm); }));
+ measure_bandwidth("murmurby2", ({ struct murmur mm; murmur_init(&mm); int j; for(j=0; j<N; j+=2) murmur_add(&mm, buf+j, 2); c=murmur_finish(&mm); }));
+ measure_bandwidth("sum84by1 ", ({ struct sum84 s; sum84_init(&s); int j; for(j=0; j<N; j++) sum84_add(&s, buf+j, 1); c=sum84_finish(&s); }));
+ measure_bandwidth("xor8by1 ", ({ int j; c=0; for(j=0; j<N; j++) c=xor8_add(c, buf+j, 1); c=xor8_finish(c); }));
+ measure_bandwidth("xor864by1", ({ int j; uint64_t x=0; for(j=0; j<N; j++) x=xor8_64_add(x, buf+j, 1); c=xor8_64_finish(x); }));
+}
+
+int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+ buf = malloc(N);
+ int i;
+ for (i=0; i<N; i++) buf[i]=random();
+ measure_bandwidths();
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/hash-benchmarks/hash-benchmark.cc b/storage/tokudb/ft-index/ft/hash-benchmarks/hash-benchmark.cc
new file mode 100644
index 00000000000..2afd05ece3a
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/hash-benchmarks/hash-benchmark.cc
@@ -0,0 +1,1205 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+/* Benchmark various hash functions. */
+
+#include <sys/time.h>
+#include <zlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <toku_assert.h>
+#include <arpa/inet.h>
+
+#define N 200000000
+#define PRINT 0
+//#define N 128
+//#define PRINT 1
+unsigned char *buf;
+
+static double tdiff (struct timeval *a, struct timeval *b) {
+ return a->tv_sec - b->tv_sec + (1e-6)*(a->tv_usec - b->tv_usec);
+}
+
+#define measure_bandwidth(str, body) ({ \
+ int c; \
+ struct timeval start,end; \
+ gettimeofday(&start, 0); \
+ body; \
+ gettimeofday(&end, 0); \
+ double diff = tdiff(&end, &start); \
+ printf("%s=%08x %d bytes in %8.6fs for %8.3fMB/s\n", str, c, N, diff, N*(1e-6)/diff); \
+ })
+
+int sum32 (void *buf, int bytecount) {
+ int *ibuf = buf;
+ int start = 0;
+ assert(bytecount%4==0);
+ while (bytecount>0) {
+ start+=*ibuf;
+ ibuf++;
+ bytecount-=4;
+ }
+ return start;
+}
+
+uint64_t sum64 (void *buf, int bytecount) {
+ uint64_t *ibuf = buf;
+ uint64_t start = 0;
+ assert(bytecount%8==0);
+ while (bytecount>0) {
+ start+=*ibuf;
+ ibuf++;
+ bytecount-=8;
+ }
+ return start;
+}
+
+static const uint32_t m = 0x5bd1e995;
+static const int r = 24;
+static const uint32_t seed = 0x3dd3b51a;
+
+#define USE_ZERO_CHECKSUM 0
+
+static uint32_t MurmurHash2 ( const void * key, int len)
+{
+ if (USE_ZERO_CHECKSUM) return 0;
+
+ // 'm' and 'r' are mixing constants generated offline.
+ // They're not really 'magic', they just happen to work well.
+
+
+ // Initialize the hash to a 'random' value
+
+ uint32_t h = seed;
+
+ // Mix 4 bytes at a time into the hash
+
+ const unsigned char * data = (const unsigned char *)key;
+
+ while(len >= 4)
+ {
+ uint32_t k = *(uint32_t *)data;
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
+ h ^= k;
+
+ data += 4;
+ len -= 4;
+ }
+
+ // Handle the last few bytes of the input array
+
+ switch(len)
+ {
+ case 3: h ^= data[2] << 16;
+ case 2: h ^= data[1] << 8;
+ case 1: h ^= data[0];
+ h *= m;
+ };
+
+ // Do a few final mixes of the hash to ensure the last few
+ // bytes are well-incorporated.
+
+ h ^= h >> 29;
+ h *= m;
+ h ^= h >> 31;
+
+ return h;
+}
+
+struct murmur {
+ int n_bytes_in_k; // How many bytes in k
+ uint32_t k; // These are the extra bytes. Bytes are shifted into the low-order bits.
+ uint32_t h; // The hash so far (up to the most recent 4-byte boundary)
+};
+
+void murmur_init (struct murmur *mm) {
+ mm->n_bytes_in_k=0;
+ mm->k =0;
+ mm->h = seed;
+}
+
+inline void murmur_add (struct murmur *mm, const void * key, unsigned int len) {
+ if (USE_ZERO_CHECKSUM) return;
+ assert(mm->n_bytes_in_k<4);
+ const unsigned char *data = key;
+ uint32_t h = mm->h;
+ {
+ int n_bytes_in_k = mm->n_bytes_in_k;
+ if (n_bytes_in_k>0) {
+ uint32_t k = mm->k;
+ while (n_bytes_in_k<4 && len>0) {
+ k = (k << 8) | *data;
+ n_bytes_in_k++;
+ data++;
+ len--;
+ }
+ if (n_bytes_in_k==4) {
+ //printf(" oldh=%08x k=%08x", h, k);
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+ h *= m;
+ h ^= k;
+ mm->n_bytes_in_k = 0;
+ mm->k=0;
+ //printf(" h=%08x\n", h);
+ } else {
+ assert(len==0);
+ mm->n_bytes_in_k = n_bytes_in_k;
+ mm->k = k;
+ mm->h = h;
+ return;
+ }
+ }
+ }
+ // We've used up the partial bytes at the beginning of k.
+ assert(mm->n_bytes_in_k==0);
+ while (len >= 4) {
+ uint32_t k = toku_dtoh32(*(uint32_t *)data);
+ //printf(" oldh=%08x k=%08x", h, k);
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
+ h ^= k;
+
+ data += 4;
+ len -= 4;
+ //printf(" h=%08x\n", h);
+ }
+ mm->h=h;
+ //printf("%s:%d h=%08x\n", __FILE__, __LINE__, h);
+ {
+ uint32_t k=0;
+ switch (len) {
+ case 3: k = *data << 16; data++;
+ case 2: k |= *data << 8; data++;
+ case 1: k |= *data;
+ }
+ mm->k = k;
+ mm->n_bytes_in_k = len;
+ //printf("now extra=%08x (%d bytes) n_bytes=%d\n", mm->k, len, mm->n_bytes_in_k);
+
+ }
+}
+
+uint32_t murmur_finish (struct murmur *mm) {
+ if (USE_ZERO_CHECKSUM) return 0;
+ uint32_t h = mm->h;
+ if (mm->n_bytes_in_k>0) {
+ h ^= mm->k;
+ h *= m;
+ }
+ if (0) {
+ // The real murmur function does this extra mixing at the end. We don't need that for fingerprint.
+ h ^= h >> 29;
+ h *= m;
+ h ^= h >> 31;
+ }
+ return h;
+}
+
+struct sum84 {
+ uint32_t sum;
+ int i;
+};
+void sum84_init (struct sum84 *s) { s->sum=0; s->i=0; };
+void sum84_add (struct sum84 *s, unsigned char *buf, int count) {
+ while (s->i%4!=0 && count>0) {
+ char v = *buf;
+ s->sum ^= v << (s->i%4)*8;
+ buf++; count--; s->i++;
+ }
+ while (count>4) {
+ s->sum ^= *(int*)buf;
+ buf+=4; count-=4;
+ }
+ while (count>0) {
+ char v = *buf;
+ s->sum ^= v << (s->i%4)*8;
+ buf++; count--; s->i++;
+ }
+}
+int sum84_finish (struct sum84 *s) {
+ return s->sum;
+}
+
+uint32_t xor8_add (uint32_t x, unsigned char *buf, int count) {
+ while (count>4) {
+ x ^= *(int*)buf;
+ buf+=4; count-=4;
+ }
+ while (count>0) {
+ char v = *buf;
+ x ^= v;
+ buf++; count--;
+ }
+ return x;
+}
+uint32_t xor8_finish (uint32_t x) {
+ return (x ^ (x>>8) ^ (x>>16) ^ (x>>24))&0xff;
+}
+
+uint64_t xor8_64_add (uint64_t x, unsigned char *buf, int count) {
+ while (count>8) {
+ x ^= *(uint64_t*)buf;
+ buf+=8; count-=8;
+ }
+ while (count>0) {
+ char v = *buf;
+ x ^= v;
+ buf++; count--;
+ }
+ return x;
+}
+uint32_t xor8_64_finish (uint64_t x) {
+ return (x ^ (x>>8) ^ (x>>16) ^ (x>>24) ^ (x>>32) ^ (x>>40) ^ (x>>48) ^ (x>>56))&0xff;
+}
+
+#define BYFOUR
+typedef long int ptrdiff_t;
+typedef unsigned int u4;
+
+static const unsigned long crc_table[8][256] =
+{
+ {
+ 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+ 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+ 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+ 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+ 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+ 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+ 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+ 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+ 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+ 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+ 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+ 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+ 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+ 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+ 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+ 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+ 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+ 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+ 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+ 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+ 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+ 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+ 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+ 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+ 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+ 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+ 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+ 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+ 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+ 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+ 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+ 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+ 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+ 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+ 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+ 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+ 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+ 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+ 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+ 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+ 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+ 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+ 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+ 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+ 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+ 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+ 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+ 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+ 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+ 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+ 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+ 0x2d02ef8dUL
+
+ },
+ {
+ 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+ 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+ 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+ 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+ 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+ 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+ 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+ 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+ 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+ 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+ 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+ 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+ 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+ 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+ 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+ 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+ 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+ 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+ 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+ 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+ 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+ 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+ 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+ 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+ 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+ 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+ 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+ 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+ 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+ 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+ 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+ 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+ 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+ 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+ 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+ 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+ 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+ 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+ 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+ 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+ 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+ 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+ 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+ 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+ 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+ 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+ 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+ 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+ 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+ 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+ 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+ 0x9324fd72UL
+ },
+ {
+ 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+ 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+ 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+ 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+ 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+ 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+ 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+ 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+ 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+ 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+ 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+ 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+ 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+ 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+ 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+ 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+ 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+ 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+ 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+ 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+ 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+ 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+ 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+ 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+ 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+ 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+ 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+ 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+ 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+ 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+ 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+ 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+ 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+ 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+ 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+ 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+ 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+ 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+ 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+ 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+ 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+ 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+ 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+ 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+ 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+ 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+ 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+ 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+ 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+ 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+ 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+ 0xbe9834edUL
+ },
+ {
+ 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+ 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+ 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+ 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+ 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+ 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+ 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+ 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+ 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+ 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+ 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+ 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+ 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+ 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+ 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+ 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+ 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+ 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+ 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+ 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+ 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+ 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+ 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+ 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+ 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+ 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+ 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+ 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+ 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+ 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+ 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+ 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+ 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+ 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+ 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+ 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+ 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+ 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+ 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+ 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+ 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+ 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+ 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+ 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+ 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+ 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+ 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+ 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+ 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+ 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+ 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+ 0xde0506f1UL
+ },
+ {
+ 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+ 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+ 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+ 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+ 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+ 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+ 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+ 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+ 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+ 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+ 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+ 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+ 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+ 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+ 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+ 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+ 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+ 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+ 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+ 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+ 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+ 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+ 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+ 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+ 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+ 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+ 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+ 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+ 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+ 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+ 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+ 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+ 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+ 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+ 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+ 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+ 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+ 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+ 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+ 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+ 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+ 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+ 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+ 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+ 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+ 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+ 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+ 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+ 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+ 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+ 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+ 0x8def022dUL
+ },
+ {
+ 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+ 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+ 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+ 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+ 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+ 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+ 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+ 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+ 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+ 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+ 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+ 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+ 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+ 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+ 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+ 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+ 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+ 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+ 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+ 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+ 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+ 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+ 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+ 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+ 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+ 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+ 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+ 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+ 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+ 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+ 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+ 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+ 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+ 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+ 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+ 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+ 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+ 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+ 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+ 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+ 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+ 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+ 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+ 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+ 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+ 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+ 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+ 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+ 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+ 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+ 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+ 0x72fd2493UL
+ },
+ {
+ 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+ 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+ 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+ 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+ 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+ 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+ 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+ 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+ 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+ 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+ 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+ 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+ 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+ 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+ 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+ 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+ 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+ 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+ 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+ 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+ 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+ 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+ 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+ 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+ 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+ 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+ 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+ 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+ 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+ 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+ 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+ 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+ 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+ 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+ 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+ 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+ 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+ 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+ 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+ 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+ 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+ 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+ 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+ 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+ 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+ 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+ 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+ 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+ 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+ 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+ 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+ 0xed3498beUL
+ },
+ {
+ 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+ 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+ 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+ 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+ 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+ 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+ 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+ 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+ 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+ 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+ 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+ 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+ 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+ 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+ 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+ 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+ 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+ 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+ 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+ 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+ 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+ 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+ 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+ 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+ 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+ 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+ 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+ 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+ 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+ 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+ 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+ 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+ 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+ 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+ 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+ 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+ 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+ 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+ 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+ 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+ 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+ 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+ 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+ 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+ 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+ 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+ 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+ 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+ 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+ 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+ 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+ 0xf10605deUL
+
+ }
+};
+inline static unsigned long crc32_little (unsigned long, const unsigned char *, unsigned);
+inline static unsigned long crc32_big (unsigned long, const unsigned char *, unsigned);
+
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+inline unsigned long ZEXPORT crc32_local(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+ if (sizeof(void *) == sizeof(ptrdiff_t)) {
+ u4 endian;
+
+ endian = 1;
+ if (*((unsigned char *)(&endian)))
+ return crc32_little(crc, buf, len);
+ else
+ return crc32_big(crc, buf, len);
+ }
+#endif /* BYFOUR */
+ crc = crc ^ 0xffffffffUL;
+ while (len >= 8) {
+ DO8;
+ len -= 8;
+ }
+ if (len) do {
+ DO1;
+ } while (--len);
+ return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+ (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+#define local static
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+inline local unsigned long crc32_little(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = (u4)crc;
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ while (len >= 32) {
+ DOLIT32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOLIT4;
+ len -= 4;
+ }
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+inline local unsigned long crc32_big(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = REV((u4)crc);
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ buf4--;
+ while (len >= 32) {
+ DOBIG32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOBIG4;
+ len -= 4;
+ }
+ buf4++;
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
+
+// Character-by-character implementation of x17.
+static uint32_t x17c (uint32_t c, void *buf, int len) {
+ int i;
+ unsigned char *cbuf=buf;
+ for (i=0; i<len; i++) {
+ c = c*17 + cbuf[i];
+ }
+ return c;
+}
+
+// x17 using shorts
+static uint32_t x17s (uint32_t c, void *buf, int len) {
+ unsigned char *cbuf=buf;
+ while ((((long)cbuf)&1 ) && len) {
+ c = c*17 + *cbuf;
+ len--; cbuf++;
+ }
+ while (len>2) {
+ uint16_t s = *(uint16_t*)cbuf;
+ c = c*17*17 + (s&0xff)*17 + (s>>8);
+ len-=2; cbuf+=2;
+ }
+ while (len) {
+ c = c*17 + *cbuf;
+ len--; cbuf++;
+ }
+ return c;
+}
+
+static uint32_t x17i (uint32_t c, void *buf, int len) {
+ unsigned char *cbuf=buf;
+ while ((((long)cbuf)&3 ) && len) {
+ c = c*17 + *cbuf;
+ len--; cbuf++;
+ }
+ while (len>4) {
+ uint32_t l = *(uint32_t*)cbuf;
+ c = c*17*17*17*17 + (l&0xff)*17*17*17 + ((l>>8)&0xff)*17*17 + ((l>>16)&0xff)*17 + ((l>>24)&0xff);
+ len-=4; cbuf+=4;
+ }
+ while (len) {
+ c = c*17 + *cbuf;
+ len--; cbuf++;
+ }
+ return c;
+}
+
+uint32_t l17_fast64 (const void *buf, int len) {
+ assert(len%8==0);
+ const uint64_t *lbuf=buf;
+ uint64_t c=0;
+ while (len>0) {
+ c = c*17 + *lbuf;
+ if (PRINT) printf("%d: c=%016lx sum=%016lx\n", __LINE__, *lbuf, c);
+ lbuf++;
+ len-=8;
+ }
+ return c&0xFFFFFFFF;
+}
+struct l1764 {
+ uint64_t sum;
+ uint64_t input;
+ int n_input_bytes;
+};
+void l1764_init(struct l1764 *l) {
+ l->sum=0;
+ l->input=0;
+ l->n_input_bytes=0;
+}
+inline void l1764_add (struct l1764 *l, const void *vbuf, int len) {
+ if (PRINT) printf("%d: n_input_bytes=%d len=%d\n", __LINE__, l->n_input_bytes, len);
+ int n_input_bytes = l->n_input_bytes;
+ const unsigned char *cbuf = vbuf;
+ // Special case short inputs
+ if (len==1) {
+ uint64_t input = l->input | ((uint64_t)(*cbuf))<<(8*n_input_bytes);
+ n_input_bytes++;
+ if (n_input_bytes==8) {
+ l->sum = l->sum*17 + input;
+ l->n_input_bytes = 0;
+ l->input = 0;
+ } else {
+ l->input = input;
+ l->n_input_bytes = n_input_bytes;
+ }
+ return;
+ } else if (len==2) {
+ uint64_t input = l->input;
+ uint64_t thisv = ((uint64_t)(*(uint16_t*)cbuf));
+ if (n_input_bytes==7) {
+ l->sum = l->sum*17 + (input | (thisv<<(8*7)));
+ l->input = thisv>>8;
+ l->n_input_bytes = 1;
+ } else if (n_input_bytes==6) {
+ l->sum = l->sum*17 + (input | (thisv<<(8*6)));
+ l->input = 0;
+ l->n_input_bytes = 0;
+ } else {
+ l->input = input | (thisv<<(8*n_input_bytes));
+ l->n_input_bytes += 2;
+ }
+ return;
+ }
+
+ uint64_t sum;
+ //assert(len>=0);
+ if (n_input_bytes) {
+ uint64_t input = l->input;
+ if (len>=8) {
+ sum = l->sum;
+ while (len>=8) {
+ uint64_t thisv = *(uint64_t*)cbuf;
+ input |= thisv<<(8*n_input_bytes);
+ sum = sum*17 + input;
+ if (PRINT) printf("%d: input=%016lx sum=%016lx\n", __LINE__, input, sum);
+ input = thisv>>(8*(8-n_input_bytes));
+ if (PRINT) printf("%d: input=%016lx\n", __LINE__, input);
+ len-=8;
+ cbuf+=8;
+ // n_input_bytes remains unchanged
+ if (PRINT) printf("%d: n_input_bytes=%d len=%d\n", __LINE__, l->n_input_bytes, len);
+ }
+ l->sum = sum;
+ }
+ if (len>=4) {
+ uint64_t thisv = *(uint32_t*)cbuf;
+ if (n_input_bytes<4) {
+ input |= thisv<<(8*n_input_bytes);
+ if (PRINT) printf("%d: input=%016lx\n", __LINE__, input);
+ n_input_bytes+=4;
+ } else {
+ input |= thisv<<(8*n_input_bytes);
+ l->sum = l->sum*17 + input;
+ if (PRINT) printf("%d: input=%016lx sum=%016lx\n", __LINE__, input, l->sum);
+ input = thisv>>(8*(8-n_input_bytes));
+ n_input_bytes-=4;
+ if (PRINT) printf("%d: input=%016lx n_input_bytes=%d\n", __LINE__, input, n_input_bytes);
+ }
+ len-=4;
+ cbuf+=4;
+ if (PRINT) printf("%d: len=%d\n", __LINE__, len);
+ }
+ //assert(n_input_bytes<=8);
+ while (n_input_bytes<8 && len) {
+ input |= ((uint64_t)(*cbuf))<<(8*n_input_bytes);
+ n_input_bytes++;
+ cbuf++;
+ len--;
+ }
+ //assert(len>=0);
+ if (n_input_bytes<8) {
+ //assert(len==0);
+ l->input = input;
+ l->n_input_bytes = n_input_bytes;
+ if (PRINT) printf("%d: n_input_bytes=%d\n", __LINE__, l->n_input_bytes);
+ return;
+ }
+ sum = l->sum*17 + input;
+ } else {
+ //assert(len>=0);
+ sum = l->sum;
+ }
+ //assert(len>=0);
+ while (len>=8) {
+ sum = sum*17 + *(uint64_t*)cbuf;
+ cbuf+=8;
+ len -=8;
+ }
+ l->sum = sum;
+ n_input_bytes = 0;
+ uint64_t input;
+ l->n_input_bytes = len;
+ // Surprisingly, the loop is the fastest on bradley's laptop.
+ if (1) {
+ int i;
+ input=0;
+ for (i=0; i<len; i++) {
+ input |= ((uint64_t)(cbuf[i]))<<(8*i);
+ }
+ } else if (0) {
+ switch (len) {
+ case 7: input = ((uint64_t)(*(uint32_t*)(cbuf))) | (((uint64_t)(*(uint16_t*)(cbuf+4)))<<32) | (((uint64_t)(*(cbuf+4)))<<48); break;
+ case 6: input = ((uint64_t)(*(uint32_t*)(cbuf))) | (((uint64_t)(*(uint16_t*)(cbuf+4)))<<32); break;
+ case 5: input = ((uint64_t)(*(uint32_t*)(cbuf))) | (((uint64_t)(*(cbuf+4)))<<32); break;
+ case 4: input = ((uint64_t)(*(uint32_t*)(cbuf))); break;
+ case 3: input = ((uint64_t)(*(uint16_t*)(cbuf))) | (((uint64_t)(*(cbuf+2)))<<16); break;
+ case 2: input = ((uint64_t)(*(uint16_t*)(cbuf))); break;
+ case 1: input = ((uint64_t)(*cbuf)); break;
+ case 0: input = 0; break;
+ default: abort();
+ }
+ } else {
+ input=0;
+ int i=0;
+ if (len>=4) { input = ((uint64_t)(*(uint32_t*)(cbuf))); cbuf+=4; len-=4; i=4;}
+ if (len>=2) { input |= ((uint64_t)(*(uint16_t*)(cbuf)))<<(i*8); cbuf+=2; len-=2; i+=2; }
+ if (len>=1) { input |= ((uint64_t)(*(uint8_t *)(cbuf)))<<(i*8); /*cbuf+=1; len-=1; i++;*/ }
+ }
+ l->input = input;
+ if (PRINT) printf("%d: n_input_bytes=%d\n", __LINE__, l->n_input_bytes);
+}
+uint32_t l1764_finish (struct l1764 *l) {
+ if (PRINT) printf("%d: n_input_bytes=%d\n", __LINE__, l->n_input_bytes);
+ assert(l->n_input_bytes==0);
+ return (l->sum)&0xffffffff;
+}
+
+uint32_t l17_fast (const void *buf, int len) {
+ assert(len%4==0);
+ const uint32_t *lbuf=buf;
+ uint32_t c=0;
+ while (len>0) {
+ c = c*17 + *lbuf;
+ lbuf++;
+ len-=4;
+ }
+ return c;
+}
+
+struct l17 {
+ uint32_t sum;
+ uint32_t input;
+ int input_len;
+};
+void l17_init (struct l17 *l17) {
+ l17->sum=0;
+ l17->input=0;
+ l17->input_len=0;
+}
+void l17_add (struct l17 *l17, const void *buf, int len) {
+ const unsigned char *cbuf=buf;
+ while (l17->input_len%4 && len) {
+ l17->input_len |= (*cbuf<<(8*(3-l17->input_len)));
+ }
+}
+
+
+#define Nu N
+
+static void measure_bandwidths (void) {
+ int canon; // what is the results supposed to be.
+ measure_bandwidth("l17fast ", c=l17_fast(buf, N));
+ measure_bandwidth("l17fast64", canon=c=l17_fast64(buf, N));
+ measure_bandwidth("l17f64i ", ({ struct l1764 l; l1764_init(&l); l1764_add(&l, buf, Nu); c=l1764_finish(&l); assert(canon==c); }));
+ measure_bandwidth("l17f64ib1", ({ struct l1764 l; l1764_init(&l); int j; for(j=0; j<Nu; j++) l1764_add(&l, buf+j, 1); c=l1764_finish(&l); assert(canon==c);}));
+ measure_bandwidth("l17f64ib2", ({ struct l1764 l; l1764_init(&l); int j; for(j=0; j<Nu; j+=2) l1764_add(&l, buf+j, 2); c=l1764_finish(&l); assert(canon==c); }));
+ measure_bandwidth("l17f64ib4", ({ struct l1764 l; l1764_init(&l); int j; for(j=0; j<Nu; j+=4) l1764_add(&l, buf+j, 4); c=l1764_finish(&l); assert(canon==c); }));
+ measure_bandwidth("l17f64ib8", ({ struct l1764 l; l1764_init(&l); int j; for(j=0; j<Nu; j+=8) l1764_add(&l, buf+j, 8); c=l1764_finish(&l); assert(canon==c); }));
+ measure_bandwidth("l17f64ib9", ({ struct l1764 l; l1764_init(&l); int j; for(j=0; j+8<Nu; j+=9) l1764_add(&l, buf+j, 9); l1764_add(&l, buf+j, N-j); c=l1764_finish(&l); assert(canon==c); }));
+ measure_bandwidth("l17f64ibc", ({ struct l1764 l; l1764_init(&l); int j; for(j=0; j+13<Nu; j+=13) l1764_add(&l, buf+j, 13); l1764_add(&l, buf+j, N-j); c=l1764_finish(&l); assert(canon==c); }));
+ measure_bandwidth("x17c ", c=x17c(0, buf, N));
+ measure_bandwidth("x17s ", c=x17s(0, buf, N));
+ measure_bandwidth("x17i ", c=x17i(0, buf, N));
+ measure_bandwidth("crc32L ", c=crc32_local(0, buf, N));
+ measure_bandwidth("crc32Lby1", ({ c=0; int j; for(j=0; j<N; j++) c=crc32_local(c, (buf+j), 1); }));
+ measure_bandwidth("crc32Lby2", ({ c=0; int j; for(j=0; j<N; j+=2) c=crc32_local(c, (buf+j), 2); }));
+ measure_bandwidth("crc32 ", c=crc32(0, buf, N));
+ measure_bandwidth("crc32by1 ", ({ c=0; int j; for(j=0; j<N; j++) c=crc32(c, buf+j, 1); }));
+ measure_bandwidth("crc32by2 ", ({ c=0; int j; for(j=0; j<N; j+=2) c=crc32(c, buf+j, 2); }));
+ measure_bandwidth("sum32 ", c=sum32(buf, N));
+ measure_bandwidth("sum64 ", c=sum64(buf, N));
+ measure_bandwidth("murmur ", c=MurmurHash2(buf, N));
+ measure_bandwidth("murmurf ", ({ struct murmur mm; murmur_init(&mm); murmur_add(&mm, buf, N); c=murmur_finish(&mm); }));
+ measure_bandwidth("sum84 ", ({ struct sum84 s; sum84_init(&s); sum84_add(&s, buf, N); c=sum84_finish(&s); }));
+ measure_bandwidth("xor32 ", ({ c=0; int j; for(j=0; j<N/4; j++) c^=*(int*)buf+j*4; }));
+ measure_bandwidth("xor8 ", c=xor8_finish(xor8_add(0, buf, N)));
+ measure_bandwidth("xor8_64 ", c=xor8_64_finish(xor8_64_add(0, buf, N)));
+ measure_bandwidth("sum8by1 ", ({ c=0; int j; for(j=0; j<N; j++) c+=buf[j]; }));
+ measure_bandwidth("murmurby1", ({ struct murmur mm; murmur_init(&mm); int j; for(j=0; j<N; j++) murmur_add(&mm, buf+j, 1); c=murmur_finish(&mm); }));
+ measure_bandwidth("murmurby2", ({ struct murmur mm; murmur_init(&mm); int j; for(j=0; j<N; j+=2) murmur_add(&mm, buf+j, 2); c=murmur_finish(&mm); }));
+ measure_bandwidth("sum84by1 ", ({ struct sum84 s; sum84_init(&s); int j; for(j=0; j<N; j++) sum84_add(&s, buf+j, 1); c=sum84_finish(&s); }));
+ measure_bandwidth("xor8by1 ", ({ int j; c=0; for(j=0; j<N; j++) c=xor8_add(c, buf+j, 1); c=xor8_finish(c); }));
+ measure_bandwidth("xor864by1", ({ int j; uint64_t x=0; for(j=0; j<N; j++) x=xor8_64_add(x, buf+j, 1); c=xor8_64_finish(x); }));
+}
+
+int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+ buf = malloc(N);
+ int i;
+ for (i=0; i<N; i++) buf[i]=random();
+ measure_bandwidths();
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/le-cursor.h b/storage/tokudb/ft-index/ft/le-cursor.h
index d443666492c..eac5a4e5de4 100644
--- a/storage/tokudb/ft-index/ft/le-cursor.h
+++ b/storage/tokudb/ft-index/ft/le-cursor.h
@@ -104,10 +104,10 @@ PATENT RIGHTS GRANT:
typedef struct le_cursor *LE_CURSOR;
-// Create a leaf cursor for a tree (ft_h) within a transaction (txn)
+// Create a leaf cursor for a tree (brt) within a transaction (txn)
// Success: returns 0, stores the LE_CURSOR in the le_cursor_result
// Failure: returns a non-zero error number
-int toku_le_cursor_create(LE_CURSOR *le_cursor_result, FT_HANDLE ft_h, TOKUTXN txn);
+int toku_le_cursor_create(LE_CURSOR *le_cursor_result, FT_HANDLE brt, TOKUTXN txn);
// Close and free the LE_CURSOR
void toku_le_cursor_close(LE_CURSOR le_cursor);
diff --git a/storage/tokudb/ft-index/ft/leafentry.h b/storage/tokudb/ft-index/ft/leafentry.h
index 5c525db5c19..b664d1675a1 100644
--- a/storage/tokudb/ft-index/ft/leafentry.h
+++ b/storage/tokudb/ft-index/ft/leafentry.h
@@ -96,10 +96,11 @@ PATENT RIGHTS GRANT:
#include <toku_portability.h>
#include <util/mempool.h>
-#include <util/omt.h>
#include "txn_manager.h"
#include "rbuf.h"
+#include "x1764.h"
+#include "omt.h"
/*
Memory format of packed leaf entry
diff --git a/storage/tokudb/ft-index/ft/locking-benchmarks/mfence-benchmark.cc b/storage/tokudb/ft-index/ft/locking-benchmarks/mfence-benchmark.cc
new file mode 100644
index 00000000000..0c8290d8d2f
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/locking-benchmarks/mfence-benchmark.cc
@@ -0,0 +1,217 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+/* Time {m,l,s}fence vs.xchgl for a memory barrier. */
+
+/* Timing numbers:
+ * Intel T2500 2GHZ
+
+do1 9.0ns/loop
+mfence: 29.0ns/loop (marginal cost= 20.0ns)
+sfence: 17.3ns/loop (marginal cost= 8.3ns)
+lfence: 23.6ns/loop (marginal cost= 14.6ns)
+ xchgl: 35.8ns/loop (marginal cost= 26.8ns)
+
+* AMD Athlon 64 X2 Dual Core Processor 4200+
+ Timings are more crazy
+
+do1 20.6ns/loop
+mfence: 12.9ns/loop (marginal cost= -7.6ns)
+sfence: 8.4ns/loop (marginal cost= -12.1ns)
+lfence: 20.2ns/loop (marginal cost= -0.3ns)
+ xchgl: 16.6ns/loop (marginal cost= -3.9ns)
+
+do1 13.0ns/loop
+mfence: 25.6ns/loop (marginal cost= 12.6ns)
+sfence: 21.0ns/loop (marginal cost= 8.1ns)
+lfence: 12.9ns/loop (marginal cost= -0.1ns)
+ xchgl: 29.3ns/loop (marginal cost= 16.3ns)
+
+*/
+
+
+#include <sys/time.h>
+#include <stdio.h>
+#include <portability/toku_atomic.h>
+
+enum { COUNT = 100000000 };
+
+static inline void xchgl (void) {
+ {
+ /*
+ * According to the Intel Architecture Software Developer's
+ * Manual, Volume 3: System Programming Guide
+ * (http://www.intel.com/design/pro/manuals/243192.htm), page
+ * 7-6, "For the P6 family processors, locked operations
+ * serialize all outstanding load and store operations (that
+ * is, wait for them to complete)."
+ * Since xchg is locked by default, it is one way to do membar.
+ */
+ int x=0, y;
+ asm volatile ("xchgl %0,%1" :"=r" (x) :"m" (y), "0" (x) :"memory");
+ }
+}
+
+static inline void mfence (void) {
+ asm volatile ("mfence":::"memory");
+}
+
+static inline void lfence (void) {
+ asm volatile ("lfence":::"memory");
+}
+
+static inline void sfence (void) {
+ asm volatile ("sfence":::"memory");
+}
+
+int lock_for_lock_and_unlock;
+static inline void lock_and_unlock (void) {
+ (void)toku_sync_lock_test_and_set(&lock_for_lock_and_unlock, 1);
+ toku_sync_lock_release(&lock_for_lock_and_unlock);
+}
+
+
+double tdiff (struct timeval *start, struct timeval *end) {
+ return ((end->tv_sec-start->tv_sec + 1e-6*(end->tv_usec + start->tv_usec))/COUNT)*1e9;
+}
+
+double nop_cost;
+
+void do1 (volatile int *x) {
+ int i;
+ struct timeval start, end;
+ gettimeofday(&start, 0);
+ for (i=0; i<COUNT; i++) {
+ x[0]++;
+ x[1]++;
+ x[2]++;
+ x[3]++;
+ }
+ gettimeofday(&end, 0);
+ printf("do1 %6.1fns/loop\n", nop_cost=tdiff(&start, &end));
+}
+
+#define doit(name) void do ##name (volatile int *x) { \
+ int i; \
+ struct timeval start, end; \
+ gettimeofday(&start, 0); \
+ for (i=0; i<COUNT; i++) { \
+ x[0]++; \
+ x[1]++; \
+ name(); \
+ x[2]++; \
+ x[3]++; \
+ } \
+ gettimeofday(&end, 0); \
+ double this_cost = tdiff(&start, &end); \
+ printf("%15s:%6.1fns/loop (marginal cost=%6.1fns)\n", #name, this_cost, this_cost-nop_cost); \
+}
+
+
+doit(mfence)
+doit(lfence)
+doit(sfence)
+doit(xchgl)
+doit(lock_and_unlock);
+
+int main (int argc __attribute__((__unused__)),
+ char *argv[] __attribute__((__unused__))) {
+ int x[4];
+ int i;
+ for (i=0; i<4; i++) {
+ do1(x);
+ domfence(x);
+ dosfence(x);
+ dolfence(x);
+ doxchgl(x);
+ dolock_and_unlock(x);
+ }
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/locking-benchmarks/process_locks.cc b/storage/tokudb/ft-index/ft/locking-benchmarks/process_locks.cc
new file mode 100644
index 00000000000..f555328f04d
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/locking-benchmarks/process_locks.cc
@@ -0,0 +1,233 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+/* Test pthread rwlocks in multiprocess environment. */
+
+/* How expensive is
+ * - Obtaining a read-only lock for the first obtainer.
+ * - Obtaining it for the second one?
+ * - The third one? */
+
+#include <toku_assert.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+
+float tdiff (struct timeval *start, struct timeval *end) {
+ return 1e6*(end->tv_sec-start->tv_sec) +(end->tv_usec - start->tv_usec);
+}
+
+#define FILE "process.data"
+
+int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+ int r;
+ int fd;
+ void *p;
+ fd=open(FILE, O_CREAT|O_RDWR|O_TRUNC, 0666); assert(fd>=0);
+ int i;
+ for (i=0; i<4096; i++) {
+ r=write(fd, "\000", 1);
+ assert(r==1);
+ }
+ p=mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (p==MAP_FAILED) {
+ printf("err=%d %s (EPERM=%d)\n", errno, strerror(errno), EPERM);
+ }
+ assert(p!=MAP_FAILED);
+ r=close(fd); assert(r==0);
+
+ pthread_rwlockattr_t attr;
+ pthread_rwlock_t *lock=p;
+ r=pthread_rwlockattr_init(&attr); assert(r==0);
+ r=pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); assert(r==0);
+ r=pthread_rwlock_init(lock, &attr); assert(r==0);
+ r=pthread_rwlock_init(lock+1, &attr); assert(r==0);
+
+ r=pthread_rwlock_wrlock(lock);
+
+ pid_t pid;
+ if ((pid=fork())==0) {
+ // I'm the child
+ r = munmap(p, 4096); assert(r==0);
+ fd = open(FILE, O_RDWR, 0666); assert(fd>=0);
+ p=mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ assert(p!=MAP_FAILED);
+ r=close(fd); assert(r==0);
+
+ printf("A0\n");
+ r=pthread_rwlock_wrlock(lock);
+ printf("C\n");
+ sleep(1);
+
+ r=pthread_rwlock_unlock(lock);
+ printf("D\n");
+
+ r=pthread_rwlock_rdlock(lock);
+ printf("E0\n");
+ sleep(1);
+
+ } else {
+ printf("A1\n");
+ sleep(1);
+ printf("B\n");
+ r=pthread_rwlock_unlock(lock); // release the lock grabbed before the fork
+ assert(r==0);
+
+ sleep(1);
+ r=pthread_rwlock_rdlock(lock);
+ assert(r==0);
+ printf("E1\n");
+ sleep(1);
+
+ int status;
+ pid_t waited=wait(&status);
+ assert(waited==pid);
+ }
+ return 0;
+
+
+#if 0
+
+ int j;
+ int i;
+ int r;
+ struct timeval start, end;
+ for (j=0; j<3; j++) {
+ for (i=0; i<K; i++) {
+ r=pthread_rwlock_init(&rwlocks[i], NULL);
+ assert(r==0);
+ }
+ gettimeofday(&start, 0);
+ for (i=0; i<K; i++) {
+ r = pthread_rwlock_tryrdlock(&rwlocks[i]);
+ assert(r==0);
+ }
+ gettimeofday(&end, 0);
+ printf("pthread_rwlock_tryrdlock took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end));
+ }
+
+ for (j=0; j<3; j++) {
+ for (i=0; i<K; i++) {
+ r=pthread_rwlock_init(&rwlocks[i], NULL);
+ assert(r==0);
+ }
+ gettimeofday(&start, 0);
+ for (i=0; i<K; i++) {
+ r = pthread_rwlock_rdlock(&rwlocks[i]);
+ assert(r==0);
+ }
+ gettimeofday(&end, 0);
+ printf("pthread_rwlock_rdlock took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end));
+ }
+
+ for (j=0; j<3; j++) {
+ for (i=0; i<K; i++) {
+ blocks[i].state=0;
+ blocks[i].mutex=0;
+ }
+ gettimeofday(&start, 0);
+ for (i=0; i<K; i++) {
+ brwl_rlock(&blocks[i]);
+ }
+ gettimeofday(&end, 0);
+ printf("brwl_rlock took %9.3fus for %d ops: %9.3fus/lock (%9.3fMops/s)\n", tdiff(&start,&end), K, tdiff(&start,&end)/K, K/tdiff(&start,&end));
+ }
+ return 0;
+#endif
+}
diff --git a/storage/tokudb/ft-index/ft/locking-benchmarks/pthread-locks.cc b/storage/tokudb/ft-index/ft/locking-benchmarks/pthread-locks.cc
new file mode 100644
index 00000000000..82dafbdee7c
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/locking-benchmarks/pthread-locks.cc
@@ -0,0 +1,272 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+/* How expensive is
+ * - Obtaining a read-only lock for the first obtainer.
+ * - Obtaining it for the second one?
+ * - The third one? */
+
+#include <toku_assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <portability/toku_atomic.h>
+
+float tdiff (struct timeval *start, struct timeval *end) {
+ return 1e6*(end->tv_sec-start->tv_sec) +(end->tv_usec - start->tv_usec);
+}
+
+/* My own rwlock implementation. */
+struct brwl {
+ int mutex;
+ int state; // 0 for unlocked, -1 for a writer, otherwise many readers
+};
+
+static inline int xchg(volatile int *ptr, int x)
+{
+ __asm__("xchgl %0,%1" :"=r" (x) :"m" (*(ptr)), "0" (x) :"memory");
+ return x;
+}
+
+static inline void sfence (void) {
+ asm volatile ("sfence":::"memory");
+}
+
+static inline void brwl_rlock_fence (struct brwl *l) {
+ while (xchg(&l->mutex, 1)) ;
+ l->state++;
+ sfence();
+ l->mutex=0;
+}
+
+static inline void brwl_rlock_xchg (struct brwl *l) {
+ while (xchg(&l->mutex, 1)) ;
+ l->state++;
+ xchg(&l->mutex, 0);
+}
+
+// Something wrong with the compiler for longs
+static inline long
+fetch_and_add (volatile long *p, long incr)
+{
+ long result = incr;
+
+ __asm__ __volatile__ ("lock; xaddl %0, %1" :
+ "+r" (result), "+m" (*p) : : "memory");
+ return result;
+}
+
+static inline int
+fetch_and_add_i (volatile int *p, int incr)
+{
+ int result = incr;
+
+ __asm__ __volatile__ ("lock; xadd %0, %1" :
+ "+r" (result), "+m" (*p) : : "memory");
+ return result;
+}
+
+static inline int
+gcc_fetch_and_add_i (volatile int *p, int incr)
+{
+ return toku_sync_fetch_and_add(p, incr);
+}
+
+static inline long
+gcc_fetch_and_add_l (volatile long *p, long incr)
+{
+ return toku_sync_fetch_and_add(p, incr);
+}
+
+// Something wrong with the compiler for longs
+/* Returns nonzero if the comparison succeeded. */
+static inline long
+compare_and_swap_full(volatile long *addr,
+ long old, long new_val)
+{
+ char result;
+ __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1"
+ : "+m"(*(addr)), "=q"(result)
+ : "r" (new_val), "a"(old) : "memory");
+ return (int) result;
+}
+
+/* Returns nonzero if the comparison succeeded. */
+// Atomically compare *addr to old_val, and replace *addr by new_val
+// if the first comparison succeeds. Returns nonzero if the comparison
+// succeeded and *addr was updated.
+static inline int
+compare_and_swap_full_i(volatile int *addr,
+ int old, int new_val)
+{
+ char result;
+ __asm__ __volatile__("lock; cmpxchg %2, %0; setz %1"
+ : "+m"(*(addr)), "=q"(result)
+ : "r" (new_val), "a"(old) : "memory");
+ return (int) result;
+}
+
+enum {K=100000};
+pthread_rwlock_t rwlocks[K];
+struct brwl blocks[K];
+pthread_mutex_t mlocks[K];
+long lvals[K];
+int ivals[K];
+
+#define TIME(s, i, init, body) ({ \
+ int j_tmp; \
+ printf("%-24s", s); \
+ for (j_tmp=0; j_tmp<3; j_tmp++) { \
+ struct timeval start,end; \
+ int i; \
+ for (i=0; i<K; i++) { \
+ init; \
+ } \
+ gettimeofday(&start, 0); \
+ for (i=0; i<K; i++) { \
+ body; \
+ } \
+ gettimeofday(&end, 0); \
+ printf(" %9.3fus", tdiff(&start,&end)/K); \
+ } \
+ printf("\n"); \
+ })
+
+int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+
+ printf("sizeof (pthread_mutex_t) %lu\n", sizeof (pthread_mutex_t));
+ printf("sizeof (pthread_cond_t) %lu\n", sizeof (pthread_cond_t));
+
+ TIME("pthread_mutex_lock_errorcheck", i,
+ ({ int r; pthread_mutexattr_t mattr;
+ r = pthread_mutexattr_init(&mattr); assert(r == 0);
+ r = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK_NP); assert(r == 0);
+ r = pthread_mutex_init(&mlocks[i], &mattr); assert(r==0);
+ r = pthread_mutexattr_destroy(&mattr); assert(r == 0); }),
+ ({ int r = pthread_mutex_lock(&mlocks[i]); assert(r==0); }));
+ TIME("pthread_mutex_lock", i,
+ ({ int r = pthread_mutex_init(&mlocks[i], NULL); assert(r==0); }),
+ ({ int r = pthread_mutex_lock(&mlocks[i]); assert(r==0); }));
+ TIME("pthread_mutex_unlock", i,
+ ({ int r = pthread_mutex_init(&mlocks[i], NULL); assert(r==0); r = pthread_mutex_lock(&mlocks[i]); assert(r==0); }),
+ ({ int r = pthread_mutex_unlock(&mlocks[i]); assert(r==0); }));
+ TIME("pthread_rwlock_tryrdlock", i,
+ ({ int r = pthread_rwlock_init(&rwlocks[i], NULL); assert(r==0); }),
+ ({ int r = pthread_rwlock_tryrdlock(&rwlocks[i]); assert(r==0); }));
+ TIME("pthread_rwlock_rdlock", i,
+ ({ int r = pthread_rwlock_init(&rwlocks[i], NULL); assert(r==0); }),
+ ({ int r = pthread_rwlock_rdlock(&rwlocks[i]); assert(r==0); }));
+ TIME("brwl_rlock_xchg", i,
+ (blocks[i].state=0, blocks[i].mutex=0),
+ brwl_rlock_xchg(&blocks[i]));
+ TIME("brwl_rlock_fence", i,
+ (blocks[i].state=0, blocks[i].mutex=0),
+ brwl_rlock_fence(&blocks[i]));
+ int fa=0;
+ TIME("fetchadd", i,
+ (void)0,
+ fetch_and_add_i(&fa, i));
+ // printf("fa=%d\n", fa);
+ fa=0;
+ TIME("gcc_fetchadd", i,
+ (void)0,
+ gcc_fetch_and_add_i(&fa, i));
+ // printf("fa=%d\n", fa);
+ long fal = 0;
+ TIME("gcc_fetchaddlong", i,
+ (void)0,
+ gcc_fetch_and_add_l(&fal, i));
+ // printf("fa=%d\n", fa);
+ TIME("compare_and_swap", i,
+ ivals[i]=0,
+ ({ int r=compare_and_swap_full_i(&ivals[i], 0, 1); assert(r==1); }));
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/test_insert_unique.cc b/storage/tokudb/ft-index/ft/locking-benchmarks/trylock-rdtsc.cc
index 29439f9d704..235526640a1 100644
--- a/storage/tokudb/ft-index/src/tests/test_insert_unique.cc
+++ b/storage/tokudb/ft-index/ft/locking-benchmarks/trylock-rdtsc.cc
@@ -88,115 +88,160 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-/**
- * Test that unique inserts work correctly. This exercises the rightmost leaf inject optimization.
- */
-
-#include <portability/toku_random.h>
-
-#include "test.h"
-
-static char random_buf[8];
-static struct random_data random_data;
-
-static void test_simple_unique_insert(DB_ENV *env) {
- int r;
- DB *db;
- r = db_create(&db, env, 0); CKERR(r);
- r = db->open(db, NULL, "db", NULL, DB_BTREE, DB_CREATE, 0644); CKERR(r);
-
- DBT key1, key2, key3;
- dbt_init(&key1, "a", sizeof("a"));
- dbt_init(&key2, "b", sizeof("b"));
- dbt_init(&key3, "c", sizeof("c"));
- r = db->put(db, NULL, &key1, &key1, DB_NOOVERWRITE); CKERR(r);
- r = db->put(db, NULL, &key1, &key1, DB_NOOVERWRITE); CKERR2(r, DB_KEYEXIST);
- r = db->put(db, NULL, &key3, &key3, DB_NOOVERWRITE); CKERR(r);
- r = db->put(db, NULL, &key3, &key3, DB_NOOVERWRITE); CKERR2(r, DB_KEYEXIST);
- r = db->put(db, NULL, &key2, &key2, DB_NOOVERWRITE); CKERR(r);
- r = db->put(db, NULL, &key2, &key2, DB_NOOVERWRITE); CKERR2(r, DB_KEYEXIST);
- // sanity check
- r = db->put(db, NULL, &key1, &key1, DB_NOOVERWRITE); CKERR2(r, DB_KEYEXIST);
- r = db->put(db, NULL, &key1, &key3, DB_NOOVERWRITE); CKERR2(r, DB_KEYEXIST);
-
- r = db->close(db, 0); CKERR(r);
- r = env->dbremove(env, NULL, "db", NULL, 0); CKERR(r);
+/* Like trylock, except use rdstc */
+#define _MULTI_THREADED
+#include <pthread.h>
+#include <stdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <rdtsc.h>
+#include <portability/toku_atomic.h>
+
+float tdiff (struct timeval *start, struct timeval *end) {
+ return 1e6*(end->tv_sec-start->tv_sec) +(end->tv_usec - start->tv_usec);
}
-static void test_large_sequential_insert_unique(DB_ENV *env) {
- int r;
- DB *db;
- r = db_create(&db, env, 0); CKERR(r);
-
- // very small nodes/basements to make a taller tree
- r = db->set_pagesize(db, 8 * 1024); CKERR(r);
- r = db->set_readpagesize(db, 2 * 1024); CKERR(r);
- r = db->open(db, NULL, "db", NULL, DB_BTREE, DB_CREATE, 0644); CKERR(r);
-
- const int val_size = 1024;
- char *XMALLOC_N(val_size, val_buf);
- memset(val_buf, 'k', val_size);
- DBT val;
- dbt_init(&val, val_buf, val_size);
-
- // grow a tree to about depth 3, taking sanity checks along the way
- const int start_num_rows = (64 * 1024 * 1024) / val_size;
- for (int i = 0; i < start_num_rows; i++) {
- DBT key;
- int k = toku_htonl(i);
- dbt_init(&key, &k, sizeof(k));
- r = db->put(db, NULL, &key, &val, DB_NOOVERWRITE); CKERR(r);
- if (i % 50 == 0) {
- // sanity check - should not be able to insert this key twice in a row
- r = db->put(db, NULL, &key, &val, DB_NOOVERWRITE); CKERR2(r, DB_KEYEXIST);
-
- // .. but re-inserting is okay, if we provisionally deleted the row
- DB_TXN *txn;
- r = env->txn_begin(env, NULL, &txn, 0); CKERR(r);
- r = db->del(db, NULL, &key, DB_DELETE_ANY); CKERR(r);
- r = db->put(db, NULL, &key, &val, DB_NOOVERWRITE); CKERR(r);
- r = txn->commit(txn, 0); CKERR(r);
- }
- if (i > 0 && i % 250 == 0) {
- // sanity check - unique checks on random keys we already inserted should
- // fail (exercises middle-of-the-tree checks)
- for (int check_i = 0; check_i < 4; check_i++) {
- DBT rand_key;
- int rand_k = toku_htonl(myrandom_r(&random_data) % i);
- dbt_init(&rand_key, &rand_k, sizeof(rand_k));
- r = db->put(db, NULL, &rand_key, &val, DB_NOOVERWRITE); CKERR2(r, DB_KEYEXIST);
- }
- }
- }
-
- toku_free(val_buf);
- r = db->close(db, 0); CKERR(r);
- r = env->dbremove(env, NULL, "db", NULL, 0); CKERR(r);
+unsigned long long rtdiff (unsigned long long a, unsigned long long b) {
+ return (b-a);
}
+/* Simple function to check the return code and exit the program
+ if the function call failed
+ */
+static void compResults(char *string, int rc) {
+ if (rc) {
+ printf("Error on : %s, rc=%d",
+ string, rc);
+ exit(EXIT_FAILURE);
+ }
+ return;
+}
-int test_main(int argc, char * const argv[]) {
- default_parse_args(argc, argv);
-
- int r;
- const int envflags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD |
- DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN | DB_PRIVATE;
+pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
- // startup
- DB_ENV *env;
- toku_os_recursive_delete(TOKU_TEST_FILENAME);
- r = toku_os_mkdir(TOKU_TEST_FILENAME, 0755); CKERR(r);
- r = db_env_create(&env, 0); CKERR(r);
- r = env->open(env, TOKU_TEST_FILENAME, envflags, 0755);
+void *rdlockThread(void *arg __attribute__((unused)))
+{
+ int rc;
+ int count=0;
- r = myinitstate_r(random(), random_buf, 8, &random_data); CKERR(r);
+ unsigned long long t_start, t_end;
- test_simple_unique_insert(env);
- test_large_sequential_insert_unique(env);
+ printf("Entered thread, getting read lock with mp wait\n");
+ Retry:
- // cleanup
- r = env->close(env, 0); CKERR(r);
+ t_start = rdtsc();
+ rc = pthread_rwlock_tryrdlock(&rwlock);
+ t_end = rdtsc();
+ printf("pthread_rwlock_tryrdlock took %llu clocks\n", rtdiff(t_start,t_end));
+ if (rc == EBUSY) {
+ if (count >= 10) {
+ printf("Retried too many times, failure!\n");
- return 0;
+ exit(EXIT_FAILURE);
+ }
+ ++count;
+ printf("Could not get lock, do other work, then RETRY...\n");
+ sleep(1);
+ goto Retry;
+ }
+ compResults("pthread_rwlock_tryrdlock() 1\n", rc);
+
+ sleep(2);
+
+ printf("unlock the read lock\n");
+ t_start = rdtsc();
+ rc = pthread_rwlock_unlock(&rwlock);
+ t_end = rdtsc();
+ compResults("pthread_rwlock_unlock()\n", rc);
+ printf("Took %llu clocks\n", rtdiff(t_start, t_end));
+
+ printf("Secondary thread complete\n");
+ return NULL;
}
+int main(int argc __attribute__((unused)), char **argv)
+{
+ int rc=0;
+ pthread_t thread;
+ unsigned long long t_start, t_end;
+
+ printf("Enter Testcase - %s\n", argv[0]);
+
+ t_start = rdtsc();
+ t_end = rdtsc();
+ printf("nop Took %llu clocks\n", rtdiff(t_start, t_end));
+
+ {
+ int N=1000;
+ int i;
+ printf("Main, get and release the write lock %d times\n", N);
+ t_start = rdtsc();
+ for (i=0; i<N; i++) {
+ rc = pthread_rwlock_wrlock(&rwlock);
+ rc = pthread_rwlock_unlock(&rwlock);
+ }
+ t_end = rdtsc();
+ compResults("pthread_rwlock_wrlock()\n", rc);
+ printf("Took %5.2f clocks/op\n", ((double)(t_end-t_start))/N);
+ }
+
+ printf("Main, get the write lock\n");
+ t_start = rdtsc();
+ rc = pthread_rwlock_wrlock(&rwlock);
+ t_end = rdtsc();
+ compResults("pthread_rwlock_wrlock()\n", rc);
+ printf("Took %llu clocks\n", rtdiff(t_start, t_end));
+
+ printf("Main, create the try read lock thread\n");
+ rc = pthread_create(&thread, NULL, rdlockThread, NULL);
+ compResults("pthread_create\n", rc);
+
+ printf("Main, wait a bit holding the write lock\n");
+ sleep(5);
+
+ printf("Main, Now unlock the write lock\n");
+ t_start = rdtsc();
+ rc = pthread_rwlock_unlock(&rwlock);
+ t_end = rdtsc();
+ compResults("pthread_rwlock_unlock()\n", rc);
+ printf("Took %llu clocks\n", rtdiff(t_start, t_end));
+
+ printf("Main, wait for the thread to end\n");
+ rc = pthread_join(thread, NULL);
+ compResults("pthread_join\n", rc);
+
+ rc = pthread_rwlock_destroy(&rwlock);
+ compResults("pthread_rwlock_destroy()\n", rc);
+ printf("Main completed\n");
+
+
+ {
+ static int lock_for_lock_and_unlock;
+ t_start = rdtsc();
+ (void)toku_sync_lock_test_and_set(&lock_for_lock_and_unlock, 1);
+ t_end = rdtsc();
+ printf("sync_lock_test_and_set took %llu clocks\n", t_end-t_start);
+
+ t_start = rdtsc();
+ toku_sync_lock_release(&lock_for_lock_and_unlock);
+ t_end = rdtsc();
+ printf("sync_lock_release took %llu clocks\n", t_end-t_start);
+ }
+
+
+ {
+ t_start = rdtsc();
+ (void)toku_sync_synchronize();
+ t_end = rdtsc();
+ printf("sync_synchornize took %llu clocks\n", t_end-t_start);
+ }
+
+ t_start = rdtsc();
+ sleep(1);
+ t_end = rdtsc();
+ printf("sleep(1) took %llu clocks\n", t_end-t_start);
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/locking-benchmarks/trylock.cc b/storage/tokudb/ft-index/ft/locking-benchmarks/trylock.cc
new file mode 100644
index 00000000000..1b056c1a0a0
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/locking-benchmarks/trylock.cc
@@ -0,0 +1,213 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#define _MULTI_THREADED
+#include <pthread.h>
+#include <stdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+float tdiff (struct timeval *start, struct timeval *end) {
+ return 1e6*(end->tv_sec-start->tv_sec) +(end->tv_usec - start->tv_usec);
+}
+
+/* Simple function to check the return code and exit the program
+ if the function call failed
+ */
+static void compResults(char *string, int rc) {
+ if (rc) {
+ printf("Error on : %s, rc=%d",
+ string, rc);
+ exit(EXIT_FAILURE);
+ }
+ return;
+}
+
+pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+void *rdlockThread(void *arg __attribute__((unused)))
+{
+ int rc;
+ int count=0;
+
+ struct timeval start, end;
+
+ printf("Entered thread, getting read lock with mp wait\n");
+ Retry:
+
+ gettimeofday(&start, 0);
+ rc = pthread_rwlock_tryrdlock(&rwlock);
+ gettimeofday(&end, 0);
+ printf("pthread_rwlock_tryrdlock took %9.3fus\n", tdiff(&start,&end));
+ if (rc == EBUSY) {
+ if (count >= 10) {
+ printf("Retried too many times, failure!\n");
+
+ exit(EXIT_FAILURE);
+ }
+ ++count;
+ printf("Could not get lock, do other work, then RETRY...\n");
+ sleep(1);
+ goto Retry;
+ }
+ compResults("pthread_rwlock_tryrdlock() 1\n", rc);
+
+ sleep(2);
+
+ printf("unlock the read lock\n");
+ gettimeofday(&start, 0);
+ rc = pthread_rwlock_unlock(&rwlock);
+ gettimeofday(&end, 0);
+ compResults("pthread_rwlock_unlock()\n", rc);
+ printf("%lu.%6lu to %lu.%6lu is %9.2f\n", start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec, tdiff(&start, &end));
+
+ printf("Secondary thread complete\n");
+ return NULL;
+}
+
+int main(int argc __attribute__((unused)), char **argv)
+{
+ int rc=0;
+ pthread_t thread;
+ struct timeval start, end;
+
+ printf("Enter Testcase - %s\n", argv[0]);
+
+ gettimeofday(&start, 0);
+ gettimeofday(&end, 0);
+ printf("nop Took %9.2f\n", tdiff(&start, &end));
+
+ {
+ int N=1000;
+ int i;
+ printf("Main, get and release the write lock %d times\n", N);
+ gettimeofday(&start, 0);
+ for (i=0; i<N; i++) {
+ rc = pthread_rwlock_wrlock(&rwlock);
+ rc = pthread_rwlock_unlock(&rwlock);
+ }
+ gettimeofday(&end, 0);
+ compResults("pthread_rwlock_wrlock()\n", rc);
+ printf("Took %9.2fns/op\n", 1000*tdiff(&start, &end)/N);
+ }
+
+ printf("Main, get the write lock\n");
+ gettimeofday(&start, 0);
+ rc = pthread_rwlock_wrlock(&rwlock);
+ gettimeofday(&end, 0);
+ compResults("pthread_rwlock_wrlock()\n", rc);
+ printf("Took %9.2f\n", tdiff(&start, &end));
+
+ printf("Main, create the try read lock thread\n");
+ rc = pthread_create(&thread, NULL, rdlockThread, NULL);
+ compResults("pthread_create\n", rc);
+
+ printf("Main, wait a bit holding the write lock\n");
+ sleep(5);
+
+ printf("Main, Now unlock the write lock\n");
+ gettimeofday(&start, 0);
+ rc = pthread_rwlock_unlock(&rwlock);
+ gettimeofday(&end, 0);
+ compResults("pthread_rwlock_unlock()\n", rc);
+ printf("Took %9.2f\n", tdiff(&start, &end));
+
+ printf("Main, wait for the thread to end\n");
+ rc = pthread_join(thread, NULL);
+ compResults("pthread_join\n", rc);
+
+ rc = pthread_rwlock_destroy(&rwlock);
+ compResults("pthread_rwlock_destroy()\n", rc);
+ printf("Main completed\n");
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/log-internal.h b/storage/tokudb/ft-index/ft/log-internal.h
index be8ab7a53da..de2abe801dc 100644
--- a/storage/tokudb/ft-index/ft/log-internal.h
+++ b/storage/tokudb/ft-index/ft/log-internal.h
@@ -99,16 +99,14 @@ PATENT RIGHTS GRANT:
#include "ft-internal.h"
#include "log.h"
#include "toku_list.h"
+#include "memarena.h"
#include "logfilemgr.h"
#include "txn.h"
#include "txn_manager.h"
-#include "rollback_log_node_cache.h"
-#include "txn_child_manager.h"
-
#include <portability/toku_pthread.h>
-
-#include <util/memarena.h>
#include <util/omt.h>
+#include "rollback_log_node_cache.h"
+#include "txn_child_manager.h"
using namespace toku;
// Locking for the logger
diff --git a/storage/tokudb/ft-index/ft/log.h b/storage/tokudb/ft-index/ft/log.h
index 18ba802df6d..418fc834751 100644
--- a/storage/tokudb/ft-index/ft/log.h
+++ b/storage/tokudb/ft-index/ft/log.h
@@ -94,17 +94,19 @@ PATENT RIGHTS GRANT:
#include <toku_portability.h>
#include <errno.h>
-#include <db.h>
+#include <db.h>
#include "fttypes.h"
#include "memory.h"
+#include "x1764.h"
+
+struct roll_entry;
+
#include "logger.h"
#include "rollback.h"
#include "recover.h"
#include "txn.h"
-struct roll_entry;
-
static inline int toku_copy_BYTESTRING(BYTESTRING *target, BYTESTRING val) {
target->len = val.len;
target->data = (char *) toku_memdup(val.data, (size_t)val.len);
@@ -115,7 +117,6 @@ static inline int toku_copy_BYTESTRING(BYTESTRING *target, BYTESTRING val) {
}
static inline void toku_free_TXNID(TXNID txnid __attribute__((__unused__))) {}
static inline void toku_free_TXNID_PAIR(TXNID_PAIR txnid __attribute__((__unused__))) {}
-
static inline void toku_free_LSN(LSN lsn __attribute__((__unused__))) {}
static inline void toku_free_uint64_t(uint64_t u __attribute__((__unused__))) {}
static inline void toku_free_uint32_t(uint32_t u __attribute__((__unused__))) {}
diff --git a/storage/tokudb/ft-index/ft/log_upgrade.cc b/storage/tokudb/ft-index/ft/log_upgrade.cc
index 8dba57e9d8d..31dbdb04d7e 100644
--- a/storage/tokudb/ft-index/ft/log_upgrade.cc
+++ b/storage/tokudb/ft-index/ft/log_upgrade.cc
@@ -321,8 +321,8 @@ toku_maybe_upgrade_log(const char *env_dir, const char *log_dir, LSN * lsn_of_cl
r = 0; //Logs are up to date
else {
FOOTPRINT(4);
- LSN last_lsn = ZERO_LSN;
- TXNID last_xid = TXNID_NONE;
+ LSN last_lsn= ZERO_LSN;
+ TXNID last_xid;
r = verify_clean_shutdown_of_log_version(log_dir, version_of_logs_on_disk, &last_lsn, &last_xid);
if (r != 0) {
goto cleanup;
diff --git a/storage/tokudb/ft-index/ft/logcursor.cc b/storage/tokudb/ft-index/ft/logcursor.cc
index 384582e000a..42be3e7514f 100644
--- a/storage/tokudb/ft-index/ft/logcursor.cc
+++ b/storage/tokudb/ft-index/ft/logcursor.cc
@@ -167,8 +167,11 @@ static int lc_open_logfile(TOKULOGCURSOR lc, int index) {
lc->cur_fp = fopen(lc->logfiles[index], "rb");
if ( lc->cur_fp == NULL )
return DB_NOTFOUND;
+ // debug printf("%s:%d %s %p %u\n", __FUNCTION__, __LINE__, lc->logfiles[index], lc->buffer, (unsigned) lc->buffer_size);
+#if !TOKU_WINDOWS //Windows reads logs fastest if we use default settings (not use setvbuf to change buffering)
r = setvbuf(lc->cur_fp, (char *) lc->buffer, _IOFBF, lc->buffer_size);
assert(r == 0);
+#endif
// position fp past header, ignore 0 length file (t:2384)
unsigned int version=0;
if ( lc_file_len(lc->logfiles[index]) >= 12 ) {
diff --git a/storage/tokudb/ft-index/ft/logformat.cc b/storage/tokudb/ft-index/ft/logformat.cc
index 4d32d9f6eac..aceedec4c5e 100644
--- a/storage/tokudb/ft-index/ft/logformat.cc
+++ b/storage/tokudb/ft-index/ft/logformat.cc
@@ -536,7 +536,7 @@ generate_log_writer (void) {
if (strcmp(field_type->name, "timestamp") == 0)
fprintf(cf, " if (timestamp == 0) timestamp = toku_get_timestamp();\n");
fprintf(cf, " wbuf_nocrc_%s(&wbuf, %s);\n", field_type->type, field_type->name));
- fprintf(cf, " wbuf_nocrc_int(&wbuf, toku_x1764_memory(wbuf.buf, wbuf.ndone));\n");
+ fprintf(cf, " wbuf_nocrc_int(&wbuf, x1764_memory(wbuf.buf, wbuf.ndone));\n");
fprintf(cf, " wbuf_nocrc_int(&wbuf, buflen);\n");
fprintf(cf, " assert(wbuf.ndone==buflen);\n");
fprintf(cf, " logger->inbuf.n_in_buf += buflen;\n");
@@ -558,7 +558,7 @@ generate_log_reader (void) {
fprintf(cf, " uint32_t checksum_in_file, len_in_file;\n");
fprintf(cf, " r=toku_fread_uint32_t_nocrclen(infile, &checksum_in_file); actual_len+=4; if (r!=0) return r;\n");
fprintf(cf, " r=toku_fread_uint32_t_nocrclen(infile, &len_in_file); actual_len+=4; if (r!=0) return r;\n");
- fprintf(cf, " if (checksum_in_file!=toku_x1764_finish(checksum) || len_in_file!=actual_len || len1 != len_in_file) return DB_BADFORMAT;\n");
+ fprintf(cf, " if (checksum_in_file!=x1764_finish(checksum) || len_in_file!=actual_len || len1 != len_in_file) return DB_BADFORMAT;\n");
fprintf(cf, " return 0;\n");
fprintf(cf, "}\n\n");
});
@@ -568,12 +568,12 @@ generate_log_reader (void) {
fprintf(cf, " uint32_t len1; int r;\n");
fprintf(cf, " uint32_t ignorelen=0;\n");
fprintf(cf, " struct x1764 checksum;\n");
- fprintf(cf, " toku_x1764_init(&checksum);\n");
+ fprintf(cf, " x1764_init(&checksum);\n");
fprintf(cf, " r = toku_fread_uint32_t(infile, &len1, &checksum, &ignorelen); if (r!=0) return r;\n");
fprintf(cf, " int cmd=fgetc(infile);\n");
fprintf(cf, " if (cmd==EOF) return EOF;\n");
fprintf(cf, " char cmdchar = (char)cmd;\n");
- fprintf(cf, " toku_x1764_add(&checksum, &cmdchar, 1);\n");
+ fprintf(cf, " x1764_add(&checksum, &cmdchar, 1);\n");
fprintf(cf, " le->cmd=(enum lt_cmd)cmd;\n");
fprintf(cf, " switch ((enum lt_cmd)cmd) {\n");
DO_LOGTYPES(lt, {
@@ -639,14 +639,14 @@ generate_logprint (void) {
fprintf(pf, " uint32_t len1, crc_in_file;\n");
fprintf(pf, " uint32_t ignorelen=0;\n");
fprintf(pf, " struct x1764 checksum;\n");
- fprintf(pf, " toku_x1764_init(&checksum);\n");
+ fprintf(pf, " x1764_init(&checksum);\n");
fprintf(pf, " r=toku_fread_uint32_t(f, &len1, &checksum, &ignorelen);\n");
fprintf(pf, " if (r==EOF) return EOF;\n");
fprintf(pf, " cmd=fgetc(f);\n");
fprintf(pf, " if (cmd==EOF) return DB_BADFORMAT;\n");
fprintf(pf, " uint32_t len_in_file, len=1+4; // cmd + len1\n");
fprintf(pf, " char charcmd = (char)cmd;\n");
- fprintf(pf, " toku_x1764_add(&checksum, &charcmd, 1);\n");
+ fprintf(pf, " x1764_add(&checksum, &charcmd, 1);\n");
fprintf(pf, " switch ((enum lt_cmd)cmd) {\n");
DO_LOGTYPES(lt, { if (strlen(lt->name)>maxnamelen) maxnamelen=strlen(lt->name); });
DO_LOGTYPES(lt, {
@@ -664,7 +664,7 @@ generate_logprint (void) {
fprintf(pf, "); if (r!=0) return r;\n");
});
fprintf(pf, " {\n");
- fprintf(pf, " uint32_t actual_murmur = toku_x1764_finish(&checksum);\n");
+ fprintf(pf, " uint32_t actual_murmur = x1764_finish(&checksum);\n");
fprintf(pf, " r = toku_fread_uint32_t_nocrclen (f, &crc_in_file); len+=4; if (r!=0) return r;\n");
fprintf(pf, " fprintf(outf, \" crc=%%08x\", crc_in_file);\n");
fprintf(pf, " if (crc_in_file!=actual_murmur) fprintf(outf, \" checksum=%%08x\", actual_murmur);\n");
@@ -806,7 +806,7 @@ generate_rollbacks (void) {
DO_ROLLBACKS(lt, {
fprintf(cf, " case RT_%s:\n", lt->name);
fprintf(cf, " mem_needed = sizeof(item->u.%s) + __builtin_offsetof(struct roll_entry, u.%s);\n", lt->name, lt->name);
- fprintf(cf, " CAST_FROM_VOIDP(item, toku_memarena_malloc(ma, mem_needed));\n");
+ fprintf(cf, " CAST_FROM_VOIDP(item, malloc_in_memarena(ma, mem_needed));\n");
fprintf(cf, " item->cmd = cmd;\n");
DO_FIELDS(field_type, lt, fprintf(cf, " rbuf_ma_%s(&rc, ma, &item->u.%s.%s);\n", field_type->type, lt->name, field_type->name));
fprintf(cf, " *itemp = item;\n");
@@ -858,7 +858,7 @@ int main (int argc, const char *const argv[]) {
fprintf2(cf, pf, "#include <ft/fttypes.h>\n");
fprintf2(cf, pf, "#include <ft/log-internal.h>\n");
fprintf(hf, "#include <ft/ft-internal.h>\n");
- fprintf(hf, "#include <util/memarena.h>\n");
+ fprintf(hf, "#include <ft/memarena.h>\n");
generate_enum();
generate_log_struct();
generate_dispatch();
diff --git a/storage/tokudb/ft-index/ft/logger.cc b/storage/tokudb/ft-index/ft/logger.cc
index bbac5cf7de3..4d1872d19a5 100644
--- a/storage/tokudb/ft-index/ft/logger.cc
+++ b/storage/tokudb/ft-index/ft/logger.cc
@@ -98,7 +98,7 @@ PATENT RIGHTS GRANT:
#include "log-internal.h"
#include "txn_manager.h"
#include "rollback_log_node_cache.h"
-
+#include "huge_page_detection.h"
#include <util/status.h>
static const int log_format_version=TOKU_LOG_VERSION;
@@ -151,8 +151,8 @@ static bool is_a_logfile_any_version (const char *name, uint64_t *number_result,
// added for #2424, improved for #2521
static bool is_a_logfile (const char *name, long long *number_result) {
bool rval;
- uint64_t result;
- uint32_t version;
+ uint64_t result= 0;
+ uint32_t version= 0;
rval = is_a_logfile_any_version(name, &result, &version);
if (rval && version != TOKU_LOG_VERSION)
rval = false;
@@ -164,6 +164,11 @@ static bool is_a_logfile (const char *name, long long *number_result) {
// TODO: can't fail
int toku_logger_create (TOKULOGGER *resultp) {
+ if (complain_and_return_true_if_huge_pages_are_enabled()) {
+ *resultp = NULL;
+ errno = TOKUDB_HUGE_PAGES_ENABLED;
+ return TOKUDB_HUGE_PAGES_ENABLED;
+ }
TOKULOGGER CALLOC(result);
if (result==0) return get_error_errno();
result->is_open=false;
@@ -182,7 +187,7 @@ int toku_logger_create (TOKULOGGER *resultp) {
result->last_completed_checkpoint_lsn = ZERO_LSN;
// next_log_file_number is uninitialized
// n_in_file is uninitialized
- result->write_block_size = FT_DEFAULT_NODE_SIZE; // default logging size is the same as the default ft block size
+ result->write_block_size = FT_DEFAULT_NODE_SIZE; // default logging size is the same as the default brt block size
toku_logfilemgr_create(&result->logfilemgr);
*resultp=result;
ml_init(&result->input_lock);
@@ -229,7 +234,7 @@ toku_logger_open_with_last_xid(const char *directory, TOKULOGGER logger, TXNID l
if (logger->is_open) return EINVAL;
int r;
- TXNID last_xid_if_clean_shutdown = TXNID_NONE;
+ TXNID last_xid_if_clean_shutdown= TXNID_NONE;
r = toku_logfilemgr_init(logger->logfilemgr, directory, &last_xid_if_clean_shutdown);
if ( r!=0 )
return r;
@@ -280,7 +285,7 @@ toku_logger_open_rollback(TOKULOGGER logger, CACHETABLE cachetable, bool create)
assert(logger->is_open);
assert(!logger->rollback_cachefile);
- FT_HANDLE t = NULL; // Note, there is no DB associated with this FT.
+ FT_HANDLE t = NULL; // Note, there is no DB associated with this BRT.
toku_ft_handle_create(&t);
int r = toku_ft_handle_open(t, toku_product_name_strings.rollback_cachefile, create, create, cachetable, NULL_TXN);
if (r == 0) {
@@ -304,26 +309,30 @@ toku_logger_open_rollback(TOKULOGGER logger, CACHETABLE cachetable, bool create)
// so it will always be clean (!h->dirty) when about to be closed.
// Rollback log can only be closed when there are no open transactions,
// so it will always be empty (no data blocks) when about to be closed.
-void toku_logger_close_rollback(TOKULOGGER logger) {
+void toku_logger_close_rollback_check_empty(TOKULOGGER logger, bool clean_shutdown) {
CACHEFILE cf = logger->rollback_cachefile; // stored in logger at rollback cachefile open
if (cf) {
FT_HANDLE ft_to_close;
- { //Find "ft_to_close"
+ { //Find "brt"
logger->rollback_cache.destroy();
FT CAST_FROM_VOIDP(ft, toku_cachefile_get_userdata(cf));
- //Verify it is safe to close it.
- assert(!ft->h->dirty); //Must not be dirty.
- toku_free_unused_blocknums(ft->blocktable, ft->h->root_blocknum);
- //Must have no data blocks (rollback logs or otherwise).
- toku_block_verify_no_data_blocks_except_root(ft->blocktable, ft->h->root_blocknum);
- assert(!ft->h->dirty);
+ if (clean_shutdown) {
+ //Verify it is safe to close it.
+ assert(!ft->h->dirty); //Must not be dirty.
+ toku_free_unused_blocknums(ft->blocktable, ft->h->root_blocknum);
+ //Must have no data blocks (rollback logs or otherwise).
+ toku_block_verify_no_data_blocks_except_root(ft->blocktable, ft->h->root_blocknum);
+ assert(!ft->h->dirty);
+ } else {
+ ft->h->dirty = 0;
+ }
ft_to_close = toku_ft_get_only_existing_ft_handle(ft);
- {
+ if (clean_shutdown) {
bool is_empty;
is_empty = toku_ft_is_empty_fast(ft_to_close);
assert(is_empty);
+ assert(!ft->h->dirty); // it should not have been dirtied by the toku_ft_is_empty test.
}
- assert(!ft->h->dirty); // it should not have been dirtied by the toku_ft_is_empty test.
}
toku_ft_handle_close(ft_to_close);
@@ -332,6 +341,10 @@ void toku_logger_close_rollback(TOKULOGGER logger) {
}
}
+void toku_logger_close_rollback(TOKULOGGER logger) {
+ toku_logger_close_rollback_check_empty(logger, true);
+}
+
// No locks held on entry
// No locks held on exit.
// No locks are needed, since you cannot legally close the log concurrently with doing anything else.
@@ -621,7 +634,7 @@ int toku_logger_find_next_unused_log_file(const char *directory, long long *resu
if (d==0) return get_error_errno();
while ((de=readdir(d))) {
if (de==0) return get_error_errno();
- long long thisl = -1;
+ long long thisl;
if ( is_a_logfile(de->d_name, &thisl) ) {
if ((long long)thisl > maxf) maxf = thisl;
}
@@ -717,7 +730,7 @@ static int open_logfile (TOKULOGGER logger)
snprintf(fname, fnamelen, "%s/log%012lld.tokulog%d", logger->directory, logger->next_log_file_number, TOKU_LOG_VERSION);
long long index = logger->next_log_file_number;
if (logger->write_log_files) {
- logger->fd = open(fname, O_CREAT+O_WRONLY+O_TRUNC+O_EXCL+O_BINARY, S_IRWXU);
+ logger->fd = open(fname, O_CREAT+O_WRONLY+O_TRUNC+O_EXCL+O_BINARY, S_IRUSR+S_IWUSR);
if (logger->fd==-1) {
return get_error_errno();
}
@@ -933,7 +946,7 @@ int toku_fread_uint8_t (FILE *f, uint8_t *v, struct x1764 *mm, uint32_t *len) {
int vi=fgetc(f);
if (vi==EOF) return -1;
uint8_t vc=(uint8_t)vi;
- toku_x1764_add(mm, &vc, 1);
+ x1764_add(mm, &vc, 1);
(*len)++;
*v = vc;
return 0;
@@ -998,8 +1011,8 @@ int toku_fread_TXNID (FILE *f, TXNID *txnid, struct x1764 *checksum, uint32_t
}
int toku_fread_TXNID_PAIR (FILE *f, TXNID_PAIR *txnid, struct x1764 *checksum, uint32_t *len) {
- TXNID parent;
- TXNID child;
+ TXNID parent= TXNID_NONE;
+ TXNID child= TXNID_NONE;
int r;
r = toku_fread_TXNID(f, &parent, checksum, len); if (r != 0) { return r; }
r = toku_fread_TXNID(f, &child, checksum, len); if (r != 0) { return r; }
@@ -1281,7 +1294,7 @@ static int peek_at_log (TOKULOGGER logger, char* filename, LSN *first_lsn) {
if (logger->write_log_files) printf("couldn't open: %s\n", strerror(er));
return er;
}
- enum { SKIP = 12+1+4 }; // read the 12 byte header, the first message, and the first len
+ enum { SKIP = 12+1+4 }; // read the 12 byte header, the first cmd, and the first len
unsigned char header[SKIP+8];
int r = read(fd, header, SKIP+8);
if (r!=SKIP+8) return 0; // cannot determine that it's archivable, so we'll assume no. If a later-log is archivable is then this one will be too.
diff --git a/storage/tokudb/ft-index/ft/logger.h b/storage/tokudb/ft-index/ft/logger.h
index 6488ec0707d..acbb5961d1e 100644
--- a/storage/tokudb/ft-index/ft/logger.h
+++ b/storage/tokudb/ft-index/ft/logger.h
@@ -112,6 +112,7 @@ int toku_logger_close(TOKULOGGER *loggerp);
void toku_logger_initialize_rollback_cache(TOKULOGGER logger, FT ft);
int toku_logger_open_rollback(TOKULOGGER logger, CACHETABLE cachetable, bool create);
void toku_logger_close_rollback(TOKULOGGER logger);
+void toku_logger_close_rollback_check_empty(TOKULOGGER logger, bool clean_shutdown);
bool toku_logger_rollback_is_open (TOKULOGGER); // return true iff the rollback is open.
void toku_logger_fsync (TOKULOGGER logger);
diff --git a/storage/tokudb/ft-index/util/memarena.cc b/storage/tokudb/ft-index/ft/memarena.cc
index 773c949e8f4..0edb51370bc 100644
--- a/storage/tokudb/ft-index/util/memarena.cc
+++ b/storage/tokudb/ft-index/ft/memarena.cc
@@ -92,34 +92,32 @@ PATENT RIGHTS GRANT:
#include <string.h>
#include <memory.h>
-#include <util/memarena.h>
+#include "memarena.h"
struct memarena {
char *buf;
size_t buf_used, buf_size;
size_t size_of_other_bufs; // the buf_size of all the other bufs.
- size_t footprint_of_other_bufs; // the footprint of all the other bufs.
char **other_bufs;
int n_other_bufs;
};
-MEMARENA toku_memarena_create_presized (size_t initial_size) {
+MEMARENA memarena_create_presized (size_t initial_size) {
MEMARENA XMALLOC(result);
result->buf_size = initial_size;
result->buf_used = 0;
result->other_bufs = NULL;
result->size_of_other_bufs = 0;
- result->footprint_of_other_bufs = 0;
result->n_other_bufs = 0;
XMALLOC_N(result->buf_size, result->buf);
return result;
}
-MEMARENA toku_memarena_create (void) {
- return toku_memarena_create_presized(1024);
+MEMARENA memarena_create (void) {
+ return memarena_create_presized(1024);
}
-void toku_memarena_clear (MEMARENA ma) {
+void memarena_clear (MEMARENA ma) {
// Free the other bufs.
int i;
for (i=0; i<ma->n_other_bufs; i++) {
@@ -130,7 +128,6 @@ void toku_memarena_clear (MEMARENA ma) {
// But reuse the main buffer
ma->buf_used = 0;
ma->size_of_other_bufs = 0;
- ma->footprint_of_other_bufs = 0;
}
static size_t
@@ -143,7 +140,7 @@ round_to_page (size_t size) {
return result;
}
-void* toku_memarena_malloc (MEMARENA ma, size_t size) {
+void* malloc_in_memarena (MEMARENA ma, size_t size) {
if (ma->buf_size < ma->buf_used + size) {
// The existing block isn't big enough.
// Add the block to the vector of blocks.
@@ -154,7 +151,6 @@ void* toku_memarena_malloc (MEMARENA ma, size_t size) {
ma->other_bufs[old_n]=ma->buf;
ma->n_other_bufs = old_n+1;
ma->size_of_other_bufs += ma->buf_size;
- ma->footprint_of_other_bufs += toku_memory_footprint(ma->buf, ma->buf_used);
}
// Make a new one
{
@@ -172,13 +168,13 @@ void* toku_memarena_malloc (MEMARENA ma, size_t size) {
return result;
}
-void *toku_memarena_memdup (MEMARENA ma, const void *v, size_t len) {
- void *r=toku_memarena_malloc(ma, len);
+void *memarena_memdup (MEMARENA ma, const void *v, size_t len) {
+ void *r=malloc_in_memarena(ma, len);
memcpy(r,v,len);
return r;
}
-void toku_memarena_destroy(MEMARENA *map) {
+void memarena_close(MEMARENA *map) {
MEMARENA ma=*map;
if (ma->buf) {
toku_free(ma->buf);
@@ -195,17 +191,33 @@ void toku_memarena_destroy(MEMARENA *map) {
*map = 0;
}
-void toku_memarena_move_buffers(MEMARENA dest, MEMARENA source) {
+#if TOKU_WINDOWS_32
+#include <windows.h>
+#include <crtdbg.h>
+#endif
+
+void memarena_move_buffers(MEMARENA dest, MEMARENA source) {
int i;
char **other_bufs = dest->other_bufs;
static int move_counter = 0;
move_counter++;
REALLOC_N(dest->n_other_bufs + source->n_other_bufs + 1, other_bufs);
+#if TOKU_WINDOWS_32
+ if (other_bufs == 0) {
+ char **new_other_bufs;
+ printf("_CrtCheckMemory:%d\n", _CrtCheckMemory());
+ printf("Z: move_counter:%d dest:%p %p %d source:%p %p %d errno:%d\n",
+ move_counter,
+ dest, dest->other_bufs, dest->n_other_bufs,
+ source, source->other_bufs, source->n_other_bufs,
+ errno);
+ new_other_bufs = toku_malloc((dest->n_other_bufs + source->n_other_bufs + 1)*sizeof (char **));
+ printf("new_other_bufs=%p errno=%d\n", new_other_bufs, errno);
+ }
+#endif
dest ->size_of_other_bufs += source->size_of_other_bufs + source->buf_size;
- dest ->footprint_of_other_bufs += source->footprint_of_other_bufs + toku_memory_footprint(source->buf, source->buf_used);
source->size_of_other_bufs = 0;
- source->footprint_of_other_bufs = 0;
assert(other_bufs);
dest->other_bufs = other_bufs;
@@ -223,23 +235,15 @@ void toku_memarena_move_buffers(MEMARENA dest, MEMARENA source) {
}
size_t
-toku_memarena_total_memory_size (MEMARENA m)
+memarena_total_memory_size (MEMARENA m)
{
- return (toku_memarena_total_size_in_use(m) +
+ return (memarena_total_size_in_use(m) +
sizeof(*m) +
m->n_other_bufs * sizeof(*m->other_bufs));
}
size_t
-toku_memarena_total_size_in_use (MEMARENA m)
+memarena_total_size_in_use (MEMARENA m)
{
return m->size_of_other_bufs + m->buf_used;
-}
-
-size_t
-toku_memarena_total_footprint (MEMARENA m)
-{
- return m->footprint_of_other_bufs + toku_memory_footprint(m->buf, m->buf_used) +
- sizeof(*m) +
- m->n_other_bufs * sizeof(*m->other_bufs);
-}
+}
diff --git a/storage/tokudb/ft-index/util/memarena.h b/storage/tokudb/ft-index/ft/memarena.h
index 0dac262ba46..949521cfd06 100644
--- a/storage/tokudb/ft-index/util/memarena.h
+++ b/storage/tokudb/ft-index/ft/memarena.h
@@ -102,35 +102,32 @@ PATENT RIGHTS GRANT:
* A memarena (as currently implemented) is not suitable for interprocess memory sharing. No reason it couldn't be made to work though.
*/
-struct memarena;
+#include "fttypes.h"
-typedef struct memarena *MEMARENA;
-
-MEMARENA toku_memarena_create_presized (size_t initial_size);
+MEMARENA memarena_create_presized (size_t initial_size);
// Effect: Create a memarena with initial size. In case of ENOMEM, aborts.
-MEMARENA toku_memarena_create (void);
+MEMARENA memarena_create (void);
// Effect: Create a memarena with default initial size. In case of ENOMEM, aborts.
-void toku_memarena_clear (MEMARENA ma);
+void memarena_clear (MEMARENA ma);
// Effect: Reset the internal state so that the allocated memory can be used again.
-void* toku_memarena_malloc (MEMARENA ma, size_t size);
+void* malloc_in_memarena (MEMARENA ma, size_t size);
// Effect: Allocate some memory. The returned value remains valid until the memarena is cleared or closed.
// In case of ENOMEM, aborts.
-void *toku_memarena_memdup (MEMARENA ma, const void *v, size_t len);
+void *memarena_memdup (MEMARENA ma, const void *v, size_t len);
-void toku_memarena_destroy(MEMARENA *ma);
+void memarena_close(MEMARENA *ma);
-void toku_memarena_move_buffers(MEMARENA dest, MEMARENA source);
+void memarena_move_buffers(MEMARENA dest, MEMARENA source);
// Effect: Move all the memory from SOURCE into DEST. When SOURCE is closed the memory won't be freed. When DEST is closed, the memory will be freed. (Unless DEST moves its memory to another memarena...)
-size_t toku_memarena_total_memory_size (MEMARENA);
+size_t memarena_total_memory_size (MEMARENA);
// Effect: Calculate the amount of memory used by a memory arena.
-size_t toku_memarena_total_size_in_use (MEMARENA);
+size_t memarena_total_size_in_use (MEMARENA);
-size_t toku_memarena_total_footprint (MEMARENA);
#endif
diff --git a/storage/tokudb/ft-index/ft/omt.cc b/storage/tokudb/ft-index/ft/omt.cc
new file mode 100644
index 00000000000..0e529476330
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/omt.cc
@@ -0,0 +1,230 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+
+#include <toku_portability.h>
+#include <memory.h>
+#include <string.h>
+#include <db.h>
+
+#include "omt.h"
+
+int
+toku_omt_create_steal_sorted_array(OMT *omtp, OMTVALUE **valuesp, uint32_t numvalues, uint32_t capacity) {
+ OMT XMALLOC(omt);
+ omt->create_steal_sorted_array(valuesp, numvalues, capacity);
+ *omtp = omt;
+ return 0;
+}
+
+//TODO: Put all omt API functions here.
+int toku_omt_create (OMT *omtp) {
+ OMT XMALLOC(omt);
+ omt->create();
+ *omtp = omt;
+ return 0;
+}
+
+void toku_omt_destroy(OMT *omtp) {
+ OMT omt=*omtp;
+ omt->destroy();
+ toku_free(omt);
+ *omtp=NULL;
+}
+
+uint32_t toku_omt_size(OMT V) {
+ return V->size();
+}
+
+int toku_omt_create_from_sorted_array(OMT *omtp, OMTVALUE *values, uint32_t numvalues) {
+ OMT XMALLOC(omt);
+ omt->create_from_sorted_array(values, numvalues);
+ *omtp=omt;
+ return 0;
+}
+
+int toku_omt_insert_at(OMT omt, OMTVALUE value, uint32_t index) {
+ return omt->insert_at(value, index);
+}
+
+int toku_omt_set_at (OMT omt, OMTVALUE value, uint32_t index) {
+ return omt->set_at(value, index);
+}
+
+int toku_omt_delete_at(OMT omt, uint32_t index) {
+ return omt->delete_at(index);
+}
+
+int toku_omt_fetch(OMT omt, uint32_t i, OMTVALUE *v) {
+ return omt->fetch(i, v);
+}
+
+struct functor {
+ int (*f)(OMTVALUE, uint32_t, void *);
+ void *v;
+};
+static_assert(std::is_pod<functor>::value, "not POD");
+
+int call_functor(const OMTVALUE &v, uint32_t idx, functor *const ftor);
+int call_functor(const OMTVALUE &v, uint32_t idx, functor *const ftor) {
+ return ftor->f(const_cast<OMTVALUE>(v), idx, ftor->v);
+}
+
+int toku_omt_iterate(OMT omt, int (*f)(OMTVALUE, uint32_t, void*), void*v) {
+ struct functor ftor = { .f = f, .v = v };
+ return omt->iterate<functor, call_functor>(&ftor);
+}
+
+int toku_omt_iterate_on_range(OMT omt, uint32_t left, uint32_t right, int (*f)(OMTVALUE, uint32_t, void*), void*v) {
+ struct functor ftor = { .f = f, .v = v };
+ return omt->iterate_on_range<functor, call_functor>(left, right, &ftor);
+}
+
+struct heftor {
+ int (*h)(OMTVALUE, void *v);
+ void *v;
+};
+static_assert(std::is_pod<heftor>::value, "not POD");
+
+int call_heftor(const OMTVALUE &v, const heftor &htor);
+int call_heftor(const OMTVALUE &v, const heftor &htor) {
+ return htor.h(const_cast<OMTVALUE>(v), htor.v);
+}
+
+int toku_omt_insert(OMT omt, OMTVALUE value, int(*h)(OMTVALUE, void*v), void *v, uint32_t *index) {
+ struct heftor htor = { .h = h, .v = v };
+ return omt->insert<heftor, call_heftor>(value, htor, index);
+}
+
+int toku_omt_find_zero(OMT V, int (*h)(OMTVALUE, void*extra), void*extra, OMTVALUE *value, uint32_t *index) {
+ struct heftor htor = { .h = h, .v = extra };
+ return V->find_zero<heftor, call_heftor>(htor, value, index);
+}
+
+int toku_omt_find(OMT V, int (*h)(OMTVALUE, void*extra), void*extra, int direction, OMTVALUE *value, uint32_t *index) {
+ struct heftor htor = { .h = h, .v = extra };
+ return V->find<heftor, call_heftor>(htor, direction, value, index);
+}
+
+int toku_omt_split_at(OMT omt, OMT *newomtp, uint32_t index) {
+ OMT XMALLOC(newomt);
+ int r = omt->split_at(newomt, index);
+ if (r != 0) {
+ toku_free(newomt);
+ } else {
+ *newomtp = newomt;
+ }
+ return r;
+}
+
+int toku_omt_merge(OMT leftomt, OMT rightomt, OMT *newomtp) {
+ OMT XMALLOC(newomt);
+ newomt->merge(leftomt, rightomt);
+ toku_free(leftomt);
+ toku_free(rightomt);
+ *newomtp = newomt;
+ return 0;
+}
+
+int toku_omt_clone_noptr(OMT *dest, OMT src) {
+ OMT XMALLOC(omt);
+ omt->clone(*src);
+ *dest = omt;
+ return 0;
+}
+
+void toku_omt_clear(OMT omt) {
+ omt->clear();
+}
+
+size_t toku_omt_memory_size (OMT omt) {
+ return omt->memory_size();
+}
+
diff --git a/storage/tokudb/ft-index/ft/omt.h b/storage/tokudb/ft-index/ft/omt.h
new file mode 100644
index 00000000000..b8f87790bd3
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/omt.h
@@ -0,0 +1,416 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#if !defined(TOKU_OMT_H)
+#define TOKU_OMT_H
+
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+
+
+// Order Maintenance Tree (OMT)
+//
+// Maintains a collection of totally ordered values, where each value has an integer weight.
+// The OMT is a mutable datatype.
+//
+// The Abstraction:
+//
+// An OMT is a vector of values, $V$, where $|V|$ is the length of the vector.
+// The vector is numbered from $0$ to $|V|-1$.
+// Each value has a weight. The weight of the $i$th element is denoted $w(V_i)$.
+//
+// We can create a new OMT, which is the empty vector.
+//
+// We can insert a new element $x$ into slot $i$, changing $V$ into $V'$ where
+// $|V'|=1+|V|$ and
+//
+// V'_j = V_j if $j<i$
+// x if $j=i$
+// V_{j-1} if $j>i$.
+//
+// We can specify $i$ using a kind of function instead of as an integer.
+// Let $b$ be a function mapping from values to nonzero integers, such that
+// the signum of $b$ is monotically increasing.
+// We can specify $i$ as the minimum integer such that $b(V_i)>0$.
+//
+// We look up a value using its index, or using a Heaviside function.
+// For lookups, we allow $b$ to be zero for some values, and again the signum of $b$ must be monotonically increasing.
+// When lookup up values, we can look up
+// $V_i$ where $i$ is the minimum integer such that $b(V_i)=0$. (With a special return code if no such value exists.)
+// (Rationale: Ordinarily we want $i$ to be unique. But for various reasons we want to allow multiple zeros, and we want the smallest $i$ in that case.)
+// $V_i$ where $i$ is the minimum integer such that $b(V_i)>0$. (Or an indication that no such value exists.)
+// $V_i$ where $i$ is the maximum integer such that $b(V_i)<0$. (Or an indication that no such value exists.)
+//
+// When looking up a value using a Heaviside function, we get the value and its index.
+//
+// We can also split an OMT into two OMTs, splitting the weight of the values evenly.
+// Find a value $j$ such that the values to the left of $j$ have about the same total weight as the values to the right of $j$.
+// The resulting two OMTs contain the values to the left of $j$ and the values to the right of $j$ respectively.
+// All of the values from the original OMT go into one of the new OMTs.
+// If the weights of the values don't split exactly evenly, then the implementation has the freedom to choose whether
+// the new left OMT or the new right OMT is larger.
+//
+// Performance:
+// Insertion and deletion should run with $O(\log |V|)$ time and $O(\log |V|)$ calls to the Heaviside function.
+// The memory required is O(|V|).
+//
+// The programming API:
+
+//typedef struct value *OMTVALUE; // A slight improvement over using void*.
+#include <util/omt.h>
+typedef void *OMTVALUE;
+typedef toku::omt<OMTVALUE> *OMT;
+
+
+int toku_omt_create (OMT *omtp);
+// Effect: Create an empty OMT. Stores it in *omtp.
+// Requires: omtp != NULL
+// Returns:
+// 0 success
+// ENOMEM out of memory (and doesn't modify *omtp)
+// Performance: constant time.
+
+int toku_omt_create_from_sorted_array(OMT *omtp, OMTVALUE *values, uint32_t numvalues);
+// Effect: Create a OMT containing values. The number of values is in numvalues.
+// Stores the new OMT in *omtp.
+// Requires: omtp != NULL
+// Requires: values != NULL
+// Requires: values is sorted
+// Returns:
+// 0 success
+// ENOMEM out of memory (and doesn't modify *omtp)
+// Performance: time=O(numvalues)
+// Rational: Normally to insert N values takes O(N lg N) amortized time.
+// If the N values are known in advance, are sorted, and
+// the structure is empty, we can batch insert them much faster.
+
+int toku_omt_create_steal_sorted_array(OMT *omtp, OMTVALUE **valuesp, uint32_t numvalues, uint32_t steal_capacity);
+// Effect: Create an OMT containing values. The number of values is in numvalues.
+// On success the OMT takes ownership of *valuesp array, and sets valuesp=NULL.
+// Requires: omtp != NULL
+// Requires: valuesp != NULL
+// Requires: *valuesp is sorted
+// Requires: *valuesp was allocated with toku_malloc
+// Requires: Capacity of the *valuesp array is <= steal_capacity
+// Requires: On success, *valuesp may not be accessed again by the caller.
+// Returns:
+// 0 success
+// ENOMEM out of memory (and doesn't modify *omtp)
+// EINVAL *valuesp == NULL or numvalues > capacity
+// Performance: time=O(1)
+// Rational: toku_omt_create_from_sorted_array takes O(numvalues) time.
+// By taking ownership of the array, we save a malloc and memcpy,
+// and possibly a free (if the caller is done with the array).
+
+void toku_omt_destroy(OMT *omtp);
+// Effect: Destroy an OMT, freeing all its memory.
+// Does not free the OMTVALUEs stored in the OMT.
+// Those values may be freed before or after calling toku_omt_destroy.
+// Also sets *omtp=NULL.
+// Requires: omtp != NULL
+// Requires: *omtp != NULL
+// Rationale: The usage is to do something like
+// toku_omt_destroy(&s->omt);
+// and now s->omt will have a NULL pointer instead of a dangling freed pointer.
+// Rationale: Returns no values since free() cannot fail.
+// Rationale: Does not free the OMTVALUEs to reduce complexity.
+// Performance: time=O(toku_omt_size(*omtp))
+
+uint32_t toku_omt_size(OMT V);
+// Effect: return |V|.
+// Requires: V != NULL
+// Performance: time=O(1)
+
+int toku_omt_iterate_on_range(OMT omt, uint32_t left, uint32_t right, int (*f)(OMTVALUE, uint32_t, void*), void*v);
+// Effect: Iterate over the values of the omt, from left to right, calling f on each value.
+// The second argument passed to f is the index of the value.
+// The third argument passed to f is v.
+// The indices run from 0 (inclusive) to toku_omt_size(omt) (exclusive).
+// We will iterate only over [left,right)
+//
+// Requires: omt != NULL
+// left <= right
+// Requires: f != NULL
+// Returns:
+// If f ever returns nonzero, then the iteration stops, and the value returned by f is returned by toku_omt_iterate.
+// If f always returns zero, then toku_omt_iterate returns 0.
+// Requires: Don't modify omt while running. (E.g., f may not insert or delete values form omt.)
+// Performance: time=O(i+\log N) where i is the number of times f is called, and N is the number of elements in omt.
+// Rational: Although the functional iterator requires defining another function (as opposed to C++ style iterator), it is much easier to read.
+
+int toku_omt_iterate(OMT omt, int (*f)(OMTVALUE, uint32_t, void*), void*v);
+// Effect: Iterate over the values of the omt, from left to right, calling f on each value.
+// The second argument passed to f is the index of the value.
+// The third argument passed to f is v.
+// The indices run from 0 (inclusive) to toku_omt_size(omt) (exclusive).
+// Requires: omt != NULL
+// Requires: f != NULL
+// Returns:
+// If f ever returns nonzero, then the iteration stops, and the value returned by f is returned by toku_omt_iterate.
+// If f always returns zero, then toku_omt_iterate returns 0.
+// Requires: Don't modify omt while running. (E.g., f may not insert or delete values form omt.)
+// Performance: time=O(i+\log N) where i is the number of times f is called, and N is the number of elements in omt.
+// Rational: Although the functional iterator requires defining another function (as opposed to C++ style iterator), it is much easier to read.
+
+int toku_omt_insert_at(OMT omt, OMTVALUE value, uint32_t idx);
+// Effect: Increases indexes of all items at slot >= index by 1.
+// Insert value into the position at index.
+//
+// Returns:
+// 0 success
+// EINVAL if index>toku_omt_size(omt)
+// ENOMEM
+// On error, omt is unchanged.
+// Performance: time=O(\log N) amortized time.
+// Rationale: Some future implementation may be O(\log N) worst-case time, but O(\log N) amortized is good enough for now.
+
+int toku_omt_set_at (OMT omt, OMTVALUE value, uint32_t idx);
+// Effect: Replaces the item at index with value.
+// Returns:
+// 0 success
+// EINVAL if index>=toku_omt_size(omt)
+// On error, omt i sunchanged.
+// Performance: time=O(\log N)
+// Rationale: The BRT needs to be able to replace a value with another copy of the same value (allocated in a different location)
+
+int toku_omt_insert(OMT omt, OMTVALUE value, int(*h)(OMTVALUE, void*v), void *v, uint32_t *idx);
+// Effect: Insert value into the OMT.
+// If there is some i such that $h(V_i, v)=0$ then returns DB_KEYEXIST.
+// Otherwise, let i be the minimum value such that $h(V_i, v)>0$.
+// If no such i exists, then let i be |V|
+// Then this has the same effect as
+// omt_insert_at(tree, value, i);
+// If index!=NULL then i is stored in *index
+// Requires: The signum of h must be monotonically increasing.
+// Returns:
+// 0 success
+// DB_KEYEXIST the key is present (h was equal to zero for some value)
+// ENOMEM
+// On nonzero return, omt is unchanged.
+// On nonzero non-DB_KEYEXIST return, *index is unchanged.
+// Performance: time=O(\log N) amortized.
+// Rationale: Some future implementation may be O(\log N) worst-case time, but O(\log N) amortized is good enough for now.
+
+int toku_omt_delete_at(OMT omt, uint32_t idx);
+// Effect: Delete the item in slot index.
+// Decreases indexes of all items at slot >= index by 1.
+// Returns
+// 0 success
+// EINVAL if index>=toku_omt_size(omt)
+// On error, omt is unchanged.
+// Rationale: To delete an item, first find its index using toku_omt_find, then delete it.
+// Performance: time=O(\log N) amortized.
+
+int toku_omt_fetch (OMT V, uint32_t i, OMTVALUE *v);
+// Effect: Set *v=V_i
+// If c!=NULL then set c's abstract offset to i.
+// Requires: v != NULL
+// Returns
+// 0 success
+// EINVAL if index>=toku_omt_size(omt)
+// On nonzero return, *v is unchanged, and c (if nonnull) is either
+// invalidated or unchanged.
+// Performance: time=O(\log N)
+// Implementation Notes: It is possible that c was previously valid and was
+// associated with a different OMT. If c is changed by this
+// function, the function must remove c's association with the old
+// OMT, and associate it with the new OMT.
+
+int toku_omt_find_zero(OMT V, int (*h)(OMTVALUE, void*extra), void*extra, OMTVALUE *value, uint32_t *idx);
+// Effect: Find the smallest i such that h(V_i, extra)>=0
+// If there is such an i and h(V_i,extra)==0 then set *index=i and return 0.
+// If there is such an i and h(V_i,extra)>0 then set *index=i and return DB_NOTFOUND.
+// If there is no such i then set *index=toku_omt_size(V) and return DB_NOTFOUND.
+// Requires: index!=NULL
+
+int toku_omt_find(OMT V, int (*h)(OMTVALUE, void*extra), void*extra, int direction, OMTVALUE *value, uint32_t *idx);
+// Effect:
+// If direction >0 then find the smallest i such that h(V_i,extra)>0.
+// If direction <0 then find the largest i such that h(V_i,extra)<0.
+// (Direction may not be equal to zero.)
+// If value!=NULL then store V_i in *value
+// If index!=NULL then store i in *index.
+// Requires: The signum of h is monotically increasing.
+// Returns
+// 0 success
+// DB_NOTFOUND no such value is found.
+// On nonzero return, *value and *index are unchanged, and c (if nonnull) is either invalidated
+// or unchanged.
+// Performance: time=O(\log N)
+// Rationale:
+// Here's how to use the find function to find various things
+// Cases for find:
+// find first value: ( h(v)=+1, direction=+1 )
+// find last value ( h(v)=-1, direction=-1 )
+// find first X ( h(v)=(v< x) ? -1 : 1 direction=+1 )
+// find last X ( h(v)=(v<=x) ? -1 : 1 direction=-1 )
+// find X or successor to X ( same as find first X. )
+//
+// Rationale: To help understand heaviside functions and behavor of find:
+// There are 7 kinds of heaviside functions.
+// The signus of the h must be monotonically increasing.
+// Given a function of the following form, A is the element
+// returned for direction>0, B is the element returned
+// for direction<0, C is the element returned for
+// direction==0 (see find_zero) (with a return of 0), and D is the element
+// returned for direction==0 (see find_zero) with a return of DB_NOTFOUND.
+// If any of A, B, or C are not found, then asking for the
+// associated direction will return DB_NOTFOUND.
+// See find_zero for more information.
+//
+// Let the following represent the signus of the heaviside function.
+//
+// -...-
+// A
+// D
+//
+// +...+
+// B
+// D
+//
+// 0...0
+// C
+//
+// -...-0...0
+// AC
+//
+// 0...0+...+
+// C B
+//
+// -...-+...+
+// AB
+// D
+//
+// -...-0...0+...+
+// AC B
+
+int toku_omt_split_at(OMT omt, OMT *newomt, uint32_t idx);
+// Effect: Create a new OMT, storing it in *newomt.
+// The values to the right of index (starting at index) are moved to *newomt.
+// Requires: omt != NULL
+// Requires: newomt != NULL
+// Returns
+// 0 success,
+// EINVAL if index > toku_omt_size(omt)
+// ENOMEM
+// On nonzero return, omt and *newomt are unmodified.
+// Performance: time=O(n)
+// Rationale: We don't need a split-evenly operation. We need to split items so that their total sizes
+// are even, and other similar splitting criteria. It's easy to split evenly by calling toku_omt_size(), and dividing by two.
+
+int toku_omt_merge(OMT leftomt, OMT rightomt, OMT *newomt);
+// Effect: Appends leftomt and rightomt to produce a new omt.
+// Sets *newomt to the new omt.
+// On success, leftomt and rightomt destroyed,.
+// Returns 0 on success
+// ENOMEM on out of memory.
+// On error, nothing is modified.
+// Performance: time=O(n) is acceptable, but one can imagine implementations that are O(\log n) worst-case.
+
+int toku_omt_clone_noptr(OMT *dest, OMT src);
+// Effect: Creates a copy of an omt.
+// Sets *dest to the clone
+// Each element is assumed to be stored directly in the omt, that is, the OMTVALUEs are not pointers, they are data. Thus no extra memory allocation is required.
+// Returns 0 on success
+// ENOMEM on out of memory.
+// On error, nothing is modified.
+// Performance: time between O(n) and O(n log n), depending how long it
+// takes to traverse src.
+
+void toku_omt_clear(OMT omt);
+// Effect: Set the tree to be empty.
+// Note: Will not reallocate or resize any memory, since returning void precludes calling malloc.
+// Performance: time=O(1)
+
+size_t toku_omt_memory_size (OMT omt);
+// Effect: Return the size (in bytes) of the omt, as it resides in main memory. Don't include any of the OMTVALUES.
+
+
+
+#endif /* #ifndef TOKU_OMT_H */
+
diff --git a/storage/tokudb/ft-index/ft/quicklz.cc b/storage/tokudb/ft-index/ft/quicklz.cc
index c7cd82c80d5..62dfb8e0192 100644
--- a/storage/tokudb/ft-index/ft/quicklz.cc
+++ b/storage/tokudb/ft-index/ft/quicklz.cc
@@ -311,7 +311,6 @@ static __inline void memcpy_up(unsigned char *dst, const unsigned char *src, ui3
#endif
}
-__attribute__((unused))
static __inline void update_hash(qlz_state_decompress *state, const unsigned char *s)
{
#if QLZ_COMPRESSION_LEVEL == 1
diff --git a/storage/tokudb/ft-index/ft/rbuf.h b/storage/tokudb/ft-index/ft/rbuf.h
index a21123bfb73..22e41881cd4 100644
--- a/storage/tokudb/ft-index/ft/rbuf.h
+++ b/storage/tokudb/ft-index/ft/rbuf.h
@@ -93,12 +93,12 @@ PATENT RIGHTS GRANT:
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#include <toku_portability.h>
+#include "memarena.h"
#include "toku_assert.h"
#include "fttypes.h"
#include "memory.h"
#include <toku_htonl.h>
-#include <util/memarena.h>
struct rbuf {
unsigned char *buf;
@@ -250,7 +250,7 @@ static inline void rbuf_FILENUMS(struct rbuf *r, FILENUMS *filenums) {
// 2954
static inline void rbuf_ma_FILENUMS (struct rbuf *r, MEMARENA ma __attribute__((__unused__)), FILENUMS *filenums) {
rbuf_ma_uint32_t(r, ma, &(filenums->num));
- filenums->filenums = (FILENUM *) toku_memarena_malloc(ma, filenums->num * sizeof(FILENUM) );
+ filenums->filenums = (FILENUM *) malloc_in_memarena(ma, filenums->num * sizeof(FILENUM) );
assert(filenums->filenums != NULL);
for (uint32_t i=0; i < filenums->num; i++) {
rbuf_ma_FILENUM(r, ma, &(filenums->filenums[i]));
@@ -271,7 +271,7 @@ static inline void rbuf_ma_BYTESTRING (struct rbuf *r, MEMARENA ma, BYTESTRING
bs->len = rbuf_int(r);
uint32_t newndone = r->ndone + bs->len;
assert(newndone <= r->size);
- bs->data = (char *) toku_memarena_memdup(ma, &r->buf[r->ndone], (size_t)bs->len);
+ bs->data = (char *) memarena_memdup(ma, &r->buf[r->ndone], (size_t)bs->len);
assert(bs->data);
r->ndone = newndone;
}
diff --git a/storage/tokudb/ft-index/ft/recover.cc b/storage/tokudb/ft-index/ft/recover.cc
index 2aac09855cd..79e5c7d1d90 100644
--- a/storage/tokudb/ft-index/ft/recover.cc
+++ b/storage/tokudb/ft-index/ft/recover.cc
@@ -98,8 +98,6 @@ PATENT RIGHTS GRANT:
#include "checkpoint.h"
#include "txn_manager.h"
-#include <util/omt.h>
-
int tokudb_recovery_trace = 0; // turn on recovery tracing, default off.
//#define DO_VERIFY_COUNTS
@@ -156,9 +154,9 @@ struct file_map_tuple {
struct __toku_db fake_db;
};
-static void file_map_tuple_init(struct file_map_tuple *tuple, FILENUM filenum, FT_HANDLE ft_handle, char *iname) {
+static void file_map_tuple_init(struct file_map_tuple *tuple, FILENUM filenum, FT_HANDLE brt, char *iname) {
tuple->filenum = filenum;
- tuple->ft_handle = ft_handle;
+ tuple->ft_handle = brt;
tuple->iname = iname;
// use a fake DB for comparisons, using the ft's cmp descriptor
memset(&tuple->fake_db, 0, sizeof(tuple->fake_db));
@@ -173,9 +171,9 @@ static void file_map_tuple_destroy(struct file_map_tuple *tuple) {
}
}
-// Map filenum to ft_handle
+// Map filenum to brt
struct file_map {
- toku::omt<struct file_map_tuple *> *filenums;
+ OMT filenums;
};
// The recovery environment
@@ -201,33 +199,31 @@ typedef struct recover_env *RECOVER_ENV;
static void file_map_init(struct file_map *fmap) {
- XMALLOC(fmap->filenums);
- fmap->filenums->create();
+ int r = toku_omt_create(&fmap->filenums);
+ assert(r == 0);
}
static void file_map_destroy(struct file_map *fmap) {
- fmap->filenums->destroy();
- toku_free(fmap->filenums);
- fmap->filenums = nullptr;
+ toku_omt_destroy(&fmap->filenums);
}
static uint32_t file_map_get_num_dictionaries(struct file_map *fmap) {
- return fmap->filenums->size();
+ return toku_omt_size(fmap->filenums);
}
static void file_map_close_dictionaries(struct file_map *fmap, LSN oplsn) {
int r;
while (1) {
- uint32_t n = fmap->filenums->size();
- if (n == 0) {
+ uint32_t n = toku_omt_size(fmap->filenums);
+ if (n == 0)
break;
- }
- struct file_map_tuple *tuple;
- r = fmap->filenums->fetch(n - 1, &tuple);
+ OMTVALUE v;
+ r = toku_omt_fetch(fmap->filenums, n-1, &v);
assert(r == 0);
- r = fmap->filenums->delete_at(n - 1);
+ r = toku_omt_delete_at(fmap->filenums, n-1);
assert(r == 0);
+ struct file_map_tuple *CAST_FROM_VOIDP(tuple, v);
assert(tuple->ft_handle);
// Logging is on again, but we must pass the right LSN into close.
if (tuple->ft_handle) { // it's a DB, not a rollback file
@@ -238,29 +234,27 @@ static void file_map_close_dictionaries(struct file_map *fmap, LSN oplsn) {
}
}
-static int file_map_h(struct file_map_tuple *const &a, const FILENUM &b) {
- if (a->filenum.fileid < b.fileid) {
- return -1;
- } else if (a->filenum.fileid > b.fileid) {
- return 1;
- } else {
- return 0;
- }
+static int file_map_h(OMTVALUE omtv, void *v) {
+ struct file_map_tuple *CAST_FROM_VOIDP(a, omtv);
+ FILENUM *CAST_FROM_VOIDP(b, v);
+ if (a->filenum.fileid < b->fileid) return -1;
+ if (a->filenum.fileid > b->fileid) return +1;
+ return 0;
}
-static int file_map_insert (struct file_map *fmap, FILENUM fnum, FT_HANDLE ft_handle, char *iname) {
+static int file_map_insert (struct file_map *fmap, FILENUM fnum, FT_HANDLE brt, char *iname) {
struct file_map_tuple *XMALLOC(tuple);
- file_map_tuple_init(tuple, fnum, ft_handle, iname);
- int r = fmap->filenums->insert<FILENUM, file_map_h>(tuple, fnum, nullptr);
+ file_map_tuple_init(tuple, fnum, brt, iname);
+ int r = toku_omt_insert(fmap->filenums, tuple, file_map_h, &fnum, NULL);
return r;
}
static void file_map_remove(struct file_map *fmap, FILENUM fnum) {
- uint32_t idx;
- struct file_map_tuple *tuple;
- int r = fmap->filenums->find_zero<FILENUM, file_map_h>(fnum, &tuple, &idx);
+ OMTVALUE v; uint32_t idx;
+ int r = toku_omt_find_zero(fmap->filenums, file_map_h, &fnum, &v, &idx);
if (r == 0) {
- r = fmap->filenums->delete_at(idx);
+ struct file_map_tuple *CAST_FROM_VOIDP(tuple, v);
+ r = toku_omt_delete_at(fmap->filenums, idx);
file_map_tuple_destroy(tuple);
toku_free(tuple);
}
@@ -268,15 +262,14 @@ static void file_map_remove(struct file_map *fmap, FILENUM fnum) {
// Look up file info: given FILENUM, return file_map_tuple (or DB_NOTFOUND)
static int file_map_find(struct file_map *fmap, FILENUM fnum, struct file_map_tuple **file_map_tuple) {
- uint32_t idx;
- struct file_map_tuple *tuple;
- int r = fmap->filenums->find_zero<FILENUM, file_map_h>(fnum, &tuple, &idx);
+ OMTVALUE v; uint32_t idx;
+ int r = toku_omt_find_zero(fmap->filenums, file_map_h, &fnum, &v, &idx);
if (r == 0) {
+ struct file_map_tuple *CAST_FROM_VOIDP(tuple, v);
assert(tuple->filenum.fileid == fnum.fileid);
*file_map_tuple = tuple;
- } else {
- assert(r == DB_NOTFOUND);
}
+ else assert(r==DB_NOTFOUND);
return r;
}
@@ -326,7 +319,7 @@ static int recover_env_init (RECOVER_ENV renv,
static void recover_env_cleanup (RECOVER_ENV renv) {
int r;
- invariant_zero(renv->fmap.filenums->size());
+ assert(toku_omt_size(renv->fmap.filenums)==0);
file_map_destroy(&renv->fmap);
if (renv->destroy_logger_at_end) {
@@ -357,48 +350,48 @@ static const char *recover_state(RECOVER_ENV renv) {
static int internal_recover_fopen_or_fcreate (RECOVER_ENV renv, bool must_create, int UU(mode), BYTESTRING *bs_iname, FILENUM filenum, uint32_t treeflags,
TOKUTXN txn, uint32_t nodesize, uint32_t basementnodesize, enum toku_compression_method compression_method, LSN max_acceptable_lsn) {
int r = 0;
- FT_HANDLE ft_handle = NULL;
+ FT_HANDLE brt = NULL;
char *iname = fixup_fname(bs_iname);
- toku_ft_handle_create(&ft_handle);
- toku_ft_set_flags(ft_handle, treeflags);
+ toku_ft_handle_create(&brt);
+ toku_ft_set_flags(brt, treeflags);
if (nodesize != 0) {
- toku_ft_handle_set_nodesize(ft_handle, nodesize);
+ toku_ft_handle_set_nodesize(brt, nodesize);
}
if (basementnodesize != 0) {
- toku_ft_handle_set_basementnodesize(ft_handle, basementnodesize);
+ toku_ft_handle_set_basementnodesize(brt, basementnodesize);
}
if (compression_method != TOKU_DEFAULT_COMPRESSION_METHOD) {
- toku_ft_handle_set_compression_method(ft_handle, compression_method);
+ toku_ft_handle_set_compression_method(brt, compression_method);
}
// set the key compare functions
if (!(treeflags & TOKU_DB_KEYCMP_BUILTIN) && renv->bt_compare) {
- toku_ft_set_bt_compare(ft_handle, renv->bt_compare);
+ toku_ft_set_bt_compare(brt, renv->bt_compare);
}
if (renv->update_function) {
- toku_ft_set_update(ft_handle, renv->update_function);
+ toku_ft_set_update(brt, renv->update_function);
}
// TODO mode (FUTURE FEATURE)
//mode = mode;
- r = toku_ft_handle_open_recovery(ft_handle, iname, must_create, must_create, renv->ct, txn, filenum, max_acceptable_lsn);
+ r = toku_ft_handle_open_recovery(brt, iname, must_create, must_create, renv->ct, txn, filenum, max_acceptable_lsn);
if (r != 0) {
//Note: If ft_handle_open fails, then close_ft will NOT write a header to disk.
//No need to provide lsn, so use the regular toku_ft_handle_close function
- toku_ft_handle_close(ft_handle);
+ toku_ft_handle_close(brt);
toku_free(iname);
if (r == ENOENT) //Not an error to simply be missing.
r = 0;
return r;
}
- file_map_insert(&renv->fmap, filenum, ft_handle, iname);
+ file_map_insert(&renv->fmap, filenum, brt, iname);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/recover.h b/storage/tokudb/ft-index/ft/recover.h
index 2ef84112784..342445d09ac 100644
--- a/storage/tokudb/ft-index/ft/recover.h
+++ b/storage/tokudb/ft-index/ft/recover.h
@@ -96,10 +96,10 @@ PATENT RIGHTS GRANT:
#include <errno.h>
#include <db.h>
-#include <util/x1764.h>
-
#include "fttypes.h"
#include "memory.h"
+#include "x1764.h"
+
typedef void (*prepared_txn_callback_t)(DB_ENV*, TOKUTXN);
typedef void (*keep_cachetable_callback_t)(DB_ENV*, CACHETABLE);
diff --git a/storage/tokudb/ft-index/ft/roll.cc b/storage/tokudb/ft-index/ft/roll.cc
index 2c8e1d9307c..78fac7df875 100644
--- a/storage/tokudb/ft-index/ft/roll.cc
+++ b/storage/tokudb/ft-index/ft/roll.cc
@@ -258,7 +258,7 @@ static int do_insertion (enum ft_msg_type type, FILENUM filenum, BYTESTRING key,
XIDS xids;
xids = toku_txn_get_xids(txn);
{
- FT_MSG_S ftmsg = { type, ZERO_MSN, xids,
+ FT_MSG_S ftcmd = { type, ZERO_MSN, xids,
.u = { .id = { (key.len > 0)
? toku_fill_dbt(&key_dbt, key.data, key.len)
: toku_init_dbt(&key_dbt),
@@ -275,7 +275,7 @@ static int do_insertion (enum ft_msg_type type, FILENUM filenum, BYTESTRING key,
// no messages above us, we can implicitly promote uxrs based on this xid
oldest_referenced_xid_estimate,
!txn->for_recovery);
- toku_ft_root_put_msg(h, &ftmsg, &gc_info);
+ toku_ft_root_put_cmd(h, &ftcmd, &gc_info);
if (reset_root_xid_that_created) {
TXNID new_root_xid_that_created = xids_get_outermost_xid(xids);
toku_reset_root_xid_that_created(h, new_root_xid_that_created);
diff --git a/storage/tokudb/ft-index/ft/rollback-apply.cc b/storage/tokudb/ft-index/ft/rollback-apply.cc
index 1dd3062b33e..d707753471a 100644
--- a/storage/tokudb/ft-index/ft/rollback-apply.cc
+++ b/storage/tokudb/ft-index/ft/rollback-apply.cc
@@ -93,8 +93,7 @@ PATENT RIGHTS GRANT:
#include "log-internal.h"
#include "rollback-apply.h"
-static void
-poll_txn_progress_function(TOKUTXN txn, uint8_t is_commit, uint8_t stall_for_checkpoint) {
+static void poll_txn_progress_function(TOKUTXN txn, uint8_t is_commit, uint8_t stall_for_checkpoint) {
if (txn->progress_poll_fun) {
TOKU_TXN_PROGRESS_S progress = {
.entries_total = txn->roll_info.num_rollentries,
@@ -125,17 +124,14 @@ int toku_abort_rollback_item (TOKUTXN txn, struct roll_entry *item, LSN lsn) {
return r;
}
-int
-note_ft_used_in_txns_parent(const FT &ft, uint32_t UU(index), TOKUTXN const child);
-int
-note_ft_used_in_txns_parent(const FT &ft, uint32_t UU(index), TOKUTXN const child) {
+int note_ft_used_in_txns_parent(const FT &ft, uint32_t UU(index), TOKUTXN const child);
+int note_ft_used_in_txns_parent(const FT &ft, uint32_t UU(index), TOKUTXN const child) {
TOKUTXN parent = child->parent;
toku_txn_maybe_note_ft(parent, ft);
return 0;
}
-static int
-apply_txn(TOKUTXN txn, LSN lsn, apply_rollback_item func) {
+static int apply_txn(TOKUTXN txn, LSN lsn, apply_rollback_item func) {
int r = 0;
// do the commit/abort calls and free everything
// we do the commit/abort calls in reverse order too.
@@ -258,9 +254,9 @@ int toku_rollback_commit(TOKUTXN txn, LSN lsn) {
}
child_log->newest_logentry = child_log->oldest_logentry = 0;
// Put all the memarena data into the parent.
- if (toku_memarena_total_size_in_use(child_log->rollentry_arena) > 0) {
+ if (memarena_total_size_in_use(child_log->rollentry_arena) > 0) {
// If there are no bytes to move, then just leave things alone, and let the memory be reclaimed on txn is closed.
- toku_memarena_move_buffers(parent_log->rollentry_arena, child_log->rollentry_arena);
+ memarena_move_buffers(parent_log->rollentry_arena, child_log->rollentry_arena);
}
// each txn tries to give back at most one rollback log node
// to the cache. All other rollback log nodes for this child
@@ -281,7 +277,7 @@ int toku_rollback_commit(TOKUTXN txn, LSN lsn) {
toku_txn_unlock(txn->parent);
}
- // Note the open FTs, the omts must be merged
+ // Note the open brts, the omts must be merged
r = txn->open_fts.iterate<struct tokutxn, note_ft_used_in_txns_parent>(txn);
assert(r==0);
@@ -303,3 +299,9 @@ int toku_rollback_abort(TOKUTXN txn, LSN lsn) {
assert(r==0);
return r;
}
+
+int toku_rollback_discard(TOKUTXN txn) {
+ txn->roll_info.current_rollback = ROLLBACK_NONE;
+ return 0;
+}
+
diff --git a/storage/tokudb/ft-index/ft/rollback-apply.h b/storage/tokudb/ft-index/ft/rollback-apply.h
index 50e53ea6d24..6016b5523df 100644
--- a/storage/tokudb/ft-index/ft/rollback-apply.h
+++ b/storage/tokudb/ft-index/ft/rollback-apply.h
@@ -99,6 +99,6 @@ int toku_abort_rollback_item (TOKUTXN txn, struct roll_entry *item, LSN lsn);
int toku_rollback_commit(TOKUTXN txn, LSN lsn);
int toku_rollback_abort(TOKUTXN txn, LSN lsn);
-
+int toku_rollback_discard(TOKUTXN txn);
#endif // ROLLBACK_APPLY_H
diff --git a/storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc b/storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc
index 7083e17bd0d..bea70a5155e 100644
--- a/storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc
+++ b/storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc
@@ -89,15 +89,15 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include "rollback-ct-callbacks.h"
+
#include <toku_portability.h>
#include <memory.h>
-
#include "ft-internal.h"
#include "fttypes.h"
+#include "memarena.h"
#include "rollback.h"
-#include "rollback-ct-callbacks.h"
-#include <util/memarena.h>
// Address used as a sentinel. Otherwise unused.
static struct serialized_rollback_log_node cloned_rollback;
diff --git a/storage/tokudb/ft-index/ft/rollback.cc b/storage/tokudb/ft-index/ft/rollback.cc
index 1b1a99d908e..3b57049a33e 100644
--- a/storage/tokudb/ft-index/ft/rollback.cc
+++ b/storage/tokudb/ft-index/ft/rollback.cc
@@ -121,7 +121,7 @@ toku_find_xid_by_xid (const TXNID &xid, const TXNID &xidfind) {
}
void *toku_malloc_in_rollback(ROLLBACK_LOG_NODE log, size_t size) {
- return toku_memarena_malloc(log->rollentry_arena, size);
+ return malloc_in_memarena(log->rollentry_arena, size);
}
void *toku_memdup_in_rollback(ROLLBACK_LOG_NODE log, const void *v, size_t len) {
@@ -146,7 +146,7 @@ PAIR_ATTR
rollback_memory_size(ROLLBACK_LOG_NODE log) {
size_t size = sizeof(*log);
if (log->rollentry_arena) {
- size += toku_memarena_total_footprint(log->rollentry_arena);
+ size += memarena_total_memory_size(log->rollentry_arena);
}
return make_rollback_pair_attr(size);
}
@@ -192,13 +192,13 @@ static void rollback_initialize_for_txn(
log->previous = previous;
log->oldest_logentry = NULL;
log->newest_logentry = NULL;
- log->rollentry_arena = toku_memarena_create();
+ log->rollentry_arena = memarena_create();
log->rollentry_resident_bytecount = 0;
log->dirty = true;
}
void make_rollback_log_empty(ROLLBACK_LOG_NODE log) {
- toku_memarena_destroy(&log->rollentry_arena);
+ memarena_close(&log->rollentry_arena);
rollback_empty_log_init(log);
}
@@ -267,7 +267,7 @@ int find_filenum (const FT &h, const FT &hfind) {
return 0;
}
-//Notify a transaction that it has touched an ft.
+//Notify a transaction that it has touched a brt.
void toku_txn_maybe_note_ft (TOKUTXN txn, FT ft) {
toku_txn_lock(txn);
FT ftv;
diff --git a/storage/tokudb/ft-index/ft/rollback_log_node_cache.cc b/storage/tokudb/ft-index/ft/rollback_log_node_cache.cc
index d3ea3471489..b45e4c03bb8 100644
--- a/storage/tokudb/ft-index/ft/rollback_log_node_cache.cc
+++ b/storage/tokudb/ft-index/ft/rollback_log_node_cache.cc
@@ -90,7 +90,7 @@ PATENT RIGHTS GRANT:
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#include <memory.h>
-#include <portability/toku_portability.h>
+#include <toku_include/toku_portability.h>
#include "rollback_log_node_cache.h"
diff --git a/storage/tokudb/ft-index/ft/sub_block.cc b/storage/tokudb/ft-index/ft/sub_block.cc
index 5d8799fb2db..7dc790a61b7 100644
--- a/storage/tokudb/ft-index/ft/sub_block.cc
+++ b/storage/tokudb/ft-index/ft/sub_block.cc
@@ -89,15 +89,16 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-#include "compress.h"
#include "sub_block.h"
+
+#include "compress.h"
#include "quicklz.h"
+#include "x1764.h"
#include <memory.h>
#include <toku_assert.h>
#include <toku_portability.h>
#include <util/threadpool.h>
-#include <util/x1764.h>
#include <stdio.h>
#include <string.h>
@@ -267,7 +268,7 @@ compress_sub_block(struct sub_block *sub_block, enum toku_compression_method met
method
);
// checksum it
- sub_block->xsum = toku_x1764_memory(sub_block->compressed_ptr, sub_block->compressed_size);
+ sub_block->xsum = x1764_memory(sub_block->compressed_ptr, sub_block->compressed_size);
}
void *
@@ -364,7 +365,7 @@ decompress_sub_block(void *compress_ptr, uint32_t compress_size, void *uncompres
int result = 0;
// verify checksum
- uint32_t xsum = toku_x1764_memory(compress_ptr, compress_size);
+ uint32_t xsum = x1764_memory(compress_ptr, compress_size);
if (xsum != expected_xsum) {
if (verbose_decompress_sub_block) fprintf(stderr, "%s:%d xsum %u expected %u\n", __FUNCTION__, __LINE__, xsum, expected_xsum);
result = EINVAL;
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-checkpoint-pending.cc b/storage/tokudb/ft-index/ft/tests/cachetable-checkpoint-pending.cc
index 615a544a7f7..c9f6033da9e 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-checkpoint-pending.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-checkpoint-pending.cc
@@ -108,9 +108,13 @@ static volatile int n_flush, n_write_me, n_keep_me, n_fetch;
static void
sleep_random (void)
{
+#if TOKU_WINDOWS
+ usleep(random() % 1000); //Will turn out to be almost always 1ms.
+#else
toku_timespec_t req = {.tv_sec = 0,
.tv_nsec = random()%1000000}; //Max just under 1ms
nanosleep(&req, NULL);
+#endif
}
int expect_value = 42; // initially 42, later 43
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-test.cc b/storage/tokudb/ft-index/ft/tests/cachetable-test.cc
index e498df10a5c..e1a1bc28c65 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-test.cc
@@ -241,6 +241,8 @@ PAIR_ATTR *sizep __attribute__((__unused__)), int * dirtyp, void*extraargs) {
return 0;
}
+#if !TOKU_WINDOWS
+
static void test_multi_filehandles (void) {
CACHETABLE t;
CACHEFILE f1,f2,f3;
@@ -289,6 +291,8 @@ static void test_multi_filehandles (void) {
toku_cachetable_close(&t);
}
+#endif
+
static void test_dirty_flush(CACHEFILE f,
int UU(fd),
CACHEKEY key,
@@ -583,11 +587,15 @@ test_main (int argc, const char *argv[]) {
test_mutex_init();
// run tests
+#if !TOKU_WINDOWS
test_multi_filehandles();
+#endif
test_cachetable_create();
for (i=0; i<1; i++) {
test_nested_pin();
+#if !TOKU_WINDOWS
test_multi_filehandles ();
+#endif
test_dirty();
test_size_resize();
//test_size_flush();
diff --git a/storage/tokudb/ft-index/ft/tests/dmt-test2.cc b/storage/tokudb/ft-index/ft/tests/dmt-test2.cc
deleted file mode 100644
index 8943aae7324..00000000000
--- a/storage/tokudb/ft-index/ft/tests/dmt-test2.cc
+++ /dev/null
@@ -1,373 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
-#ident "$Id$"
-/*
-COPYING CONDITIONS NOTICE:
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation, and provided that the
- following conditions are met:
-
- * Redistributions of source code must retain this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below).
-
- * Redistributions in binary form must reproduce this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below) in the documentation and/or other materials
- provided with the distribution.
-
- 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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-COPYRIGHT NOTICE:
-
- TokuDB, Tokutek Fractal Tree Indexing Library.
- Copyright (C) 2007-2013 Tokutek, Inc.
-
-DISCLAIMER:
-
- 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.
-
-UNIVERSITY PATENT NOTICE:
-
- The technology is licensed by the Massachusetts Institute of
- Technology, Rutgers State University of New Jersey, and the Research
- Foundation of State University of New York at Stony Brook under
- United States of America Serial No. 11/760379 and to the patents
- and/or patent applications resulting from it.
-
-PATENT MARKING NOTICE:
-
- This software is covered by US Patent No. 8,185,551.
- This software is covered by US Patent No. 8,489,638.
-
-PATENT RIGHTS GRANT:
-
- "THIS IMPLEMENTATION" means the copyrightable works distributed by
- Tokutek as part of the Fractal Tree project.
-
- "PATENT CLAIMS" means the claims of patents that are owned or
- licensable by Tokutek, both currently or in the future; and that in
- the absence of this license would be infringed by THIS
- IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
-
- "PATENT CHALLENGE" shall mean a challenge to the validity,
- patentability, enforceability and/or non-infringement of any of the
- PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
-
- Tokutek hereby grants to you, for the term and geographical scope of
- the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
- irrevocable (except as stated in this section) patent license to
- make, have made, use, offer to sell, sell, import, transfer, and
- otherwise run, modify, and propagate the contents of THIS
- IMPLEMENTATION, where such license applies only to the PATENT
- CLAIMS. This grant does not include claims that would be infringed
- only as a consequence of further modifications of THIS
- IMPLEMENTATION. If you or your agent or licensee institute or order
- or agree to the institution of patent litigation against any entity
- (including a cross-claim or counterclaim in a lawsuit) alleging that
- THIS IMPLEMENTATION constitutes direct or contributory patent
- infringement, or inducement of patent infringement, then any rights
- granted to you under this License shall terminate as of the date
- such litigation is filed. If you or your agent or exclusive
- licensee institute or order or agree to the institution of a PATENT
- CHALLENGE, then Tokutek may terminate any rights granted to you
- under this License.
-*/
-
-#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
-
-#include "test.h"
-
-#include <util/dmt.h>
-
-static void
-parse_args (int argc, const char *argv[]) {
- const char *argv0=argv[0];
- while (argc>1) {
- int resultcode=0;
- if (strcmp(argv[1], "-v")==0) {
- verbose++;
- } else if (strcmp(argv[1], "-q")==0) {
- verbose = 0;
- } else if (strcmp(argv[1], "-h")==0) {
- do_usage:
- fprintf(stderr, "Usage:\n%s [-v|-h]\n", argv0);
- exit(resultcode);
- } else {
- resultcode=1;
- goto do_usage;
- }
- argc--;
- argv++;
- }
-}
-/* End ".h like" stuff. */
-
-struct value {
- uint32_t number;
-};
-#define V(x) ((struct value *)(x))
-
-
-
-const uint32_t MAXNUM = 1024;
-const uint32_t MAXLEN = 32;
-char data[MAXNUM][MAXLEN];
-
-struct val_type {
- char c[MAXLEN];
-};
-
-namespace toku {
-class vwriter {
- public:
- size_t get_size(void) const {
- size_t len = strlen(v.c);
- invariant(len < sizeof(val_type));
- return len + 1;
- }
- void write_to(val_type *const dest) const {
- strcpy(dest->c, v.c);
- }
-
- vwriter(const char* c) {
- invariant(strlen(c) < sizeof(val_type));
- strcpy(v.c, c);
- }
-
- vwriter(const uint32_t klpair_len, val_type *const src) {
- invariant(strlen(src->c) < sizeof(val_type));
- strcpy(v.c, src->c);
- invariant(klpair_len == get_size());
- }
- private:
- val_type v;
-};
-}
-
-/* Globals */
-typedef toku::dmt<val_type, val_type*, toku::vwriter> vdmt;
-
-const unsigned int random_seed = 0xFEADACBA;
-
-///////////////
-
-
-static void fail_one_verify(uint32_t len, uint32_t num, vdmt *v) {
- val_type* fetched_data;
- int count = 0;
- v->verify();
- for (uint32_t i = 0; i < num; i++) {
- uint32_t fetched_len;
- int r = v->fetch(i-count, &fetched_len, &fetched_data);
- if (r != 0 || fetched_len != len || strcmp(fetched_data->c, data[i])) {
- count++;
- continue;
- }
- }
- invariant(count == 1);
-}
-
-static void verify(uint32_t len, uint32_t num, vdmt *v) {
- v->verify();
- val_type* fetched_data;
- for (uint32_t i = 0; i < num; i++) {
- uint32_t fetched_len;
- int r = v->fetch(i, &fetched_len, &fetched_data);
- CKERR(r);
- invariant(fetched_len == len);
- invariant(!strcmp(fetched_data->c, data[i]));
- }
-}
-
-
-static void test_builder_fixed(uint32_t len, uint32_t num) {
- srandom(random_seed);
- assert(len > 1);
- assert(len <= MAXLEN);
- assert(num <= MAXNUM);
- for (uint32_t i = 0; i < num; i++) {
- for (uint32_t j = 0; j < len-1; j++) {
- data[i][j] = random() % 255 + 1; //This way it doesn't end up being 0 and thought of as NUL
- }
- data[i][len-1] = '\0'; //cap it
- }
-
- vdmt::builder builder;
- builder.create(num, num * len);
-
- for (uint32_t i = 0; i < num; i++) {
- vwriter vfun(data[i]);
- builder.append(vfun);
- }
- invariant(builder.value_length_is_fixed());
- vdmt v;
- builder.build(&v);
- invariant(v.value_length_is_fixed());
- invariant(v.get_fixed_length() == len || num == 0);
-
- invariant(v.size() == num);
-
- verify(len, num, &v);
-
- for (uint32_t change = 0; change < num; change++) {
- vdmt v2;
- v2.clone(v);
- v2.delete_at(change);
- fail_one_verify(len, num, &v2);
-
- vwriter vfun(data[change]);
- v2.insert_at(vfun, change);
- verify(len, num, &v2);
- v2.destroy();
- }
-
- v.destroy();
-}
-
-static void test_builder_variable(uint32_t len, uint32_t len2, uint32_t num) {
- srandom(random_seed);
- assert(len > 1);
- assert(len <= MAXLEN);
- assert(num <= MAXNUM);
- assert(num > 3);
- uint32_t which2 = random() % num;
- for (uint32_t i = 0; i < num; i++) {
- uint32_t thislen = i == which2 ? len2 : len;
- for (uint32_t j = 0; j < thislen-1; j++) {
- data[i][j] = random() % 255 + 1; //This way it doesn't end up being 0 and thought of as NUL
- }
- data[i][thislen-1] = '\0'; //cap it
- }
-
- vdmt::builder builder;
- builder.create(num, (num-1) * len + len2);
-
- for (uint32_t i = 0; i < num; i++) {
- vwriter vfun(data[i]);
- builder.append(vfun);
- }
- invariant(!builder.value_length_is_fixed());
- vdmt v;
- builder.build(&v);
- invariant(!v.value_length_is_fixed());
-
- invariant(v.size() == num);
-
- val_type* fetched_data;
- for (uint32_t i = 0; i < num; i++) {
- uint32_t fetched_len;
- int r = v.fetch(i, &fetched_len, &fetched_data);
- CKERR(r);
- if (i == which2) {
- invariant(fetched_len == len2);
- invariant(!strcmp(fetched_data->c, data[i]));
- } else {
- invariant(fetched_len == len);
- invariant(!strcmp(fetched_data->c, data[i]));
- }
- }
-
- v.destroy();
-}
-
-static void test_create_from_sorted_memory_of_fixed_sized_elements_and_serialize(uint32_t len, uint32_t num) {
- srandom(random_seed);
- assert(len <= MAXLEN);
- assert(num <= MAXNUM);
- for (uint32_t i = 0; i < num; i++) {
- for (uint32_t j = 0; j < len-1; j++) {
- data[i][j] = random() % 255 + 1; //This way it doesn't end up being 0 and thought of as NUL
- }
- data[i][len-1] = '\0'; //cap it
- }
-
- char *flat = (char*)toku_xmalloc(len * num);
- char *p = flat;
- for (uint32_t i = 0; i < num; i++) {
- memcpy(p, data[i], len);
- p += len;
- }
- vdmt v;
-
- v.create_from_sorted_memory_of_fixed_size_elements(flat, num, len*num, len);
- invariant(v.value_length_is_fixed());
- invariant(v.get_fixed_length() == len);
-
- invariant(v.size() == num);
-
- val_type* fetched_data;
- for (uint32_t i = 0; i < num; i++) {
- uint32_t fetched_len;
- int r = v.fetch(i, &fetched_len, &fetched_data);
- CKERR(r);
- invariant(fetched_len == len);
- invariant(!strcmp(fetched_data->c, data[i]));
- }
-
- char *serialized_flat = (char*)toku_xmalloc(len*num);
- struct wbuf wb;
- wbuf_nocrc_init(&wb, serialized_flat, len*num);
- v.prepare_for_serialize();
- v.serialize_values(len*num, &wb);
- invariant(!memcmp(serialized_flat, flat, len*num));
-
-
- if (num > 1) {
- //Currently converting to dtree treats the entire thing as NOT fixed length.
- //Optional additional perf here.
- uint32_t which = (random() % (num-1)) + 1; // Not last, not first
- invariant(which > 0 && which < num-1);
- v.delete_at(which);
-
- memmove(flat + which*len, flat+(which+1)*len, (num-which-1) * len);
- v.prepare_for_serialize();
- wbuf_nocrc_init(&wb, serialized_flat, len*(num-1));
- v.serialize_values(len*(num-1), &wb);
- invariant(!memcmp(serialized_flat, flat, len*(num-1)));
- }
-
- toku_free(flat);
- toku_free(serialized_flat);
-
- v.destroy();
-}
-
-int
-test_main(int argc, const char *argv[]) {
- parse_args(argc, argv);
- // Do test with size divisible by 4 and not
- test_builder_fixed(4, 0);
- test_builder_fixed(5, 0);
- test_builder_fixed(4, 1);
- test_builder_fixed(5, 1);
- test_builder_fixed(4, 100);
- test_builder_fixed(5, 100);
- // Do test with zero, one, or both sizes divisible
- test_builder_variable(4, 8, 100);
- test_builder_variable(4, 5, 100);
- test_builder_variable(5, 8, 100);
- test_builder_variable(5, 10, 100);
-
- test_create_from_sorted_memory_of_fixed_sized_elements_and_serialize(4, 0);
- test_create_from_sorted_memory_of_fixed_sized_elements_and_serialize(5, 0);
- test_create_from_sorted_memory_of_fixed_sized_elements_and_serialize(4, 1);
- test_create_from_sorted_memory_of_fixed_sized_elements_and_serialize(5, 1);
- test_create_from_sorted_memory_of_fixed_sized_elements_and_serialize(4, 100);
- test_create_from_sorted_memory_of_fixed_sized_elements_and_serialize(5, 100);
-
- return 0;
-}
-
diff --git a/storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc b/storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc
index 8759732a76e..4bf02021d23 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc
@@ -101,9 +101,9 @@ int64_key_cmp (DB *db UU(), const DBT *a, const DBT *b) {
}
static void
-test_prefetch_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
+test_prefetch_read(int fd, FT_HANDLE UU(brt), FT brt_h) {
int r;
- ft_h->compare_fun = int64_key_cmp;
+ brt_h->compare_fun = int64_key_cmp;
FT_CURSOR XMALLOC(cursor);
FTNODE dn = NULL;
PAIR_ATTR attr;
@@ -120,7 +120,7 @@ test_prefetch_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
// quick test to see that we have the right behavior when we set
// disable_prefetching to true
cursor->disable_prefetching = true;
- fill_bfe_for_prefetch(&bfe, ft_h, cursor);
+ fill_bfe_for_prefetch(&bfe, brt_h, cursor);
FTNODE_DISK_DATA ndd = NULL;
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd, &bfe);
assert(r==0);
@@ -139,14 +139,14 @@ test_prefetch_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
// now enable prefetching again
cursor->disable_prefetching = false;
- fill_bfe_for_prefetch(&bfe, ft_h, cursor);
+ fill_bfe_for_prefetch(&bfe, brt_h, cursor);
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd, &bfe);
assert(r==0);
assert(dn->n_children == 3);
assert(BP_STATE(dn,0) == PT_AVAIL);
assert(BP_STATE(dn,1) == PT_AVAIL);
assert(BP_STATE(dn,2) == PT_AVAIL);
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_COMPRESSED);
assert(BP_STATE(dn,1) == PT_COMPRESSED);
assert(BP_STATE(dn,2) == PT_COMPRESSED);
@@ -161,14 +161,14 @@ test_prefetch_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
uint64_t left_key = 150;
toku_fill_dbt(&cursor->range_lock_left_key, &left_key, sizeof(uint64_t));
cursor->left_is_neg_infty = false;
- fill_bfe_for_prefetch(&bfe, ft_h, cursor);
+ fill_bfe_for_prefetch(&bfe, brt_h, cursor);
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd, &bfe);
assert(r==0);
assert(dn->n_children == 3);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_AVAIL);
assert(BP_STATE(dn,2) == PT_AVAIL);
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_COMPRESSED);
assert(BP_STATE(dn,2) == PT_COMPRESSED);
@@ -183,14 +183,14 @@ test_prefetch_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
uint64_t right_key = 151;
toku_fill_dbt(&cursor->range_lock_right_key, &right_key, sizeof(uint64_t));
cursor->right_is_pos_infty = false;
- fill_bfe_for_prefetch(&bfe, ft_h, cursor);
+ fill_bfe_for_prefetch(&bfe, brt_h, cursor);
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd, &bfe);
assert(r==0);
assert(dn->n_children == 3);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_AVAIL);
assert(BP_STATE(dn,2) == PT_ON_DISK);
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_COMPRESSED);
assert(BP_STATE(dn,2) == PT_ON_DISK);
@@ -204,14 +204,14 @@ test_prefetch_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
left_key = 100000;
right_key = 100000;
- fill_bfe_for_prefetch(&bfe, ft_h, cursor);
+ fill_bfe_for_prefetch(&bfe, brt_h, cursor);
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd, &bfe);
assert(r==0);
assert(dn->n_children == 3);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_ON_DISK);
assert(BP_STATE(dn,2) == PT_AVAIL);
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_ON_DISK);
assert(BP_STATE(dn,2) == PT_COMPRESSED);
@@ -225,14 +225,14 @@ test_prefetch_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
left_key = 100;
right_key = 100;
- fill_bfe_for_prefetch(&bfe, ft_h, cursor);
+ fill_bfe_for_prefetch(&bfe, brt_h, cursor);
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd, &bfe);
assert(r==0);
assert(dn->n_children == 3);
assert(BP_STATE(dn,0) == PT_AVAIL);
assert(BP_STATE(dn,1) == PT_ON_DISK);
assert(BP_STATE(dn,2) == PT_ON_DISK);
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_COMPRESSED);
assert(BP_STATE(dn,1) == PT_ON_DISK);
assert(BP_STATE(dn,2) == PT_ON_DISK);
@@ -248,9 +248,9 @@ test_prefetch_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
}
static void
-test_subset_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
+test_subset_read(int fd, FT_HANDLE UU(brt), FT brt_h) {
int r;
- ft_h->compare_fun = int64_key_cmp;
+ brt_h->compare_fun = int64_key_cmp;
FT_CURSOR XMALLOC(cursor);
FTNODE dn = NULL;
FTNODE_DISK_DATA ndd = NULL;
@@ -271,7 +271,7 @@ test_subset_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
toku_fill_dbt(&right, &right_key, sizeof(right_key));
fill_bfe_for_subset_read(
&bfe,
- ft_h,
+ brt_h,
NULL,
&left,
&right,
@@ -292,11 +292,11 @@ test_subset_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
assert(BP_STATE(dn,1) == PT_ON_DISK);
assert(BP_STATE(dn,2) == PT_AVAIL);
// need to call this twice because we had a subset read before, that touched the clock
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_ON_DISK);
assert(BP_STATE(dn,2) == PT_AVAIL);
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_ON_DISK);
assert(BP_STATE(dn,2) == PT_COMPRESSED);
@@ -317,11 +317,11 @@ test_subset_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
assert(BP_STATE(dn,1) == PT_AVAIL);
assert(BP_STATE(dn,2) == PT_AVAIL);
// need to call this twice because we had a subset read before, that touched the clock
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_COMPRESSED);
assert(BP_STATE(dn,2) == PT_AVAIL);
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_ON_DISK);
assert(BP_STATE(dn,1) == PT_COMPRESSED);
assert(BP_STATE(dn,2) == PT_COMPRESSED);
@@ -341,11 +341,11 @@ test_subset_read(int fd, FT_HANDLE UU(ft), FT ft_h) {
assert(BP_STATE(dn,1) == PT_AVAIL);
assert(BP_STATE(dn,2) == PT_ON_DISK);
// need to call this twice because we had a subset read before, that touched the clock
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_AVAIL);
assert(BP_STATE(dn,1) == PT_COMPRESSED);
assert(BP_STATE(dn,2) == PT_ON_DISK);
- toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(dn,0) == PT_COMPRESSED);
assert(BP_STATE(dn,1) == PT_COMPRESSED);
assert(BP_STATE(dn,2) == PT_ON_DISK);
@@ -412,9 +412,9 @@ test_prefetching(void) {
xids_destroy(&xids_123);
xids_destroy(&xids_234);
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -422,32 +422,32 @@ test_prefetching(void) {
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ brt->ft = brt_h;
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA ndd = NULL;
- r = toku_serialize_ftnode_to(fd, make_blocknum(20), &sn, &ndd, true, ft->ft, false);
+ r = toku_serialize_ftnode_to(fd, make_blocknum(20), &sn, &ndd, true, brt->ft, false);
assert(r==0);
- test_prefetch_read(fd, ft, ft_h);
- test_subset_read(fd, ft, ft_h);
+ test_prefetch_read(fd, brt, brt_h);
+ test_subset_read(fd, brt, brt_h);
toku_free(sn.childkeys[0].data);
toku_free(sn.childkeys[1].data);
@@ -457,11 +457,11 @@ test_prefetching(void) {
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(ndd);
r = close(fd); assert(r != -1);
diff --git a/storage/tokudb/ft-index/ft/tests/ft-clock-test.cc b/storage/tokudb/ft-index/ft/tests/ft-clock-test.cc
index b637b9d3986..ce31c04bac7 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-clock-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-clock-test.cc
@@ -115,18 +115,13 @@ le_add_to_bn(bn_data* bn, uint32_t idx, const char *key, int keylen, const char
{
LEAFENTRY r = NULL;
uint32_t size_needed = LE_CLEAN_MEMSIZE(vallen);
- void *maybe_free = nullptr;
bn->get_space_for_insert(
idx,
key,
keylen,
size_needed,
- &r,
- &maybe_free
+ &r
);
- if (maybe_free) {
- toku_free(maybe_free);
- }
resource_assert(r);
r->type = LE_CLEAN;
r->u.clean.vallen = vallen;
@@ -144,11 +139,11 @@ le_malloc(bn_data* bn, uint32_t idx, const char *key, const char *val)
static void
-test1(int fd, FT ft_h, FTNODE *dn) {
+test1(int fd, FT brt_h, FTNODE *dn) {
int r;
struct ftnode_fetch_extra bfe_all;
- ft_h->compare_fun = string_key_cmp;
- fill_bfe_for_full_read(&bfe_all, ft_h);
+ brt_h->compare_fun = string_key_cmp;
+ fill_bfe_for_full_read(&bfe_all, brt_h);
FTNODE_DISK_DATA ndd = NULL;
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, dn, &ndd, &bfe_all);
bool is_leaf = ((*dn)->height == 0);
@@ -159,12 +154,12 @@ test1(int fd, FT ft_h, FTNODE *dn) {
// should sweep and NOT get rid of anything
PAIR_ATTR attr;
memset(&attr,0,sizeof(attr));
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
for (int i = 0; i < (*dn)->n_children; i++) {
assert(BP_STATE(*dn,i) == PT_AVAIL);
}
// should sweep and get compress all
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
for (int i = 0; i < (*dn)->n_children; i++) {
if (!is_leaf) {
assert(BP_STATE(*dn,i) == PT_COMPRESSED);
@@ -177,12 +172,12 @@ test1(int fd, FT ft_h, FTNODE *dn) {
bool req = toku_ftnode_pf_req_callback(*dn, &bfe_all);
assert(req);
toku_ftnode_pf_callback(*dn, ndd, &bfe_all, fd, &size);
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
for (int i = 0; i < (*dn)->n_children; i++) {
assert(BP_STATE(*dn,i) == PT_AVAIL);
}
// should sweep and get compress all
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
for (int i = 0; i < (*dn)->n_children; i++) {
if (!is_leaf) {
assert(BP_STATE(*dn,i) == PT_COMPRESSED);
@@ -195,15 +190,15 @@ test1(int fd, FT ft_h, FTNODE *dn) {
req = toku_ftnode_pf_req_callback(*dn, &bfe_all);
assert(req);
toku_ftnode_pf_callback(*dn, ndd, &bfe_all, fd, &size);
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
for (int i = 0; i < (*dn)->n_children; i++) {
assert(BP_STATE(*dn,i) == PT_AVAIL);
}
(*dn)->dirty = 1;
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
for (int i = 0; i < (*dn)->n_children; i++) {
assert(BP_STATE(*dn,i) == PT_AVAIL);
}
@@ -217,7 +212,7 @@ static int search_cmp(const struct ft_search& UU(so), const DBT* UU(key)) {
}
static void
-test2(int fd, FT ft_h, FTNODE *dn) {
+test2(int fd, FT brt_h, FTNODE *dn) {
struct ftnode_fetch_extra bfe_subset;
DBT left, right;
DB dummy_db;
@@ -226,10 +221,10 @@ test2(int fd, FT ft_h, FTNODE *dn) {
memset(&right, 0, sizeof(right));
ft_search_t search_t;
- ft_h->compare_fun = string_key_cmp;
+ brt_h->compare_fun = string_key_cmp;
fill_bfe_for_subset_read(
&bfe_subset,
- ft_h,
+ brt_h,
ft_search_init(&search_t, search_cmp, FT_SEARCH_LEFT, nullptr, nullptr, nullptr),
&left,
&right,
@@ -251,11 +246,11 @@ test2(int fd, FT ft_h, FTNODE *dn) {
assert(!BP_SHOULD_EVICT(*dn, 1));
PAIR_ATTR attr;
memset(&attr,0,sizeof(attr));
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(*dn, 0) == (is_leaf) ? PT_ON_DISK : PT_COMPRESSED);
assert(BP_STATE(*dn, 1) == PT_AVAIL);
assert(BP_SHOULD_EVICT(*dn, 1));
- toku_ftnode_pe_callback(*dn, attr, ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, attr, brt_h, def_pe_finalize_impl, nullptr);
assert(BP_STATE(*dn, 1) == (is_leaf) ? PT_ON_DISK : PT_COMPRESSED);
bool req = toku_ftnode_pf_req_callback(*dn, &bfe_subset);
@@ -271,7 +266,7 @@ test2(int fd, FT ft_h, FTNODE *dn) {
}
static void
-test3_leaf(int fd, FT ft_h, FTNODE *dn) {
+test3_leaf(int fd, FT brt_h, FTNODE *dn) {
struct ftnode_fetch_extra bfe_min;
DBT left, right;
DB dummy_db;
@@ -279,10 +274,10 @@ test3_leaf(int fd, FT ft_h, FTNODE *dn) {
memset(&left, 0, sizeof(left));
memset(&right, 0, sizeof(right));
- ft_h->compare_fun = string_key_cmp;
+ brt_h->compare_fun = string_key_cmp;
fill_bfe_for_min_read(
&bfe_min,
- ft_h
+ brt_h
);
FTNODE_DISK_DATA ndd = NULL;
int r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, dn, &ndd, &bfe_min);
@@ -346,9 +341,9 @@ test_serialize_nonleaf(void) {
xids_destroy(&xids_123);
xids_destroy(&xids_234);
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -356,33 +351,33 @@ test_serialize_nonleaf(void) {
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA ndd = NULL;
- r = toku_serialize_ftnode_to(fd, make_blocknum(20), &sn, &ndd, true, ft->ft, false);
+ r = toku_serialize_ftnode_to(fd, make_blocknum(20), &sn, &ndd, true, brt->ft, false);
assert(r==0);
- test1(fd, ft_h, &dn);
- test2(fd, ft_h, &dn);
+ test1(fd, brt_h, &dn);
+ test2(fd, brt_h, &dn);
toku_free(hello_string);
destroy_nonleaf_childinfo(BNC(&sn, 0));
@@ -391,11 +386,11 @@ test_serialize_nonleaf(void) {
toku_free(sn.childkeys);
toku_free(ndd);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
r = close(fd); assert(r != -1);
}
@@ -430,9 +425,9 @@ test_serialize_leaf(void) {
le_malloc(BLB_DATA(&sn, 0), 1, "b", "bval");
le_malloc(BLB_DATA(&sn, 1), 0, "x", "xval");
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -440,33 +435,33 @@ test_serialize_leaf(void) {
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA ndd = NULL;
- r = toku_serialize_ftnode_to(fd, make_blocknum(20), &sn, &ndd, true, ft->ft, false);
+ r = toku_serialize_ftnode_to(fd, make_blocknum(20), &sn, &ndd, true, brt->ft, false);
assert(r==0);
- test1(fd, ft_h, &dn);
- test3_leaf(fd, ft_h,&dn);
+ test1(fd, brt_h, &dn);
+ test3_leaf(fd, brt_h,&dn);
for (int i = 0; i < sn.n_children-1; ++i) {
toku_free(sn.childkeys[i].data);
@@ -477,11 +472,11 @@ test_serialize_leaf(void) {
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(ndd);
r = close(fd); assert(r != -1);
}
diff --git a/storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc b/storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc
index 285ee64e8a3..42351e3108d 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc
@@ -105,18 +105,13 @@ le_add_to_bn(bn_data* bn, uint32_t idx, char *key, int keylen, char *val, int va
{
LEAFENTRY r = NULL;
uint32_t size_needed = LE_CLEAN_MEMSIZE(vallen);
- void *maybe_free = nullptr;
bn->get_space_for_insert(
idx,
key,
keylen,
size_needed,
- &r,
- &maybe_free
+ &r
);
- if (maybe_free) {
- toku_free(maybe_free);
- }
resource_assert(r);
r->type = LE_CLEAN;
r->u.clean.vallen = vallen;
@@ -132,7 +127,7 @@ long_key_cmp(DB *UU(e), const DBT *a, const DBT *b)
}
static void
-test_serialize_leaf(int valsize, int nelts, double entropy, int ser_runs, int deser_runs) {
+test_serialize_leaf(int valsize, int nelts, double entropy) {
// struct ft_handle source_ft;
struct ftnode *sn, *dn;
@@ -186,9 +181,9 @@ test_serialize_leaf(int valsize, int nelts, double entropy, int ser_runs, int de
}
}
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -196,99 +191,70 @@ test_serialize_leaf(int valsize, int nelts, double entropy, int ser_runs, int de
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- ft_h->compare_fun = long_key_cmp;
- toku_blocktable_create_new(&ft_h->blocktable);
+ brt_h->compare_fun = long_key_cmp;
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
- struct timeval total_start;
- struct timeval total_end;
- total_start.tv_sec = total_start.tv_usec = 0;
- total_end.tv_sec = total_end.tv_usec = 0;
struct timeval t[2];
+ gettimeofday(&t[0], NULL);
FTNODE_DISK_DATA ndd = NULL;
- for (int i = 0; i < ser_runs; i++) {
- gettimeofday(&t[0], NULL);
- ndd = NULL;
- sn->dirty = 1;
- r = toku_serialize_ftnode_to(fd, make_blocknum(20), sn, &ndd, true, ft->ft, false);
- assert(r==0);
- gettimeofday(&t[1], NULL);
- total_start.tv_sec += t[0].tv_sec;
- total_start.tv_usec += t[0].tv_usec;
- total_end.tv_sec += t[1].tv_sec;
- total_end.tv_usec += t[1].tv_usec;
- toku_free(ndd);
- }
+ r = toku_serialize_ftnode_to(fd, make_blocknum(20), sn, &ndd, true, brt->ft, false);
+ assert(r==0);
+ gettimeofday(&t[1], NULL);
double dt;
- dt = (total_end.tv_sec - total_start.tv_sec) + ((total_end.tv_usec - total_start.tv_usec) / USECS_PER_SEC);
- dt *= 1000;
- dt /= ser_runs;
- printf("serialize leaf(ms): %0.05lf (average of %d runs)\n", dt, ser_runs);
-
- //reset
- total_start.tv_sec = total_start.tv_usec = 0;
- total_end.tv_sec = total_end.tv_usec = 0;
+ dt = (t[1].tv_sec - t[0].tv_sec) + ((t[1].tv_usec - t[0].tv_usec) / USECS_PER_SEC);
+ printf("serialize leaf: %0.05lf\n", dt);
struct ftnode_fetch_extra bfe;
- for (int i = 0; i < deser_runs; i++) {
- fill_bfe_for_full_read(&bfe, ft_h);
- gettimeofday(&t[0], NULL);
- FTNODE_DISK_DATA ndd2 = NULL;
- r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd2, &bfe);
- assert(r==0);
- gettimeofday(&t[1], NULL);
-
- total_start.tv_sec += t[0].tv_sec;
- total_start.tv_usec += t[0].tv_usec;
- total_end.tv_sec += t[1].tv_sec;
- total_end.tv_usec += t[1].tv_usec;
-
- toku_ftnode_free(&dn);
- toku_free(ndd2);
- }
- dt = (total_end.tv_sec - total_start.tv_sec) + ((total_end.tv_usec - total_start.tv_usec) / USECS_PER_SEC);
- dt *= 1000;
- dt /= deser_runs;
- printf("deserialize leaf(ms): %0.05lf (average of %d runs)\n", dt, deser_runs);
- printf("io time(ms) %lf decompress time(ms) %lf deserialize time(ms) %lf (average of %d runs)\n",
- tokutime_to_seconds(bfe.io_time)*1000,
- tokutime_to_seconds(bfe.decompress_time)*1000,
- tokutime_to_seconds(bfe.deserialize_time)*1000,
- deser_runs
+ fill_bfe_for_full_read(&bfe, brt_h);
+ gettimeofday(&t[0], NULL);
+ FTNODE_DISK_DATA ndd2 = NULL;
+ r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd2, &bfe);
+ assert(r==0);
+ gettimeofday(&t[1], NULL);
+ dt = (t[1].tv_sec - t[0].tv_sec) + ((t[1].tv_usec - t[0].tv_usec) / USECS_PER_SEC);
+ printf("deserialize leaf: %0.05lf\n", dt);
+ printf("io time %lf decompress time %lf deserialize time %lf\n",
+ tokutime_to_seconds(bfe.io_time),
+ tokutime_to_seconds(bfe.decompress_time),
+ tokutime_to_seconds(bfe.deserialize_time)
);
+ toku_ftnode_free(&dn);
toku_ftnode_free(&sn);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
+ toku_free(ndd);
+ toku_free(ndd2);
r = close(fd); assert(r != -1);
}
static void
-test_serialize_nonleaf(int valsize, int nelts, double entropy, int ser_runs, int deser_runs) {
+test_serialize_nonleaf(int valsize, int nelts, double entropy) {
// struct ft_handle source_ft;
struct ftnode sn, *dn;
@@ -346,9 +312,9 @@ test_serialize_nonleaf(int valsize, int nelts, double entropy, int ser_runs, int
xids_destroy(&xids_0);
xids_destroy(&xids_123);
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -356,25 +322,25 @@ test_serialize_nonleaf(int valsize, int nelts, double entropy, int ser_runs, int
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- ft_h->compare_fun = long_key_cmp;
- toku_blocktable_create_new(&ft_h->blocktable);
+ brt_h->compare_fun = long_key_cmp;
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
@@ -382,29 +348,26 @@ test_serialize_nonleaf(int valsize, int nelts, double entropy, int ser_runs, int
struct timeval t[2];
gettimeofday(&t[0], NULL);
FTNODE_DISK_DATA ndd = NULL;
- r = toku_serialize_ftnode_to(fd, make_blocknum(20), &sn, &ndd, true, ft->ft, false);
+ r = toku_serialize_ftnode_to(fd, make_blocknum(20), &sn, &ndd, true, brt->ft, false);
assert(r==0);
gettimeofday(&t[1], NULL);
double dt;
dt = (t[1].tv_sec - t[0].tv_sec) + ((t[1].tv_usec - t[0].tv_usec) / USECS_PER_SEC);
- dt *= 1000;
- printf("serialize nonleaf(ms): %0.05lf (IGNORED RUNS=%d)\n", dt, ser_runs);
+ printf("serialize nonleaf: %0.05lf\n", dt);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_h);
+ fill_bfe_for_full_read(&bfe, brt_h);
gettimeofday(&t[0], NULL);
FTNODE_DISK_DATA ndd2 = NULL;
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, &dn, &ndd2, &bfe);
assert(r==0);
gettimeofday(&t[1], NULL);
dt = (t[1].tv_sec - t[0].tv_sec) + ((t[1].tv_usec - t[0].tv_usec) / USECS_PER_SEC);
- dt *= 1000;
- printf("deserialize nonleaf(ms): %0.05lf (IGNORED RUNS=%d)\n", dt, deser_runs);
- printf("io time(ms) %lf decompress time(ms) %lf deserialize time(ms) %lf (IGNORED RUNS=%d)\n",
- tokutime_to_seconds(bfe.io_time)*1000,
- tokutime_to_seconds(bfe.decompress_time)*1000,
- tokutime_to_seconds(bfe.deserialize_time)*1000,
- deser_runs
+ printf("deserialize nonleaf: %0.05lf\n", dt);
+ printf("io time %lf decompress time %lf deserialize time %lf\n",
+ tokutime_to_seconds(bfe.io_time),
+ tokutime_to_seconds(bfe.decompress_time),
+ tokutime_to_seconds(bfe.deserialize_time)
);
toku_ftnode_free(&dn);
@@ -418,11 +381,11 @@ test_serialize_nonleaf(int valsize, int nelts, double entropy, int ser_runs, int
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(ndd);
toku_free(ndd2);
@@ -431,32 +394,19 @@ test_serialize_nonleaf(int valsize, int nelts, double entropy, int ser_runs, int
int
test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute__((__unused__))) {
- const int DEFAULT_RUNS = 5;
- long valsize, nelts, ser_runs = DEFAULT_RUNS, deser_runs = DEFAULT_RUNS;
+ long valsize, nelts;
double entropy = 0.3;
- if (argc != 3 && argc != 5) {
- fprintf(stderr, "Usage: %s <valsize> <nelts> [<serialize_runs> <deserialize_runs>]\n", argv[0]);
- fprintf(stderr, "Default (and min) runs is %d\n", DEFAULT_RUNS);
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <valsize> <nelts>\n", argv[0]);
return 2;
}
valsize = strtol(argv[1], NULL, 0);
nelts = strtol(argv[2], NULL, 0);
- if (argc == 5) {
- ser_runs = strtol(argv[3], NULL, 0);
- deser_runs = strtol(argv[4], NULL, 0);
- }
-
- if (ser_runs <= 0) {
- ser_runs = DEFAULT_RUNS;
- }
- if (deser_runs <= 0) {
- deser_runs = DEFAULT_RUNS;
- }
initialize_dummymsn();
- test_serialize_leaf(valsize, nelts, entropy, ser_runs, deser_runs);
- test_serialize_nonleaf(valsize, nelts, entropy, ser_runs, deser_runs);
+ test_serialize_leaf(valsize, nelts, entropy);
+ test_serialize_nonleaf(valsize, nelts, entropy);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/tests/ft-serialize-sub-block-test.cc b/storage/tokudb/ft-index/ft/tests/ft-serialize-sub-block-test.cc
index 47865bfcce7..ca8c806f04e 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-serialize-sub-block-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-serialize-sub-block-test.cc
@@ -92,9 +92,9 @@ PATENT RIGHTS GRANT:
#include "test.h"
-// create a ft and put n rows into it
-// write the ft to the file
-// verify the rows in the ft
+// create a brt and put n rows into it
+// write the brt to the file
+// verify the rows in the brt
static void test_sub_block(int n) {
if (verbose) printf("%s:%d %d\n", __FUNCTION__, __LINE__, n);
@@ -107,14 +107,14 @@ static void test_sub_block(int n) {
int error;
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int i;
unlink(fname);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- error = toku_open_ft_handle(fname, true, &ft, nodesize, basementnodesize, compression_method, ct, null_txn, toku_builtin_compare_fun);
+ error = toku_open_ft_handle(fname, true, &brt, nodesize, basementnodesize, compression_method, ct, null_txn, toku_builtin_compare_fun);
assert(error == 0);
// insert keys 0, 1, 2, .. (n-1)
@@ -124,20 +124,20 @@ static void test_sub_block(int n) {
DBT key, val;
toku_fill_dbt(&key, &k, sizeof k);
toku_fill_dbt(&val, &v, sizeof v);
- toku_ft_insert(ft, &key, &val, 0);
+ toku_ft_insert(brt, &key, &val, 0);
assert(error == 0);
}
// write to the file
- error = toku_close_ft_handle_nolsn(ft, 0);
+ error = toku_close_ft_handle_nolsn(brt, 0);
assert(error == 0);
- // verify the ft by walking a cursor through the rows
- error = toku_open_ft_handle(fname, false, &ft, nodesize, basementnodesize, compression_method, ct, null_txn, toku_builtin_compare_fun);
+ // verify the brt by walking a cursor through the rows
+ error = toku_open_ft_handle(fname, false, &brt, nodesize, basementnodesize, compression_method, ct, null_txn, toku_builtin_compare_fun);
assert(error == 0);
FT_CURSOR cursor;
- error = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ error = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(error == 0);
for (i=0; ; i++) {
@@ -155,7 +155,7 @@ static void test_sub_block(int n) {
toku_ft_cursor_close(cursor);
- error = toku_close_ft_handle_nolsn(ft, 0);
+ error = toku_close_ft_handle_nolsn(brt, 0);
assert(error == 0);
toku_cachetable_close(&ct);
diff --git a/storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc b/storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc
index 25a6a0227bc..adfd2b7efd4 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc
@@ -98,53 +98,57 @@ PATENT RIGHTS GRANT:
#endif
static size_t
+calc_le_size(int keylen, int vallen) {
+ return LE_CLEAN_MEMSIZE(vallen) + keylen + sizeof(uint32_t);
+}
+
+static void
le_add_to_bn(bn_data* bn, uint32_t idx, const char *key, int keysize, const char *val, int valsize)
{
LEAFENTRY r = NULL;
uint32_t size_needed = LE_CLEAN_MEMSIZE(valsize);
- void *maybe_free = nullptr;
bn->get_space_for_insert(
- idx,
+ idx,
key,
keysize,
size_needed,
- &r,
- &maybe_free
+ &r
);
- if (maybe_free) {
- toku_free(maybe_free);
- }
resource_assert(r);
r->type = LE_CLEAN;
r->u.clean.vallen = valsize;
memcpy(r->u.clean.val, val, valsize);
- return size_needed + keysize + sizeof(uint32_t);
}
-class test_key_le_pair {
- public:
- uint32_t keylen;
- char* keyp;
- LEAFENTRY le;
-
- test_key_le_pair() : keylen(), keyp(), le() {}
- void init(const char *_keyp, const char *_val) {
- init(_keyp, strlen(_keyp) + 1, _val, strlen(_val) + 1);
- }
- void init(const char * _keyp, uint32_t _keylen, const char*_val, uint32_t _vallen) {
- keylen = _keylen;
+static KLPAIR
+le_fastmalloc(struct mempool * mp, const char *key, int keylen, const char *val, int vallen)
+{
+ KLPAIR kl;
+ size_t le_size = calc_le_size(keylen, vallen);
+ CAST_FROM_VOIDP(kl, toku_mempool_malloc(mp, le_size, 1));
+ resource_assert(kl);
+ kl->keylen = keylen;
+ memcpy(kl->key_le, key, keylen);
+ LEAFENTRY le = get_le_from_klpair(kl);
+ le->type = LE_CLEAN;
+ le->u.clean.vallen = vallen;
+ memcpy(le->u.clean.val, val, vallen);
+ return kl;
+}
- CAST_FROM_VOIDP(le, toku_malloc(LE_CLEAN_MEMSIZE(_vallen)));
- le->type = LE_CLEAN;
- le->u.clean.vallen = _vallen;
- memcpy(le->u.clean.val, _val, _vallen);
+static KLPAIR
+le_malloc(struct mempool * mp, const char *key, const char *val)
+{
+ int keylen = strlen(key) + 1;
+ int vallen = strlen(val) + 1;
+ return le_fastmalloc(mp, key, keylen, val, vallen);
+}
- CAST_FROM_VOIDP(keyp, toku_xmemdup(_keyp, keylen));
- }
- ~test_key_le_pair() {
- toku_free(le);
- toku_free(keyp);
- }
+struct check_leafentries_struct {
+ int nelts;
+ LEAFENTRY *elts;
+ int i;
+ int (*cmp)(OMTVALUE, void *);
};
enum ftnode_verify_type {
@@ -162,18 +166,18 @@ string_key_cmp(DB *UU(e), const DBT *a, const DBT *b)
}
static void
-setup_dn(enum ftnode_verify_type bft, int fd, FT ft_h, FTNODE *dn, FTNODE_DISK_DATA* ndd) {
+setup_dn(enum ftnode_verify_type bft, int fd, FT brt_h, FTNODE *dn, FTNODE_DISK_DATA* ndd) {
int r;
- ft_h->compare_fun = string_key_cmp;
+ brt_h->compare_fun = string_key_cmp;
if (bft == read_all) {
struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft_h);
+ fill_bfe_for_full_read(&bfe, brt_h);
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, dn, ndd, &bfe);
assert(r==0);
}
else if (bft == read_compressed || bft == read_none) {
struct ftnode_fetch_extra bfe;
- fill_bfe_for_min_read(&bfe, ft_h);
+ fill_bfe_for_min_read(&bfe, brt_h);
r = toku_deserialize_ftnode_from(fd, make_blocknum(20), 0/*pass zero for hash*/, dn, ndd, &bfe);
assert(r==0);
// assert all bp's are compressed or on disk.
@@ -183,7 +187,7 @@ setup_dn(enum ftnode_verify_type bft, int fd, FT ft_h, FTNODE *dn, FTNODE_DISK_D
// if read_none, get rid of the compressed bp's
if (bft == read_none) {
if ((*dn)->height == 0) {
- toku_ftnode_pe_callback(*dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
// assert all bp's are on disk
for (int i = 0; i < (*dn)->n_children; i++) {
if ((*dn)->height == 0) {
@@ -200,7 +204,7 @@ setup_dn(enum ftnode_verify_type bft, int fd, FT ft_h, FTNODE *dn, FTNODE_DISK_D
// that it is available
// then run partial eviction to get it compressed
PAIR_ATTR attr;
- fill_bfe_for_full_read(&bfe, ft_h);
+ fill_bfe_for_full_read(&bfe, brt_h);
assert(toku_ftnode_pf_req_callback(*dn, &bfe));
r = toku_ftnode_pf_callback(*dn, *ndd, &bfe, fd, &attr);
assert(r==0);
@@ -208,21 +212,21 @@ setup_dn(enum ftnode_verify_type bft, int fd, FT ft_h, FTNODE *dn, FTNODE_DISK_D
for (int i = 0; i < (*dn)->n_children; i++) {
assert(BP_STATE(*dn,i) == PT_AVAIL);
}
- toku_ftnode_pe_callback(*dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
for (int i = 0; i < (*dn)->n_children; i++) {
// assert all bp's are still available, because we touched the clock
assert(BP_STATE(*dn,i) == PT_AVAIL);
// now assert all should be evicted
assert(BP_SHOULD_EVICT(*dn, i));
}
- toku_ftnode_pe_callback(*dn, make_pair_attr(0xffffffff), ft_h, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(*dn, make_pair_attr(0xffffffff), brt_h, def_pe_finalize_impl, nullptr);
for (int i = 0; i < (*dn)->n_children; i++) {
assert(BP_STATE(*dn,i) == PT_COMPRESSED);
}
}
}
// now decompress them
- fill_bfe_for_full_read(&bfe, ft_h);
+ fill_bfe_for_full_read(&bfe, brt_h);
assert(toku_ftnode_pf_req_callback(*dn, &bfe));
PAIR_ATTR attr;
r = toku_ftnode_pf_callback(*dn, *ndd, &bfe, fd, &attr);
@@ -239,20 +243,20 @@ setup_dn(enum ftnode_verify_type bft, int fd, FT ft_h, FTNODE *dn, FTNODE_DISK_D
}
}
-static void write_sn_to_disk(int fd, FT_HANDLE ft, FTNODE sn, FTNODE_DISK_DATA* src_ndd, bool do_clone) {
+static void write_sn_to_disk(int fd, FT_HANDLE brt, FTNODE sn, FTNODE_DISK_DATA* src_ndd, bool do_clone) {
int r;
if (do_clone) {
void* cloned_node_v = NULL;
PAIR_ATTR attr;
long clone_size;
- toku_ftnode_clone_callback(sn, &cloned_node_v, &clone_size, &attr, false, ft->ft);
+ toku_ftnode_clone_callback(sn, &cloned_node_v, &clone_size, &attr, false, brt->ft);
FTNODE CAST_FROM_VOIDP(cloned_node, cloned_node_v);
- r = toku_serialize_ftnode_to(fd, make_blocknum(20), cloned_node, src_ndd, false, ft->ft, false);
+ r = toku_serialize_ftnode_to(fd, make_blocknum(20), cloned_node, src_ndd, false, brt->ft, false);
assert(r==0);
toku_ftnode_free(&cloned_node);
}
else {
- r = toku_serialize_ftnode_to(fd, make_blocknum(20), sn, src_ndd, true, ft->ft, false);
+ r = toku_serialize_ftnode_to(fd, make_blocknum(20), sn, src_ndd, true, brt->ft, false);
assert(r==0);
}
}
@@ -286,15 +290,16 @@ test_serialize_leaf_check_msn(enum ftnode_verify_type bft, bool do_clone) {
BP_STATE(&sn,1) = PT_AVAIL;
set_BLB(&sn, 0, toku_create_empty_bn());
set_BLB(&sn, 1, toku_create_empty_bn());
+ KLPAIR elts[3];
le_add_to_bn(BLB_DATA(&sn, 0), 0, "a", 2, "aval", 5);
le_add_to_bn(BLB_DATA(&sn, 0), 1, "b", 2, "bval", 5);
le_add_to_bn(BLB_DATA(&sn, 1), 0, "x", 2, "xval", 5);
BLB_MAX_MSN_APPLIED(&sn, 0) = ((MSN) { MIN_MSN.msn + 73 });
BLB_MAX_MSN_APPLIED(&sn, 1) = POSTSERIALIZE_MSN_ON_DISK;
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -302,33 +307,33 @@ test_serialize_leaf_check_msn(enum ftnode_verify_type bft, bool do_clone) {
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ brt->ft = brt_h;
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA src_ndd = NULL;
FTNODE_DISK_DATA dest_ndd = NULL;
- write_sn_to_disk(fd, ft, &sn, &src_ndd, do_clone);
+ write_sn_to_disk(fd, brt, &sn, &src_ndd, do_clone);
- setup_dn(bft, fd, ft_h, &dn, &dest_ndd);
+ setup_dn(bft, fd, brt_h, &dn, &dest_ndd);
assert(dn->thisnodename.b==20);
@@ -341,10 +346,11 @@ test_serialize_leaf_check_msn(enum ftnode_verify_type bft, bool do_clone) {
{
// Man, this is way too ugly. This entire test suite needs to be refactored.
// Create a dummy mempool and put the leaves there. Ugh.
- test_key_le_pair elts[3];
- elts[0].init("a", "aval");
- elts[1].init("b", "bval");
- elts[2].init("x", "xval");
+ struct mempool dummy_mp;
+ toku_mempool_construct(&dummy_mp, 1024);
+ elts[0] = le_malloc(&dummy_mp, "a", "aval");
+ elts[1] = le_malloc(&dummy_mp, "b", "bval");
+ elts[2] = le_malloc(&dummy_mp, "x", "xval");
const uint32_t npartitions = dn->n_children;
assert(dn->totalchildkeylens==(2*(npartitions-1)));
uint32_t last_i = 0;
@@ -355,21 +361,22 @@ test_serialize_leaf_check_msn(enum ftnode_verify_type bft, bool do_clone) {
if (bn > 0) {
assert(dest_ndd[bn].start >= dest_ndd[bn-1].start + dest_ndd[bn-1].size);
}
- for (uint32_t i = 0; i < BLB_DATA(dn, bn)->num_klpairs(); i++) {
+ for (uint32_t i = 0; i < BLB_DATA(dn, bn)->omt_size(); i++) {
LEAFENTRY curr_le;
uint32_t curr_keylen;
void* curr_key;
BLB_DATA(dn, bn)->fetch_klpair(i, &curr_le, &curr_keylen, &curr_key);
- assert(leafentry_memsize(curr_le) == leafentry_memsize(elts[last_i].le));
- assert(memcmp(curr_le, elts[last_i].le, leafentry_memsize(curr_le)) == 0);
+ assert(leafentry_memsize(curr_le) == leafentry_memsize(get_le_from_klpair(elts[last_i])));
+ assert(memcmp(curr_le, get_le_from_klpair(elts[last_i]), leafentry_memsize(curr_le)) == 0);
if (bn < npartitions-1) {
- assert(strcmp((char*)dn->childkeys[bn].data, elts[last_i].keyp) <= 0);
+ assert(strcmp((char*)dn->childkeys[bn].data, (char*)(elts[last_i]->key_le)) <= 0);
}
// TODO for later, get a key comparison here as well
last_i++;
}
}
+ toku_mempool_destroy(&dummy_mp);
assert(last_i == 3);
}
toku_ftnode_free(&dn);
@@ -383,11 +390,11 @@ test_serialize_leaf_check_msn(enum ftnode_verify_type bft, bool do_clone) {
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(src_ndd);
toku_free(dest_ndd);
@@ -429,14 +436,14 @@ test_serialize_leaf_with_large_pivots(enum ftnode_verify_type bft, bool do_clone
if (i < nrows-1) {
uint32_t keylen;
void* curr_key;
- BLB_DATA(&sn, i)->fetch_key_and_len(0, &keylen, &curr_key);
+ BLB_DATA(&sn, i)->fetch_le_key_and_len(0, &keylen, &curr_key);
toku_memdup_dbt(&sn.childkeys[i], curr_key, keylen);
}
}
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -444,32 +451,32 @@ test_serialize_leaf_with_large_pivots(enum ftnode_verify_type bft, bool do_clone
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ brt->ft = brt_h;
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA src_ndd = NULL;
FTNODE_DISK_DATA dest_ndd = NULL;
- write_sn_to_disk(fd, ft, &sn, &src_ndd, do_clone);
+ write_sn_to_disk(fd, brt, &sn, &src_ndd, do_clone);
- setup_dn(bft, fd, ft_h, &dn, &dest_ndd);
+ setup_dn(bft, fd, brt_h, &dn, &dest_ndd);
assert(dn->thisnodename.b==20);
@@ -478,14 +485,18 @@ test_serialize_leaf_with_large_pivots(enum ftnode_verify_type bft, bool do_clone
{
// Man, this is way too ugly. This entire test suite needs to be refactored.
// Create a dummy mempool and put the leaves there. Ugh.
- test_key_le_pair *les = new test_key_le_pair[nrows];
+ struct mempool dummy_mp;
+ size_t le_size = calc_le_size(keylens, vallens);
+ size_t mpsize = nrows * le_size;
+ toku_mempool_construct(&dummy_mp, mpsize);
+ KLPAIR les[nrows];
{
char key[keylens], val[vallens];
key[keylens-1] = '\0';
for (uint32_t i = 0; i < nrows; ++i) {
char c = 'a' + i;
memset(key, c, keylens-1);
- les[i].init((char *) &key, sizeof(key), (char *) &val, sizeof(val));
+ les[i] = le_fastmalloc(&dummy_mp, (char *) &key, sizeof(key), (char *) &val, sizeof(val));
}
}
const uint32_t npartitions = dn->n_children;
@@ -497,23 +508,23 @@ test_serialize_leaf_with_large_pivots(enum ftnode_verify_type bft, bool do_clone
if (bn > 0) {
assert(dest_ndd[bn].start >= dest_ndd[bn-1].start + dest_ndd[bn-1].size);
}
- assert(BLB_DATA(dn, bn)->num_klpairs() > 0);
- for (uint32_t i = 0; i < BLB_DATA(dn, bn)->num_klpairs(); i++) {
+ assert(BLB_DATA(dn, bn)->omt_size() > 0);
+ for (uint32_t i = 0; i < BLB_DATA(dn, bn)->omt_size(); i++) {
LEAFENTRY curr_le;
uint32_t curr_keylen;
void* curr_key;
BLB_DATA(dn, bn)->fetch_klpair(i, &curr_le, &curr_keylen, &curr_key);
- assert(leafentry_memsize(curr_le) == leafentry_memsize(les[last_i].le));
- assert(memcmp(curr_le, les[last_i].le, leafentry_memsize(curr_le)) == 0);
+ assert(leafentry_memsize(curr_le) == leafentry_memsize(get_le_from_klpair(les[last_i])));
+ assert(memcmp(curr_le, get_le_from_klpair(les[last_i]), leafentry_memsize(curr_le)) == 0);
if (bn < npartitions-1) {
- assert(strcmp((char*)dn->childkeys[bn].data, les[last_i].keyp) <= 0);
+ assert(strcmp((char*)dn->childkeys[bn].data, (char*)(les[last_i]->key_le)) <= 0);
}
// TODO for later, get a key comparison here as well
last_i++;
}
}
+ toku_mempool_destroy(&dummy_mp);
assert(last_i == nrows);
- delete[] les;
}
toku_ftnode_free(&dn);
@@ -526,11 +537,11 @@ test_serialize_leaf_with_large_pivots(enum ftnode_verify_type bft, bool do_clone
}
toku_free(sn.bp);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(src_ndd);
toku_free(dest_ndd);
@@ -541,6 +552,7 @@ static void
test_serialize_leaf_with_many_rows(enum ftnode_verify_type bft, bool do_clone) {
int r;
struct ftnode sn, *dn;
+ const int keylens = sizeof(int), vallens = sizeof(int);
const uint32_t nrows = 196*1024;
int fd = open(TOKU_TEST_FILENAME, O_RDWR|O_CREAT|O_BINARY, S_IRWXU|S_IRWXG|S_IRWXO); assert(fd >= 0);
@@ -554,23 +566,22 @@ test_serialize_leaf_with_many_rows(enum ftnode_verify_type bft, bool do_clone) {
sn.dirty = 1;
sn.oldest_referenced_xid_known = TXNID_NONE;
- XMALLOC_N(sn.n_children, sn.bp);
- XMALLOC_N(sn.n_children-1, sn.childkeys);
+ MALLOC_N(sn.n_children, sn.bp);
+ MALLOC_N(sn.n_children-1, sn.childkeys);
sn.totalchildkeylens = (sn.n_children-1)*sizeof(int);
for (int i = 0; i < sn.n_children; ++i) {
BP_STATE(&sn,i) = PT_AVAIL;
set_BLB(&sn, i, toku_create_empty_bn());
}
- size_t total_size = 0;
for (uint32_t i = 0; i < nrows; ++i) {
uint32_t key = i;
uint32_t val = i;
- total_size += le_add_to_bn(BLB_DATA(&sn, 0), i, (char *) &key, sizeof(key), (char *) &val, sizeof(val));
+ le_add_to_bn(BLB_DATA(&sn, 0), i, (char *) &key, sizeof(key), (char *) &val, sizeof(val));
}
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -578,33 +589,33 @@ test_serialize_leaf_with_many_rows(enum ftnode_verify_type bft, bool do_clone) {
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA src_ndd = NULL;
FTNODE_DISK_DATA dest_ndd = NULL;
- write_sn_to_disk(fd, ft, &sn, &src_ndd, do_clone);
+ write_sn_to_disk(fd, brt, &sn, &src_ndd, do_clone);
- setup_dn(bft, fd, ft_h, &dn, &dest_ndd);
+ setup_dn(bft, fd, brt_h, &dn, &dest_ndd);
assert(dn->thisnodename.b==20);
@@ -613,11 +624,15 @@ test_serialize_leaf_with_many_rows(enum ftnode_verify_type bft, bool do_clone) {
{
// Man, this is way too ugly. This entire test suite needs to be refactored.
// Create a dummy mempool and put the leaves there. Ugh.
- test_key_le_pair *les = new test_key_le_pair[nrows];
+ struct mempool dummy_mp;
+ size_t le_size = calc_le_size(keylens, vallens);
+ size_t mpsize = nrows * le_size;
+ toku_mempool_construct(&dummy_mp, mpsize);
+ KLPAIR les[nrows];
{
int key = 0, val = 0;
for (uint32_t i = 0; i < nrows; ++i, key++, val++) {
- les[i].init((char *) &key, sizeof(key), (char *) &val, sizeof(val));
+ les[i] = le_fastmalloc(&dummy_mp, (char *) &key, sizeof(key), (char *) &val, sizeof(val));
}
}
const uint32_t npartitions = dn->n_children;
@@ -629,17 +644,17 @@ test_serialize_leaf_with_many_rows(enum ftnode_verify_type bft, bool do_clone) {
if (bn > 0) {
assert(dest_ndd[bn].start >= dest_ndd[bn-1].start + dest_ndd[bn-1].size);
}
- assert(BLB_DATA(dn, bn)->num_klpairs() > 0);
- for (uint32_t i = 0; i < BLB_DATA(dn, bn)->num_klpairs(); i++) {
+ assert(BLB_DATA(dn, bn)->omt_size() > 0);
+ for (uint32_t i = 0; i < BLB_DATA(dn, bn)->omt_size(); i++) {
LEAFENTRY curr_le;
uint32_t curr_keylen;
void* curr_key;
BLB_DATA(dn, bn)->fetch_klpair(i, &curr_le, &curr_keylen, &curr_key);
- assert(leafentry_memsize(curr_le) == leafentry_memsize(les[last_i].le));
- assert(memcmp(curr_le, les[last_i].le, leafentry_memsize(curr_le)) == 0);
+ assert(leafentry_memsize(curr_le) == leafentry_memsize(get_le_from_klpair(les[last_i])));
+ assert(memcmp(curr_le, get_le_from_klpair(les[last_i]), leafentry_memsize(curr_le)) == 0);
if (bn < npartitions-1) {
uint32_t *CAST_FROM_VOIDP(pivot, dn->childkeys[bn].data);
- void* tmp = les[last_i].keyp;
+ void* tmp = les[last_i]->key_le;
uint32_t *CAST_FROM_VOIDP(item, tmp);
assert(*pivot >= *item);
}
@@ -649,8 +664,8 @@ test_serialize_leaf_with_many_rows(enum ftnode_verify_type bft, bool do_clone) {
// don't check soft_copy_is_up_to_date or seqinsert
assert(BLB_DATA(dn, bn)->get_disk_size() < 128*1024); // BN_MAX_SIZE, apt to change
}
+ toku_mempool_destroy(&dummy_mp);
assert(last_i == nrows);
- delete[] les;
}
toku_ftnode_free(&dn);
@@ -663,11 +678,11 @@ test_serialize_leaf_with_many_rows(enum ftnode_verify_type bft, bool do_clone) {
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(src_ndd);
toku_free(dest_ndd);
@@ -712,9 +727,9 @@ test_serialize_leaf_with_large_rows(enum ftnode_verify_type bft, bool do_clone)
le_add_to_bn(BLB_DATA(&sn, 0), i,key, 8, val, val_size);
}
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -722,33 +737,33 @@ test_serialize_leaf_with_large_rows(enum ftnode_verify_type bft, bool do_clone)
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA src_ndd = NULL;
FTNODE_DISK_DATA dest_ndd = NULL;
- write_sn_to_disk(fd, ft, &sn, &src_ndd, do_clone);
+ write_sn_to_disk(fd, brt, &sn, &src_ndd, do_clone);
- setup_dn(bft, fd, ft_h, &dn, &dest_ndd);
+ setup_dn(bft, fd, brt_h, &dn, &dest_ndd);
assert(dn->thisnodename.b==20);
@@ -757,7 +772,11 @@ test_serialize_leaf_with_large_rows(enum ftnode_verify_type bft, bool do_clone)
{
// Man, this is way too ugly. This entire test suite needs to be refactored.
// Create a dummy mempool and put the leaves there. Ugh.
- test_key_le_pair *les = new test_key_le_pair[nrows];
+ struct mempool dummy_mp;
+ size_t le_size = calc_le_size(key_size, val_size);
+ size_t mpsize = nrows * le_size;
+ toku_mempool_construct(&dummy_mp, mpsize);
+ KLPAIR les[nrows];
{
char key[key_size], val[val_size];
key[key_size-1] = '\0';
@@ -766,7 +785,7 @@ test_serialize_leaf_with_large_rows(enum ftnode_verify_type bft, bool do_clone)
char c = 'a' + i;
memset(key, c, key_size-1);
memset(val, c, val_size-1);
- les[i].init(key, key_size, val, val_size);
+ les[i] = le_fastmalloc(&dummy_mp, key, key_size, val, val_size);
}
}
const uint32_t npartitions = dn->n_children;
@@ -779,24 +798,24 @@ test_serialize_leaf_with_large_rows(enum ftnode_verify_type bft, bool do_clone)
if (bn > 0) {
assert(dest_ndd[bn].start >= dest_ndd[bn-1].start + dest_ndd[bn-1].size);
}
- assert(BLB_DATA(dn, bn)->num_klpairs() > 0);
- for (uint32_t i = 0; i < BLB_DATA(dn, bn)->num_klpairs(); i++) {
+ assert(BLB_DATA(dn, bn)->omt_size() > 0);
+ for (uint32_t i = 0; i < BLB_DATA(dn, bn)->omt_size(); i++) {
LEAFENTRY curr_le;
uint32_t curr_keylen;
void* curr_key;
BLB_DATA(dn, bn)->fetch_klpair(i, &curr_le, &curr_keylen, &curr_key);
- assert(leafentry_memsize(curr_le) == leafentry_memsize(les[last_i].le));
- assert(memcmp(curr_le, les[last_i].le, leafentry_memsize(curr_le)) == 0);
+ assert(leafentry_memsize(curr_le) == leafentry_memsize(get_le_from_klpair(les[last_i])));
+ assert(memcmp(curr_le, get_le_from_klpair(les[last_i]), leafentry_memsize(curr_le)) == 0);
if (bn < npartitions-1) {
- assert(strcmp((char*)dn->childkeys[bn].data, (char*)(les[last_i].keyp)) <= 0);
+ assert(strcmp((char*)dn->childkeys[bn].data, (char*)(les[last_i]->key_le)) <= 0);
}
// TODO for later, get a key comparison here as well
last_i++;
}
// don't check soft_copy_is_up_to_date or seqinsert
}
+ toku_mempool_destroy(&dummy_mp);
assert(last_i == 7);
- delete[] les;
}
toku_ftnode_free(&dn);
@@ -809,11 +828,11 @@ test_serialize_leaf_with_large_rows(enum ftnode_verify_type bft, bool do_clone)
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(src_ndd);
toku_free(dest_ndd);
@@ -852,13 +871,14 @@ test_serialize_leaf_with_empty_basement_nodes(enum ftnode_verify_type bft, bool
set_BLB(&sn, i, toku_create_empty_bn());
BLB_SEQINSERT(&sn, i) = 0;
}
+ KLPAIR elts[3];
le_add_to_bn(BLB_DATA(&sn, 1), 0, "a", 2, "aval", 5);
le_add_to_bn(BLB_DATA(&sn, 3), 0, "b", 2, "bval", 5);
le_add_to_bn(BLB_DATA(&sn, 5), 0, "x", 2, "xval", 5);
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -866,32 +886,32 @@ test_serialize_leaf_with_empty_basement_nodes(enum ftnode_verify_type bft, bool
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA src_ndd = NULL;
FTNODE_DISK_DATA dest_ndd = NULL;
- write_sn_to_disk(fd, ft, &sn, &src_ndd, do_clone);
+ write_sn_to_disk(fd, brt, &sn, &src_ndd, do_clone);
- setup_dn(bft, fd, ft_h, &dn, &dest_ndd);
+ setup_dn(bft, fd, brt_h, &dn, &dest_ndd);
assert(dn->thisnodename.b==20);
@@ -901,13 +921,13 @@ test_serialize_leaf_with_empty_basement_nodes(enum ftnode_verify_type bft, bool
assert(dn->height == 0);
assert(dn->n_children>0);
{
- test_key_le_pair elts[3];
-
// Man, this is way too ugly. This entire test suite needs to be refactored.
// Create a dummy mempool and put the leaves there. Ugh.
- elts[0].init("a", "aval");
- elts[1].init("b", "bval");
- elts[2].init("x", "xval");
+ struct mempool dummy_mp;
+ toku_mempool_construct(&dummy_mp, 1024);
+ elts[0] = le_malloc(&dummy_mp, "a", "aval");
+ elts[1] = le_malloc(&dummy_mp, "b", "bval");
+ elts[2] = le_malloc(&dummy_mp, "x", "xval");
const uint32_t npartitions = dn->n_children;
assert(dn->totalchildkeylens==(2*(npartitions-1)));
uint32_t last_i = 0;
@@ -917,21 +937,22 @@ test_serialize_leaf_with_empty_basement_nodes(enum ftnode_verify_type bft, bool
if (bn > 0) {
assert(dest_ndd[bn].start >= dest_ndd[bn-1].start + dest_ndd[bn-1].size);
}
- for (uint32_t i = 0; i < BLB_DATA(dn, bn)->num_klpairs(); i++) {
+ for (uint32_t i = 0; i < BLB_DATA(dn, bn)->omt_size(); i++) {
LEAFENTRY curr_le;
uint32_t curr_keylen;
void* curr_key;
BLB_DATA(dn, bn)->fetch_klpair(i, &curr_le, &curr_keylen, &curr_key);
- assert(leafentry_memsize(curr_le) == leafentry_memsize(elts[last_i].le));
- assert(memcmp(curr_le, elts[last_i].le, leafentry_memsize(curr_le)) == 0);
+ assert(leafentry_memsize(curr_le) == leafentry_memsize(get_le_from_klpair(elts[last_i])));
+ assert(memcmp(curr_le, get_le_from_klpair(elts[last_i]), leafentry_memsize(curr_le)) == 0);
if (bn < npartitions-1) {
- assert(strcmp((char*)dn->childkeys[bn].data, (char*)(elts[last_i].keyp)) <= 0);
+ assert(strcmp((char*)dn->childkeys[bn].data, (char*)(elts[last_i]->key_le)) <= 0);
}
// TODO for later, get a key comparison here as well
last_i++;
}
}
+ toku_mempool_destroy(&dummy_mp);
assert(last_i == 3);
}
toku_ftnode_free(&dn);
@@ -945,11 +966,11 @@ test_serialize_leaf_with_empty_basement_nodes(enum ftnode_verify_type bft, bool
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(src_ndd);
toku_free(dest_ndd);
@@ -984,9 +1005,9 @@ test_serialize_leaf_with_multiple_empty_basement_nodes(enum ftnode_verify_type b
set_BLB(&sn, i, toku_create_empty_bn());
}
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -994,33 +1015,33 @@ test_serialize_leaf_with_multiple_empty_basement_nodes(enum ftnode_verify_type b
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA src_ndd = NULL;
FTNODE_DISK_DATA dest_ndd = NULL;
- write_sn_to_disk(fd, ft, &sn, &src_ndd, do_clone);
+ write_sn_to_disk(fd, brt, &sn, &src_ndd, do_clone);
- setup_dn(bft, fd, ft_h, &dn, &dest_ndd);
+ setup_dn(bft, fd, brt_h, &dn, &dest_ndd);
assert(dn->thisnodename.b==20);
@@ -1038,7 +1059,7 @@ test_serialize_leaf_with_multiple_empty_basement_nodes(enum ftnode_verify_type b
if (i > 0) {
assert(dest_ndd[i].start >= dest_ndd[i-1].start + dest_ndd[i-1].size);
}
- assert(BLB_DATA(dn, i)->num_klpairs() == 0);
+ assert(BLB_DATA(dn, i)->omt_size() == 0);
}
}
toku_ftnode_free(&dn);
@@ -1052,11 +1073,11 @@ test_serialize_leaf_with_multiple_empty_basement_nodes(enum ftnode_verify_type b
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(src_ndd);
toku_free(dest_ndd);
@@ -1110,9 +1131,9 @@ test_serialize_nonleaf(enum ftnode_verify_type bft, bool do_clone) {
xids_destroy(&xids_123);
xids_destroy(&xids_234);
- FT_HANDLE XMALLOC(ft);
- FT XCALLOC(ft_h);
- toku_ft_init(ft_h,
+ FT_HANDLE XMALLOC(brt);
+ FT XCALLOC(brt_h);
+ toku_ft_init(brt_h,
make_blocknum(0),
ZERO_LSN,
TXNID_NONE,
@@ -1120,32 +1141,32 @@ test_serialize_nonleaf(enum ftnode_verify_type bft, bool do_clone) {
128*1024,
TOKU_DEFAULT_COMPRESSION_METHOD,
16);
- ft->ft = ft_h;
+ brt->ft = brt_h;
- toku_blocktable_create_new(&ft_h->blocktable);
+ toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
//Want to use block #20
BLOCKNUM b = make_blocknum(0);
while (b.b < 20) {
- toku_allocate_blocknum(ft_h->blocktable, &b, ft_h);
+ toku_allocate_blocknum(brt_h->blocktable, &b, brt_h);
}
assert(b.b == 20);
{
DISKOFF offset;
DISKOFF size;
- toku_blocknum_realloc_on_disk(ft_h->blocktable, b, 100, &offset, ft_h, fd, false);
+ toku_blocknum_realloc_on_disk(brt_h->blocktable, b, 100, &offset, brt_h, fd, false);
assert(offset==BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_translate_blocknum_to_offset_size(ft_h->blocktable, b, &offset, &size);
+ toku_translate_blocknum_to_offset_size(brt_h->blocktable, b, &offset, &size);
assert(offset == BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
assert(size == 100);
}
FTNODE_DISK_DATA src_ndd = NULL;
FTNODE_DISK_DATA dest_ndd = NULL;
- write_sn_to_disk(fd, ft, &sn, &src_ndd, do_clone);
+ write_sn_to_disk(fd, brt, &sn, &src_ndd, do_clone);
- setup_dn(bft, fd, ft_h, &dn, &dest_ndd);
+ setup_dn(bft, fd, brt_h, &dn, &dest_ndd);
assert(dn->thisnodename.b==20);
@@ -1176,11 +1197,11 @@ test_serialize_nonleaf(enum ftnode_verify_type bft, bool do_clone) {
toku_free(sn.bp);
toku_free(sn.childkeys);
- toku_block_free(ft_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
- toku_blocktable_destroy(&ft_h->blocktable);
- toku_free(ft_h->h);
- toku_free(ft_h);
- toku_free(ft);
+ toku_block_free(brt_h->blocktable, BLOCK_ALLOCATOR_TOTAL_HEADER_RESERVE);
+ toku_blocktable_destroy(&brt_h->blocktable);
+ toku_free(brt_h->h);
+ toku_free(brt_h);
+ toku_free(brt);
toku_free(src_ndd);
toku_free(dest_ndd);
diff --git a/storage/tokudb/ft-index/ft/tests/ft-test-cursor-2.cc b/storage/tokudb/ft-index/ft/tests/ft-test-cursor-2.cc
index 8421e5eb39f..f252c9fef4c 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-test-cursor-2.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-test-cursor-2.cc
@@ -113,14 +113,14 @@ static void test_multiple_ft_cursor_dbts(int n) {
int r;
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursors[n];
unlink(fname);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r==0);
int i;
@@ -129,14 +129,14 @@ static void test_multiple_ft_cursor_dbts(int n) {
char key[10],val[10];
snprintf(key, sizeof key, "k%04d", i);
snprintf(val, sizeof val, "v%04d", i);
- toku_ft_insert(ft,
+ toku_ft_insert(brt,
toku_fill_dbt(&kbt, key, 1+strlen(key)),
toku_fill_dbt(&vbt, val, 1+strlen(val)),
0);
}
for (i=0; i<n; i++) {
- r = toku_ft_cursor(ft, &cursors[i], NULL, false, false);
+ r = toku_ft_cursor(brt, &cursors[i], NULL, false, false);
assert(r == 0);
}
@@ -166,7 +166,7 @@ static void test_multiple_ft_cursor_dbts(int n) {
toku_free(ptrs[i]);
}
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
diff --git a/storage/tokudb/ft-index/ft/tests/ft-test-cursor.cc b/storage/tokudb/ft-index/ft/tests/ft-test-cursor.cc
index 4132ae968ed..3502c5adb61 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-test-cursor.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-test-cursor.cc
@@ -102,11 +102,11 @@ static int test_ft_cursor_keycompare(DB *desc __attribute__((unused)), const DBT
return toku_keycompare(a->data, a->size, b->data, b->size);
}
-static void assert_cursor_notfound(FT_HANDLE ft, int position) {
+static void assert_cursor_notfound(FT_HANDLE brt, int position) {
FT_CURSOR cursor=0;
int r;
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
struct check_pair pair = {0,0,0,0,0};
@@ -117,11 +117,11 @@ static void assert_cursor_notfound(FT_HANDLE ft, int position) {
toku_ft_cursor_close(cursor);
}
-static void assert_cursor_value(FT_HANDLE ft, int position, long long value) {
+static void assert_cursor_value(FT_HANDLE brt, int position, long long value) {
FT_CURSOR cursor=0;
int r;
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
if (test_cursor_debug && verbose) printf("key: ");
@@ -133,11 +133,11 @@ static void assert_cursor_value(FT_HANDLE ft, int position, long long value) {
toku_ft_cursor_close(cursor);
}
-static void assert_cursor_first_last(FT_HANDLE ft, long long firstv, long long lastv) {
+static void assert_cursor_first_last(FT_HANDLE brt, long long firstv, long long lastv) {
FT_CURSOR cursor=0;
int r;
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
if (test_cursor_debug && verbose) printf("first key: ");
@@ -162,7 +162,7 @@ static void assert_cursor_first_last(FT_HANDLE ft, long long firstv, long long l
static void test_ft_cursor_first(int n) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
int i;
@@ -172,7 +172,7 @@ static void test_ft_cursor_first(int n) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
/* insert a bunch of kv pairs */
@@ -184,15 +184,15 @@ static void test_ft_cursor_first(int n) {
toku_fill_dbt(&kbt, key, strlen(key)+1);
v = i;
toku_fill_dbt(&vbt, &v, sizeof v);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
}
if (n == 0)
- assert_cursor_notfound(ft, DB_FIRST);
+ assert_cursor_notfound(brt, DB_FIRST);
else
- assert_cursor_value(ft, DB_FIRST, 0);
+ assert_cursor_value(brt, DB_FIRST, 0);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -200,7 +200,7 @@ static void test_ft_cursor_first(int n) {
static void test_ft_cursor_last(int n) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
int i;
@@ -210,7 +210,7 @@ static void test_ft_cursor_last(int n) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
/* insert keys 0, 1, .. (n-1) */
@@ -222,16 +222,16 @@ static void test_ft_cursor_last(int n) {
toku_fill_dbt(&kbt, key, strlen(key)+1);
v = i;
toku_fill_dbt(&vbt, &v, sizeof v);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
assert(r==0);
}
if (n == 0)
- assert_cursor_notfound(ft, DB_LAST);
+ assert_cursor_notfound(brt, DB_LAST);
else
- assert_cursor_value(ft, DB_LAST, n-1);
+ assert_cursor_value(brt, DB_LAST, n-1);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -239,7 +239,7 @@ static void test_ft_cursor_last(int n) {
static void test_ft_cursor_first_last(int n) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
int i;
@@ -249,7 +249,7 @@ static void test_ft_cursor_first_last(int n) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
/* insert a bunch of kv pairs */
@@ -262,16 +262,16 @@ static void test_ft_cursor_first_last(int n) {
v = i;
toku_fill_dbt(&vbt, &v, sizeof v);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
}
if (n == 0) {
- assert_cursor_notfound(ft, DB_FIRST);
- assert_cursor_notfound(ft, DB_LAST);
+ assert_cursor_notfound(brt, DB_FIRST);
+ assert_cursor_notfound(brt, DB_LAST);
} else
- assert_cursor_first_last(ft, 0, n-1);
+ assert_cursor_first_last(brt, 0, n-1);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -281,7 +281,7 @@ static void test_ft_cursor_first_last(int n) {
static void test_ft_cursor_rfirst(int n) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
int i;
@@ -291,7 +291,7 @@ static void test_ft_cursor_rfirst(int n) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
/* insert keys n-1, n-2, ... , 0 */
@@ -304,26 +304,26 @@ static void test_ft_cursor_rfirst(int n) {
toku_fill_dbt(&kbt, key, strlen(key)+1);
v = i;
toku_fill_dbt(&vbt, &v, sizeof v);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
}
if (n == 0)
- assert_cursor_notfound(ft, DB_FIRST);
+ assert_cursor_notfound(brt, DB_FIRST);
else
- assert_cursor_value(ft, DB_FIRST, 0);
+ assert_cursor_value(brt, DB_FIRST, 0);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
}
-static void assert_cursor_walk(FT_HANDLE ft, int n) {
+static void assert_cursor_walk(FT_HANDLE brt, int n) {
FT_CURSOR cursor=0;
int i;
int r;
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
if (test_cursor_debug && verbose) printf("key: ");
@@ -345,7 +345,7 @@ static void assert_cursor_walk(FT_HANDLE ft, int n) {
static void test_ft_cursor_walk(int n) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
int i;
@@ -355,7 +355,7 @@ static void test_ft_cursor_walk(int n) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
/* insert a bunch of kv pairs */
@@ -367,25 +367,25 @@ static void test_ft_cursor_walk(int n) {
toku_fill_dbt(&kbt, key, strlen(key)+1);
v = i;
toku_fill_dbt(&vbt, &v, sizeof v);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
}
/* walk the tree */
- assert_cursor_walk(ft, n);
+ assert_cursor_walk(brt, n);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
}
-static void assert_cursor_rwalk(FT_HANDLE ft, int n) {
+static void assert_cursor_rwalk(FT_HANDLE brt, int n) {
FT_CURSOR cursor=0;
int i;
int r;
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
if (test_cursor_debug && verbose) printf("key: ");
@@ -407,7 +407,7 @@ static void assert_cursor_rwalk(FT_HANDLE ft, int n) {
static void test_ft_cursor_rwalk(int n) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
int i;
@@ -417,7 +417,7 @@ static void test_ft_cursor_rwalk(int n) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
/* insert a bunch of kv pairs */
@@ -429,13 +429,13 @@ static void test_ft_cursor_rwalk(int n) {
toku_fill_dbt(&kbt, &k, sizeof k);
v = i;
toku_fill_dbt(&vbt, &v, sizeof v);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
}
/* walk the tree */
- assert_cursor_rwalk(ft, n);
+ assert_cursor_rwalk(brt, n);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -462,13 +462,13 @@ ascending_key_string_checkf (ITEMLEN keylen, bytevec key, ITEMLEN UU(vallen), by
}
// The keys are strings (null terminated)
-static void assert_cursor_walk_inorder(FT_HANDLE ft, int n) {
+static void assert_cursor_walk_inorder(FT_HANDLE brt, int n) {
FT_CURSOR cursor=0;
int i;
int r;
char *prevkey = 0;
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
if (test_cursor_debug && verbose) printf("key: ");
@@ -488,7 +488,7 @@ static void assert_cursor_walk_inorder(FT_HANDLE ft, int n) {
static void test_ft_cursor_rand(int n) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
int i;
@@ -498,7 +498,7 @@ static void test_ft_cursor_rand(int n) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
/* insert a bunch of kv pairs */
@@ -513,22 +513,22 @@ static void test_ft_cursor_rand(int n) {
v = i;
toku_fill_dbt(&vbt, &v, sizeof v);
struct check_pair pair = {kbt.size, key, len_ignore, 0, 0};
- r = toku_ft_lookup(ft, &kbt, lookup_checkf, &pair);
+ r = toku_ft_lookup(brt, &kbt, lookup_checkf, &pair);
if (r == 0) {
assert(pair.call_count==1);
if (verbose) printf("dup");
continue;
}
assert(pair.call_count==0);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
break;
}
}
/* walk the tree */
- assert_cursor_walk_inorder(ft, n);
+ assert_cursor_walk_inorder(brt, n);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -536,7 +536,7 @@ static void test_ft_cursor_rand(int n) {
static void test_ft_cursor_split(int n) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursor=0;
int r;
int keyseqnum;
@@ -548,7 +548,7 @@ static void test_ft_cursor_split(int n) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
/* insert a bunch of kv pairs */
@@ -560,10 +560,10 @@ static void test_ft_cursor_split(int n) {
toku_fill_dbt(&kbt, key, strlen(key)+1);
v = keyseqnum;
toku_fill_dbt(&vbt, &v, sizeof v);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
}
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
if (test_cursor_debug && verbose) printf("key: ");
@@ -583,7 +583,7 @@ static void test_ft_cursor_split(int n) {
toku_fill_dbt(&kbt, key, strlen(key)+1);
v = keyseqnum;
toku_fill_dbt(&vbt, &v, sizeof v);
- toku_ft_insert(ft, &kbt, &vbt, 0);
+ toku_ft_insert(brt, &kbt, &vbt, 0);
}
if (test_cursor_debug && verbose) printf("key: ");
@@ -601,7 +601,7 @@ static void test_ft_cursor_split(int n) {
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -612,19 +612,19 @@ static void test_multiple_ft_cursors(int n) {
int r;
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursors[n];
unlink(fname);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
int i;
for (i=0; i<n; i++) {
- r = toku_ft_cursor(ft, &cursors[i], NULL, false, false);
+ r = toku_ft_cursor(brt, &cursors[i], NULL, false, false);
assert(r == 0);
}
@@ -632,7 +632,7 @@ static void test_multiple_ft_cursors(int n) {
toku_ft_cursor_close(cursors[i]);
}
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -653,7 +653,7 @@ static void test_multiple_ft_cursor_walk(int n) {
int r;
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
const int cursor_gap = 1000;
const int ncursors = n/cursor_gap;
FT_CURSOR cursors[ncursors];
@@ -665,13 +665,13 @@ static void test_multiple_ft_cursor_walk(int n) {
int cachesize = 2 * h * ncursors * nodesize;
toku_cachetable_create(&ct, cachesize, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
int c;
/* create the cursors */
for (c=0; c<ncursors; c++) {
- r = toku_ft_cursor(ft, &cursors[c], NULL, false, false);
+ r = toku_ft_cursor(brt, &cursors[c], NULL, false, false);
assert(r == 0);
}
@@ -686,7 +686,7 @@ static void test_multiple_ft_cursor_walk(int n) {
toku_fill_dbt(&key, &k, sizeof k);
toku_fill_dbt(&val, &v, sizeof v);
- toku_ft_insert(ft, &key, &val, 0);
+ toku_ft_insert(brt, &key, &val, 0);
}
/* point cursor i / cursor_gap to the current last key i */
@@ -720,7 +720,7 @@ static void test_multiple_ft_cursor_walk(int n) {
toku_ft_cursor_close(cursors[i]);
}
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -731,14 +731,14 @@ static void test_ft_cursor_set(int n, int cursor_op) {
int r;
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursor=0;
unlink(fname);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
int i;
@@ -750,10 +750,10 @@ static void test_ft_cursor_set(int n, int cursor_op) {
DBT key,val;
toku_fill_dbt(&key, &k, sizeof k);
toku_fill_dbt(&val, &v, sizeof v);
- toku_ft_insert(ft, &key, &val, 0);
+ toku_ft_insert(brt, &key, &val, 0);
}
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
/* set cursor to random keys in set { 0, 10, 20, .. 10*(n-1) } */
@@ -788,7 +788,7 @@ static void test_ft_cursor_set(int n, int cursor_op) {
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -799,14 +799,14 @@ static void test_ft_cursor_set_range(int n) {
int r;
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursor=0;
unlink(fname);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(r==0);
int i;
@@ -819,10 +819,10 @@ static void test_ft_cursor_set_range(int n) {
DBT key, val;
toku_fill_dbt(&key, &k, sizeof k);
toku_fill_dbt(&val, &v, sizeof v);
- toku_ft_insert(ft, &key, &val, 0);
+ toku_ft_insert(brt, &key, &val, 0);
}
- r = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(r==0);
/* pick random keys v in 0 <= v < 10*n, the cursor should point
@@ -848,7 +848,7 @@ static void test_ft_cursor_set_range(int n) {
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
toku_cachetable_close(&ct);
@@ -859,17 +859,17 @@ static void test_ft_cursor_delete(int n) {
int error;
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursor=0;
unlink(fname);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(error == 0);
- error = toku_ft_cursor(ft, &cursor, NULL, false, false);
+ error = toku_ft_cursor(brt, &cursor, NULL, false, false);
assert(error == 0);
DBT key, val;
@@ -882,7 +882,7 @@ static void test_ft_cursor_delete(int n) {
v = i;
toku_fill_dbt(&key, &k, sizeof k);
toku_fill_dbt(&val, &v, sizeof v);
- toku_ft_insert(ft, &key, &val, 0);
+ toku_ft_insert(brt, &key, &val, 0);
}
/* walk the tree and delete under the cursor */
@@ -905,7 +905,7 @@ static void test_ft_cursor_delete(int n) {
toku_ft_cursor_close(cursor);
- error = toku_close_ft_handle_nolsn(ft, 0);
+ error = toku_close_ft_handle_nolsn(brt, 0);
assert(error == 0);
toku_cachetable_close(&ct);
diff --git a/storage/tokudb/ft-index/ft/tests/ft-test-header.cc b/storage/tokudb/ft-index/ft/tests/ft-test-header.cc
index cf3a9838860..5044ab940df 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-test-header.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-test-header.cc
@@ -92,7 +92,7 @@ PATENT RIGHTS GRANT:
#include "test.h"
// The purpose of this test is to verify that certain information in the
-// ft_header is properly serialized and deserialized.
+// brt_header is properly serialized and deserialized.
static TOKUTXN const null_txn = 0;
diff --git a/storage/tokudb/ft-index/ft/tests/ft-test.cc b/storage/tokudb/ft-index/ft/tests/ft-test.cc
index 7bd77595954..ac744272173 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-test.cc
@@ -214,7 +214,7 @@ static void test_multiple_ft_handles_one_db_one_file (void) {
/* Check to see if data can be read that was written. */
static void test_read_what_was_written (void) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
const int NVALS=10000;
@@ -224,34 +224,34 @@ static void test_read_what_was_written (void) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
/* Now see if we can read an empty tree in. */
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 0, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 0, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
/* See if we can put something in it. */
{
DBT k,v;
- toku_ft_insert(ft, toku_fill_dbt(&k, "hello", 6), toku_fill_dbt(&v, "there", 6), null_txn);
+ toku_ft_insert(brt, toku_fill_dbt(&k, "hello", 6), toku_fill_dbt(&v, "there", 6), null_txn);
}
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
/* Now see if we can read it in and get the value. */
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 0, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 0, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
- ft_lookup_and_check_nodup(ft, "hello", "there");
+ ft_lookup_and_check_nodup(brt, "hello", "there");
- assert(toku_verify_ft(ft)==0);
+ assert(toku_verify_ft(brt)==0);
/* Now put a bunch (NVALS) of things in. */
{
@@ -262,14 +262,14 @@ static void test_read_what_was_written (void) {
snprintf(key, 100, "key%d", i);
snprintf(val, 100, "val%d", i);
if (i<600) {
- int verify_result=toku_verify_ft(ft);;
+ int verify_result=toku_verify_ft(brt);;
assert(verify_result==0);
}
- toku_ft_insert(ft, toku_fill_dbt(&k, key, strlen(key)+1), toku_fill_dbt(&v, val, strlen(val)+1), null_txn);
+ toku_ft_insert(brt, toku_fill_dbt(&k, key, strlen(key)+1), toku_fill_dbt(&v, val, strlen(val)+1), null_txn);
if (i<600) {
- int verify_result=toku_verify_ft(ft);
+ int verify_result=toku_verify_ft(brt);
if (verify_result) {
- r = toku_dump_ft(stdout, ft);
+ r = toku_dump_ft(stdout, brt);
assert(r==0);
assert(0);
}
@@ -279,7 +279,7 @@ static void test_read_what_was_written (void) {
char expectedval[100];
snprintf(key, 100, "key%d", j);
snprintf(expectedval, 100, "val%d", j);
- ft_lookup_and_check_nodup(ft, key, expectedval);
+ ft_lookup_and_check_nodup(brt, key, expectedval);
}
}
}
@@ -287,9 +287,9 @@ static void test_read_what_was_written (void) {
}
if (verbose) printf("Now read them out\n");
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r==0);
- //dump_ft(ft);
+ //dump_ft(brt);
/* See if we can read them all out again. */
{
@@ -298,31 +298,31 @@ static void test_read_what_was_written (void) {
char key[100],expectedval[100];
snprintf(key, 100, "key%d", i);
snprintf(expectedval, 100, "val%d", i);
- ft_lookup_and_check_nodup(ft, key, expectedval);
+ ft_lookup_and_check_nodup(brt, key, expectedval);
}
}
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
if (verbose) printf("%s:%d About to close %p\n", __FILE__, __LINE__, ct);
toku_cachetable_close(&ct);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 0, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 0, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
- ft_lookup_and_check_nodup(ft, "hello", "there");
+ ft_lookup_and_check_nodup(brt, "hello", "there");
{
int i;
for (i=0; i<NVALS; i++) {
char key[100],expectedval[100];
snprintf(key, 100, "key%d", i);
snprintf(expectedval, 100, "val%d", i);
- ft_lookup_and_check_nodup(ft, key, expectedval);
+ ft_lookup_and_check_nodup(brt, key, expectedval);
}
}
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
@@ -334,7 +334,7 @@ static void test_read_what_was_written (void) {
/* Test c_get(DB_LAST) on an empty tree */
static void test_cursor_last_empty(void) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursor=0;
int r;
if (verbose) printf("%s", __FUNCTION__);
@@ -343,9 +343,9 @@ static void test_cursor_last_empty(void) {
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
- r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false); assert(r==0);
{
struct check_pair pair = {0,0,0,0,0};
r = toku_ft_cursor_get(cursor, NULL, lookup_checkf, &pair, DB_LAST);
@@ -359,7 +359,7 @@ static void test_cursor_last_empty(void) {
assert(r==DB_NOTFOUND);
}
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
toku_cachetable_close(&ct);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
@@ -368,7 +368,7 @@ static void test_cursor_last_empty(void) {
static void test_cursor_next (void) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursor=0;
int r;
DBT kbt, vbt;
@@ -377,12 +377,12 @@ static void test_cursor_next (void) {
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
- toku_ft_insert(ft, toku_fill_dbt(&kbt, "hello", 6), toku_fill_dbt(&vbt, "there", 6), null_txn);
- toku_ft_insert(ft, toku_fill_dbt(&kbt, "byebye", 7), toku_fill_dbt(&vbt, "byenow", 7), null_txn);
+ toku_ft_insert(brt, toku_fill_dbt(&kbt, "hello", 6), toku_fill_dbt(&vbt, "there", 6), null_txn);
+ toku_ft_insert(brt, toku_fill_dbt(&kbt, "byebye", 7), toku_fill_dbt(&vbt, "byenow", 7), null_txn);
if (verbose) printf("%s:%d calling toku_ft_cursor(...)\n", __FILE__, __LINE__);
- r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false); assert(r==0);
toku_init_dbt(&kbt);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
toku_init_dbt(&vbt);
@@ -411,7 +411,7 @@ static void test_cursor_next (void) {
}
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
toku_cachetable_close(&ct);
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, toku_get_n_items_malloced()); toku_print_malloced_items();
@@ -436,7 +436,7 @@ static int wrong_compare_fun(DB* UU(desc), const DBT *a, const DBT *b) {
static void test_wrongendian_compare (int wrong_p, unsigned int N) {
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
unsigned int i;
@@ -455,7 +455,7 @@ static void test_wrongendian_compare (int wrong_p, unsigned int N) {
//printf("%s:%d WRONG=%d\n", __FILE__, __LINE__, wrong_p);
if (0) { // ???? Why is this commented out?
- r = toku_open_ft_handle(fname, 1, &ft, 1<<20, 1<<17, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, wrong_p ? wrong_compare_fun : toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<20, 1<<17, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, wrong_p ? wrong_compare_fun : toku_builtin_compare_fun); assert(r==0);
for (i=1; i<257; i+=255) {
unsigned char a[4],b[4];
b[3] = a[0] = (unsigned char)(i&255);
@@ -470,11 +470,11 @@ static void test_wrongendian_compare (int wrong_p, unsigned int N) {
printf("%s:%d insert: %02x%02x%02x%02x -> %02x%02x%02x%02x\n", __FILE__, __LINE__,
((char*)kbt.data)[0], ((char*)kbt.data)[1], ((char*)kbt.data)[2], ((char*)kbt.data)[3],
((char*)vbt.data)[0], ((char*)vbt.data)[1], ((char*)vbt.data)[2], ((char*)vbt.data)[3]);
- toku_ft_insert(ft, &kbt, &vbt, null_txn);
+ toku_ft_insert(brt, &kbt, &vbt, null_txn);
}
{
FT_CURSOR cursor=0;
- r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false); assert(r==0);
for (i=0; i<2; i++) {
unsigned char a[4],b[4];
@@ -489,13 +489,13 @@ static void test_wrongendian_compare (int wrong_p, unsigned int N) {
}
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
}
}
{
toku_cachetable_verify(ct);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<20, 1<<17, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, wrong_p ? wrong_compare_fun : toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<20, 1<<17, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, wrong_p ? wrong_compare_fun : toku_builtin_compare_fun); assert(r==0);
toku_cachetable_verify(ct);
for (i=0; i<N; i++) {
@@ -511,11 +511,11 @@ static void test_wrongendian_compare (int wrong_p, unsigned int N) {
if (0) printf("%s:%d insert: %02x%02x%02x%02x -> %02x%02x%02x%02x\n", __FILE__, __LINE__,
((unsigned char*)kbt.data)[0], ((unsigned char*)kbt.data)[1], ((unsigned char*)kbt.data)[2], ((unsigned char*)kbt.data)[3],
((unsigned char*)vbt.data)[0], ((unsigned char*)vbt.data)[1], ((unsigned char*)vbt.data)[2], ((unsigned char*)vbt.data)[3]);
- toku_ft_insert(ft, &kbt, &vbt, null_txn);
+ toku_ft_insert(brt, &kbt, &vbt, null_txn);
toku_cachetable_verify(ct);
}
FT_CURSOR cursor=0;
- r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false); assert(r==0);
for (i=0; i<N; i++) {
unsigned char a[4],b[4];
@@ -530,7 +530,7 @@ static void test_wrongendian_compare (int wrong_p, unsigned int N) {
toku_cachetable_verify(ct);
}
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r==0);
}
toku_cachetable_close(&ct);
@@ -806,8 +806,8 @@ static void test_ft_delete_cursor_first(int n) {
toku_cachetable_close(&ct);
}
-/* test for bug: insert message in a nonleaf node, delete removes the
- insert message, but lookup finds the insert message
+/* test for bug: insert cmd in a nonleaf node, delete removes the
+ insert cmd, but lookup finds the insert cmd
build a 2 level tree, and expect the last insertion to be
buffered. then delete and lookup. */
@@ -881,22 +881,22 @@ static void test_ft_delete(void) {
static void test_new_ft_cursor_create_close (void) {
int r;
- FT_HANDLE ft=0;
+ FT_HANDLE brt=0;
int n = 8;
FT_CURSOR cursors[n];
- toku_ft_handle_create(&ft);
+ toku_ft_handle_create(&brt);
int i;
for (i=0; i<n; i++) {
- r = toku_ft_cursor(ft, &cursors[i], NULL, false, false); assert(r == 0);
+ r = toku_ft_cursor(brt, &cursors[i], NULL, false, false); assert(r == 0);
}
for (i=0; i<n; i++) {
toku_ft_cursor_close(cursors[i]);
}
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r == 0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r == 0);
}
static void test_new_ft_cursor_first(int n) {
@@ -1177,14 +1177,14 @@ static void test_new_ft_cursor_set_range(int n) {
int r;
CACHETABLE ct;
- FT_HANDLE ft=0;
+ FT_HANDLE brt=0;
FT_CURSOR cursor=0;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
unlink(fname);
- toku_ft_handle_create(&ft);
- toku_ft_handle_set_nodesize(ft, 4096);
- r = toku_ft_handle_open(ft, fname, 1, 1, ct, null_txn); assert(r==0);
+ toku_ft_handle_create(&brt);
+ toku_ft_handle_set_nodesize(brt, 4096);
+ r = toku_ft_handle_open(brt, fname, 1, 1, ct, null_txn); assert(r==0);
int i;
@@ -1194,10 +1194,10 @@ static void test_new_ft_cursor_set_range(int n) {
DBT key, val;
int k = toku_htonl(10*i);
int v = 10*i;
- toku_ft_insert(ft, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
+ toku_ft_insert(brt, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
}
- r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false); assert(r==0);
/* pick random keys v in 0 <= v < 10*n, the cursor should point
to the smallest key in the tree that is >= v */
@@ -1226,7 +1226,7 @@ static void test_new_ft_cursor_set_range(int n) {
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
}
@@ -1236,14 +1236,14 @@ static void test_new_ft_cursor_set(int n, int cursor_op, DB *db) {
int r;
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
FT_CURSOR cursor=0;
unlink(fname);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare); assert(r==0);
int i;
@@ -1252,10 +1252,10 @@ static void test_new_ft_cursor_set(int n, int cursor_op, DB *db) {
DBT key, val;
int k = toku_htonl(10*i);
int v = 10*i;
- toku_ft_insert(ft, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
+ toku_ft_insert(brt, toku_fill_dbt(&key, &k, sizeof k), toku_fill_dbt(&val, &v, sizeof v), 0); assert(r == 0);
}
- r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false); assert(r==0);
/* set cursor to random keys in set { 0, 10, 20, .. 10*(n-1) } */
for (i=0; i<n; i++) {
@@ -1287,7 +1287,7 @@ static void test_new_ft_cursor_set(int n, int cursor_op, DB *db) {
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
}
diff --git a/storage/tokudb/ft-index/ft/tests/ftloader-test-bad-generate.cc b/storage/tokudb/ft-index/ft/tests/ftloader-test-bad-generate.cc
index 9ae24f7c4ec..95e3c5784cb 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-bad-generate.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-bad-generate.cc
@@ -158,19 +158,19 @@ static void test_extractor(int nrows, int nrowsets, bool expect_fail) {
// open the ft_loader. this runs the extractor.
const int N = 1;
- FT_HANDLE fts[N];
+ FT_HANDLE brts[N];
DB* dbs[N];
const char *fnames[N];
ft_compare_func compares[N];
for (int i = 0; i < N; i++) {
- fts[i] = NULL;
+ brts[i] = NULL;
dbs[i] = NULL;
fnames[i] = "";
compares[i] = compare_int;
}
FTLOADER loader;
- r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, fts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, nullptr, true, 0, false, true);
+ r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, brts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, nullptr, true, 0, false, true);
assert(r == 0);
struct rowset *rowset[nrowsets];
diff --git a/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor-errors.cc b/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor-errors.cc
index 007fd39fe08..378eca46a56 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor-errors.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor-errors.cc
@@ -165,12 +165,12 @@ static void test_extractor(int nrows, int nrowsets, bool expect_fail, const char
// open the ft_loader. this runs the extractor.
const int N = 1;
- FT_HANDLE fts[N];
+ FT_HANDLE brts[N];
DB* dbs[N];
const char *fnames[N];
ft_compare_func compares[N];
for (int i = 0; i < N; i++) {
- fts[i] = NULL;
+ brts[i] = NULL;
dbs[i] = NULL;
fnames[i] = "";
compares[i] = compare_int;
@@ -180,7 +180,7 @@ static void test_extractor(int nrows, int nrowsets, bool expect_fail, const char
sprintf(temp, "%s/%s", testdir, "tempXXXXXX");
FTLOADER loader;
- r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, fts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, nullptr, true, 0, false, true);
+ r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, brts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, nullptr, true, 0, false, true);
assert(r == 0);
struct rowset *rowset[nrowsets];
diff --git a/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc b/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc
index afba44a7a22..9938cb12f6d 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc
@@ -89,7 +89,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2010-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-// The purpose of this test is to test the extractor component of the ft loader. We insert rowsets into the extractor queue and verify temp files
+// The purpose of this test is to test the extractor component of the brt loader. We insert rowsets into the extractor queue and verify temp files
// after the extractor is finished.
#define DONT_DEPRECATE_MALLOC
@@ -387,12 +387,12 @@ static void test_extractor(int nrows, int nrowsets, const char *testdir) {
// open the ft_loader. this runs the extractor.
const int N = 1;
- FT_HANDLE fts[N];
+ FT_HANDLE brts[N];
DB* dbs[N];
const char *fnames[N];
ft_compare_func compares[N];
for (int i = 0; i < N; i++) {
- fts[i] = NULL;
+ brts[i] = NULL;
dbs[i] = NULL;
fnames[i] = "";
compares[i] = compare_int;
@@ -402,7 +402,7 @@ static void test_extractor(int nrows, int nrowsets, const char *testdir) {
sprintf(temp, "%s/%s", testdir, "tempXXXXXX");
FTLOADER loader;
- r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, fts, dbs, fnames, compares, temp, ZERO_LSN, nullptr, true, 0, false, true);
+ r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, brts, dbs, fnames, compares, temp, ZERO_LSN, nullptr, true, 0, false, true);
assert(r == 0);
struct rowset *rowset[nrowsets];
diff --git a/storage/tokudb/ft-index/ft/tests/ftloader-test-merge-files-dbufio.cc b/storage/tokudb/ft-index/ft/tests/ftloader-test-merge-files-dbufio.cc
index cdd4c1d6691..33ceb99e0b7 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-merge-files-dbufio.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-merge-files-dbufio.cc
@@ -385,7 +385,7 @@ static void test (const char *directory, bool is_error) {
}
FTLOADER bl;
- FT_HANDLE *XCALLOC_N(N_DEST_DBS, fts);
+ FT_HANDLE *XCALLOC_N(N_DEST_DBS, brts);
DB* *XCALLOC_N(N_DEST_DBS, dbs);
const char **XMALLOC_N(N_DEST_DBS, new_fnames_in_env);
for (int i=0; i<N_DEST_DBS; i++) {
@@ -407,7 +407,7 @@ static void test (const char *directory, bool is_error) {
ct,
(generate_row_for_put_func)NULL,
(DB*)NULL,
- N_DEST_DBS, fts, dbs,
+ N_DEST_DBS, brts, dbs,
new_fnames_in_env,
bt_compare_functions,
"tempxxxxxx",
@@ -517,7 +517,7 @@ static void test (const char *directory, bool is_error) {
destroy_dbufio_fileset(bfs);
toku_free(fnames);
toku_free(fds);
- toku_free(fts);
+ toku_free(brts);
toku_free(dbs);
toku_free(new_fnames_in_env);
toku_free(bt_compare_functions);
diff --git a/storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc b/storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc
index cdf0a14ab00..af3be12e0b1 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc
@@ -126,12 +126,12 @@ static void test_loader_open(int ndbs) {
FTLOADER loader;
// open the ft_loader. this runs the extractor.
- FT_HANDLE fts[ndbs];
+ FT_HANDLE brts[ndbs];
DB* dbs[ndbs];
const char *fnames[ndbs];
ft_compare_func compares[ndbs];
for (int i = 0; i < ndbs; i++) {
- fts[i] = NULL;
+ brts[i] = NULL;
dbs[i] = NULL;
fnames[i] = "";
compares[i] = my_compare;
@@ -143,7 +143,7 @@ static void test_loader_open(int ndbs) {
for (i = 0; ; i++) {
set_my_malloc_trigger(i+1);
- r = toku_ft_loader_open(&loader, NULL, NULL, NULL, ndbs, fts, dbs, fnames, compares, "", ZERO_LSN, nullptr, true, 0, false, true);
+ r = toku_ft_loader_open(&loader, NULL, NULL, NULL, ndbs, brts, dbs, fnames, compares, "", ZERO_LSN, nullptr, true, 0, false, true);
if (r == 0)
break;
}
diff --git a/storage/tokudb/ft-index/ft/tests/ftloader-test-writer-errors.cc b/storage/tokudb/ft-index/ft/tests/ftloader-test-writer-errors.cc
index 7767cee00e0..c72b6f847a3 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-writer-errors.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-writer-errors.cc
@@ -213,7 +213,7 @@ static int write_dbfile (char *tf_template, int n, char *output_name, bool expec
ft_loader_set_error_function(&bl.error_callback, NULL, NULL);
ft_loader_set_poll_function(&bl.poll_callback, loader_poll_callback, NULL);
- result = toku_loader_write_ft_from_q_in_C(&bl, &desc, fd, 1000, q2, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD, 16);
+ result = toku_loader_write_brt_from_q_in_C(&bl, &desc, fd, 1000, q2, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD, 16);
toku_set_func_malloc_only(NULL);
toku_set_func_realloc_only(NULL);
diff --git a/storage/tokudb/ft-index/ft/tests/ftloader-test-writer.cc b/storage/tokudb/ft-index/ft/tests/ftloader-test-writer.cc
index bf0641a3939..53d6bde27a0 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-writer.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-writer.cc
@@ -137,9 +137,9 @@ static void verify_dbfile(int n, const char *name) {
toku_ft_set_bt_compare(t, compare_ints);
r = toku_ft_handle_open(t, name, 0, 0, ct, null_txn); assert(r==0);
- if (verbose) traceit("Verifying ft internals");
+ if (verbose) traceit("Verifying brt internals");
r = toku_verify_ft(t);
- if (verbose) traceit("Verified ft internals");
+ if (verbose) traceit("Verified brt internals");
FT_CURSOR cursor = NULL;
r = toku_ft_cursor(t, &cursor, NULL, false, false); assert(r == 0);
@@ -262,7 +262,7 @@ static void test_write_dbfile (char *tf_template, int n, char *output_name, TXNI
assert(fd>=0);
if (verbose) traceit("write to file");
- r = toku_loader_write_ft_from_q_in_C(&bl, &desc, fd, 1000, q2, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD, 16);
+ r = toku_loader_write_brt_from_q_in_C(&bl, &desc, fd, 1000, q2, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD, 16);
assert(r==0);
r = queue_destroy(q2);
diff --git a/storage/tokudb/ft-index/ft/tests/ftloader-test.cc b/storage/tokudb/ft-index/ft/tests/ftloader-test.cc
index 343262720a8..2fc2d309f64 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test.cc
@@ -425,7 +425,7 @@ static void test_merge_files (const char *tf_template, const char *output_name)
int fd = open(output_name, O_RDWR | O_CREAT | O_BINARY, S_IRWXU|S_IRWXG|S_IRWXO);
assert(fd>=0);
- r = toku_loader_write_ft_from_q_in_C(&bl, &desc, fd, 1000, q, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD, 16);
+ r = toku_loader_write_brt_from_q_in_C(&bl, &desc, fd, 1000, q, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD, 16);
assert(r==0);
destroy_merge_fileset(&fs);
diff --git a/storage/tokudb/ft-index/ft/tests/is_empty.cc b/storage/tokudb/ft-index/ft/tests/is_empty.cc
index 40dfd6bb5e5..0927e2b5894 100644
--- a/storage/tokudb/ft-index/ft/tests/is_empty.cc
+++ b/storage/tokudb/ft-index/ft/tests/is_empty.cc
@@ -98,7 +98,7 @@ PATENT RIGHTS GRANT:
#define FILENAME "test0.ft"
static void test_it (int N) {
- FT_HANDLE ft;
+ FT_HANDLE brt;
int r;
toku_os_recursive_delete(TOKU_TEST_FILENAME);
r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU); CKERR(r);
@@ -119,18 +119,18 @@ static void test_it (int N) {
TOKUTXN txn;
r = toku_txn_begin_txn((DB_TXN*)NULL, (TOKUTXN)0, &txn, logger, TXN_SNAPSHOT_ROOT, false); CKERR(r);
- r = toku_open_ft_handle(FILENAME, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun); CKERR(r);
+ r = toku_open_ft_handle(FILENAME, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun); CKERR(r);
r = toku_txn_commit_txn(txn, false, NULL, NULL); CKERR(r);
toku_txn_close_txn(txn);
CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
r = toku_checkpoint(cp, logger, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT); CKERR(r);
- r = toku_close_ft_handle_nolsn(ft, NULL); CKERR(r);
+ r = toku_close_ft_handle_nolsn(brt, NULL); CKERR(r);
unsigned int rands[N];
for (int i=0; i<N; i++) {
r = toku_txn_begin_txn((DB_TXN*)NULL, (TOKUTXN)0, &txn, logger, TXN_SNAPSHOT_ROOT, false); CKERR(r);
- r = toku_open_ft_handle(FILENAME, 0, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun); CKERR(r);
+ r = toku_open_ft_handle(FILENAME, 0, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun); CKERR(r);
r = toku_txn_commit_txn(txn, false, NULL, NULL); CKERR(r);
toku_txn_close_txn(txn);
@@ -141,19 +141,19 @@ static void test_it (int N) {
snprintf(key, sizeof(key), "key%x.%x", rands[i], i);
memset(val, 'v', sizeof(val));
val[sizeof(val)-1]=0;
- toku_ft_insert(ft, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), txn);
+ toku_ft_insert(brt, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), txn);
r = toku_txn_commit_txn(txn, false, NULL, NULL); CKERR(r);
toku_txn_close_txn(txn);
r = toku_checkpoint(cp, logger, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT); CKERR(r);
- r = toku_close_ft_handle_nolsn(ft, NULL); CKERR(r);
+ r = toku_close_ft_handle_nolsn(brt, NULL); CKERR(r);
if (verbose) printf("i=%d\n", i);
}
for (int i=0; i<N; i++) {
r = toku_txn_begin_txn((DB_TXN*)NULL, (TOKUTXN)0, &txn, logger, TXN_SNAPSHOT_ROOT, false); CKERR(r);
- r = toku_open_ft_handle(FILENAME, 0, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun); CKERR(r);
+ r = toku_open_ft_handle(FILENAME, 0, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun); CKERR(r);
r = toku_txn_commit_txn(txn, false, NULL, NULL); CKERR(r);
toku_txn_close_txn(txn);
@@ -161,11 +161,11 @@ static void test_it (int N) {
char key[100];
DBT k;
snprintf(key, sizeof(key), "key%x.%x", rands[i], i);
- toku_ft_delete(ft, toku_fill_dbt(&k, key, 1+strlen(key)), txn);
+ toku_ft_delete(brt, toku_fill_dbt(&k, key, 1+strlen(key)), txn);
if (0) {
bool is_empty;
- is_empty = toku_ft_is_empty_fast(ft);
+ is_empty = toku_ft_is_empty_fast(brt);
assert(!is_empty);
}
@@ -173,23 +173,23 @@ static void test_it (int N) {
toku_txn_close_txn(txn);
r = toku_checkpoint(cp, logger, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT); CKERR(r);
- r = toku_close_ft_handle_nolsn(ft, NULL); CKERR(r);
+ r = toku_close_ft_handle_nolsn(brt, NULL); CKERR(r);
if (verbose) printf("d=%d\n", i);
}
r = toku_txn_begin_txn((DB_TXN*)NULL, (TOKUTXN)0, &txn, logger, TXN_SNAPSHOT_ROOT, false); CKERR(r);
- r = toku_open_ft_handle(FILENAME, 0, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun); CKERR(r);
+ r = toku_open_ft_handle(FILENAME, 0, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun); CKERR(r);
r = toku_txn_commit_txn(txn, false, NULL, NULL); CKERR(r);
toku_txn_close_txn(txn);
if (0) {
bool is_empty;
- is_empty = toku_ft_is_empty_fast(ft);
+ is_empty = toku_ft_is_empty_fast(brt);
assert(is_empty);
}
r = toku_checkpoint(cp, logger, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT); CKERR(r);
- r = toku_close_ft_handle_nolsn(ft, NULL); CKERR(r);
+ r = toku_close_ft_handle_nolsn(brt, NULL); CKERR(r);
r = toku_checkpoint(cp, logger, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT); CKERR(r);
toku_logger_close_rollback(logger);
diff --git a/storage/tokudb/ft-index/ft/tests/keyrange.cc b/storage/tokudb/ft-index/ft/tests/keyrange.cc
index 67651ae4f21..566db381f85 100644
--- a/storage/tokudb/ft-index/ft/tests/keyrange.cc
+++ b/storage/tokudb/ft-index/ft/tests/keyrange.cc
@@ -132,8 +132,8 @@ static void reload (uint64_t limit) {
enum memory_state {
LEAVE_IN_MEMORY, // leave the state in main memory
- CLOSE_AND_RELOAD, // close the fts and reload them into main memory (that will cause >1 partitio in many leaves.)
- CLOSE_AND_REOPEN_LEAVE_ON_DISK // close the fts, reopen them, but leave the state on disk.
+ CLOSE_AND_RELOAD, // close the brts and reload them into main memory (that will cause >1 partitio in many leaves.)
+ CLOSE_AND_REOPEN_LEAVE_ON_DISK // close the brts, reopen them, but leave the state on disk.
};
static void maybe_reopen (enum memory_state ms, uint64_t limit) {
diff --git a/storage/tokudb/ft-index/ft/tests/le-cursor-provdel.cc b/storage/tokudb/ft-index/ft/tests/le-cursor-provdel.cc
index d22b0f130e6..22c7f6b8640 100644
--- a/storage/tokudb/ft-index/ft/tests/le-cursor-provdel.cc
+++ b/storage/tokudb/ft-index/ft/tests/le-cursor-provdel.cc
@@ -138,8 +138,8 @@ create_populate_tree(const char *logdir, const char *fname, int n) {
error = toku_txn_begin_txn(NULL, NULL, &txn, logger, TXN_SNAPSHOT_NONE, false);
assert(error == 0);
- FT_HANDLE ft = NULL;
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, test_ft_cursor_keycompare);
+ FT_HANDLE brt = NULL;
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, test_ft_cursor_keycompare);
assert(error == 0);
error = toku_txn_commit_txn(txn, true, NULL, NULL);
@@ -158,7 +158,7 @@ create_populate_tree(const char *logdir, const char *fname, int n) {
toku_fill_dbt(&key, &k, sizeof k);
DBT val;
toku_fill_dbt(&val, &v, sizeof v);
- toku_ft_insert(ft, &key, &val, txn);
+ toku_ft_insert(brt, &key, &val, txn);
assert(error == 0);
}
@@ -166,7 +166,7 @@ create_populate_tree(const char *logdir, const char *fname, int n) {
assert(error == 0);
toku_txn_close_txn(txn);
- error = toku_close_ft_handle_nolsn(ft, NULL);
+ error = toku_close_ft_handle_nolsn(brt, NULL);
assert(error == 0);
CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
@@ -208,8 +208,8 @@ test_provdel(const char *logdir, const char *fname, int n) {
error = toku_txn_begin_txn(NULL, NULL, &txn, logger, TXN_SNAPSHOT_NONE, false);
assert(error == 0);
- FT_HANDLE ft = NULL;
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, test_ft_cursor_keycompare);
+ FT_HANDLE brt = NULL;
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, test_ft_cursor_keycompare);
assert(error == 0);
error = toku_txn_commit_txn(txn, true, NULL, NULL);
@@ -225,7 +225,7 @@ test_provdel(const char *logdir, const char *fname, int n) {
int k = toku_htonl(i);
DBT key;
toku_fill_dbt(&key, &k, sizeof k);
- toku_ft_delete(ft, &key, txn);
+ toku_ft_delete(brt, &key, txn);
assert(error == 0);
}
@@ -234,7 +234,7 @@ test_provdel(const char *logdir, const char *fname, int n) {
assert(error == 0);
LE_CURSOR cursor = NULL;
- error = toku_le_cursor_create(&cursor, ft, cursortxn);
+ error = toku_le_cursor_create(&cursor, brt, cursortxn);
assert(error == 0);
DBT key;
@@ -267,7 +267,7 @@ test_provdel(const char *logdir, const char *fname, int n) {
assert(error == 0);
toku_txn_close_txn(txn);
- error = toku_close_ft_handle_nolsn(ft, NULL);
+ error = toku_close_ft_handle_nolsn(brt, NULL);
assert(error == 0);
CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
error = toku_checkpoint(cp, logger, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT);
diff --git a/storage/tokudb/ft-index/ft/tests/le-cursor-right.cc b/storage/tokudb/ft-index/ft/tests/le-cursor-right.cc
index 050a278098f..78415855a51 100644
--- a/storage/tokudb/ft-index/ft/tests/le-cursor-right.cc
+++ b/storage/tokudb/ft-index/ft/tests/le-cursor-right.cc
@@ -142,8 +142,8 @@ create_populate_tree(const char *logdir, const char *fname, int n) {
error = toku_txn_begin_txn(NULL, NULL, &txn, logger, TXN_SNAPSHOT_NONE, false);
assert(error == 0);
- FT_HANDLE ft = NULL;
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, test_keycompare);
+ FT_HANDLE brt = NULL;
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, test_keycompare);
assert(error == 0);
error = toku_txn_commit_txn(txn, true, NULL, NULL);
@@ -162,14 +162,14 @@ create_populate_tree(const char *logdir, const char *fname, int n) {
toku_fill_dbt(&key, &k, sizeof k);
DBT val;
toku_fill_dbt(&val, &v, sizeof v);
- toku_ft_insert(ft, &key, &val, txn);
+ toku_ft_insert(brt, &key, &val, txn);
}
error = toku_txn_commit_txn(txn, true, NULL, NULL);
assert(error == 0);
toku_txn_close_txn(txn);
- error = toku_close_ft_handle_nolsn(ft, NULL);
+ error = toku_close_ft_handle_nolsn(brt, NULL);
assert(error == 0);
CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
@@ -198,13 +198,13 @@ test_pos_infinity(const char *fname, int n) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- FT_HANDLE ft = NULL;
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_keycompare);
+ FT_HANDLE brt = NULL;
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_keycompare);
assert(error == 0);
// position the cursor at -infinity
LE_CURSOR cursor = NULL;
- error = toku_le_cursor_create(&cursor, ft, NULL);
+ error = toku_le_cursor_create(&cursor, brt, NULL);
assert(error == 0);
for (int i = 0; i < 2*n; i++) {
@@ -217,7 +217,7 @@ test_pos_infinity(const char *fname, int n) {
toku_le_cursor_close(cursor);
- error = toku_close_ft_handle_nolsn(ft, 0);
+ error = toku_close_ft_handle_nolsn(brt, 0);
assert(error == 0);
toku_cachetable_close(&ct);
@@ -232,13 +232,13 @@ test_neg_infinity(const char *fname, int n) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- FT_HANDLE ft = NULL;
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_keycompare);
+ FT_HANDLE brt = NULL;
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_keycompare);
assert(error == 0);
// position the LE_CURSOR at +infinity
LE_CURSOR cursor = NULL;
- error = toku_le_cursor_create(&cursor, ft, NULL);
+ error = toku_le_cursor_create(&cursor, brt, NULL);
assert(error == 0);
DBT key;
@@ -271,7 +271,7 @@ test_neg_infinity(const char *fname, int n) {
toku_le_cursor_close(cursor);
- error = toku_close_ft_handle_nolsn(ft, 0);
+ error = toku_close_ft_handle_nolsn(brt, 0);
assert(error == 0);
toku_cachetable_close(&ct);
@@ -286,13 +286,13 @@ test_between(const char *fname, int n) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- FT_HANDLE ft = NULL;
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_keycompare);
+ FT_HANDLE brt = NULL;
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_keycompare);
assert(error == 0);
// position the LE_CURSOR at +infinity
LE_CURSOR cursor = NULL;
- error = toku_le_cursor_create(&cursor, ft, NULL);
+ error = toku_le_cursor_create(&cursor, brt, NULL);
assert(error == 0);
DBT key;
@@ -337,7 +337,7 @@ test_between(const char *fname, int n) {
toku_le_cursor_close(cursor);
- error = toku_close_ft_handle_nolsn(ft, 0);
+ error = toku_close_ft_handle_nolsn(brt, 0);
assert(error == 0);
toku_cachetable_close(&ct);
diff --git a/storage/tokudb/ft-index/ft/tests/le-cursor-walk.cc b/storage/tokudb/ft-index/ft/tests/le-cursor-walk.cc
index 0cebb50a768..3e08461da64 100644
--- a/storage/tokudb/ft-index/ft/tests/le-cursor-walk.cc
+++ b/storage/tokudb/ft-index/ft/tests/le-cursor-walk.cc
@@ -139,8 +139,8 @@ create_populate_tree(const char *logdir, const char *fname, int n) {
error = toku_txn_begin_txn(NULL, NULL, &txn, logger, TXN_SNAPSHOT_NONE, false);
assert(error == 0);
- FT_HANDLE ft = NULL;
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, test_ft_cursor_keycompare);
+ FT_HANDLE brt = NULL;
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, test_ft_cursor_keycompare);
assert(error == 0);
error = toku_txn_commit_txn(txn, true, NULL, NULL);
@@ -159,14 +159,14 @@ create_populate_tree(const char *logdir, const char *fname, int n) {
toku_fill_dbt(&key, &k, sizeof k);
DBT val;
toku_fill_dbt(&val, &v, sizeof v);
- toku_ft_insert(ft, &key, &val, txn);
+ toku_ft_insert(brt, &key, &val, txn);
}
error = toku_txn_commit_txn(txn, true, NULL, NULL);
assert(error == 0);
toku_txn_close_txn(txn);
- error = toku_close_ft_handle_nolsn(ft, NULL);
+ error = toku_close_ft_handle_nolsn(brt, NULL);
assert(error == 0);
CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
@@ -194,12 +194,12 @@ walk_tree(const char *fname, int n) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- FT_HANDLE ft = NULL;
- error = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
+ FT_HANDLE brt = NULL;
+ error = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare);
assert(error == 0);
LE_CURSOR cursor = NULL;
- error = toku_le_cursor_create(&cursor, ft, NULL);
+ error = toku_le_cursor_create(&cursor, brt, NULL);
assert(error == 0);
DBT key;
@@ -224,7 +224,7 @@ walk_tree(const char *fname, int n) {
toku_le_cursor_close(cursor);
- error = toku_close_ft_handle_nolsn(ft, 0);
+ error = toku_close_ft_handle_nolsn(brt, 0);
assert(error == 0);
toku_cachetable_close(&ct);
diff --git a/storage/tokudb/ft-index/ft/tests/make-tree.cc b/storage/tokudb/ft-index/ft/tests/make-tree.cc
index a8a04b7a6a4..56df485173d 100644
--- a/storage/tokudb/ft-index/ft/tests/make-tree.cc
+++ b/storage/tokudb/ft-index/ft/tests/make-tree.cc
@@ -103,10 +103,10 @@ PATENT RIGHTS GRANT:
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
@@ -119,14 +119,14 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
DBT theval; toku_fill_dbt(&theval, val, vallen);
// get an index that we can use to create a new leaf entry
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
MSN msn = next_dummymsn();
// apply an insert to the leaf node
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u = {.id = { &thekey, &theval }} };
- toku_ft_bn_apply_msg_once(BLB(leafnode,0), &msg, idx, NULL, &gc_info, NULL, NULL);
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u = {.id = { &thekey, &theval }} };
+ toku_ft_bn_apply_cmd_once(BLB(leafnode,0), &cmd, idx, NULL, &gc_info, NULL, NULL);
leafnode->max_msn_applied_to_node_on_disk = msn;
@@ -146,29 +146,29 @@ populate_leaf(FTNODE leafnode, int seq, int n, int *minkey, int *maxkey) {
}
static void
-insert_into_child_buffer(FT_HANDLE ft, FTNODE node, int childnum, int minkey, int maxkey) {
+insert_into_child_buffer(FT_HANDLE brt, FTNODE node, int childnum, int minkey, int maxkey) {
for (unsigned int val = htonl(minkey); val <= htonl(maxkey); val++) {
MSN msn = next_dummymsn();
unsigned int key = htonl(val);
DBT thekey; toku_fill_dbt(&thekey, &key, sizeof key);
DBT theval; toku_fill_dbt(&theval, &val, sizeof val);
- toku_ft_append_to_child_buffer(ft->ft->compare_fun, NULL, node, childnum, FT_INSERT, msn, xids_get_root_xids(), true, &thekey, &theval);
+ toku_ft_append_to_child_buffer(brt->ft->compare_fun, NULL, node, childnum, FT_INSERT, msn, xids_get_root_xids(), true, &thekey, &theval);
node->max_msn_applied_to_node_on_disk = msn;
}
}
static FTNODE
-make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
+make_tree(FT_HANDLE brt, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
FTNODE node;
if (height == 0) {
- node = make_node(ft, 0);
+ node = make_node(brt, 0);
populate_leaf(node, *seq, nperleaf, minkey, maxkey);
*seq += nperleaf;
} else {
- node = make_node(ft, height);
+ node = make_node(brt, height);
int minkeys[fanout], maxkeys[fanout];
for (int childnum = 0; childnum < fanout; childnum++) {
- FTNODE child = make_tree(ft, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
+ FTNODE child = make_tree(brt, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
if (childnum == 0) {
toku_ft_nonleaf_append_child(node, child, NULL);
} else {
@@ -176,8 +176,8 @@ make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *min
DBT pivotkey;
toku_ft_nonleaf_append_child(node, child, toku_fill_dbt(&pivotkey, &k, sizeof k));
}
- toku_unpin_ftnode(ft->ft, child);
- insert_into_child_buffer(ft, node, childnum, minkeys[childnum], maxkeys[childnum]);
+ toku_unpin_ftnode(brt->ft, child);
+ insert_into_child_buffer(brt, node, childnum, minkeys[childnum], maxkeys[childnum]);
}
*minkey = minkeys[0];
*maxkey = maxkeys[0];
@@ -211,31 +211,31 @@ test_make_tree(int height, int fanout, int nperleaf, int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
// make a tree
int seq = 0, minkey, maxkey;
- FTNODE newroot = make_tree(ft, height, fanout, nperleaf, &seq, &minkey, &maxkey);
+ FTNODE newroot = make_tree(brt, height, fanout, nperleaf, &seq, &minkey, &maxkey);
// set the new root to point to the new tree
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
- ft->ft->h->max_msn_in_ft = last_dummymsn(); // capture msn of last message injected into tree
+ brt->ft->h->max_msn_in_ft = last_dummymsn(); // capture msn of last message injected into tree
// unpin the new root
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r == 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/ft/tests/mempool-115.cc b/storage/tokudb/ft-index/ft/tests/mempool-115.cc
index 3b9280364e8..8b5d2d69195 100644
--- a/storage/tokudb/ft-index/ft/tests/mempool-115.cc
+++ b/storage/tokudb/ft-index/ft/tests/mempool-115.cc
@@ -96,18 +96,13 @@ le_add_to_bn(bn_data* bn, uint32_t idx, const char *key, int keysize, const cha
{
LEAFENTRY r = NULL;
uint32_t size_needed = LE_CLEAN_MEMSIZE(valsize);
- void *maybe_free = nullptr;
bn->get_space_for_insert(
idx,
key,
keysize,
size_needed,
- &r,
- &maybe_free
+ &r
);
- if (maybe_free) {
- toku_free(maybe_free);
- }
resource_assert(r);
r->type = LE_CLEAN;
r->u.clean.vallen = valsize;
@@ -118,19 +113,14 @@ static void
le_overwrite(bn_data* bn, uint32_t idx, const char *key, int keysize, const char *val, int valsize) {
LEAFENTRY r = NULL;
uint32_t size_needed = LE_CLEAN_MEMSIZE(valsize);
- void *maybe_free = nullptr;
bn->get_space_for_overwrite(
idx,
key,
keysize,
size_needed, // old_le_size
size_needed,
- &r,
- &maybe_free
+ &r
);
- if (maybe_free) {
- toku_free(maybe_free);
- }
resource_assert(r);
r->type = LE_CLEAN;
r->u.clean.vallen = valsize;
diff --git a/storage/tokudb/ft-index/ft/tests/minicron-test.cc b/storage/tokudb/ft-index/ft/tests/minicron-test.cc
index 5f953f1b694..4345289f4ec 100644
--- a/storage/tokudb/ft-index/ft/tests/minicron-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/minicron-test.cc
@@ -115,8 +115,8 @@ __attribute__((__noreturn__))
never_run (void *a) {
assert(a==0);
assert(0);
-#if defined(GCOV)
- return 0;
+#if TOKU_WINDOWS || defined(GCOV)
+ return 0; //ICC ignores the noreturn attribute.
#endif
}
diff --git a/storage/tokudb/ft-index/ft/tests/msnfilter.cc b/storage/tokudb/ft-index/ft/tests/msnfilter.cc
index 9881f4bb1a4..1c1cba86f1c 100644
--- a/storage/tokudb/ft-index/ft/tests/msnfilter.cc
+++ b/storage/tokudb/ft-index/ft/tests/msnfilter.cc
@@ -89,17 +89,17 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
// Verify that a message with an old msn is ignored
-// by toku_apply_msg_to_leaf()
+// by toku_apply_cmd_to_leaf()
//
// method:
// - inject valid message, verify that new value is in row
-// - inject message with same msn and new value, verify that original value is still in key (verify msg.msn == node.max_msn is rejected)
+// - inject message with same msn and new value, verify that original value is still in key (verify cmd.msn == node.max_msn is rejected)
// - inject valid message with new value2, verify that row has new value2
-// - inject message with old msn, verify that row still has value2 (verify msg.msn < node.max_msn is rejected)
+// - inject message with old msn, verify that row still has value2 (verify cmd.msn < node.max_msn is rejected)
// TODO:
-// - verify that no work is done by messages that should be ignored (via workdone arg to ft_leaf_put_msg())
+// - verify that no work is done by messages that should be ignored (via workdone arg to ft_leaf_put_cmd())
// - maybe get counter of messages ignored for old msn (once the counter is implemented in ft-ops.c)
#include "ft-internal.h"
@@ -108,16 +108,16 @@ PATENT RIGHTS GRANT:
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
static void
-append_leaf(FT_HANDLE ft, FTNODE leafnode, void *key, uint32_t keylen, void *val, uint32_t vallen) {
+append_leaf(FT_HANDLE brt, FTNODE leafnode, void *key, uint32_t keylen, void *val, uint32_t vallen) {
assert(leafnode->height == 0);
DBT thekey; toku_fill_dbt(&thekey, key, keylen);
@@ -130,48 +130,48 @@ append_leaf(FT_HANDLE ft, FTNODE leafnode, void *key, uint32_t keylen, void *val
// apply an insert to the leaf node
MSN msn = next_dummymsn();
- ft->ft->h->max_msn_in_ft = msn;
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
+ brt->ft->h->max_msn_in_ft = msn;
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- toku_ft_leaf_apply_msg(ft->ft->compare_fun, ft->ft->update_fun, &ft->ft->cmp_descriptor, leafnode, -1, &msg, &gc_info, nullptr, nullptr);
+ toku_ft_leaf_apply_cmd(brt->ft->compare_fun, brt->ft->update_fun, &brt->ft->cmp_descriptor, leafnode, -1, &cmd, &gc_info, nullptr, nullptr);
{
- int r = toku_ft_lookup(ft, &thekey, lookup_checkf, &pair);
+ int r = toku_ft_lookup(brt, &thekey, lookup_checkf, &pair);
assert(r==0);
assert(pair.call_count==1);
}
- FT_MSG_S badmsg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &badval }} };
- toku_ft_leaf_apply_msg(ft->ft->compare_fun, ft->ft->update_fun, &ft->ft->cmp_descriptor, leafnode, -1, &badmsg, &gc_info, nullptr, nullptr);
+ FT_MSG_S badcmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &badval }} };
+ toku_ft_leaf_apply_cmd(brt->ft->compare_fun, brt->ft->update_fun, &brt->ft->cmp_descriptor, leafnode, -1, &badcmd, &gc_info, nullptr, nullptr);
// message should be rejected for duplicate msn, row should still have original val
{
- int r = toku_ft_lookup(ft, &thekey, lookup_checkf, &pair);
+ int r = toku_ft_lookup(brt, &thekey, lookup_checkf, &pair);
assert(r==0);
assert(pair.call_count==2);
}
// now verify that message with proper msn gets through
msn = next_dummymsn();
- ft->ft->h->max_msn_in_ft = msn;
- FT_MSG_S msg2 = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &val2 }} };
- toku_ft_leaf_apply_msg(ft->ft->compare_fun, ft->ft->update_fun, &ft->ft->cmp_descriptor, leafnode, -1, &msg2, &gc_info, nullptr, nullptr);
+ brt->ft->h->max_msn_in_ft = msn;
+ FT_MSG_S cmd2 = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &val2 }} };
+ toku_ft_leaf_apply_cmd(brt->ft->compare_fun, brt->ft->update_fun, &brt->ft->cmp_descriptor, leafnode, -1, &cmd2, &gc_info, nullptr, nullptr);
// message should be accepted, val should have new value
{
- int r = toku_ft_lookup(ft, &thekey, lookup_checkf, &pair2);
+ int r = toku_ft_lookup(brt, &thekey, lookup_checkf, &pair2);
assert(r==0);
assert(pair2.call_count==1);
}
// now verify that message with lesser (older) msn is rejected
msn.msn = msn.msn - 10;
- FT_MSG_S msg3 = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &badval } }};
- toku_ft_leaf_apply_msg(ft->ft->compare_fun, ft->ft->update_fun, &ft->ft->cmp_descriptor, leafnode, -1, &msg3, &gc_info, nullptr, nullptr);
+ FT_MSG_S cmd3 = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &badval } }};
+ toku_ft_leaf_apply_cmd(brt->ft->compare_fun, brt->ft->update_fun, &brt->ft->cmp_descriptor, leafnode, -1, &cmd3, &gc_info, nullptr, nullptr);
// message should be rejected, val should still have value in pair2
{
- int r = toku_ft_lookup(ft, &thekey, lookup_checkf, &pair2);
+ int r = toku_ft_lookup(brt, &thekey, lookup_checkf, &pair2);
assert(r==0);
assert(pair2.call_count==2);
}
@@ -181,11 +181,11 @@ append_leaf(FT_HANDLE ft, FTNODE leafnode, void *key, uint32_t keylen, void *val
}
static void
-populate_leaf(FT_HANDLE ft, FTNODE leafnode, int k, int v) {
+populate_leaf(FT_HANDLE brt, FTNODE leafnode, int k, int v) {
char vbuf[32]; // store v in a buffer large enough to dereference unaligned int's
memset(vbuf, 0, sizeof vbuf);
memcpy(vbuf, &v, sizeof v);
- append_leaf(ft, leafnode, &k, sizeof k, vbuf, sizeof v);
+ append_leaf(brt, leafnode, &k, sizeof k, vbuf, sizeof v);
}
static void
@@ -204,16 +204,16 @@ test_msnfilter(int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
- FTNODE newroot = make_node(ft, 0);
+ FTNODE newroot = make_node(brt, 0);
// set the new root to point to the new tree
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
// KLUDGE: Unpin the new root so toku_ft_lookup() can pin it. (Pin lock is no longer a recursive
// mutex.) Just leaving it unpinned for this test program works because it is the only
@@ -221,17 +221,17 @@ test_msnfilter(int do_verify) {
// node and unlock it again before and after each message injection, but that requires more
// work than it's worth (setting up dummy callbacks, etc.)
//
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
- populate_leaf(ft, newroot, htonl(2), 1);
+ populate_leaf(brt, newroot, htonl(2), 1);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r == 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/ft/tests/dmt-test.cc b/storage/tokudb/ft-index/ft/tests/omt-test.cc
index e4f1e53751e..b63d1b42de2 100644
--- a/storage/tokudb/ft-index/ft/tests/dmt-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/omt-test.cc
@@ -90,103 +90,10 @@ PATENT RIGHTS GRANT:
#include "test.h"
-#include <util/dmt.h>
+#include "omt.h"
+#include <util/omt.h>
-typedef void *DMTVALUE;
-
-class dmtvalue_writer {
-public:
- size_t get_size(void) const {
- return sizeof(DMTVALUE);
- }
- void write_to(DMTVALUE *const dest) const {
- *dest = value;
- }
-
- dmtvalue_writer(DMTVALUE _value)
- : value(_value) {
- }
- dmtvalue_writer(const uint32_t size UU(), DMTVALUE *const src)
- : value(*src) {
- paranoid_invariant(size == sizeof(DMTVALUE));
- }
-private:
- const DMTVALUE value;
-};
-
-typedef toku::dmt<DMTVALUE, DMTVALUE, dmtvalue_writer> *DMT;
-
-static int dmt_insert_at(DMT dmt, DMTVALUE value, uint32_t index) {
- dmtvalue_writer functor(value);
- return dmt->insert_at(functor, index);
-}
-
-static DMT dmt_create_from_sorted_array(DMTVALUE *values, uint32_t numvalues) {
- DMT XMALLOC(dmt);
- dmt->create();
- for (uint32_t i = 0; i < numvalues; i++) {
- dmt_insert_at(dmt, values[i], i);
- }
- return dmt;
-}
-
-struct heftor {
- int (*h)(DMTVALUE, void *v);
- void *v;
-};
-
-int call_heftor(const uint32_t size, const DMTVALUE &v, const heftor &htor);
-int call_heftor(const uint32_t size, const DMTVALUE &v, const heftor &htor) {
- invariant(size == sizeof(DMTVALUE));
- return htor.h(const_cast<DMTVALUE>(v), htor.v);
-}
-
-static int dmt_insert(DMT dmt, DMTVALUE value, int(*h)(DMTVALUE, void*v), void *v, uint32_t *index) {
- struct heftor htor = { .h = h, .v = v };
- dmtvalue_writer functor(value);
- return dmt->insert<heftor, call_heftor>(functor, htor, index);
-}
-
-static int dmt_find_zero(DMT V, int (*h)(DMTVALUE, void*extra), void*extra, DMTVALUE *value, uint32_t *index) {
- struct heftor htor = { .h = h, .v = extra };
- uint32_t ignore;
- return V->find_zero<heftor, call_heftor>(htor, &ignore, value, index);
-}
-
-static int dmt_find(DMT V, int (*h)(DMTVALUE, void*extra), void*extra, int direction, DMTVALUE *value, uint32_t *index) {
- struct heftor htor = { .h = h, .v = extra };
- uint32_t ignore;
- return V->find<heftor, call_heftor>(htor, direction, &ignore, value, index);
-}
-
-static int dmt_split_at(DMT dmt, DMT *newdmtp, uint32_t index) {
- if (index > dmt->size()) { return EINVAL; }
- DMT XMALLOC(newdmt);
- newdmt->create();
- int r;
-
- for (uint32_t i = index; i < dmt->size(); i++) {
- DMTVALUE v;
- r = dmt->fetch(i, nullptr, &v);
- invariant_zero(r);
- r = dmt_insert_at(newdmt, v, i-index);
- invariant_zero(r);
- }
- if (dmt->size() > 0) {
- for (uint32_t i = dmt->size(); i > index; i--) {
- r = dmt->delete_at(i - 1);
- invariant_zero(r);
- }
- }
- r = 0;
-
- if (r != 0) {
- toku_free(newdmt);
- } else {
- *newdmtp = newdmt;
- }
- return r;
-}
+typedef OMTVALUE TESTVALUE;
static void
parse_args (int argc, const char *argv[]) {
@@ -226,25 +133,26 @@ enum close_when_done {
KEEP_WHEN_DONE
};
enum create_type {
+ STEAL_ARRAY,
BATCH_INSERT,
INSERT_AT,
INSERT_AT_ALMOST_RANDOM,
};
/* Globals */
-DMT global_dmt;
-DMTVALUE* values = nullptr;
-struct value* nums = nullptr;
+OMT global_omt;
+TESTVALUE* values = NULL;
+struct value* nums = NULL;
uint32_t length;
static void
cleanup_globals (void) {
assert(values);
toku_free(values);
- values = nullptr;
+ values = NULL;
assert(nums);
toku_free(nums);
- nums = nullptr;
+ nums = NULL;
}
const unsigned int random_seed = 0xFEADACBA;
@@ -270,7 +178,7 @@ init_identity_values (unsigned int seed, uint32_t num_elements) {
for (i = 0; i < length; i++) {
nums[i].number = i;
- values[i] = (DMTVALUE)&nums[i];
+ values[i] = (TESTVALUE)&nums[i];
}
}
@@ -285,7 +193,7 @@ init_distinct_sorted_values (unsigned int seed, uint32_t num_elements) {
for (i = 0; i < length; i++) {
number += (uint32_t)(random() % 32) + 1;
nums[i].number = number;
- values[i] = (DMTVALUE)&nums[i];
+ values[i] = (TESTVALUE)&nums[i];
}
}
@@ -321,22 +229,25 @@ static void
test_close (enum close_when_done do_close) {
if (do_close == KEEP_WHEN_DONE) return;
assert(do_close == CLOSE_WHEN_DONE);
- global_dmt->destroy();
- toku_free(global_dmt);
- global_dmt = nullptr;
+ toku_omt_destroy(&global_omt);
+ assert(global_omt==NULL);
}
static void
test_create (enum close_when_done do_close) {
- XMALLOC(global_dmt);
- global_dmt->create();
+ int r;
+ global_omt = NULL;
+
+ r = toku_omt_create(&global_omt);
+ CKERR(r);
+ assert(global_omt!=NULL);
test_close(do_close);
}
static void
test_create_size (enum close_when_done do_close) {
test_create(KEEP_WHEN_DONE);
- assert(global_dmt->size() == 0);
+ assert(toku_omt_size(global_omt) == 0);
test_close(do_close);
}
@@ -347,24 +258,24 @@ test_create_insert_at_almost_random (enum close_when_done do_close) {
uint32_t size = 0;
test_create(KEEP_WHEN_DONE);
- r = dmt_insert_at(global_dmt, values[0], global_dmt->size()+1);
+ r = toku_omt_insert_at(global_omt, values[0], toku_omt_size(global_omt)+1);
CKERR2(r, EINVAL);
- r = dmt_insert_at(global_dmt, values[0], global_dmt->size()+2);
+ r = toku_omt_insert_at(global_omt, values[0], toku_omt_size(global_omt)+2);
CKERR2(r, EINVAL);
for (i = 0; i < length/2; i++) {
- assert(size==global_dmt->size());
- r = dmt_insert_at(global_dmt, values[i], i);
+ assert(size==toku_omt_size(global_omt));
+ r = toku_omt_insert_at(global_omt, values[i], i);
CKERR(r);
- assert(++size==global_dmt->size());
- r = dmt_insert_at(global_dmt, values[length-1-i], i+1);
+ assert(++size==toku_omt_size(global_omt));
+ r = toku_omt_insert_at(global_omt, values[length-1-i], i+1);
CKERR(r);
- assert(++size==global_dmt->size());
+ assert(++size==toku_omt_size(global_omt));
}
- r = dmt_insert_at(global_dmt, values[0], global_dmt->size()+1);
+ r = toku_omt_insert_at(global_omt, values[0], toku_omt_size(global_omt)+1);
CKERR2(r, EINVAL);
- r = dmt_insert_at(global_dmt, values[0], global_dmt->size()+2);
+ r = toku_omt_insert_at(global_omt, values[0], toku_omt_size(global_omt)+2);
CKERR2(r, EINVAL);
- assert(size==global_dmt->size());
+ assert(size==toku_omt_size(global_omt));
test_close(do_close);
}
@@ -375,30 +286,39 @@ test_create_insert_at_sequential (enum close_when_done do_close) {
uint32_t size = 0;
test_create(KEEP_WHEN_DONE);
- r = dmt_insert_at(global_dmt, values[0], global_dmt->size()+1);
+ r = toku_omt_insert_at(global_omt, values[0], toku_omt_size(global_omt)+1);
CKERR2(r, EINVAL);
- r = dmt_insert_at(global_dmt, values[0], global_dmt->size()+2);
+ r = toku_omt_insert_at(global_omt, values[0], toku_omt_size(global_omt)+2);
CKERR2(r, EINVAL);
for (i = 0; i < length; i++) {
- assert(size==global_dmt->size());
- r = dmt_insert_at(global_dmt, values[i], i);
+ assert(size==toku_omt_size(global_omt));
+ r = toku_omt_insert_at(global_omt, values[i], i);
CKERR(r);
- assert(++size==global_dmt->size());
+ assert(++size==toku_omt_size(global_omt));
}
- r = dmt_insert_at(global_dmt, values[0], global_dmt->size()+1);
+ r = toku_omt_insert_at(global_omt, values[0], toku_omt_size(global_omt)+1);
CKERR2(r, EINVAL);
- r = dmt_insert_at(global_dmt, values[0], global_dmt->size()+2);
+ r = toku_omt_insert_at(global_omt, values[0], toku_omt_size(global_omt)+2);
CKERR2(r, EINVAL);
- assert(size==global_dmt->size());
+ assert(size==toku_omt_size(global_omt));
test_close(do_close);
}
static void
test_create_from_sorted_array (enum create_type create_choice, enum close_when_done do_close) {
- global_dmt = nullptr;
+ int r;
+ global_omt = NULL;
if (create_choice == BATCH_INSERT) {
- global_dmt = dmt_create_from_sorted_array(values, length);
+ r = toku_omt_create_from_sorted_array(&global_omt, values, length);
+ CKERR(r);
+ }
+ else if (create_choice == STEAL_ARRAY) {
+ TESTVALUE* MALLOC_N(length, values_copy);
+ memcpy(values_copy, values, length*sizeof(*values));
+ r = toku_omt_create_steal_sorted_array(&global_omt, &values_copy, length, length);
+ CKERR(r);
+ assert(values_copy==NULL);
}
else if (create_choice == INSERT_AT) {
test_create_insert_at_sequential(KEEP_WHEN_DONE);
@@ -406,35 +326,33 @@ test_create_from_sorted_array (enum create_type create_choice, enum close_when_d
else if (create_choice == INSERT_AT_ALMOST_RANDOM) {
test_create_insert_at_almost_random(KEEP_WHEN_DONE);
}
- else {
- assert(false);
- }
+ else assert(false);
- assert(global_dmt!=nullptr);
+ assert(global_omt!=NULL);
test_close(do_close);
}
static void
test_create_from_sorted_array_size (enum create_type create_choice, enum close_when_done do_close) {
test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
- assert(global_dmt->size()==length);
+ assert(toku_omt_size(global_omt)==length);
test_close(do_close);
}
static void
-test_fetch_verify (DMT dmtree, DMTVALUE* val, uint32_t len ) {
+test_fetch_verify (OMT omtree, TESTVALUE* val, uint32_t len ) {
uint32_t i;
int r;
- DMTVALUE v = (DMTVALUE)&i;
- DMTVALUE oldv = v;
+ TESTVALUE v = (TESTVALUE)&i;
+ TESTVALUE oldv = v;
- assert(len == dmtree->size());
+ assert(len == toku_omt_size(omtree));
for (i = 0; i < len; i++) {
assert(oldv!=val[i]);
- v = nullptr;
- r = dmtree->fetch(i, nullptr, &v);
+ v = NULL;
+ r = toku_omt_fetch(omtree, i, &v);
CKERR(r);
- assert(v != nullptr);
+ assert(v != NULL);
assert(v != oldv);
assert(v == val[i]);
assert(V(v)->number == V(val[i])->number);
@@ -443,7 +361,7 @@ test_fetch_verify (DMT dmtree, DMTVALUE* val, uint32_t len ) {
for (i = len; i < len*2; i++) {
v = oldv;
- r = dmtree->fetch(i, nullptr, &v);
+ r = toku_omt_fetch(omtree, i, &v);
CKERR2(r, EINVAL);
assert(v == oldv);
}
@@ -453,45 +371,30 @@ test_fetch_verify (DMT dmtree, DMTVALUE* val, uint32_t len ) {
static void
test_create_fetch_verify (enum create_type create_choice, enum close_when_done do_close) {
test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
- test_fetch_verify(global_dmt, values, length);
+ test_fetch_verify(global_omt, values, length);
test_close(do_close);
}
static int iterate_helper_error_return = 1;
static int
-iterate_helper (DMTVALUE v, uint32_t idx, void* extra) {
- if (extra == nullptr) return iterate_helper_error_return;
- DMTVALUE* vals = (DMTVALUE *)extra;
- assert(v != nullptr);
+iterate_helper (TESTVALUE v, uint32_t idx, void* extra) {
+ if (extra == NULL) return iterate_helper_error_return;
+ TESTVALUE* vals = (TESTVALUE *)extra;
+ assert(v != NULL);
assert(v == vals[idx]);
assert(V(v)->number == V(vals[idx])->number);
return 0;
}
-struct functor {
- int (*f)(DMTVALUE, uint32_t, void *);
- void *v;
-};
-
-int call_functor(const uint32_t size, const DMTVALUE &v, uint32_t idx, functor *const ftor);
-int call_functor(const uint32_t size, const DMTVALUE &v, uint32_t idx, functor *const ftor) {
- invariant(size == sizeof(DMTVALUE));
- return ftor->f(const_cast<DMTVALUE>(v), idx, ftor->v);
-}
-
-static int dmt_iterate(DMT dmt, int (*f)(DMTVALUE, uint32_t, void*), void*v) {
- struct functor ftor = { .f = f, .v = v };
- return dmt->iterate<functor, call_functor>(&ftor);
-}
static void
-test_iterate_verify (DMT dmtree, DMTVALUE* vals, uint32_t len) {
+test_iterate_verify (OMT omtree, TESTVALUE* vals, uint32_t len) {
int r;
iterate_helper_error_return = 0;
- r = dmt_iterate(dmtree, iterate_helper, (void*)vals);
+ r = toku_omt_iterate(omtree, iterate_helper, (void*)vals);
CKERR(r);
iterate_helper_error_return = 0xFEEDABBA;
- r = dmt_iterate(dmtree, iterate_helper, nullptr);
+ r = toku_omt_iterate(omtree, iterate_helper, NULL);
if (!len) {
CKERR2(r, 0);
}
@@ -503,7 +406,7 @@ test_iterate_verify (DMT dmtree, DMTVALUE* vals, uint32_t len) {
static void
test_create_iterate_verify (enum create_type create_choice, enum close_when_done do_close) {
test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
- test_iterate_verify(global_dmt, values, length);
+ test_iterate_verify(global_omt, values, length);
test_close(do_close);
}
@@ -528,26 +431,19 @@ permute_array (uint32_t* arr, uint32_t len) {
}
}
-static int
-dmt_set_at (DMT dmt, DMTVALUE value, uint32_t index) {
- int r = dmt->delete_at(index);
- if (r!=0) return r;
- return dmt_insert_at(dmt, value, index);
-}
-
static void
test_create_set_at (enum create_type create_choice, enum close_when_done do_close) {
uint32_t i = 0;
- struct value* old_nums = nullptr;
+ struct value* old_nums = NULL;
MALLOC_N(length, old_nums);
assert(nums);
- uint32_t* perm = nullptr;
+ uint32_t* perm = NULL;
MALLOC_N(length, perm);
assert(perm);
- DMTVALUE* old_values = nullptr;
+ TESTVALUE* old_values = NULL;
MALLOC_N(length, old_values);
assert(old_values);
@@ -563,22 +459,22 @@ test_create_set_at (enum create_type create_choice, enum close_when_done do_clos
}
test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
int r;
- r = dmt_set_at (global_dmt, values[0], length);
+ r = toku_omt_set_at (global_omt, values[0], length);
CKERR2(r,EINVAL);
- r = dmt_set_at (global_dmt, values[0], length+1);
+ r = toku_omt_set_at (global_omt, values[0], length+1);
CKERR2(r,EINVAL);
for (i = 0; i < length; i++) {
uint32_t choice = perm[i];
values[choice] = &nums[choice];
nums[choice].number = (uint32_t)random();
- r = dmt_set_at (global_dmt, values[choice], choice);
+ r = toku_omt_set_at (global_omt, values[choice], choice);
CKERR(r);
- test_iterate_verify(global_dmt, values, length);
- test_fetch_verify(global_dmt, values, length);
+ test_iterate_verify(global_omt, values, length);
+ test_fetch_verify(global_omt, values, length);
}
- r = dmt_set_at (global_dmt, values[0], length);
+ r = toku_omt_set_at (global_omt, values[0], length);
CKERR2(r,EINVAL);
- r = dmt_set_at (global_dmt, values[0], length+1);
+ r = toku_omt_set_at (global_omt, values[0], length+1);
CKERR2(r,EINVAL);
toku_free(perm);
@@ -589,8 +485,8 @@ test_create_set_at (enum create_type create_choice, enum close_when_done do_clos
}
static int
-insert_helper (DMTVALUE value, void* extra_insert) {
- DMTVALUE to_insert = (DMTVALUE)extra_insert;
+insert_helper (TESTVALUE value, void* extra_insert) {
+ TESTVALUE to_insert = (OMTVALUE)extra_insert;
assert(to_insert);
if (V(value)->number < V(to_insert)->number) return -1;
@@ -602,7 +498,7 @@ static void
test_create_insert (enum close_when_done do_close) {
uint32_t i = 0;
- uint32_t* perm = nullptr;
+ uint32_t* perm = NULL;
MALLOC_N(length, perm);
assert(perm);
@@ -614,11 +510,11 @@ test_create_insert (enum close_when_done do_close) {
length = 0;
while (length < size) {
uint32_t choice = perm[length];
- DMTVALUE to_insert = &nums[choice];
+ TESTVALUE to_insert = &nums[choice];
uint32_t idx = UINT32_MAX;
- assert(length==global_dmt->size());
- r = dmt_insert(global_dmt, to_insert, insert_helper, to_insert, &idx);
+ assert(length==toku_omt_size(global_omt));
+ r = toku_omt_insert(global_omt, to_insert, insert_helper, to_insert, &idx);
CKERR(r);
assert(idx <= length);
if (idx > 0) {
@@ -628,24 +524,24 @@ test_create_insert (enum close_when_done do_close) {
assert(V(to_insert)->number < V(values[idx])->number);
}
length++;
- assert(length==global_dmt->size());
+ assert(length==toku_omt_size(global_omt));
/* Make room */
for (i = length-1; i > idx; i--) {
values[i] = values[i-1];
}
values[idx] = to_insert;
- test_fetch_verify(global_dmt, values, length);
- test_iterate_verify(global_dmt, values, length);
+ test_fetch_verify(global_omt, values, length);
+ test_iterate_verify(global_omt, values, length);
idx = UINT32_MAX;
- r = dmt_insert(global_dmt, to_insert, insert_helper, to_insert, &idx);
+ r = toku_omt_insert(global_omt, to_insert, insert_helper, to_insert, &idx);
CKERR2(r, DB_KEYEXIST);
assert(idx < length);
assert(V(values[idx])->number == V(to_insert)->number);
- assert(length==global_dmt->size());
+ assert(length==toku_omt_size(global_omt));
- test_iterate_verify(global_dmt, values, length);
- test_fetch_verify(global_dmt, values, length);
+ test_iterate_verify(global_omt, values, length);
+ test_fetch_verify(global_omt, values, length);
}
toku_free(perm);
@@ -659,118 +555,91 @@ test_create_delete_at (enum create_type create_choice, enum close_when_done do_c
int r = ENOSYS;
test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
- assert(length == global_dmt->size());
- r = global_dmt->delete_at(length);
+ assert(length == toku_omt_size(global_omt));
+ r = toku_omt_delete_at(global_omt, length);
CKERR2(r,EINVAL);
- assert(length == global_dmt->size());
- r = global_dmt->delete_at(length+1);
+ assert(length == toku_omt_size(global_omt));
+ r = toku_omt_delete_at(global_omt, length+1);
CKERR2(r,EINVAL);
while (length > 0) {
- assert(length == global_dmt->size());
+ assert(length == toku_omt_size(global_omt));
uint32_t index_to_delete = random()%length;
- r = global_dmt->delete_at(index_to_delete);
+ r = toku_omt_delete_at(global_omt, index_to_delete);
CKERR(r);
for (i = index_to_delete+1; i < length; i++) {
values[i-1] = values[i];
}
length--;
- test_fetch_verify(global_dmt, values, length);
- test_iterate_verify(global_dmt, values, length);
+ test_fetch_verify(global_omt, values, length);
+ test_iterate_verify(global_omt, values, length);
}
assert(length == 0);
- assert(length == global_dmt->size());
- r = global_dmt->delete_at(length);
+ assert(length == toku_omt_size(global_omt));
+ r = toku_omt_delete_at(global_omt, length);
CKERR2(r, EINVAL);
- assert(length == global_dmt->size());
- r = global_dmt->delete_at(length+1);
+ assert(length == toku_omt_size(global_omt));
+ r = toku_omt_delete_at(global_omt, length+1);
CKERR2(r, EINVAL);
test_close(do_close);
}
-static int dmt_merge(DMT leftdmt, DMT rightdmt, DMT *newdmtp) {
- DMT XMALLOC(newdmt);
- newdmt->create();
- int r;
- for (uint32_t i = 0; i < leftdmt->size(); i++) {
- DMTVALUE v;
- r = leftdmt->fetch(i, nullptr, &v);
- invariant_zero(r);
- r = newdmt->insert_at(v, i);
- invariant_zero(r);
- }
- uint32_t offset = leftdmt->size();
- for (uint32_t i = 0; i < rightdmt->size(); i++) {
- DMTVALUE v;
- r = rightdmt->fetch(i, nullptr, &v);
- invariant_zero(r);
- r = newdmt->insert_at(v, i+offset);
- invariant_zero(r);
- }
- leftdmt->destroy();
- rightdmt->destroy();
- toku_free(leftdmt);
- toku_free(rightdmt);
- *newdmtp = newdmt;
- return 0;
-}
-
static void
test_split_merge (enum create_type create_choice, enum close_when_done do_close) {
int r = ENOSYS;
uint32_t i = 0;
- DMT left_split = nullptr;
- DMT right_split = nullptr;
+ OMT left_split = NULL;
+ OMT right_split = NULL;
test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
for (i = 0; i <= length; i++) {
- r = dmt_split_at(global_dmt, &right_split, length+1);
+ r = toku_omt_split_at(global_omt, &right_split, length+1);
CKERR2(r,EINVAL);
- r = dmt_split_at(global_dmt, &right_split, length+2);
+ r = toku_omt_split_at(global_omt, &right_split, length+2);
CKERR2(r,EINVAL);
//
// test successful split
//
- r = dmt_split_at(global_dmt, &right_split, i);
+ r = toku_omt_split_at(global_omt, &right_split, i);
CKERR(r);
- left_split = global_dmt;
- global_dmt = nullptr;
- assert(left_split->size() == i);
- assert(right_split->size() == length - i);
+ left_split = global_omt;
+ global_omt = NULL;
+ assert(toku_omt_size(left_split) == i);
+ assert(toku_omt_size(right_split) == length - i);
test_fetch_verify(left_split, values, i);
test_iterate_verify(left_split, values, i);
test_fetch_verify(right_split, &values[i], length - i);
test_iterate_verify(right_split, &values[i], length - i);
//
- // verify that new global_dmt's cannot do bad splits
+ // verify that new global_omt's cannot do bad splits
//
- r = dmt_split_at(left_split, &global_dmt, i+1);
+ r = toku_omt_split_at(left_split, &global_omt, i+1);
CKERR2(r,EINVAL);
- assert(left_split->size() == i);
- assert(right_split->size() == length - i);
- r = dmt_split_at(left_split, &global_dmt, i+2);
+ assert(toku_omt_size(left_split) == i);
+ assert(toku_omt_size(right_split) == length - i);
+ r = toku_omt_split_at(left_split, &global_omt, i+2);
CKERR2(r,EINVAL);
- assert(left_split->size() == i);
- assert(right_split->size() == length - i);
- r = dmt_split_at(right_split, &global_dmt, length - i + 1);
+ assert(toku_omt_size(left_split) == i);
+ assert(toku_omt_size(right_split) == length - i);
+ r = toku_omt_split_at(right_split, &global_omt, length - i + 1);
CKERR2(r,EINVAL);
- assert(left_split->size() == i);
- assert(right_split->size() == length - i);
- r = dmt_split_at(right_split, &global_dmt, length - i + 1);
+ assert(toku_omt_size(left_split) == i);
+ assert(toku_omt_size(right_split) == length - i);
+ r = toku_omt_split_at(right_split, &global_omt, length - i + 1);
CKERR2(r,EINVAL);
- assert(left_split->size() == i);
- assert(right_split->size() == length - i);
+ assert(toku_omt_size(left_split) == i);
+ assert(toku_omt_size(right_split) == length - i);
//
// test merge
//
- r = dmt_merge(left_split,right_split,&global_dmt);
+ r = toku_omt_merge(left_split,right_split,&global_omt);
CKERR(r);
- left_split = nullptr;
- right_split = nullptr;
- assert(global_dmt->size() == length);
- test_fetch_verify(global_dmt, values, length);
- test_iterate_verify(global_dmt, values, length);
+ left_split = NULL;
+ right_split = NULL;
+ assert(toku_omt_size(global_omt) == length);
+ test_fetch_verify(global_omt, values, length);
+ test_iterate_verify(global_omt, values, length);
}
test_close(do_close);
}
@@ -824,8 +693,8 @@ typedef struct {
static int
-test_heaviside (DMTVALUE v_dmt, void* x) {
- DMTVALUE v = (DMTVALUE) v_dmt;
+test_heaviside (OMTVALUE v_omt, void* x) {
+ TESTVALUE v = (OMTVALUE) v_omt;
h_extra* extra = (h_extra*)x;
assert(v && x);
assert(extra->first_zero <= extra->first_pos);
@@ -843,24 +712,24 @@ heavy_extra (h_extra* extra, uint32_t first_zero, uint32_t first_pos) {
}
static void
-test_find_dir (int dir, void* extra, int (*h)(DMTVALUE, void*),
+test_find_dir (int dir, void* extra, int (*h)(OMTVALUE, void*),
int r_expect, bool idx_will_change, uint32_t idx_expect,
uint32_t number_expect, bool UU(cursor_valid)) {
uint32_t idx = UINT32_MAX;
uint32_t old_idx = idx;
- DMTVALUE dmt_val;
+ TESTVALUE omt_val;
int r;
- dmt_val = nullptr;
+ omt_val = NULL;
- /* Verify we can pass nullptr value. */
- dmt_val = nullptr;
+ /* Verify we can pass NULL value. */
+ omt_val = NULL;
idx = old_idx;
if (dir == 0) {
- r = dmt_find_zero(global_dmt, h, extra, nullptr, &idx);
+ r = toku_omt_find_zero(global_omt, h, extra, NULL, &idx);
}
else {
- r = dmt_find( global_dmt, h, extra, dir, nullptr, &idx);
+ r = toku_omt_find( global_omt, h, extra, dir, NULL, &idx);
}
CKERR2(r, r_expect);
if (idx_will_change) {
@@ -869,38 +738,38 @@ test_find_dir (int dir, void* extra, int (*h)(DMTVALUE, void*),
else {
assert(idx == old_idx);
}
- assert(dmt_val == nullptr);
+ assert(omt_val == NULL);
- /* Verify we can pass nullptr idx. */
- dmt_val = nullptr;
+ /* Verify we can pass NULL idx. */
+ omt_val = NULL;
idx = old_idx;
if (dir == 0) {
- r = dmt_find_zero(global_dmt, h, extra, &dmt_val, 0);
+ r = toku_omt_find_zero(global_omt, h, extra, &omt_val, 0);
}
else {
- r = dmt_find( global_dmt, h, extra, dir, &dmt_val, 0);
+ r = toku_omt_find( global_omt, h, extra, dir, &omt_val, 0);
}
CKERR2(r, r_expect);
assert(idx == old_idx);
if (r == DB_NOTFOUND) {
- assert(dmt_val == nullptr);
+ assert(omt_val == NULL);
}
else {
- assert(V(dmt_val)->number == number_expect);
+ assert(V(omt_val)->number == number_expect);
}
- /* Verify we can pass nullptr both. */
- dmt_val = nullptr;
+ /* Verify we can pass NULL both. */
+ omt_val = NULL;
idx = old_idx;
if (dir == 0) {
- r = dmt_find_zero(global_dmt, h, extra, nullptr, 0);
+ r = toku_omt_find_zero(global_omt, h, extra, NULL, 0);
}
else {
- r = dmt_find( global_dmt, h, extra, dir, nullptr, 0);
+ r = toku_omt_find( global_omt, h, extra, dir, NULL, 0);
}
CKERR2(r, r_expect);
assert(idx == old_idx);
- assert(dmt_val == nullptr);
+ assert(omt_val == NULL);
}
static void
@@ -988,34 +857,33 @@ runtests_create_choice (enum create_type create_choice) {
static void
test_clone(uint32_t nelts)
// Test that each clone operation gives the right data back. If nelts is
-// zero, also tests that you still get a valid DMT back and that the way
+// zero, also tests that you still get a valid OMT back and that the way
// to deallocate it still works.
{
- DMT src = nullptr, dest = nullptr;
- int r = 0;
+ OMT src = NULL, dest = NULL;
+ int r;
- XMALLOC(src);
- src->create();
+ r = toku_omt_create(&src);
+ assert_zero(r);
for (long i = 0; i < nelts; ++i) {
- r = dmt_insert_at(src, (DMTVALUE) i, i);
+ r = toku_omt_insert_at(src, (OMTVALUE) i, i);
assert_zero(r);
}
- XMALLOC(dest);
- dest->clone(*src);
- assert(dest->size() == nelts);
+ r = toku_omt_clone_noptr(&dest, src);
+ assert_zero(r);
+ assert(dest != NULL);
+ assert(toku_omt_size(dest) == nelts);
for (long i = 0; i < nelts; ++i) {
- DMTVALUE v;
+ OMTVALUE v;
long l;
- r = dest->fetch(i, nullptr, &v);
+ r = toku_omt_fetch(dest, i, &v);
assert_zero(r);
l = (long) v;
assert(l == i);
}
- dest->destroy();
- toku_free(dest);
- src->destroy();
- toku_free(src);
+ toku_omt_destroy(&dest);
+ toku_omt_destroy(&src);
}
int
@@ -1025,6 +893,7 @@ test_main(int argc, const char *argv[]) {
test_create( CLOSE_WHEN_DONE);
test_create_size( CLOSE_WHEN_DONE);
runtests_create_choice(BATCH_INSERT);
+ runtests_create_choice(STEAL_ARRAY);
runtests_create_choice(INSERT_AT);
runtests_create_choice(INSERT_AT_ALMOST_RANDOM);
test_clone(0);
diff --git a/storage/tokudb/ft-index/ft/tests/orthopush-flush.cc b/storage/tokudb/ft-index/ft/tests/orthopush-flush.cc
index 7c198a3cb46..cfac10fb921 100644
--- a/storage/tokudb/ft-index/ft/tests/orthopush-flush.cc
+++ b/storage/tokudb/ft-index/ft/tests/orthopush-flush.cc
@@ -219,7 +219,7 @@ insert_random_message_to_bn(
*keyp = toku_xmemdup(keydbt->data, keydbt->size);
int64_t numbytes;
toku_le_apply_msg(&msg, NULL, NULL, 0, &non_mvcc_gc_info, save, &numbytes);
- toku_ft_bn_apply_msg(t->ft->compare_fun, t->ft->update_fun, NULL, blb, &msg, &non_mvcc_gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd(t->ft->compare_fun, t->ft->update_fun, NULL, blb, &msg, &non_mvcc_gc_info, NULL, NULL);
if (msn.msn > blb->max_msn_applied.msn) {
blb->max_msn_applied = msn;
}
@@ -269,11 +269,11 @@ insert_same_message_to_bns(
*keyp = toku_xmemdup(keydbt->data, keydbt->size);
int64_t numbytes;
toku_le_apply_msg(&msg, NULL, NULL, 0, &non_mvcc_gc_info, save, &numbytes);
- toku_ft_bn_apply_msg(t->ft->compare_fun, t->ft->update_fun, NULL, blb1, &msg, &non_mvcc_gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd(t->ft->compare_fun, t->ft->update_fun, NULL, blb1, &msg, &non_mvcc_gc_info, NULL, NULL);
if (msn.msn > blb1->max_msn_applied.msn) {
blb1->max_msn_applied = msn;
}
- toku_ft_bn_apply_msg(t->ft->compare_fun, t->ft->update_fun, NULL, blb2, &msg, &non_mvcc_gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd(t->ft->compare_fun, t->ft->update_fun, NULL, blb2, &msg, &non_mvcc_gc_info, NULL, NULL);
if (msn.msn > blb2->max_msn_applied.msn) {
blb2->max_msn_applied = msn;
}
@@ -685,7 +685,7 @@ flush_to_leaf(FT_HANDLE t, bool make_leaf_up_to_date, bool use_flush) {
if (make_leaf_up_to_date) {
for (i = 0; i < num_parent_messages; ++i) {
if (!parent_messages_is_fresh[i]) {
- toku_ft_leaf_apply_msg(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child, -1, parent_messages[i], &non_mvcc_gc_info, NULL, NULL);
+ toku_ft_leaf_apply_cmd(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child, -1, parent_messages[i], &non_mvcc_gc_info, NULL, NULL);
}
}
for (i = 0; i < 8; ++i) {
@@ -734,7 +734,7 @@ flush_to_leaf(FT_HANDLE t, bool make_leaf_up_to_date, bool use_flush) {
int total_messages = 0;
for (i = 0; i < 8; ++i) {
- total_messages += BLB_DATA(child, i)->num_klpairs();
+ total_messages += BLB_DATA(child, i)->omt_size();
}
assert(total_messages <= num_parent_messages + num_child_messages);
@@ -747,7 +747,7 @@ flush_to_leaf(FT_HANDLE t, bool make_leaf_up_to_date, bool use_flush) {
memset(parent_messages_present, 0, sizeof parent_messages_present);
memset(child_messages_present, 0, sizeof child_messages_present);
for (int j = 0; j < 8; ++j) {
- uint32_t len = BLB_DATA(child, j)->num_klpairs();
+ uint32_t len = BLB_DATA(child, j)->omt_size();
for (uint32_t idx = 0; idx < len; ++idx) {
LEAFENTRY le;
DBT keydbt, valdbt;
@@ -909,7 +909,7 @@ flush_to_leaf_with_keyrange(FT_HANDLE t, bool make_leaf_up_to_date) {
for (i = 0; i < num_parent_messages; ++i) {
if (dummy_cmp(NULL, parent_messages[i]->u.id.key, &childkeys[7]) <= 0 &&
!parent_messages_is_fresh[i]) {
- toku_ft_leaf_apply_msg(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child, -1, parent_messages[i], &non_mvcc_gc_info, NULL, NULL);
+ toku_ft_leaf_apply_cmd(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child, -1, parent_messages[i], &non_mvcc_gc_info, NULL, NULL);
}
}
for (i = 0; i < 8; ++i) {
@@ -969,7 +969,7 @@ flush_to_leaf_with_keyrange(FT_HANDLE t, bool make_leaf_up_to_date) {
int total_messages = 0;
for (i = 0; i < 8; ++i) {
- total_messages += BLB_DATA(child, i)->num_klpairs();
+ total_messages += BLB_DATA(child, i)->omt_size();
}
assert(total_messages <= num_parent_messages + num_child_messages);
@@ -1105,8 +1105,8 @@ compare_apply_and_flush(FT_HANDLE t, bool make_leaf_up_to_date) {
if (make_leaf_up_to_date) {
for (i = 0; i < num_parent_messages; ++i) {
if (!parent_messages_is_fresh[i]) {
- toku_ft_leaf_apply_msg(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child1, -1, parent_messages[i], &non_mvcc_gc_info, NULL, NULL);
- toku_ft_leaf_apply_msg(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child2, -1, parent_messages[i], &non_mvcc_gc_info, NULL, NULL);
+ toku_ft_leaf_apply_cmd(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child1, -1, parent_messages[i], &non_mvcc_gc_info, NULL, NULL);
+ toku_ft_leaf_apply_cmd(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child2, -1, parent_messages[i], &non_mvcc_gc_info, NULL, NULL);
}
}
for (i = 0; i < 8; ++i) {
@@ -1145,10 +1145,10 @@ compare_apply_and_flush(FT_HANDLE t, bool make_leaf_up_to_date) {
toku_ftnode_free(&parentnode);
for (int j = 0; j < 8; ++j) {
- bn_data* first = BLB_DATA(child1, j);
- bn_data* second = BLB_DATA(child2, j);
- uint32_t len = first->num_klpairs();
- assert(len == second->num_klpairs());
+ BN_DATA first = BLB_DATA(child1, j);
+ BN_DATA second = BLB_DATA(child2, j);
+ uint32_t len = first->omt_size();
+ assert(len == second->omt_size());
for (uint32_t idx = 0; idx < len; ++idx) {
LEAFENTRY le1, le2;
DBT key1dbt, val1dbt, key2dbt, val2dbt;
diff --git a/storage/tokudb/ft-index/ft/tests/shortcut.cc b/storage/tokudb/ft-index/ft/tests/shortcut.cc
index 15ff6e563f9..d972279cb77 100644
--- a/storage/tokudb/ft-index/ft/tests/shortcut.cc
+++ b/storage/tokudb/ft-index/ft/tests/shortcut.cc
@@ -96,7 +96,7 @@ static const char *fname = TOKU_TEST_FILENAME;
static TOKUTXN const null_txn = 0;
CACHETABLE ct;
-FT_HANDLE ft;
+FT_HANDLE brt;
FT_CURSOR cursor;
static int test_ft_cursor_keycompare(DB *db __attribute__((unused)), const DBT *a, const DBT *b) {
@@ -109,15 +109,15 @@ test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute
unlink(fname);
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare); assert(r==0);
- r = toku_ft_cursor(ft, &cursor, NULL, false, false); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, test_ft_cursor_keycompare); assert(r==0);
+ r = toku_ft_cursor(brt, &cursor, NULL, false, false); assert(r==0);
int i;
for (i=0; i<1000; i++) {
char string[100];
snprintf(string, sizeof(string), "%04d", i);
DBT key,val;
- toku_ft_insert(ft, toku_fill_dbt(&key, string, 5), toku_fill_dbt(&val, string, 5), 0);
+ toku_ft_insert(brt, toku_fill_dbt(&key, string, 5), toku_fill_dbt(&val, string, 5), 0);
}
{
@@ -132,7 +132,7 @@ test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute
// This will invalidate due to the root counter bumping, but the OMT itself will still be valid.
{
DBT key, val;
- toku_ft_insert(ft, toku_fill_dbt(&key, "d", 2), toku_fill_dbt(&val, "w", 2), 0);
+ toku_ft_insert(brt, toku_fill_dbt(&key, "d", 2), toku_fill_dbt(&val, "w", 2), 0);
}
{
@@ -141,7 +141,7 @@ test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute
}
toku_ft_cursor_close(cursor);
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-flush.cc b/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-flush.cc
index 976a5a5b958..e3a6116624e 100644
--- a/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-flush.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-flush.cc
@@ -230,14 +230,15 @@ doit (bool after_child_pin) {
FTNODE node = NULL;
struct ftnode_fetch_extra bfe;
fill_bfe_for_min_read(&bfe, t->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 1);
@@ -248,14 +249,15 @@ doit (bool after_child_pin) {
assert(checkpoint_callback_called);
// now let's pin the root again and make sure it is flushed
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 1);
@@ -284,14 +286,15 @@ doit (bool after_child_pin) {
// now pin the root, verify that we have a message in there, and that it is clean
//
fill_bfe_for_full_read(&bfe, c_ft->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
node_root,
toku_cachetable_hash(c_ft->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(!node->dirty);
@@ -302,16 +305,17 @@ doit (bool after_child_pin) {
else {
assert(toku_bnc_nbytesinbuf(BNC(node, 0)) > 0);
}
- toku_unpin_ftnode(c_ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
node_leaf,
toku_cachetable_hash(c_ft->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
@@ -322,7 +326,7 @@ doit (bool after_child_pin) {
else {
assert(BLB_NBYTESINDATA(node,0) == 0);
}
- toku_unpin_ftnode(c_ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
struct check_pair pair1 = {2, "a", 0, NULL, 0};
DBT k;
diff --git a/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-merge.cc b/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-merge.cc
index d3950ee746a..c8127d7287a 100644
--- a/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-merge.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-merge.cc
@@ -248,7 +248,7 @@ doit (int state) {
struct ftnode_fetch_extra bfe;
fill_bfe_for_min_read(&bfe, t->ft);
- toku_pin_ftnode_with_dep_nodes(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
@@ -256,8 +256,7 @@ doit (int state) {
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->height == 1);
assert(node->n_children == 2);
@@ -267,7 +266,7 @@ doit (int state) {
assert(checkpoint_callback_called);
// now let's pin the root again and make sure it is has merged
- toku_pin_ftnode_with_dep_nodes(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
@@ -275,8 +274,7 @@ doit (int state) {
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->height == 1);
assert(node->n_children == 1);
@@ -307,7 +305,7 @@ doit (int state) {
// now pin the root, verify that the state is what we expect
//
fill_bfe_for_full_read(&bfe, c_ft->ft);
- toku_pin_ftnode_with_dep_nodes(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
node_root,
toku_cachetable_hash(c_ft->ft->cf, node_root),
@@ -315,8 +313,7 @@ doit (int state) {
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->height == 1);
assert(!node->dirty);
@@ -334,11 +331,11 @@ doit (int state) {
else {
assert(false);
}
- toku_unpin_ftnode(c_ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
// now let's verify the leaves are what we expect
if (state == flt_flush_before_merge || state == flt_flush_before_pin_second_node_for_merge) {
- toku_pin_ftnode_with_dep_nodes(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
left_child,
toku_cachetable_hash(c_ft->ft->cf, left_child),
@@ -346,16 +343,15 @@ doit (int state) {
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
assert(node->n_children == 1);
- assert(BLB_DATA(node, 0)->num_klpairs() == 1);
- toku_unpin_ftnode(c_ft->ft, node);
+ assert(BLB_DATA(node, 0)->omt_size() == 1);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
- toku_pin_ftnode_with_dep_nodes(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
right_child,
toku_cachetable_hash(c_ft->ft->cf, right_child),
@@ -363,17 +359,16 @@ doit (int state) {
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
assert(node->n_children == 1);
- assert(BLB_DATA(node, 0)->num_klpairs() == 1);
- toku_unpin_ftnode(c_ft->ft, node);
+ assert(BLB_DATA(node, 0)->omt_size() == 1);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
}
else if (state == ft_flush_aflter_merge || state == flt_flush_before_unpin_remove) {
- toku_pin_ftnode_with_dep_nodes(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
left_child,
toku_cachetable_hash(c_ft->ft->cf, left_child),
@@ -381,14 +376,13 @@ doit (int state) {
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
assert(node->n_children == 1);
- assert(BLB_DATA(node, 0)->num_klpairs() == 2);
- toku_unpin_ftnode(c_ft->ft, node);
+ assert(BLB_DATA(node, 0)->omt_size() == 2);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
}
else {
assert(false);
diff --git a/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-rebalance.cc b/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-rebalance.cc
index 0a78e260e34..89176adba5c 100644
--- a/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-rebalance.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-rebalance.cc
@@ -268,14 +268,15 @@ doit (int state) {
struct ftnode_fetch_extra bfe;
fill_bfe_for_min_read(&bfe, t->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 2);
@@ -285,14 +286,15 @@ doit (int state) {
assert(checkpoint_callback_called);
// now let's pin the root again and make sure it is has rebalanced
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 2);
@@ -323,14 +325,15 @@ doit (int state) {
// now pin the root, verify that the state is what we expect
//
fill_bfe_for_full_read(&bfe, c_ft->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
node_root,
toku_cachetable_hash(c_ft->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(!node->dirty);
@@ -340,38 +343,41 @@ doit (int state) {
left_child = BP_BLOCKNUM(node,0);
right_child = BP_BLOCKNUM(node,1);
- toku_unpin_ftnode(c_ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
// now let's verify the leaves are what we expect
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
left_child,
toku_cachetable_hash(c_ft->ft->cf, left_child),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
assert(node->n_children == 1);
- assert(BLB_DATA(node, 0)->num_klpairs() == 2);
- toku_unpin_ftnode(c_ft->ft, node);
+ assert(BLB_DATA(node, 0)->omt_size() == 2);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
right_child,
toku_cachetable_hash(c_ft->ft->cf, right_child),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
assert(node->n_children == 1);
- assert(BLB_DATA(node, 0)->num_klpairs() == 2);
- toku_unpin_ftnode(c_ft->ft, node);
+ assert(BLB_DATA(node, 0)->omt_size() == 2);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
+
DBT k;
struct check_pair pair1 = {2, "a", 0, NULL, 0};
diff --git a/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-split.cc b/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-split.cc
index c1f7f0d9b1f..f4b08f25c42 100644
--- a/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-split.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-checkpoint-during-split.cc
@@ -244,14 +244,15 @@ doit (bool after_split) {
FTNODE node = NULL;
struct ftnode_fetch_extra bfe;
fill_bfe_for_min_read(&bfe, t->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 1);
@@ -261,14 +262,15 @@ doit (bool after_split) {
assert(checkpoint_callback_called);
// now let's pin the root again and make sure it is has split
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 2);
@@ -299,14 +301,15 @@ doit (bool after_split) {
// now pin the root, verify that we have a message in there, and that it is clean
//
fill_bfe_for_full_read(&bfe, c_ft->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
node_root,
toku_cachetable_hash(c_ft->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(!node->dirty);
@@ -322,55 +325,58 @@ doit (bool after_split) {
left_child = BP_BLOCKNUM(node,0);
assert(left_child.b == node_leaf.b);
}
- toku_unpin_ftnode(c_ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
// now let's verify the leaves are what we expect
if (after_split) {
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
left_child,
toku_cachetable_hash(c_ft->ft->cf, left_child),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
assert(node->n_children == 1);
- assert(BLB_DATA(node, 0)->num_klpairs() == 1);
- toku_unpin_ftnode(c_ft->ft, node);
+ assert(BLB_DATA(node, 0)->omt_size() == 1);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
right_child,
toku_cachetable_hash(c_ft->ft->cf, right_child),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
assert(node->n_children == 1);
- assert(BLB_DATA(node, 0)->num_klpairs() == 1);
- toku_unpin_ftnode(c_ft->ft, node);
+ assert(BLB_DATA(node, 0)->omt_size() == 1);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
}
else {
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
c_ft->ft,
left_child,
toku_cachetable_hash(c_ft->ft->cf, left_child),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 0);
assert(!node->dirty);
assert(node->n_children == 1);
- assert(BLB_DATA(node, 0)->num_klpairs() == 2);
- toku_unpin_ftnode(c_ft->ft, node);
+ assert(BLB_DATA(node, 0)->omt_size() == 2);
+ toku_unpin_ftnode_off_client_thread(c_ft->ft, node);
}
diff --git a/storage/tokudb/ft-index/ft/tests/test-dirty-flushes-on-cleaner.cc b/storage/tokudb/ft-index/ft/tests/test-dirty-flushes-on-cleaner.cc
index 39b835e278f..b62b9e063a1 100644
--- a/storage/tokudb/ft-index/ft/tests/test-dirty-flushes-on-cleaner.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-dirty-flushes-on-cleaner.cc
@@ -103,7 +103,7 @@ static DB * const null_db = 0;
enum { NODESIZE = 1024, KSIZE=NODESIZE-100, TOKU_PSIZE=20 };
CACHETABLE ct;
-FT_HANDLE ft;
+FT_HANDLE brt;
const char *fname = TOKU_TEST_FILENAME;
static int update_func(
@@ -134,11 +134,11 @@ doit (void) {
toku_cachetable_create(&ct, 500*1024*1024, ZERO_LSN, NULL_LOGGER);
unlink(fname);
- r = toku_open_ft_handle(fname, 1, &ft, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ r = toku_open_ft_handle(fname, 1, &brt, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r==0);
- ft->ft->update_fun = update_func;
- ft->ft->update_fun = update_func;
+ brt->ft->update_fun = update_func;
+ brt->ft->update_fun = update_func;
toku_testsetup_initialize(); // must precede any other toku_testsetup calls
@@ -146,16 +146,16 @@ doit (void) {
pivots[0] = toku_strdup("kkkkk");
int pivot_len = 6;
- r = toku_testsetup_leaf(ft, &node_leaf, 2, pivots, &pivot_len);
+ r = toku_testsetup_leaf(brt, &node_leaf, 2, pivots, &pivot_len);
assert(r==0);
- r = toku_testsetup_nonleaf(ft, 1, &node_internal, 1, &node_leaf, 0, 0);
+ r = toku_testsetup_nonleaf(brt, 1, &node_internal, 1, &node_leaf, 0, 0);
assert(r==0);
- r = toku_testsetup_nonleaf(ft, 2, &node_root, 1, &node_internal, 0, 0);
+ r = toku_testsetup_nonleaf(brt, 2, &node_root, 1, &node_internal, 0, 0);
assert(r==0);
- r = toku_testsetup_root(ft, node_root);
+ r = toku_testsetup_root(brt, node_root);
assert(r==0);
//
@@ -165,7 +165,7 @@ doit (void) {
// now we insert a row into each leaf node
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf,
"a", // key
2, // keylen
@@ -174,7 +174,7 @@ doit (void) {
);
assert(r==0);
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf,
"z", // key
2, // keylen
@@ -187,7 +187,7 @@ doit (void) {
// now we insert filler data so that the rebalance
// keeps it at two nodes
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf,
"b", // key
2, // keylen
@@ -196,7 +196,7 @@ doit (void) {
);
assert(r==0);
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf,
"y", // key
2, // keylen
@@ -211,7 +211,7 @@ doit (void) {
//
for (int i = 0; i < 100000; i++) {
r = toku_testsetup_insert_to_nonleaf (
- ft,
+ brt,
node_internal,
FT_DELETE_ANY,
"jj", // this key does not exist, so its message application should be a no-op
@@ -226,7 +226,7 @@ doit (void) {
// now insert a broadcast message into the root
//
r = toku_testsetup_insert_to_nonleaf (
- ft,
+ brt,
node_root,
FT_UPDATE_BROADCAST_ALL,
NULL,
@@ -239,28 +239,27 @@ doit (void) {
// now lock and release the leaf node to make sure it is what we expect it to be.
FTNODE node = NULL;
struct ftnode_fetch_extra bfe;
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode_with_dep_nodes(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_leaf,
- toku_cachetable_hash(ft->ft->cf, node_leaf),
+ toku_cachetable_hash(brt->ft->cf, node_leaf),
&bfe,
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->dirty);
assert(node->n_children == 2);
assert(BP_STATE(node,0) == PT_AVAIL);
assert(BP_STATE(node,1) == PT_AVAIL);
- toku_unpin_ftnode(ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(brt->ft, node);
// now do a lookup on one of the keys, this should bring a leaf node up to date
DBT k;
struct check_pair pair = {2, "a", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
assert(r==0);
//
@@ -269,38 +268,36 @@ doit (void) {
// node is in memory and another is
// on disk
//
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode_with_dep_nodes(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_leaf,
- toku_cachetable_hash(ft->ft->cf, node_leaf),
+ toku_cachetable_hash(brt->ft->cf, node_leaf),
&bfe,
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->dirty);
assert(node->n_children == 2);
assert(BP_STATE(node,0) == PT_AVAIL);
assert(BP_STATE(node,1) == PT_AVAIL);
- toku_unpin_ftnode(ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(brt->ft, node);
//
// now let us induce a clean on the internal node
//
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode_with_dep_nodes(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
+ toku_cachetable_hash(brt->ft->cf, node_internal),
&bfe,
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
assert(node->dirty);
@@ -310,26 +307,25 @@ doit (void) {
r = toku_ftnode_cleaner_callback(
node,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
- ft->ft
+ toku_cachetable_hash(brt->ft->cf, node_internal),
+ brt->ft
);
// verify that node_internal's buffer is empty
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode_with_dep_nodes(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
+ toku_cachetable_hash(brt->ft->cf, node_internal),
&bfe,
PL_WRITE_EXPENSIVE,
0,
NULL,
- &node,
- true
+ &node
);
// check that buffers are empty
assert(toku_bnc_nbytesinbuf(BNC(node, 0)) == 0);
- toku_unpin_ftnode(ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(brt->ft, node);
//
// now run a checkpoint to get everything clean,
@@ -341,14 +337,14 @@ doit (void) {
// check that lookups on the two keys is still good
struct check_pair pair1 = {2, "a", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
assert(r==0);
struct check_pair pair2 = {2, "z", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
assert(r==0);
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
toku_free(pivots[0]);
diff --git a/storage/tokudb/ft-index/ft/tests/test-flushes-on-cleaner.cc b/storage/tokudb/ft-index/ft/tests/test-flushes-on-cleaner.cc
index 32b03496e5e..291d409018a 100644
--- a/storage/tokudb/ft-index/ft/tests/test-flushes-on-cleaner.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-flushes-on-cleaner.cc
@@ -103,7 +103,7 @@ static DB * const null_db = 0;
enum { NODESIZE = 1024, KSIZE=NODESIZE-100, TOKU_PSIZE=20 };
CACHETABLE ct;
-FT_HANDLE ft;
+FT_HANDLE brt;
const char *fname = TOKU_TEST_FILENAME;
static int update_func(
@@ -134,11 +134,11 @@ doit (bool keep_other_bn_in_memory) {
toku_cachetable_create(&ct, 500*1024*1024, ZERO_LSN, NULL_LOGGER);
unlink(fname);
- r = toku_open_ft_handle(fname, 1, &ft, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ r = toku_open_ft_handle(fname, 1, &brt, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r==0);
- ft->options.update_fun = update_func;
- ft->ft->update_fun = update_func;
+ brt->options.update_fun = update_func;
+ brt->ft->update_fun = update_func;
toku_testsetup_initialize(); // must precede any other toku_testsetup calls
@@ -146,16 +146,16 @@ doit (bool keep_other_bn_in_memory) {
pivots[0] = toku_strdup("kkkkk");
int pivot_len = 6;
- r = toku_testsetup_leaf(ft, &node_leaf, 2, pivots, &pivot_len);
+ r = toku_testsetup_leaf(brt, &node_leaf, 2, pivots, &pivot_len);
assert(r==0);
- r = toku_testsetup_nonleaf(ft, 1, &node_internal, 1, &node_leaf, 0, 0);
+ r = toku_testsetup_nonleaf(brt, 1, &node_internal, 1, &node_leaf, 0, 0);
assert(r==0);
- r = toku_testsetup_nonleaf(ft, 2, &node_root, 1, &node_internal, 0, 0);
+ r = toku_testsetup_nonleaf(brt, 2, &node_root, 1, &node_internal, 0, 0);
assert(r==0);
- r = toku_testsetup_root(ft, node_root);
+ r = toku_testsetup_root(brt, node_root);
assert(r==0);
//
@@ -165,7 +165,7 @@ doit (bool keep_other_bn_in_memory) {
// now we insert a row into each leaf node
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf,
"a", // key
2, // keylen
@@ -174,7 +174,7 @@ doit (bool keep_other_bn_in_memory) {
);
assert(r==0);
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf,
"z", // key
2, // keylen
@@ -187,7 +187,7 @@ doit (bool keep_other_bn_in_memory) {
// now we insert filler data so that the rebalance
// keeps it at two nodes
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf,
"b", // key
2, // keylen
@@ -196,7 +196,7 @@ doit (bool keep_other_bn_in_memory) {
);
assert(r==0);
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf,
"y", // key
2, // keylen
@@ -211,7 +211,7 @@ doit (bool keep_other_bn_in_memory) {
//
for (int i = 0; i < 100000; i++) {
r = toku_testsetup_insert_to_nonleaf (
- ft,
+ brt,
node_internal,
FT_DELETE_ANY,
"jj", // this key does not exist, so its message application should be a no-op
@@ -226,7 +226,7 @@ doit (bool keep_other_bn_in_memory) {
// now insert a broadcast message into the root
//
r = toku_testsetup_insert_to_nonleaf (
- ft,
+ brt,
node_root,
FT_UPDATE_BROADCAST_ALL,
NULL,
@@ -245,32 +245,33 @@ doit (bool keep_other_bn_in_memory) {
// now lock and release the leaf node to make sure it is what we expect it to be.
FTNODE node = NULL;
struct ftnode_fetch_extra bfe;
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_leaf,
- toku_cachetable_hash(ft->ft->cf, node_leaf),
+ toku_cachetable_hash(brt->ft->cf, node_leaf),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(!node->dirty);
assert(node->n_children == 2);
// a hack to get the basement nodes evicted
for (int i = 0; i < 20; i++) {
- toku_ftnode_pe_callback(node, make_pair_attr(0xffffffff), ft->ft, def_pe_finalize_impl, nullptr);
+ toku_ftnode_pe_callback(node, make_pair_attr(0xffffffff), brt->ft, def_pe_finalize_impl, nullptr);
}
// this ensures that when we do the lookups below,
// that the data is read off disk
assert(BP_STATE(node,0) == PT_ON_DISK);
assert(BP_STATE(node,1) == PT_ON_DISK);
- toku_unpin_ftnode(ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(brt->ft, node);
// now do a lookup on one of the keys, this should bring a leaf node up to date
DBT k;
struct check_pair pair = {2, "a", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
assert(r==0);
if (keep_other_bn_in_memory) {
@@ -281,7 +282,7 @@ doit (bool keep_other_bn_in_memory) {
// but only one should have broadcast message
// applied.
//
- fill_bfe_for_full_read(&bfe, ft->ft);
+ fill_bfe_for_full_read(&bfe, brt->ft);
}
else {
//
@@ -290,16 +291,17 @@ doit (bool keep_other_bn_in_memory) {
// node is in memory and another is
// on disk
//
- fill_bfe_for_min_read(&bfe, ft->ft);
+ fill_bfe_for_min_read(&bfe, brt->ft);
}
- toku_pin_ftnode(
- ft->ft,
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_leaf,
- toku_cachetable_hash(ft->ft->cf, node_leaf),
+ toku_cachetable_hash(brt->ft->cf, node_leaf),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(!node->dirty);
assert(node->n_children == 2);
@@ -310,20 +312,21 @@ doit (bool keep_other_bn_in_memory) {
else {
assert(BP_STATE(node,1) == PT_ON_DISK);
}
- toku_unpin_ftnode(ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(brt->ft, node);
//
// now let us induce a clean on the internal node
//
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
+ toku_cachetable_hash(brt->ft->cf, node_internal),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(!node->dirty);
@@ -333,24 +336,25 @@ doit (bool keep_other_bn_in_memory) {
r = toku_ftnode_cleaner_callback(
node,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
- ft->ft
+ toku_cachetable_hash(brt->ft->cf, node_internal),
+ brt->ft
);
// verify that node_internal's buffer is empty
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
+ toku_cachetable_hash(brt->ft->cf, node_internal),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
// check that buffers are empty
assert(toku_bnc_nbytesinbuf(BNC(node, 0)) == 0);
- toku_unpin_ftnode(ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(brt->ft, node);
//
// now run a checkpoint to get everything clean,
@@ -361,14 +365,14 @@ doit (bool keep_other_bn_in_memory) {
// check that lookups on the two keys is still good
struct check_pair pair1 = {2, "a", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
assert(r==0);
struct check_pair pair2 = {2, "z", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
assert(r==0);
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
toku_free(pivots[0]);
diff --git a/storage/tokudb/ft-index/ft/tests/test-hot-with-bounds.cc b/storage/tokudb/ft-index/ft/tests/test-hot-with-bounds.cc
index b6eaab3073a..40ed00bcdc2 100644
--- a/storage/tokudb/ft-index/ft/tests/test-hot-with-bounds.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-hot-with-bounds.cc
@@ -183,14 +183,15 @@ doit (void) {
FTNODE node = NULL;
struct ftnode_fetch_extra bfe;
fill_bfe_for_min_read(&bfe, t->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 3);
@@ -212,14 +213,15 @@ doit (void) {
// only the middle buffer, let's verify this.
node = NULL;
fill_bfe_for_min_read(&bfe, t->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_root,
toku_cachetable_hash(t->ft->cf, node_root),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 3);
diff --git a/storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc b/storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc
index 0335c284cb3..b0a5dfe7817 100644
--- a/storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc
@@ -213,7 +213,7 @@ test_le_offsets (void) {
static void
test_ule_packs_to_nothing (ULE ule) {
LEAFENTRY le;
- int r = le_pack(ule, NULL, 0, NULL, 0, 0, &le, nullptr);
+ int r = le_pack(ule, NULL, 0, NULL, 0, 0, &le);
assert(r==0);
assert(le==NULL);
}
@@ -319,7 +319,7 @@ test_le_pack_committed (void) {
size_t memsize;
LEAFENTRY le;
- int r = le_pack(&ule, nullptr, 0, nullptr, 0, 0, &le, nullptr);
+ int r = le_pack(&ule, nullptr, 0, nullptr, 0, 0, &le);
assert(r==0);
assert(le!=NULL);
memsize = le_memsize_from_ule(&ule);
@@ -329,7 +329,7 @@ test_le_pack_committed (void) {
verify_ule_equal(&ule, &tmp_ule);
LEAFENTRY tmp_le;
size_t tmp_memsize;
- r = le_pack(&tmp_ule, nullptr, 0, nullptr, 0, 0, &tmp_le, nullptr);
+ r = le_pack(&tmp_ule, nullptr, 0, nullptr, 0, 0, &tmp_le);
tmp_memsize = le_memsize_from_ule(&tmp_ule);
assert(r==0);
assert(tmp_memsize == memsize);
@@ -377,7 +377,7 @@ test_le_pack_uncommitted (uint8_t committed_type, uint8_t prov_type, int num_pla
size_t memsize;
LEAFENTRY le;
- int r = le_pack(&ule, nullptr, 0, nullptr, 0, 0, &le, nullptr);
+ int r = le_pack(&ule, nullptr, 0, nullptr, 0, 0, &le);
assert(r==0);
assert(le!=NULL);
memsize = le_memsize_from_ule(&ule);
@@ -387,7 +387,7 @@ test_le_pack_uncommitted (uint8_t committed_type, uint8_t prov_type, int num_pla
verify_ule_equal(&ule, &tmp_ule);
LEAFENTRY tmp_le;
size_t tmp_memsize;
- r = le_pack(&tmp_ule, nullptr, 0, nullptr, 0, 0, &tmp_le, nullptr);
+ r = le_pack(&tmp_ule, nullptr, 0, nullptr, 0, 0, &tmp_le);
tmp_memsize = le_memsize_from_ule(&tmp_ule);
assert(r==0);
assert(tmp_memsize == memsize);
@@ -448,7 +448,7 @@ test_le_apply(ULE ule_initial, FT_MSG msg, ULE ule_expected) {
LEAFENTRY le_expected;
LEAFENTRY le_result;
- r = le_pack(ule_initial, nullptr, 0, nullptr, 0, 0, &le_initial, nullptr);
+ r = le_pack(ule_initial, nullptr, 0, nullptr, 0, 0, &le_initial);
CKERR(r);
size_t result_memsize = 0;
@@ -467,7 +467,7 @@ test_le_apply(ULE ule_initial, FT_MSG msg, ULE ule_expected) {
}
size_t expected_memsize = 0;
- r = le_pack(ule_expected, nullptr, 0, nullptr, 0, 0, &le_expected, nullptr);
+ r = le_pack(ule_expected, nullptr, 0, nullptr, 0, 0, &le_expected);
CKERR(r);
if (le_expected) {
expected_memsize = leafentry_memsize(le_expected);
@@ -749,7 +749,7 @@ test_le_apply_messages(void) {
static bool ule_worth_running_garbage_collection(ULE ule, TXNID oldest_referenced_xid_known) {
LEAFENTRY le;
- int r = le_pack(ule, nullptr, 0, nullptr, 0, 0, &le, nullptr); CKERR(r);
+ int r = le_pack(ule, nullptr, 0, nullptr, 0, 0, &le); CKERR(r);
invariant_notnull(le);
txn_gc_info gc_info(nullptr, oldest_referenced_xid_known, oldest_referenced_xid_known, true);
bool worth_running = toku_le_worth_running_garbage_collection(le, &gc_info);
diff --git a/storage/tokudb/ft-index/ft/tests/test-merges-on-cleaner.cc b/storage/tokudb/ft-index/ft/tests/test-merges-on-cleaner.cc
index 142a41ae6c9..d6b8d361b47 100644
--- a/storage/tokudb/ft-index/ft/tests/test-merges-on-cleaner.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-merges-on-cleaner.cc
@@ -102,7 +102,7 @@ static DB * const null_db = 0;
enum { NODESIZE = 1024, KSIZE=NODESIZE-100, TOKU_PSIZE=20 };
CACHETABLE ct;
-FT_HANDLE ft;
+FT_HANDLE brt;
const char *fname = TOKU_TEST_FILENAME;
static int update_func(
@@ -133,30 +133,30 @@ doit (void) {
toku_cachetable_create(&ct, 500*1024*1024, ZERO_LSN, NULL_LOGGER);
unlink(fname);
- r = toku_open_ft_handle(fname, 1, &ft, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ r = toku_open_ft_handle(fname, 1, &brt, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r==0);
- ft->options.update_fun = update_func;
- ft->ft->update_fun = update_func;
+ brt->options.update_fun = update_func;
+ brt->ft->update_fun = update_func;
toku_testsetup_initialize(); // must precede any other toku_testsetup calls
- r = toku_testsetup_leaf(ft, &node_leaf[0], 1, NULL, NULL);
+ r = toku_testsetup_leaf(brt, &node_leaf[0], 1, NULL, NULL);
assert(r==0);
- r = toku_testsetup_leaf(ft, &node_leaf[1], 1, NULL, NULL);
+ r = toku_testsetup_leaf(brt, &node_leaf[1], 1, NULL, NULL);
assert(r==0);
char* pivots[1];
pivots[0] = toku_strdup("kkkkk");
int pivot_len = 6;
- r = toku_testsetup_nonleaf(ft, 1, &node_internal, 2, node_leaf, pivots, &pivot_len);
+ r = toku_testsetup_nonleaf(brt, 1, &node_internal, 2, node_leaf, pivots, &pivot_len);
assert(r==0);
- r = toku_testsetup_nonleaf(ft, 2, &node_root, 1, &node_internal, 0, 0);
+ r = toku_testsetup_nonleaf(brt, 2, &node_root, 1, &node_internal, 0, 0);
assert(r==0);
- r = toku_testsetup_root(ft, node_root);
+ r = toku_testsetup_root(brt, node_root);
assert(r==0);
//
@@ -166,7 +166,7 @@ doit (void) {
// now we insert a row into each leaf node
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf[0],
"a", // key
2, // keylen
@@ -175,7 +175,7 @@ doit (void) {
);
assert(r==0);
r = toku_testsetup_insert_to_leaf (
- ft,
+ brt,
node_leaf[1],
"z", // key
2, // keylen
@@ -190,7 +190,7 @@ doit (void) {
//
for (int i = 0; i < 100000; i++) {
r = toku_testsetup_insert_to_nonleaf (
- ft,
+ brt,
node_internal,
FT_DELETE_ANY,
"jj", // this key does not exist, so its message application should be a no-op
@@ -205,7 +205,7 @@ doit (void) {
// now insert a broadcast message into the root
//
r = toku_testsetup_insert_to_nonleaf (
- ft,
+ brt,
node_root,
FT_UPDATE_BROADCAST_ALL,
NULL,
@@ -219,27 +219,28 @@ doit (void) {
// now let us induce a clean on the internal node
//
FTNODE node;
- toku_pin_node_with_min_bfe(&node, node_leaf[1], ft);
+ toku_pin_node_with_min_bfe(&node, node_leaf[1], brt);
// hack to get merge going
BLB_SEQINSERT(node, node->n_children-1) = false;
- toku_unpin_ftnode(ft->ft, node);
+ toku_unpin_ftnode(brt->ft, node);
// now do a lookup on one of the keys, this should bring a leaf node up to date
DBT k;
struct check_pair pair = {2, "a", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
assert(r==0);
struct ftnode_fetch_extra bfe;
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
+ toku_cachetable_hash(brt->ft->cf, node_internal),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->n_children == 2);
// we expect that this flushes its buffer, that
@@ -248,26 +249,27 @@ doit (void) {
r = toku_ftnode_cleaner_callback(
node,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
- ft->ft
+ toku_cachetable_hash(brt->ft->cf, node_internal),
+ brt->ft
);
// verify that node_internal's buffer is empty
- fill_bfe_for_min_read(&bfe, ft->ft);
- toku_pin_ftnode(
- ft->ft,
+ fill_bfe_for_min_read(&bfe, brt->ft);
+ toku_pin_ftnode_off_client_thread(
+ brt->ft,
node_internal,
- toku_cachetable_hash(ft->ft->cf, node_internal),
+ toku_cachetable_hash(brt->ft->cf, node_internal),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
// check that merge happened
assert(node->n_children == 1);
// check that buffers are empty
assert(toku_bnc_nbytesinbuf(BNC(node, 0)) == 0);
- toku_unpin_ftnode(ft->ft, node);
+ toku_unpin_ftnode_off_client_thread(brt->ft, node);
//
// now run a checkpoint to get everything clean,
@@ -279,14 +281,14 @@ doit (void) {
// check that lookups on the two keys is still good
struct check_pair pair1 = {2, "a", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
assert(r==0);
struct check_pair pair2 = {2, "z", 0, NULL, 0};
- r = toku_ft_lookup(ft, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
+ r = toku_ft_lookup(brt, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
assert(r==0);
- r = toku_close_ft_handle_nolsn(ft, 0); assert(r==0);
+ r = toku_close_ft_handle_nolsn(brt, 0); assert(r==0);
toku_cachetable_close(&ct);
toku_free(pivots[0]);
diff --git a/storage/tokudb/ft-index/ft/tests/test-oldest-referenced-xid-flush.cc b/storage/tokudb/ft-index/ft/tests/test-oldest-referenced-xid-flush.cc
index 60728582389..32a8714f06d 100644
--- a/storage/tokudb/ft-index/ft/tests/test-oldest-referenced-xid-flush.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-oldest-referenced-xid-flush.cc
@@ -169,14 +169,15 @@ static void test_oldest_referenced_xid_gets_propogated(void) {
FTNODE node = NULL;
struct ftnode_fetch_extra bfe;
fill_bfe_for_min_read(&bfe, t->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
child_nonleaf_blocknum,
toku_cachetable_hash(t->ft->cf, child_nonleaf_blocknum),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 1);
assert(node->n_children == 1);
@@ -185,14 +186,15 @@ static void test_oldest_referenced_xid_gets_propogated(void) {
toku_unpin_ftnode(t->ft, node);
// now verify the root - keep it pinned so we can flush it below
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
root_blocknum,
toku_cachetable_hash(t->ft->cf, root_blocknum),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->height == 2);
assert(node->n_children == 1);
@@ -220,14 +222,15 @@ static void test_oldest_referenced_xid_gets_propogated(void) {
// pin the child, verify that oldest referenced xid was
// propogated from parent to child during the flush
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
child_nonleaf_blocknum,
toku_cachetable_hash(t->ft->cf, child_nonleaf_blocknum),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->oldest_referenced_xid_known == flush_xid);
diff --git a/storage/tokudb/ft-index/ft/tests/test-pick-child-to-flush.cc b/storage/tokudb/ft-index/ft/tests/test-pick-child-to-flush.cc
index 96482177a31..b8b44e669f5 100644
--- a/storage/tokudb/ft-index/ft/tests/test-pick-child-to-flush.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-pick-child-to-flush.cc
@@ -189,7 +189,7 @@ doit (void) {
r = toku_testsetup_root(t, node_root);
assert(r==0);
- char filler[900-2*bn_data::HEADER_LENGTH];
+ char filler[900];
memset(filler, 0, sizeof(filler));
// now we insert filler data so that a merge does not happen
r = toku_testsetup_insert_to_leaf (
diff --git a/storage/tokudb/ft-index/ft/tests/test.h b/storage/tokudb/ft-index/ft/tests/test.h
index f22d8cdbf67..ad1fc7c148e 100644
--- a/storage/tokudb/ft-index/ft/tests/test.h
+++ b/storage/tokudb/ft-index/ft/tests/test.h
@@ -121,7 +121,7 @@ PATENT RIGHTS GRANT:
const ITEMLEN len_ignore = 0xFFFFFFFF;
-// dummymsn needed to simulate msn because test messages are injected at a lower level than toku_ft_root_put_msg()
+// dummymsn needed to simulate msn because test messages are injected at a lower level than toku_ft_root_put_cmd()
#define MIN_DUMMYMSN ((MSN) {(uint64_t)1<<62})
static MSN dummymsn;
static int dummymsn_initialized = 0;
diff --git a/storage/tokudb/ft-index/ft/tests/test1308a.cc b/storage/tokudb/ft-index/ft/tests/test1308a.cc
index a39953ad354..908c648090a 100644
--- a/storage/tokudb/ft-index/ft/tests/test1308a.cc
+++ b/storage/tokudb/ft-index/ft/tests/test1308a.cc
@@ -1,6 +1,6 @@
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
-// Test the first case for the bug in #1308 (ft-serialize.c:33 does the cast wrong)
+// Test the first case for the bug in #1308 (brt-serialize.c:33 does the cast wrong)
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:
diff --git a/storage/tokudb/ft-index/ft/tests/test3681.cc b/storage/tokudb/ft-index/ft/tests/test3681.cc
index 44f522d059f..ee7cc4ceff8 100644
--- a/storage/tokudb/ft-index/ft/tests/test3681.cc
+++ b/storage/tokudb/ft-index/ft/tests/test3681.cc
@@ -89,10 +89,10 @@ PATENT RIGHTS GRANT:
#ident "$Id$"
// Test for #3681: iibench hangs. The scenario is
-// * Thread 1 calls root_put_msg, get_and_pin_root, 1 holds read lock on the root.
+// * Thread 1 calls root_put_cmd, get_and_pin_root, 1 holds read lock on the root.
// * Thread 2 calls checkpoint, marks the root for checkpoint.
// * Thread 2 calls end_checkpoint, tries to write lock the root, sets want_write, and blocks on the rwlock because there is a reader.
-// * Thread 1 calls apply_msg_to_in_memory_leaves, calls get_and_pin_if_in_memory, tries to get a read lock on the root node and blocks on the rwlock because there is a write request on the lock.
+// * Thread 1 calls apply_cmd_to_in_memory_leaves, calls get_and_pin_if_in_memory, tries to get a read lock on the root node and blocks on the rwlock because there is a write request on the lock.
#include "checkpoint.h"
diff --git a/storage/tokudb/ft-index/ft/tests/test3884.cc b/storage/tokudb/ft-index/ft/tests/test3884.cc
index 7fc3059800d..817e0d82212 100644
--- a/storage/tokudb/ft-index/ft/tests/test3884.cc
+++ b/storage/tokudb/ft-index/ft/tests/test3884.cc
@@ -119,18 +119,13 @@ le_add_to_bn(bn_data* bn, uint32_t idx, const char *key, int keysize, const cha
{
LEAFENTRY r = NULL;
uint32_t size_needed = LE_CLEAN_MEMSIZE(valsize);
- void *maybe_free = nullptr;
bn->get_space_for_insert(
idx,
key,
keysize,
size_needed,
- &r,
- &maybe_free
+ &r
);
- if (maybe_free) {
- toku_free(maybe_free);
- }
resource_assert(r);
r->type = LE_CLEAN;
r->u.clean.vallen = valsize;
@@ -217,20 +212,20 @@ test_split_on_boundary(void)
unlink(fname);
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
FTNODE nodea, nodeb;
DBT splitk;
// if we haven't done it right, we should hit the assert in the top of move_leafentries
- ftleaf_split(ft->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
+ ftleaf_split(brt->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
verify_basement_node_msns(nodea, dummy_msn_3884);
verify_basement_node_msns(nodeb, dummy_msn_3884);
- toku_unpin_ftnode(ft->ft, nodeb);
- r = toku_close_ft_handle_nolsn(ft, NULL); assert(r == 0);
+ toku_unpin_ftnode(brt->ft, nodeb);
+ r = toku_close_ft_handle_nolsn(brt, NULL); assert(r == 0);
toku_cachetable_close(&ct);
if (splitk.data) {
@@ -287,17 +282,17 @@ test_split_with_everything_on_the_left(void)
unlink(fname);
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
FTNODE nodea, nodeb;
DBT splitk;
// if we haven't done it right, we should hit the assert in the top of move_leafentries
- ftleaf_split(ft->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
+ ftleaf_split(brt->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
- toku_unpin_ftnode(ft->ft, nodeb);
- r = toku_close_ft_handle_nolsn(ft, NULL); assert(r == 0);
+ toku_unpin_ftnode(brt->ft, nodeb);
+ r = toku_close_ft_handle_nolsn(brt, NULL); assert(r == 0);
toku_cachetable_close(&ct);
if (splitk.data) {
@@ -359,17 +354,17 @@ test_split_on_boundary_of_last_node(void)
unlink(fname);
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
FTNODE nodea, nodeb;
DBT splitk;
// if we haven't done it right, we should hit the assert in the top of move_leafentries
- ftleaf_split(ft->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
+ ftleaf_split(brt->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
- toku_unpin_ftnode(ft->ft, nodeb);
- r = toku_close_ft_handle_nolsn(ft, NULL); assert(r == 0);
+ toku_unpin_ftnode(brt->ft, nodeb);
+ r = toku_close_ft_handle_nolsn(brt, NULL); assert(r == 0);
toku_cachetable_close(&ct);
if (splitk.data) {
@@ -423,17 +418,17 @@ test_split_at_begin(void)
unlink(fname);
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
FTNODE nodea, nodeb;
DBT splitk;
// if we haven't done it right, we should hit the assert in the top of move_leafentries
- ftleaf_split(ft->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
+ ftleaf_split(brt->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
- toku_unpin_ftnode(ft->ft, nodeb);
- r = toku_close_ft_handle_nolsn(ft, NULL); assert(r == 0);
+ toku_unpin_ftnode(brt->ft, nodeb);
+ r = toku_close_ft_handle_nolsn(brt, NULL); assert(r == 0);
toku_cachetable_close(&ct);
if (splitk.data) {
@@ -483,17 +478,17 @@ test_split_at_end(void)
unlink(fname);
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
FTNODE nodea, nodeb;
DBT splitk;
// if we haven't done it right, we should hit the assert in the top of move_leafentries
- ftleaf_split(ft->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
+ ftleaf_split(brt->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
- toku_unpin_ftnode(ft->ft, nodeb);
- r = toku_close_ft_handle_nolsn(ft, NULL); assert(r == 0);
+ toku_unpin_ftnode(brt->ft, nodeb);
+ r = toku_close_ft_handle_nolsn(brt, NULL); assert(r == 0);
toku_cachetable_close(&ct);
if (splitk.data) {
@@ -537,20 +532,20 @@ test_split_odd_nodes(void)
unlink(fname);
CACHETABLE ct;
- FT_HANDLE ft;
+ FT_HANDLE brt;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(fname, 1, &ft, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
+ r = toku_open_ft_handle(fname, 1, &brt, nodesize, bnsize, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0);
FTNODE nodea, nodeb;
DBT splitk;
// if we haven't done it right, we should hit the assert in the top of move_leafentries
- ftleaf_split(ft->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
+ ftleaf_split(brt->ft, &sn, &nodea, &nodeb, &splitk, true, SPLIT_EVENLY, 0, NULL);
verify_basement_node_msns(nodea, dummy_msn_3884);
verify_basement_node_msns(nodeb, dummy_msn_3884);
- toku_unpin_ftnode(ft->ft, nodeb);
- r = toku_close_ft_handle_nolsn(ft, NULL); assert(r == 0);
+ toku_unpin_ftnode(brt->ft, nodeb);
+ r = toku_close_ft_handle_nolsn(brt, NULL); assert(r == 0);
toku_cachetable_close(&ct);
if (splitk.data) {
diff --git a/storage/tokudb/ft-index/ft/tests/test4244.cc b/storage/tokudb/ft-index/ft/tests/test4244.cc
index 10810c7710e..76a5340797f 100644
--- a/storage/tokudb/ft-index/ft/tests/test4244.cc
+++ b/storage/tokudb/ft-index/ft/tests/test4244.cc
@@ -150,20 +150,21 @@ doit (void) {
FTNODE node;
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, t->ft);
- toku_pin_ftnode(
+ toku_pin_ftnode_off_client_thread(
t->ft,
node_internal,
toku_cachetable_hash(t->ft->cf, node_internal),
&bfe,
PL_WRITE_EXPENSIVE,
- &node,
- true
+ 0,
+ NULL,
+ &node
);
assert(node->n_children == 1);
// simply assert that the buffer is less than 50MB,
// we inserted 100MB of data in there.
assert(toku_bnc_nbytesinbuf(BNC(node, 0)) < 50*1000*1000);
- toku_unpin_ftnode(t->ft, node);
+ toku_unpin_ftnode_off_client_thread(t->ft, node);
r = toku_close_ft_handle_nolsn(t, 0); assert(r==0);
toku_cachetable_close(&ct);
diff --git a/storage/tokudb/ft-index/ft/tests/test_logcursor.cc b/storage/tokudb/ft-index/ft/tests/test_logcursor.cc
index 7b3f46e3d38..db1bc853a70 100644
--- a/storage/tokudb/ft-index/ft/tests/test_logcursor.cc
+++ b/storage/tokudb/ft-index/ft/tests/test_logcursor.cc
@@ -145,9 +145,9 @@ int test_main(int argc, const char *argv[]) {
int r = 0;
// start from a clean directory
- char rmrf_msg[100];
- sprintf(rmrf_msg, "rm -rf %s", LOGDIR);
- r = system(rmrf_msg);
+ char rmrf_cmd[100];
+ sprintf(rmrf_cmd, "rm -rf %s", LOGDIR);
+ r = system(rmrf_cmd);
CKERR(r);
toku_os_mkdir(LOGDIR, S_IRWXU+S_IRWXG+S_IRWXO);
if ( (r=create_logfiles()) !=0 ) return r;
@@ -155,7 +155,7 @@ int test_main(int argc, const char *argv[]) {
if ( (r=test_0()) !=0 ) return r;
if ( (r=test_1()) !=0 ) return r;
- r = system(rmrf_msg);
+ r = system(rmrf_cmd);
CKERR(r);
return r;
}
diff --git a/storage/tokudb/ft-index/ft/tests/test_rightmost_leaf_seqinsert_heuristic.cc b/storage/tokudb/ft-index/ft/tests/test_rightmost_leaf_seqinsert_heuristic.cc
deleted file mode 100644
index 100e5153636..00000000000
--- a/storage/tokudb/ft-index/ft/tests/test_rightmost_leaf_seqinsert_heuristic.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
-#ident "$Id$"
-/*
-COPYING CONDITIONS NOTICE:
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation, and provided that the
- following conditions are met:
-
- * Redistributions of source code must retain this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below).
-
- * Redistributions in binary form must reproduce this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below) in the documentation and/or other materials
- provided with the distribution.
-
- 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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-COPYRIGHT NOTICE:
-
- TokuDB, Tokutek Fractal Tree Indexing Library.
- Copyright (C) 2007-2014 Tokutek, Inc.
-
-DISCLAIMER:
-
- 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.
-
-UNIVERSITY PATENT NOTICE:
-
- The technology is licensed by the Massachusetts Institute of
- Technology, Rutgers State University of New Jersey, and the Research
- Foundation of State University of New York at Stony Brook under
- United States of America Serial No. 11/760379 and to the patents
- and/or patent applications resulting from it.
-
-PATENT MARKING NOTICE:
-
- This software is covered by US Patent No. 8,185,551.
- This software is covered by US Patent No. 8,489,638.
-
-PATENT RIGHTS GRANT:
-
- "THIS IMPLEMENTATION" means the copyrightable works distributed by
- Tokutek as part of the Fractal Tree project.
-
- "PATENT CLAIMS" means the claims of patents that are owned or
- licensable by Tokutek, both currently or in the future; and that in
- the absence of this license would be infringed by THIS
- IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
-
- "PATENT CHALLENGE" shall mean a challenge to the validity,
- patentability, enforceability and/or non-infringement of any of the
- PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
-
- Tokutek hereby grants to you, for the term and geographical scope of
- the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
- irrevocable (except as stated in this section) patent license to
- make, have made, use, offer to sell, sell, import, transfer, and
- otherwise run, modify, and propagate the contents of THIS
- IMPLEMENTATION, where such license applies only to the PATENT
- CLAIMS. This grant does not include claims that would be infringed
- only as a consequence of further modifications of THIS
- IMPLEMENTATION. If you or your agent or licensee institute or order
- or agree to the institution of patent litigation against any entity
- (including a cross-claim or counterclaim in a lawsuit) alleging that
- THIS IMPLEMENTATION constitutes direct or contributory patent
- infringement, or inducement of patent infringement, then any rights
- granted to you under this License shall terminate as of the date
- such litigation is filed. If you or your agent or exclusive
- licensee institute or order or agree to the institution of a PATENT
- CHALLENGE, then Tokutek may terminate any rights granted to you
- under this License.
-*/
-
-#ident "Copyright (c) 2014 Tokutek Inc. All rights reserved."
-
-#include "test.h"
-
-#include <ft/ybt.h>
-#include <ft/ft-cachetable-wrappers.h>
-
-// Each FT maintains a sequential insert heuristic to determine if its
-// worth trying to insert directly into a well-known rightmost leaf node.
-//
-// The heuristic is only maintained when a rightmost leaf node is known.
-//
-// This test verifies that sequential inserts increase the seqinsert score
-// and that a single non-sequential insert resets the score.
-
-static void test_seqinsert_heuristic(void) {
- int r = 0;
- char name[TOKU_PATH_MAX + 1];
- toku_path_join(name, 2, TOKU_TEST_FILENAME, "ftdata");
- toku_os_recursive_delete(TOKU_TEST_FILENAME);
- r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU); CKERR(r);
-
- FT_HANDLE ft_handle;
- CACHETABLE ct;
- toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(name, 1, &ft_handle,
- 4*1024*1024, 64*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD, ct, NULL,
- toku_builtin_compare_fun); CKERR(r);
- FT ft = ft_handle->ft;
-
- int k;
- DBT key, val;
- const int val_size = 1024 * 1024;
- char *XMALLOC_N(val_size, val_buf);
- memset(val_buf, 'x', val_size);
- toku_fill_dbt(&val, val_buf, val_size);
-
- // Insert many rows sequentially. This is enough data to:
- // - force the root to split (the righmost leaf will then be known)
- // - raise the seqinsert score high enough to enable direct rightmost injections
- const int rows_to_insert = 200;
- for (int i = 0; i < rows_to_insert; i++) {
- k = toku_htonl(i);
- toku_fill_dbt(&key, &k, sizeof(k));
- toku_ft_insert(ft_handle, &key, &val, NULL);
- }
- invariant(ft->rightmost_blocknum.b != RESERVED_BLOCKNUM_NULL);
- invariant(ft->seqinsert_score == FT_SEQINSERT_SCORE_THRESHOLD);
-
- // Insert on the left extreme. The seq insert score is high enough
- // that we will attempt to insert into the rightmost leaf. We won't
- // be successful because key 0 won't be in the bounds of the rightmost leaf.
- // This failure should reset the seqinsert score back to 0.
- k = toku_htonl(0);
- toku_fill_dbt(&key, &k, sizeof(k));
- toku_ft_insert(ft_handle, &key, &val, NULL);
- invariant(ft->seqinsert_score == 0);
-
- // Insert in the middle. The score should not go up.
- k = toku_htonl(rows_to_insert / 2);
- toku_fill_dbt(&key, &k, sizeof(k));
- toku_ft_insert(ft_handle, &key, &val, NULL);
- invariant(ft->seqinsert_score == 0);
-
- // Insert on the right extreme. The score should go up.
- k = toku_htonl(rows_to_insert);
- toku_fill_dbt(&key, &k, sizeof(k));
- toku_ft_insert(ft_handle, &key, &val, NULL);
- invariant(ft->seqinsert_score == 1);
-
- // Insert again on the right extreme again, the score should go up.
- k = toku_htonl(rows_to_insert + 1);
- toku_fill_dbt(&key, &k, sizeof(k));
- toku_ft_insert(ft_handle, &key, &val, NULL);
- invariant(ft->seqinsert_score == 2);
-
- // Insert close to, but not at, the right extreme. The score should reset.
- // -- the magic number 4 derives from the fact that vals are 1mb and nodes are 4mb
- k = toku_htonl(rows_to_insert - 4);
- toku_fill_dbt(&key, &k, sizeof(k));
- toku_ft_insert(ft_handle, &key, &val, NULL);
- invariant(ft->seqinsert_score == 0);
-
- toku_free(val_buf);
- toku_ft_handle_close(ft_handle);
- toku_cachetable_close(&ct);
- toku_os_recursive_delete(TOKU_TEST_FILENAME);
-}
-
-int test_main(int argc, const char *argv[]) {
- default_parse_args(argc, argv);
- test_seqinsert_heuristic();
- return 0;
-}
diff --git a/storage/tokudb/ft-index/ft/tests/test_rightmost_leaf_split_merge.cc b/storage/tokudb/ft-index/ft/tests/test_rightmost_leaf_split_merge.cc
deleted file mode 100644
index 517fc277fd3..00000000000
--- a/storage/tokudb/ft-index/ft/tests/test_rightmost_leaf_split_merge.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
-#ident "$Id$"
-/*
-COPYING CONDITIONS NOTICE:
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation, and provided that the
- following conditions are met:
-
- * Redistributions of source code must retain this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below).
-
- * Redistributions in binary form must reproduce this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below) in the documentation and/or other materials
- provided with the distribution.
-
- 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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-COPYRIGHT NOTICE:
-
- TokuDB, Tokutek Fractal Tree Indexing Library.
- Copyright (C) 2007-2014 Tokutek, Inc.
-
-DISCLAIMER:
-
- 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.
-
-UNIVERSITY PATENT NOTICE:
-
- The technology is licensed by the Massachusetts Institute of
- Technology, Rutgers State University of New Jersey, and the Research
- Foundation of State University of New York at Stony Brook under
- United States of America Serial No. 11/760379 and to the patents
- and/or patent applications resulting from it.
-
-PATENT MARKING NOTICE:
-
- This software is covered by US Patent No. 8,185,551.
- This software is covered by US Patent No. 8,489,638.
-
-PATENT RIGHTS GRANT:
-
- "THIS IMPLEMENTATION" means the copyrightable works distributed by
- Tokutek as part of the Fractal Tree project.
-
- "PATENT CLAIMS" means the claims of patents that are owned or
- licensable by Tokutek, both currently or in the future; and that in
- the absence of this license would be infringed by THIS
- IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
-
- "PATENT CHALLENGE" shall mean a challenge to the validity,
- patentability, enforceability and/or non-infringement of any of the
- PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
-
- Tokutek hereby grants to you, for the term and geographical scope of
- the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
- irrevocable (except as stated in this section) patent license to
- make, have made, use, offer to sell, sell, import, transfer, and
- otherwise run, modify, and propagate the contents of THIS
- IMPLEMENTATION, where such license applies only to the PATENT
- CLAIMS. This grant does not include claims that would be infringed
- only as a consequence of further modifications of THIS
- IMPLEMENTATION. If you or your agent or licensee institute or order
- or agree to the institution of patent litigation against any entity
- (including a cross-claim or counterclaim in a lawsuit) alleging that
- THIS IMPLEMENTATION constitutes direct or contributory patent
- infringement, or inducement of patent infringement, then any rights
- granted to you under this License shall terminate as of the date
- such litigation is filed. If you or your agent or exclusive
- licensee institute or order or agree to the institution of a PATENT
- CHALLENGE, then Tokutek may terminate any rights granted to you
- under this License.
-*/
-
-#ident "Copyright (c) 2014 Tokutek Inc. All rights reserved."
-
-#include "test.h"
-
-#include <ft/ybt.h>
-#include <ft/ft-cachetable-wrappers.h>
-
-// Promotion tracks the rightmost blocknum in the FT when a message
-// is successfully promoted to a non-root leaf node on the right extreme.
-//
-// This test verifies that a split or merge of the rightmost leaf properly
-// maintains the rightmost blocknum (which is constant - the pair's swap values,
-// like the root blocknum).
-
-static void test_split_merge(void) {
- int r = 0;
- char name[TOKU_PATH_MAX + 1];
- toku_path_join(name, 2, TOKU_TEST_FILENAME, "ftdata");
- toku_os_recursive_delete(TOKU_TEST_FILENAME);
- r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU); CKERR(r);
-
- FT_HANDLE ft_handle;
- CACHETABLE ct;
- toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- r = toku_open_ft_handle(name, 1, &ft_handle,
- 4*1024*1024, 64*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD, ct, NULL,
- toku_builtin_compare_fun); CKERR(r);
-
- // We have a root blocknum, but no rightmost blocknum yet.
- FT ft = ft_handle->ft;
- invariant(ft->h->root_blocknum.b != RESERVED_BLOCKNUM_NULL);
- invariant(ft->rightmost_blocknum.b == RESERVED_BLOCKNUM_NULL);
-
- int k;
- DBT key, val;
- const int val_size = 1 * 1024 * 1024;
- char *XMALLOC_N(val_size, val_buf);
- memset(val_buf, 'x', val_size);
- toku_fill_dbt(&val, val_buf, val_size);
-
- // Insert 16 rows (should induce a few splits)
- const int rows_to_insert = 16;
- for (int i = 0; i < rows_to_insert; i++) {
- k = toku_htonl(i);
- toku_fill_dbt(&key, &k, sizeof(k));
- toku_ft_insert(ft_handle, &key, &val, NULL);
- }
-
- // rightmost blocknum should be set, because the root split and promotion
- // did a rightmost insertion directly into the rightmost leaf, lazily
- // initializing the rightmost blocknum.
- invariant(ft->rightmost_blocknum.b != RESERVED_BLOCKNUM_NULL);
-
- BLOCKNUM root_blocknum = ft->h->root_blocknum;
- FTNODE root_node;
- struct ftnode_fetch_extra bfe;
- fill_bfe_for_full_read(&bfe, ft);
- toku_pin_ftnode(ft, root_blocknum,
- toku_cachetable_hash(ft->cf, ft->h->root_blocknum),
- &bfe, PL_WRITE_EXPENSIVE, &root_node, true);
- // root blocknum should be consistent
- invariant(root_node->thisnodename.b == ft->h->root_blocknum.b);
- // root should have split at least once, and it should now be at height 1
- invariant(root_node->n_children > 1);
- invariant(root_node->height == 1);
- // rightmost blocknum should no longer be the root, since the root split
- invariant(ft->h->root_blocknum.b != ft->rightmost_blocknum.b);
- // the right child should have the rightmost blocknum
- invariant(BP_BLOCKNUM(root_node, root_node->n_children - 1).b == ft->rightmost_blocknum.b);
-
- BLOCKNUM rightmost_blocknum_before_merge = ft->rightmost_blocknum;
- const int num_children_before_merge = root_node->n_children;
-
- // delete the last 6 rows.
- // - 1mb each, so 6mb deleted
- // - should be enough to delete the entire rightmost leaf + some of its neighbor
- const int rows_to_delete = 6;
- toku_unpin_ftnode(ft, root_node);
- for (int i = 0; i < rows_to_delete; i++) {
- k = toku_htonl(rows_to_insert - i);
- toku_fill_dbt(&key, &k, sizeof(k));
- toku_ft_delete(ft_handle, &key, NULL);
- }
- toku_pin_ftnode(ft, root_blocknum,
- toku_cachetable_hash(ft->cf, root_blocknum),
- &bfe, PL_WRITE_EXPENSIVE, &root_node, true);
-
- // - rightmost leaf should be fusible after those deletes (which were promoted directly to the leaf)
- FTNODE rightmost_leaf;
- toku_pin_ftnode(ft, rightmost_blocknum_before_merge,
- toku_cachetable_hash(ft->cf, rightmost_blocknum_before_merge),
- &bfe, PL_WRITE_EXPENSIVE, &rightmost_leaf, true);
- invariant(get_node_reactivity(ft, rightmost_leaf) == RE_FUSIBLE);
- toku_unpin_ftnode(ft, rightmost_leaf);
-
- // - merge the rightmost child now that it's fusible
- toku_ft_merge_child(ft, root_node, root_node->n_children - 1);
- toku_pin_ftnode(ft, root_blocknum,
- toku_cachetable_hash(ft->cf, root_blocknum),
- &bfe, PL_WRITE_EXPENSIVE, &root_node, true);
-
- // the merge should have worked, and the root should still be at height 1
- invariant(root_node->n_children < num_children_before_merge);
- invariant(root_node->height == 1);
- // the rightmost child of the root has the rightmost blocknum
- invariant(BP_BLOCKNUM(root_node, root_node->n_children - 1).b == ft->rightmost_blocknum.b);
- // the value for rightmost blocknum itself should not have changed
- // (we keep it constant, like the root blocknum)
- invariant(rightmost_blocknum_before_merge.b == ft->rightmost_blocknum.b);
-
- toku_unpin_ftnode(ft, root_node);
-
- toku_free(val_buf);
- toku_ft_handle_close(ft_handle);
- toku_cachetable_close(&ct);
- toku_os_recursive_delete(TOKU_TEST_FILENAME);
-}
-
-int test_main(int argc, const char *argv[]) {
- default_parse_args(argc, argv);
- test_split_merge();
- return 0;
-}
diff --git a/storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc b/storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc
index 5eef196f611..edb1b6262a3 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc
@@ -106,10 +106,10 @@ PATENT RIGHTS GRANT:
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
@@ -122,14 +122,14 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
DBT theval; toku_fill_dbt(&theval, val, vallen);
// get an index that we can use to create a new leaf entry
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
MSN msn = next_dummymsn();
// apply an insert to the leaf node
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- toku_ft_bn_apply_msg_once(BLB(leafnode, 0), &msg, idx, NULL, &gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd_once(BLB(leafnode, 0), &cmd, idx, NULL, &gc_info, NULL, NULL);
// Create bad tree (don't do following):
// leafnode->max_msn_applied_to_node = msn;
@@ -150,13 +150,13 @@ populate_leaf(FTNODE leafnode, int seq, int n, int *minkey, int *maxkey) {
}
static void
-insert_into_child_buffer(FT_HANDLE ft, FTNODE node, int childnum, int minkey, int maxkey) {
+insert_into_child_buffer(FT_HANDLE brt, FTNODE node, int childnum, int minkey, int maxkey) {
for (unsigned int val = htonl(minkey); val <= htonl(maxkey); val++) {
MSN msn = next_dummymsn();
unsigned int key = htonl(val);
DBT thekey; toku_fill_dbt(&thekey, &key, sizeof key);
DBT theval; toku_fill_dbt(&theval, &val, sizeof val);
- toku_ft_append_to_child_buffer(ft->ft->compare_fun, NULL, node, childnum, FT_INSERT, msn, xids_get_root_xids(), true, &thekey, &theval);
+ toku_ft_append_to_child_buffer(brt->ft->compare_fun, NULL, node, childnum, FT_INSERT, msn, xids_get_root_xids(), true, &thekey, &theval);
// Create bad tree (don't do following):
// node->max_msn_applied_to_node = msn;
@@ -164,17 +164,17 @@ insert_into_child_buffer(FT_HANDLE ft, FTNODE node, int childnum, int minkey, in
}
static FTNODE
-make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
+make_tree(FT_HANDLE brt, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
FTNODE node;
if (height == 0) {
- node = make_node(ft, 0);
+ node = make_node(brt, 0);
populate_leaf(node, *seq, nperleaf, minkey, maxkey);
*seq += nperleaf;
} else {
- node = make_node(ft, height);
+ node = make_node(brt, height);
int minkeys[fanout], maxkeys[fanout];
for (int childnum = 0; childnum < fanout; childnum++) {
- FTNODE child = make_tree(ft, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
+ FTNODE child = make_tree(brt, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
if (childnum == 0) {
toku_ft_nonleaf_append_child(node, child, NULL);
} else {
@@ -182,8 +182,8 @@ make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *min
DBT pivotkey;
toku_ft_nonleaf_append_child(node, child, toku_fill_dbt(&pivotkey, &k, sizeof k));
}
- toku_unpin_ftnode(ft->ft, child);
- insert_into_child_buffer(ft, node, childnum, minkeys[childnum], maxkeys[childnum]);
+ toku_unpin_ftnode(brt->ft, child);
+ insert_into_child_buffer(brt, node, childnum, minkeys[childnum], maxkeys[childnum]);
}
*minkey = minkeys[0];
*maxkey = maxkeys[0];
@@ -214,32 +214,32 @@ test_make_tree(int height, int fanout, int nperleaf, int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
// make a tree
int seq = 0, minkey, maxkey;
- FTNODE newroot = make_tree(ft, height, fanout, nperleaf, &seq, &minkey, &maxkey);
+ FTNODE newroot = make_tree(brt, height, fanout, nperleaf, &seq, &minkey, &maxkey);
// set the new root to point to the new tree
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
// Create bad tree (don't do following):
// newroot->max_msn_applied_to_node = last_dummymsn(); // capture msn of last message injected into tree
// unpin the new root
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r != 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc b/storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc
index 0d477ea22c4..156fc36666f 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc
@@ -88,17 +88,17 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
-// generate a tree with bad pivots and check that ft->verify finds them
+// generate a tree with bad pivots and check that brt->verify finds them
#include <ft-cachetable-wrappers.h>
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
@@ -111,13 +111,13 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
DBT theval; toku_fill_dbt(&theval, val, vallen);
// get an index that we can use to create a new leaf entry
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
// apply an insert to the leaf node
MSN msn = next_dummymsn();
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- toku_ft_bn_apply_msg_once(BLB(leafnode, 0), &msg, idx, NULL, &gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd_once(BLB(leafnode, 0), &cmd, idx, NULL, &gc_info, NULL, NULL);
// dont forget to dirty the node
leafnode->dirty = 1;
@@ -135,17 +135,17 @@ populate_leaf(FTNODE leafnode, int seq, int n, int *minkey, int *maxkey) {
}
static FTNODE
-make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
+make_tree(FT_HANDLE brt, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
FTNODE node;
if (height == 0) {
- node = make_node(ft, 0);
+ node = make_node(brt, 0);
populate_leaf(node, *seq, nperleaf, minkey, maxkey);
*seq += nperleaf;
} else {
- node = make_node(ft, height);
+ node = make_node(brt, height);
int minkeys[fanout], maxkeys[fanout];
for (int childnum = 0; childnum < fanout; childnum++) {
- FTNODE child = make_tree(ft, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
+ FTNODE child = make_tree(brt, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
if (childnum == 0) {
toku_ft_nonleaf_append_child(node, child, NULL);
} else {
@@ -153,7 +153,7 @@ make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *min
DBT pivotkey;
toku_ft_nonleaf_append_child(node, child, toku_fill_dbt(&pivotkey, &k, sizeof k));
}
- toku_unpin_ftnode(ft->ft, child);
+ toku_unpin_ftnode(brt->ft, child);
}
*minkey = minkeys[0];
*maxkey = maxkeys[0];
@@ -184,29 +184,29 @@ test_make_tree(int height, int fanout, int nperleaf, int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
// make a tree
int seq = 0, minkey, maxkey;
- FTNODE newroot = make_tree(ft, height, fanout, nperleaf, &seq, &minkey, &maxkey);
+ FTNODE newroot = make_tree(brt, height, fanout, nperleaf, &seq, &minkey, &maxkey);
// discard the old root block
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
// unpin the new root
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r != 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/ft/tests/verify-dup-in-leaf.cc b/storage/tokudb/ft-index/ft/tests/verify-dup-in-leaf.cc
index ee0256b4882..0f9f2a1000d 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-dup-in-leaf.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-dup-in-leaf.cc
@@ -89,17 +89,17 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
// generate a tree with a single leaf node containing duplicate keys
-// check that ft verify finds them
+// check that brt verify finds them
#include <ft-cachetable-wrappers.h>
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
@@ -112,13 +112,13 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
DBT theval; toku_fill_dbt(&theval, val, vallen);
// get an index that we can use to create a new leaf entry
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
// apply an insert to the leaf node
MSN msn = next_dummymsn();
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- toku_ft_bn_apply_msg_once(BLB(leafnode, 0), &msg, idx, NULL, &gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd_once(BLB(leafnode, 0), &cmd, idx, NULL, &gc_info, NULL, NULL);
// dont forget to dirty the node
leafnode->dirty = 1;
@@ -142,31 +142,31 @@ test_dup_in_leaf(int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
// discard the old root block
- FTNODE newroot = make_node(ft, 0);
+ FTNODE newroot = make_node(brt, 0);
populate_leaf(newroot, htonl(2), 1);
populate_leaf(newroot, htonl(2), 2);
// set the new root to point to the new tree
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
// unpin the new root
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r != 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc b/storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc
index f2b74dc3891..219f1f7da59 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc
@@ -88,17 +88,17 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
-// generate a tree with duplicate pivots and check that ft->verify finds them
+// generate a tree with duplicate pivots and check that brt->verify finds them
#include <ft-cachetable-wrappers.h>
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
@@ -111,13 +111,13 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
DBT theval; toku_fill_dbt(&theval, val, vallen);
// get an index that we can use to create a new leaf entry
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
// apply an insert to the leaf node
MSN msn = next_dummymsn();
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- toku_ft_bn_apply_msg_once(BLB(leafnode, 0), &msg, idx, NULL, &gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd_once(BLB(leafnode, 0), &cmd, idx, NULL, &gc_info, NULL, NULL);
// dont forget to dirty the node
leafnode->dirty = 1;
@@ -135,17 +135,17 @@ populate_leaf(FTNODE leafnode, int seq, int n, int *minkey, int *maxkey) {
}
static FTNODE
-make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
+make_tree(FT_HANDLE brt, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
FTNODE node;
if (height == 0) {
- node = make_node(ft, 0);
+ node = make_node(brt, 0);
populate_leaf(node, *seq, nperleaf, minkey, maxkey);
*seq += nperleaf;
} else {
- node = make_node(ft, height);
+ node = make_node(brt, height);
int minkeys[fanout], maxkeys[fanout];
for (int childnum = 0; childnum < fanout; childnum++) {
- FTNODE child = make_tree(ft, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
+ FTNODE child = make_tree(brt, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
if (childnum == 0) {
toku_ft_nonleaf_append_child(node, child, NULL);
} else {
@@ -153,7 +153,7 @@ make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *min
DBT pivotkey;
toku_ft_nonleaf_append_child(node, child, toku_fill_dbt(&pivotkey, &k, sizeof k));
}
- toku_unpin_ftnode(ft->ft, child);
+ toku_unpin_ftnode(brt->ft, child);
}
*minkey = minkeys[0];
*maxkey = maxkeys[0];
@@ -187,30 +187,30 @@ test_make_tree(int height, int fanout, int nperleaf, int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
// make a tree
int seq = 0, minkey, maxkey;
- FTNODE newroot = make_tree(ft, height, fanout, nperleaf, &seq, &minkey, &maxkey);
+ FTNODE newroot = make_tree(brt, height, fanout, nperleaf, &seq, &minkey, &maxkey);
// discard the old root block
// set the new root to point to the new tree
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
// unpin the new root
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r != 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc b/storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc
index 7efdd374f01..f68b4d72e53 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc
@@ -89,17 +89,17 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
// generate a tree with misrouted messages in the child buffers.
-// check that ft verify finds them.
+// check that brt verify finds them.
#include <ft-cachetable-wrappers.h>
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
@@ -112,13 +112,13 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
DBT theval; toku_fill_dbt(&theval, val, vallen);
// get an index that we can use to create a new leaf entry
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
// apply an insert to the leaf node
MSN msn = next_dummymsn();
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- toku_ft_bn_apply_msg_once(BLB(leafnode,0), &msg, idx, NULL, &gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd_once(BLB(leafnode,0), &cmd, idx, NULL, &gc_info, NULL, NULL);
// dont forget to dirty the node
leafnode->dirty = 1;
@@ -136,7 +136,7 @@ populate_leaf(FTNODE leafnode, int seq, int n, int *minkey, int *maxkey) {
}
static void
-insert_into_child_buffer(FT_HANDLE ft, FTNODE node, int childnum, int minkey, int maxkey) {
+insert_into_child_buffer(FT_HANDLE brt, FTNODE node, int childnum, int minkey, int maxkey) {
int k = htonl(maxkey);
maxkey = htonl(k+1);
for (unsigned int val = htonl(minkey); val <= htonl(maxkey); val++) {
@@ -144,22 +144,22 @@ insert_into_child_buffer(FT_HANDLE ft, FTNODE node, int childnum, int minkey, in
DBT thekey; toku_fill_dbt(&thekey, &key, sizeof key);
DBT theval; toku_fill_dbt(&theval, &val, sizeof val);
MSN msn = next_dummymsn();
- toku_ft_append_to_child_buffer(ft->ft->compare_fun, NULL, node, childnum, FT_INSERT, msn, xids_get_root_xids(), true, &thekey, &theval);
+ toku_ft_append_to_child_buffer(brt->ft->compare_fun, NULL, node, childnum, FT_INSERT, msn, xids_get_root_xids(), true, &thekey, &theval);
}
}
static FTNODE
-make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
+make_tree(FT_HANDLE brt, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
FTNODE node;
if (height == 0) {
- node = make_node(ft, 0);
+ node = make_node(brt, 0);
populate_leaf(node, *seq, nperleaf, minkey, maxkey);
*seq += nperleaf;
} else {
- node = make_node(ft, height);
+ node = make_node(brt, height);
int minkeys[fanout], maxkeys[fanout];
for (int childnum = 0; childnum < fanout; childnum++) {
- FTNODE child = make_tree(ft, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
+ FTNODE child = make_tree(brt, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
if (childnum == 0) {
toku_ft_nonleaf_append_child(node, child, NULL);
} else {
@@ -167,8 +167,8 @@ make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *min
DBT pivotkey;
toku_ft_nonleaf_append_child(node, child, toku_fill_dbt(&pivotkey, &k, sizeof k));
}
- toku_unpin_ftnode(ft->ft, child);
- insert_into_child_buffer(ft, node, childnum, minkeys[childnum], maxkeys[childnum]);
+ toku_unpin_ftnode(brt->ft, child);
+ insert_into_child_buffer(brt, node, childnum, minkeys[childnum], maxkeys[childnum]);
}
*minkey = minkeys[0];
*maxkey = maxkeys[0];
@@ -199,30 +199,30 @@ test_make_tree(int height, int fanout, int nperleaf, int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
// make a tree
int seq = 0, minkey, maxkey;
- FTNODE newroot = make_tree(ft, height, fanout, nperleaf, &seq, &minkey, &maxkey);
+ FTNODE newroot = make_tree(brt, height, fanout, nperleaf, &seq, &minkey, &maxkey);
// discard the old root block
// set the new root to point to the new tree
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
// unpin the new root
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r != 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc b/storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc
index 92d68dd56ee..c1e9f6f5727 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc
@@ -89,17 +89,17 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
// generate a tree with a single leaf node containing unsorted keys
-// check that ft verify finds them
+// check that brt verify finds them
#include <ft-cachetable-wrappers.h>
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
@@ -114,13 +114,13 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
toku_fill_dbt(&theval, val, vallen);
// get an index that we can use to create a new leaf entry
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
// apply an insert to the leaf node
MSN msn = next_dummymsn();
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- toku_ft_bn_apply_msg_once(BLB(leafnode, 0), &msg, idx, NULL, &gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd_once(BLB(leafnode, 0), &cmd, idx, NULL, &gc_info, NULL, NULL);
// dont forget to dirty the node
leafnode->dirty = 1;
@@ -144,30 +144,30 @@ test_dup_in_leaf(int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
// discard the old root block
- FTNODE newroot = make_node(ft, 0);
+ FTNODE newroot = make_node(brt, 0);
populate_leaf(newroot, htonl(2), 1);
populate_leaf(newroot, htonl(1), 2);
// set the new root to point to the new tree
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
// unpin the new root
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r != 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc b/storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc
index e1b9d9aba22..c209e679072 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc
@@ -88,17 +88,17 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
-// generate a tree with unsorted pivots and check that ft->verify finds them
+// generate a tree with unsorted pivots and check that brt->verify finds them
#include <ft-cachetable-wrappers.h>
#include "test.h"
static FTNODE
-make_node(FT_HANDLE ft, int height) {
+make_node(FT_HANDLE brt, int height) {
FTNODE node = NULL;
int n_children = (height == 0) ? 1 : 0;
- toku_create_new_ftnode(ft, &node, height, n_children);
+ toku_create_new_ftnode(brt, &node, height, n_children);
if (n_children) BP_STATE(node,0) = PT_AVAIL;
return node;
}
@@ -111,13 +111,13 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
DBT theval; toku_fill_dbt(&theval, val, vallen);
// get an index that we can use to create a new leaf entry
- uint32_t idx = BLB_DATA(leafnode, 0)->num_klpairs();
+ uint32_t idx = BLB_DATA(leafnode, 0)->omt_size();
// apply an insert to the leaf node
MSN msn = next_dummymsn();
- FT_MSG_S msg = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
+ FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u={.id = { &thekey, &theval }} };
txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
- toku_ft_bn_apply_msg_once(BLB(leafnode, 0), &msg, idx, NULL, &gc_info, NULL, NULL);
+ toku_ft_bn_apply_cmd_once(BLB(leafnode, 0), &cmd, idx, NULL, &gc_info, NULL, NULL);
// dont forget to dirty the node
leafnode->dirty = 1;
@@ -135,17 +135,17 @@ populate_leaf(FTNODE leafnode, int seq, int n, int *minkey, int *maxkey) {
}
static FTNODE
-make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
+make_tree(FT_HANDLE brt, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
FTNODE node;
if (height == 0) {
- node = make_node(ft, 0);
+ node = make_node(brt, 0);
populate_leaf(node, *seq, nperleaf, minkey, maxkey);
*seq += nperleaf;
} else {
- node = make_node(ft, height);
+ node = make_node(brt, height);
int minkeys[fanout], maxkeys[fanout];
for (int childnum = 0; childnum < fanout; childnum++) {
- FTNODE child = make_tree(ft, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
+ FTNODE child = make_tree(brt, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
if (childnum == 0) {
toku_ft_nonleaf_append_child(node, child, NULL);
} else {
@@ -153,7 +153,7 @@ make_tree(FT_HANDLE ft, int height, int fanout, int nperleaf, int *seq, int *min
DBT pivotkey;
toku_ft_nonleaf_append_child(node, child, toku_fill_dbt(&pivotkey, &k, sizeof k));
}
- toku_unpin_ftnode(ft->ft, child);
+ toku_unpin_ftnode(brt->ft, child);
}
*minkey = minkeys[0];
*maxkey = maxkeys[0];
@@ -184,29 +184,29 @@ test_make_tree(int height, int fanout, int nperleaf, int do_verify) {
CACHETABLE ct = NULL;
toku_cachetable_create(&ct, 0, ZERO_LSN, NULL_LOGGER);
- // create the ft
+ // create the brt
TOKUTXN null_txn = NULL;
- FT_HANDLE ft = NULL;
- r = toku_open_ft_handle(fname, 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
+ FT_HANDLE brt = NULL;
+ r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
assert(r == 0);
// make a tree
int seq = 0, minkey, maxkey;
- FTNODE newroot = make_tree(ft, height, fanout, nperleaf, &seq, &minkey, &maxkey);
+ FTNODE newroot = make_tree(brt, height, fanout, nperleaf, &seq, &minkey, &maxkey);
// discard the old root block
- toku_ft_set_new_root_blocknum(ft->ft, newroot->thisnodename);
+ toku_ft_set_new_root_blocknum(brt->ft, newroot->thisnodename);
// unpin the new root
- toku_unpin_ftnode(ft->ft, newroot);
+ toku_unpin_ftnode(brt->ft, newroot);
if (do_verify) {
- r = toku_verify_ft(ft);
+ r = toku_verify_ft(brt);
assert(r != 0);
}
// flush to the file system
- r = toku_close_ft_handle_nolsn(ft, 0);
+ r = toku_close_ft_handle_nolsn(brt, 0);
assert(r == 0);
// shutdown the cachetable
diff --git a/storage/tokudb/ft-index/util/tests/x1764-test.cc b/storage/tokudb/ft-index/ft/tests/x1764-test.cc
index d8a0b1d0eb3..721cb0b1222 100644
--- a/storage/tokudb/ft-index/util/tests/x1764-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/x1764-test.cc
@@ -88,17 +88,17 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
-#include "test.h"
-#include <util/x1764.h>
+
+#include "test.h"
static void
test0 (void) {
- uint32_t c = toku_x1764_memory("", 0);
+ uint32_t c = x1764_memory("", 0);
assert(c==~(0U));
struct x1764 cs;
- toku_x1764_init(&cs);
- toku_x1764_add(&cs, "", 0);
- c = toku_x1764_finish(&cs);
+ x1764_init(&cs);
+ x1764_add(&cs, "", 0);
+ c = x1764_finish(&cs);
assert(c==~(0U));
}
@@ -110,7 +110,7 @@ test1 (void) {
for (i=0; i<=8; i++) {
uint64_t expect64 = (i==8) ? v : v&((1LL<<(8*i))-1);
uint32_t expect = expect64 ^ (expect64>>32);
- c = toku_x1764_memory(&v, i);
+ c = x1764_memory(&v, i);
//printf("i=%d c=%08x expect=%08x\n", i, c, expect);
assert(c==~expect);
}
@@ -127,33 +127,33 @@ test2 (void) {
int j;
for (j=i; j<=N; j++) {
// checksum from i (inclusive to j (exclusive)
- uint32_t c = toku_x1764_memory(&v[i], j-i);
+ uint32_t c = x1764_memory(&v[i], j-i);
// Now compute the checksum incrementally with various strides.
int stride;
for (stride=1; stride<=j-i; stride++) {
int k;
struct x1764 s;
- toku_x1764_init(&s);
+ x1764_init(&s);
for (k=i; k+stride<=j; k+=stride) {
- toku_x1764_add(&s, &v[k], stride);
+ x1764_add(&s, &v[k], stride);
}
- toku_x1764_add(&s, &v[k], j-k);
- uint32_t c2 = toku_x1764_finish(&s);
+ x1764_add(&s, &v[k], j-k);
+ uint32_t c2 = x1764_finish(&s);
assert(c2==c);
}
// Now use some random strides.
{
int k=i;
struct x1764 s;
- toku_x1764_init(&s);
+ x1764_init(&s);
while (1) {
stride=random()%16;
if (k+stride>j) break;
- toku_x1764_add(&s, &v[k], stride);
+ x1764_add(&s, &v[k], stride);
k+=stride;
}
- toku_x1764_add(&s, &v[k], j-k);
- uint32_t c2 = toku_x1764_finish(&s);
+ x1764_add(&s, &v[k], j-k);
+ uint32_t c2 = x1764_finish(&s);
assert(c2==c);
}
}
@@ -170,8 +170,8 @@ test3 (void)
for (int off=0; off<32; off++) {
if (verbose) {printf("."); fflush(stdout);}
for (int len=0; len+off<datalen; len++) {
- uint32_t reference_sum = toku_x1764_memory_simple(data+off, len);
- uint32_t fast_sum = toku_x1764_memory (data+off, len);
+ uint32_t reference_sum = x1764_memory_simple(data+off, len);
+ uint32_t fast_sum = x1764_memory (data+off, len);
assert(reference_sum==fast_sum);
}
}
diff --git a/storage/tokudb/ft-index/ft/tests/xid_lsn_independent.cc b/storage/tokudb/ft-index/ft/tests/xid_lsn_independent.cc
index 93762525a09..88dcdb17e05 100644
--- a/storage/tokudb/ft-index/ft/tests/xid_lsn_independent.cc
+++ b/storage/tokudb/ft-index/ft/tests/xid_lsn_independent.cc
@@ -119,13 +119,13 @@ static void test_xid_lsn_independent(int N) {
test_setup(TOKU_TEST_FILENAME, &logger, &ct);
- FT_HANDLE ft;
+ FT_HANDLE brt;
TOKUTXN txn;
r = toku_txn_begin_txn((DB_TXN*)NULL, (TOKUTXN)0, &txn, logger, TXN_SNAPSHOT_NONE, false);
CKERR(r);
- r = toku_open_ft_handle("ftfile", 1, &ft, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun);
+ r = toku_open_ft_handle("ftfile", 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, txn, toku_builtin_compare_fun);
CKERR(r);
r = toku_txn_commit_txn(txn, false, NULL, NULL);
@@ -143,7 +143,7 @@ static void test_xid_lsn_independent(int N) {
snprintf(key, sizeof(key), "key%x.%x", rands[i], i);
memset(val, 'v', sizeof(val));
val[sizeof(val)-1]=0;
- toku_ft_insert(ft, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), txn);
+ toku_ft_insert(brt, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), txn);
}
{
TOKUTXN txn2;
@@ -172,7 +172,7 @@ static void test_xid_lsn_independent(int N) {
CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
r = toku_checkpoint(cp, logger, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT);
CKERR(r);
- r = toku_close_ft_handle_nolsn(ft, NULL);
+ r = toku_close_ft_handle_nolsn(brt, NULL);
CKERR(r);
clean_shutdown(&logger, &ct);
diff --git a/storage/tokudb/ft-index/ft/tokuftdump.cc b/storage/tokudb/ft-index/ft/tokuftdump.cc
index a7d94f41d78..3db319a5b45 100644
--- a/storage/tokudb/ft-index/ft/tokuftdump.cc
+++ b/storage/tokudb/ft-index/ft/tokuftdump.cc
@@ -246,11 +246,10 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) {
printf(" layout_version_read_from_disk=%d\n", n->layout_version_read_from_disk);
printf(" build_id=%d\n", n->build_id);
printf(" max_msn_applied_to_node_on_disk=%" PRId64 " (0x%" PRIx64 ")\n", n->max_msn_applied_to_node_on_disk.msn, n->max_msn_applied_to_node_on_disk.msn);
- printf("io time %lf decompress time %lf deserialize time %lf\n",
- tokutime_to_seconds(bfe.io_time),
- tokutime_to_seconds(bfe.decompress_time),
- tokutime_to_seconds(bfe.deserialize_time)
- );
+ printf(" io time %lf decompress time %lf deserialize time %lf\n",
+ tokutime_to_seconds(bfe.io_time),
+ tokutime_to_seconds(bfe.decompress_time),
+ tokutime_to_seconds(bfe.deserialize_time));
printf(" n_children=%d\n", n->n_children);
printf(" total_childkeylens=%u\n", n->totalchildkeylens);
@@ -311,9 +310,9 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) {
}
} else {
printf(" n_bytes_in_buffer= %" PRIu64 "", BLB_DATA(n, i)->get_disk_size());
- printf(" items_in_buffer=%u\n", BLB_DATA(n, i)->num_klpairs());
+ printf(" items_in_buffer=%u\n", BLB_DATA(n, i)->omt_size());
if (do_dump_data) {
- BLB_DATA(n, i)->iterate<void, print_le>(NULL);
+ BLB_DATA(n, i)->omt_iterate<void, print_le>(NULL);
}
}
}
@@ -433,7 +432,7 @@ static void verify_block(unsigned char *cp, uint64_t file_offset, uint64_t size)
printf("header length too big: %u\n", header_length);
return;
}
- uint32_t header_xsum = toku_x1764_memory(cp, header_length);
+ uint32_t header_xsum = x1764_memory(cp, header_length);
uint32_t expected_xsum = toku_dtoh32(get_unaligned_uint32(&cp[header_length]));
if (header_xsum != expected_xsum) {
printf("header checksum failed: %u %u\n", header_xsum, expected_xsum);
@@ -451,7 +450,7 @@ static void verify_block(unsigned char *cp, uint64_t file_offset, uint64_t size)
// verify the sub block header
uint32_t offset = header_length + 4;
for (uint32_t i = 0 ; i < n_sub_blocks; i++) {
- uint32_t xsum = toku_x1764_memory(cp + offset, sub_block[i].compressed_size);
+ uint32_t xsum = x1764_memory(cp + offset, sub_block[i].compressed_size);
printf("%u: %u %u %u", i, sub_block[i].compressed_size, sub_block[i].uncompressed_size, sub_block[i].xsum);
if (xsum != sub_block[i].xsum)
printf(" fail %u offset %" PRIu64, xsum, file_offset + offset);
@@ -683,8 +682,9 @@ int main (int argc, const char *const argv[]) {
}
if (!do_header && !do_rootnode && !do_fragmentation && !do_translation_table && !do_garbage) {
printf("Block translation:");
-
toku_dump_translation_table(stdout, ft->blocktable);
+
+ dump_header(ft);
struct __dump_node_extra info;
info.fd = fd;
diff --git a/storage/tokudb/ft-index/ft/txn.cc b/storage/tokudb/ft-index/ft/txn.cc
index 403c8e92c45..b517b2f995d 100644
--- a/storage/tokudb/ft-index/ft/txn.cc
+++ b/storage/tokudb/ft-index/ft/txn.cc
@@ -628,7 +628,7 @@ void toku_txn_complete_txn(TOKUTXN txn) {
assert(txn->roll_info.spilled_rollback_tail.b == ROLLBACK_NONE.b);
assert(txn->roll_info.current_rollback.b == ROLLBACK_NONE.b);
assert(txn->num_pin == 0);
- assert(txn->state == TOKUTXN_COMMITTING || txn->state == TOKUTXN_ABORTING);
+ assert(txn->state == TOKUTXN_COMMITTING || txn->state == TOKUTXN_ABORTING || txn->state == TOKUTXN_PREPARING);
if (txn->parent) {
toku_txn_manager_handle_snapshot_destroy_for_child_txn(
txn,
@@ -786,6 +786,11 @@ void toku_txn_set_client_id(TOKUTXN txn, uint64_t client_id) {
txn->client_id = client_id;
}
+int toku_txn_discard_txn(TOKUTXN txn) {
+ int r = toku_rollback_discard(txn);
+ return r;
+}
+
#include <toku_race_tools.h>
void __attribute__((__constructor__)) toku_txn_status_helgrind_ignore(void);
void toku_txn_status_helgrind_ignore(void) {
diff --git a/storage/tokudb/ft-index/ft/txn.h b/storage/tokudb/ft-index/ft/txn.h
index 5e83d6511a2..053e24aec1a 100644
--- a/storage/tokudb/ft-index/ft/txn.h
+++ b/storage/tokudb/ft-index/ft/txn.h
@@ -154,6 +154,8 @@ int toku_txn_abort_txn(TOKUTXN txn,
int toku_txn_abort_with_lsn(TOKUTXN txn, LSN oplsn,
TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra);
+int toku_txn_discard_txn(TOKUTXN);
+
void toku_txn_prepare_txn (TOKUTXN txn, TOKU_XA_XID *xid);
// Effect: Do the internal work of preparing a transaction (does not log the prepare record).
diff --git a/storage/tokudb/ft-index/ft/txn_manager.cc b/storage/tokudb/ft-index/ft/txn_manager.cc
index 12c6ba4e887..a155db493c1 100644
--- a/storage/tokudb/ft-index/ft/txn_manager.cc
+++ b/storage/tokudb/ft-index/ft/txn_manager.cc
@@ -350,6 +350,27 @@ find_by_xid (const TOKUTXN &txn, const TXNID &txnidfind) {
return 0;
}
+#if 0
+static void
+omt_insert_at_end_unless_recovery(OMT omt, int (*h)(OMTVALUE, void*extra), TOKUTXN txn, OMTVALUE v, bool for_recovery)
+// Effect: insert v into omt that is sorted by xid gotten from txn.
+// Rationale:
+// During recovery, we get txns in the order that they did their first
+// write operation, which is not necessarily monotonically increasing.
+// During normal operation, txns are created with strictly increasing
+// txnids, so we can always insert at the end.
+{
+ int r;
+ uint32_t idx = toku_omt_size(omt);
+ if (for_recovery) {
+ r = toku_omt_find_zero(omt, h, (void *) txn->txnid64, NULL, &idx);
+ invariant(r==DB_NOTFOUND);
+ }
+ r = toku_omt_insert_at(omt, v, idx);
+ lazy_assert_zero(r);
+}
+#endif
+
static TXNID
max_xid(TXNID a, TXNID b) {
return a < b ? b : a;
diff --git a/storage/tokudb/ft-index/ft/ule-internal.h b/storage/tokudb/ft-index/ft/ule-internal.h
index 00b9847a13f..5c005acf887 100644
--- a/storage/tokudb/ft-index/ft/ule-internal.h
+++ b/storage/tokudb/ft-index/ft/ule-internal.h
@@ -149,8 +149,7 @@ le_pack(ULE ule, // data to be packed into new leafentry
void* keyp,
uint32_t keylen,
uint32_t old_le_size,
- LEAFENTRY * const new_leafentry_p, // this is what this function creates
- void **const maybe_free
+ LEAFENTRY * const new_leafentry_p // this is what this function creates
);
diff --git a/storage/tokudb/ft-index/ft/ule.cc b/storage/tokudb/ft-index/ft/ule.cc
index c364fc4603e..dc4198bda3d 100644
--- a/storage/tokudb/ft-index/ft/ule.cc
+++ b/storage/tokudb/ft-index/ft/ule.cc
@@ -252,27 +252,26 @@ static inline size_t uxr_unpack_length_and_bit(UXR uxr, uint8_t *p);
static inline size_t uxr_unpack_data(UXR uxr, uint8_t *p);
static void get_space_for_le(
- bn_data* data_buffer,
+ bn_data* data_buffer,
uint32_t idx,
void* keyp,
uint32_t keylen,
uint32_t old_le_size,
- size_t size,
- LEAFENTRY* new_le_space,
- void **const maybe_free
- )
+ size_t size,
+ LEAFENTRY* new_le_space
+ )
{
- if (data_buffer == nullptr) {
+ if (data_buffer == NULL) {
CAST_FROM_VOIDP(*new_le_space, toku_xmalloc(size));
}
else {
// this means we are overwriting something
if (old_le_size > 0) {
- data_buffer->get_space_for_overwrite(idx, keyp, keylen, old_le_size, size, new_le_space, maybe_free);
+ data_buffer->get_space_for_overwrite(idx, keyp, keylen, old_le_size, size, new_le_space);
}
// this means we are inserting something new
else {
- data_buffer->get_space_for_insert(idx, keyp, keylen, size, new_le_space, maybe_free);
+ data_buffer->get_space_for_insert(idx, keyp, keylen, size, new_le_space);
}
}
}
@@ -506,12 +505,19 @@ toku_le_apply_msg(FT_MSG msg,
int64_t newnumbytes = 0;
uint64_t oldmemsize = 0;
uint32_t keylen = ft_msg_get_keylen(msg);
+ LEAFENTRY copied_old_le = NULL;
+ size_t old_le_size = old_leafentry ? leafentry_memsize(old_leafentry) : 0;
+ toku::scoped_malloc copied_old_le_buf(old_le_size);
+ if (old_leafentry) {
+ CAST_FROM_VOIDP(copied_old_le, copied_old_le_buf.get());
+ memcpy(copied_old_le, old_leafentry, old_le_size);
+ }
if (old_leafentry == NULL) {
msg_init_empty_ule(&ule);
} else {
oldmemsize = leafentry_memsize(old_leafentry);
- le_unpack(&ule, old_leafentry); // otherwise unpack leafentry
+ le_unpack(&ule, copied_old_le); // otherwise unpack leafentry
oldnumbytes = ule_get_innermost_numbytes(&ule, keylen);
}
msg_modify_ule(&ule, msg); // modify unpacked leafentry
@@ -544,28 +550,21 @@ toku_le_apply_msg(FT_MSG msg,
STATUS_INC(LE_APPLY_GC_BYTES_IN, size_before_gc);
STATUS_INC(LE_APPLY_GC_BYTES_OUT, size_after_gc);
}
-
- void *maybe_free = nullptr;
- int r = le_pack(
+ int rval = le_pack(
&ule, // create packed leafentry
data_buffer,
idx,
ft_msg_get_key(msg), // contract of this function is caller has this set, always
keylen, // contract of this function is caller has this set, always
oldmemsize,
- new_leafentry_p,
- &maybe_free
+ new_leafentry_p
);
- invariant_zero(r);
+ invariant_zero(rval);
if (*new_leafentry_p) {
newnumbytes = ule_get_innermost_numbytes(&ule, keylen);
}
*numbytes_delta_p = newnumbytes - oldnumbytes;
-
ule_cleanup(&ule);
- if (maybe_free != nullptr) {
- toku_free(maybe_free);
- }
}
bool toku_le_worth_running_garbage_collection(LEAFENTRY le, txn_gc_info *gc_info) {
@@ -622,8 +621,15 @@ toku_le_garbage_collect(LEAFENTRY old_leaf_entry,
ULE_S ule;
int64_t oldnumbytes = 0;
int64_t newnumbytes = 0;
+ LEAFENTRY copied_old_le = NULL;
+ size_t old_le_size = old_leaf_entry ? leafentry_memsize(old_leaf_entry) : 0;
+ toku::scoped_malloc copied_old_le_buf(old_le_size);
+ if (old_leaf_entry) {
+ CAST_FROM_VOIDP(copied_old_le, copied_old_le_buf.get());
+ memcpy(copied_old_le, old_leaf_entry, old_le_size);
+ }
- le_unpack(&ule, old_leaf_entry);
+ le_unpack(&ule, copied_old_le);
oldnumbytes = ule_get_innermost_numbytes(&ule, keylen);
uint32_t old_mem_size = leafentry_memsize(old_leaf_entry);
@@ -648,7 +654,6 @@ toku_le_garbage_collect(LEAFENTRY old_leaf_entry,
STATUS_INC(LE_APPLY_GC_BYTES_OUT, size_after_gc);
}
- void *maybe_free = nullptr;
int r = le_pack(
&ule,
data_buffer,
@@ -656,19 +661,14 @@ toku_le_garbage_collect(LEAFENTRY old_leaf_entry,
keyp,
keylen,
old_mem_size,
- new_leaf_entry,
- &maybe_free
+ new_leaf_entry
);
- invariant_zero(r);
+ assert(r == 0);
if (*new_leaf_entry) {
newnumbytes = ule_get_innermost_numbytes(&ule, keylen);
}
*numbytes_delta_p = newnumbytes - oldnumbytes;
-
ule_cleanup(&ule);
- if (maybe_free != nullptr) {
- toku_free(maybe_free);
- }
}
/////////////////////////////////////////////////////////////////////////////////
@@ -963,7 +963,7 @@ update_le_status(ULE ule, size_t memsize) {
}
// Purpose is to return a newly allocated leaf entry in packed format, or
-// return null if leaf entry should be destroyed (if no transaction records
+// return null if leaf entry should be destroyed (if no transaction records
// are for inserts).
// Transaction records in packed le are stored inner to outer (first xr is innermost),
// with some information extracted out of the transaction records into the header.
@@ -975,8 +975,7 @@ le_pack(ULE ule, // data to be packed into new leafentry
void* keyp,
uint32_t keylen,
uint32_t old_le_size,
- LEAFENTRY * const new_leafentry_p, // this is what this function creates
- void **const maybe_free
+ LEAFENTRY * const new_leafentry_p // this is what this function creates
)
{
invariant(ule->num_cuxrs > 0);
@@ -1002,10 +1001,10 @@ le_pack(ULE ule, // data to be packed into new leafentry
rval = 0;
goto cleanup;
}
-found_insert:
+found_insert:;
memsize = le_memsize_from_ule(ule);
LEAFENTRY new_leafentry;
- get_space_for_le(data_buffer, idx, keyp, keylen, old_le_size, memsize, &new_leafentry, maybe_free);
+ get_space_for_le(data_buffer, idx, keyp, keylen, old_le_size, memsize, &new_leafentry);
//p always points to first unused byte after leafentry we are packing
uint8_t *p;
@@ -1057,7 +1056,7 @@ found_insert:
for (i = 0; i < ule->num_cuxrs; i++) {
p += uxr_pack_length_and_bit(ule->uxrs + ule->num_cuxrs - 1 - i, p);
}
-
+
//pack interesting values inner to outer
if (ule->num_puxrs!=0) {
UXR innermost = ule->uxrs + ule->num_cuxrs + ule->num_puxrs - 1;
@@ -1095,7 +1094,7 @@ found_insert:
size_t bytes_written;
bytes_written = (size_t)p - (size_t)new_leafentry;
invariant(bytes_written == memsize);
-
+
#if ULE_DEBUG
if (omt) { //Disable recursive debugging.
size_t memsize_verify = leafentry_memsize(new_leafentry);
@@ -2261,6 +2260,9 @@ cleanup:
return r;
}
+#if TOKU_WINDOWS
+#pragma pack(push, 1)
+#endif
// This is an on-disk format. static_asserts verify everything is packed and aligned correctly.
struct __attribute__ ((__packed__)) leafentry_13 {
struct leafentry_committed_13 {
@@ -2288,6 +2290,9 @@ struct __attribute__ ((__packed__)) leafentry_13 {
};
static_assert(18 == sizeof(leafentry_13), "wrong size");
static_assert(9 == __builtin_offsetof(leafentry_13, u), "wrong offset");
+#if TOKU_WINDOWS
+#pragma pack(pop)
+#endif
//Requires:
// Leafentry that ule represents should not be destroyed (is not just all deletes)
@@ -2462,14 +2467,12 @@ toku_le_upgrade_13_14(LEAFENTRY_13 old_leafentry,
// malloc instead of a mempool. However after supporting upgrade,
// we need to use mempools and the OMT.
rval = le_pack(&ule, // create packed leafentry
- nullptr,
+ NULL,
0, //only matters if we are passing in a bn_data
- nullptr, //only matters if we are passing in a bn_data
+ NULL, //only matters if we are passing in a bn_data
0, //only matters if we are passing in a bn_data
0, //only matters if we are passing in a bn_data
- new_leafentry_p,
- nullptr //only matters if we are passing in a bn_data
- );
+ new_leafentry_p);
ule_cleanup(&ule);
*new_leafentry_memorysize = leafentry_memsize(*new_leafentry_p);
return rval;
diff --git a/storage/tokudb/ft-index/ft/wbuf.h b/storage/tokudb/ft-index/ft/wbuf.h
index 93cfe0c7185..282233920a7 100644
--- a/storage/tokudb/ft-index/ft/wbuf.h
+++ b/storage/tokudb/ft-index/ft/wbuf.h
@@ -95,9 +95,9 @@ PATENT RIGHTS GRANT:
#include <string.h>
#include <portability/toku_htonl.h>
-#include <util/x1764.h>
#include "fttypes.h"
+#include "x1764.h"
#define CRC_INCR
@@ -121,7 +121,7 @@ static inline void wbuf_nocrc_init (struct wbuf *w, void *buf, DISKOFF size) {
static inline void wbuf_init (struct wbuf *w, void *buf, DISKOFF size) {
wbuf_nocrc_init(w, buf, size);
- toku_x1764_init(&w->checksum);
+ x1764_init(&w->checksum);
}
static inline size_t wbuf_get_woffset(struct wbuf *w) {
@@ -142,7 +142,7 @@ static inline void wbuf_nocrc_uint8_t (struct wbuf *w, uint8_t ch) {
static inline void wbuf_char (struct wbuf *w, unsigned char ch) {
wbuf_nocrc_char (w, ch);
- toku_x1764_add(&w->checksum, &w->buf[w->ndone-1], 1);
+ x1764_add(&w->checksum, &w->buf[w->ndone-1], 1);
}
//Write an int that MUST be in network order regardless of disk order
@@ -150,7 +150,7 @@ static void wbuf_network_int (struct wbuf *w, int32_t i) __attribute__((__unused
static void wbuf_network_int (struct wbuf *w, int32_t i) {
assert(w->ndone + 4 <= w->size);
*(uint32_t*)(&w->buf[w->ndone]) = toku_htonl(i);
- toku_x1764_add(&w->checksum, &w->buf[w->ndone], 4);
+ x1764_add(&w->checksum, &w->buf[w->ndone], 4);
w->ndone += 4;
}
@@ -176,7 +176,7 @@ static inline void wbuf_nocrc_int (struct wbuf *w, int32_t i) {
static inline void wbuf_int (struct wbuf *w, int32_t i) {
wbuf_nocrc_int(w, i);
- toku_x1764_add(&w->checksum, &w->buf[w->ndone-4], 4);
+ x1764_add(&w->checksum, &w->buf[w->ndone-4], 4);
}
static inline void wbuf_nocrc_uint (struct wbuf *w, uint32_t i) {
@@ -187,13 +187,6 @@ static inline void wbuf_uint (struct wbuf *w, uint32_t i) {
wbuf_int(w, (int32_t)i);
}
-static inline uint8_t* wbuf_nocrc_reserve_literal_bytes(struct wbuf *w, uint32_t nbytes) {
- assert(w->ndone + nbytes <= w->size);
- uint8_t * dest = w->buf + w->ndone;
- w->ndone += nbytes;
- return dest;
-}
-
static inline void wbuf_nocrc_literal_bytes(struct wbuf *w, bytevec bytes_bv, uint32_t nbytes) {
const unsigned char *bytes = (const unsigned char *) bytes_bv;
#if 0
@@ -207,7 +200,7 @@ static inline void wbuf_nocrc_literal_bytes(struct wbuf *w, bytevec bytes_bv, ui
static inline void wbuf_literal_bytes(struct wbuf *w, bytevec bytes_bv, uint32_t nbytes) {
wbuf_nocrc_literal_bytes(w, bytes_bv, nbytes);
- toku_x1764_add(&w->checksum, &w->buf[w->ndone-nbytes], nbytes);
+ x1764_add(&w->checksum, &w->buf[w->ndone-nbytes], nbytes);
}
static void wbuf_nocrc_bytes (struct wbuf *w, bytevec bytes_bv, uint32_t nbytes) {
diff --git a/storage/tokudb/ft-index/ft/worker-thread-benchmarks/threadpool.cc b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/threadpool.cc
new file mode 100644
index 00000000000..a1fda8c373c
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/threadpool.cc
@@ -0,0 +1,166 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include <stdio.h>
+#include <stdlib.h>
+#include <toku_assert.h>
+#include <malloc.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "threadpool.h"
+#include <portability/toku_atomic.h>
+
+// use gcc builtin fetch_and_add 0->no 1->yes
+#define DO_ATOMIC_FETCH_AND_ADD 0
+
+struct threadpool {
+ int max_threads;
+ int current_threads;
+ int busy_threads;
+ pthread_t pids[];
+};
+
+int threadpool_create(THREADPOOL *threadpoolptr, int max_threads) {
+ size_t size = sizeof (struct threadpool) + max_threads*sizeof (pthread_t);
+ struct threadpool *threadpool = (struct threadpool *) malloc(size);
+ if (threadpool == 0)
+ return ENOMEM;
+ threadpool->max_threads = max_threads;
+ threadpool->current_threads = 0;
+ threadpool->busy_threads = 0;
+ int i;
+ for (i=0; i<max_threads; i++)
+ threadpool->pids[i] = 0;
+ *threadpoolptr = threadpool;
+ return 0;
+}
+
+void threadpool_destroy(THREADPOOL *threadpoolptr) {
+ struct threadpool *threadpool = *threadpoolptr;
+ int i;
+ for (i=0; i<threadpool->current_threads; i++) {
+ int r; void *ret;
+ r = pthread_join(threadpool->pids[i], &ret);
+ assert(r == 0);
+ }
+ *threadpoolptr = 0;
+ free(threadpool);
+}
+
+void threadpool_maybe_add(THREADPOOL threadpool, void *(*f)(void *), void *arg) {
+ if (threadpool->current_threads < threadpool->max_threads) {
+ int r = pthread_create(&threadpool->pids[threadpool->current_threads], 0, f, arg);
+ if (r == 0) {
+ threadpool->current_threads++;
+ threadpool_set_thread_busy(threadpool);
+ }
+ }
+}
+
+void threadpool_set_thread_busy(THREADPOOL threadpool) {
+#if DO_ATOMIC_FETCH_AND_ADD
+ (void) toku_sync_fetch_and_add(&threadpool->busy_threads, 1);
+#else
+ threadpool->busy_threads++;
+#endif
+}
+
+void threadpool_set_thread_idle(THREADPOOL threadpool) {
+#if DO_ATOMIC_FETCH_AND_ADD
+ (void) toku_sync_fetch_and_add(&threadpool->busy_threads, -1);
+#else
+ threadpool->busy_threads--;
+#endif
+}
+
+int threadpool_get_current_threads(THREADPOOL threadpool) {
+ return threadpool->current_threads;
+}
diff --git a/storage/tokudb/ft-index/ft/worker-thread-benchmarks/threadpool.h b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/threadpool.h
new file mode 100644
index 00000000000..e2d37b486c1
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/threadpool.h
@@ -0,0 +1,136 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+// A threadpool is a limited set of threads that can be used to apply a
+// function to work contained in a work queue. The work queue is outside
+// of the scope of the threadpool; the threadpool merely provides
+// mechanisms to grow the number of threads in the threadpool on demand.
+
+typedef struct threadpool *THREADPOOL;
+
+// Create a new threadpool
+// Effects: a new threadpool is allocated and initialized. the number of
+// threads in the threadpool is limited to max_threads. initially, there
+// are no threads in the pool.
+// Returns: if there are no errors, the threadpool is set and zero is returned.
+// Otherwise, an error number is returned.
+
+int threadpool_create(THREADPOOL *threadpoolptr, int max_threads);
+
+// Destroy a threadpool
+// Effects: the calling thread joins with all of the threads in the threadpool.
+// Effects: the threadpool memory is freed.
+// Returns: the threadpool is set to null.
+
+void threadpool_destroy(THREADPOOL *threadpoolptr);
+
+// Maybe add a thread to the threadpool.
+// Effects: the number of threads in the threadpool is expanded by 1 as long
+// as the current number of threads in the threadpool is less than the max
+// and there are no idle threads.
+// Effects: if the thread is create, it calls the function f with argument arg
+// Expects: external serialization on this function; only one thread may
+// execute this function
+
+void threadpool_maybe_add(THREADPOOL theadpool, void *(*f)(void *), void *arg);
+
+// Set the current thread busy
+// Effects: the threadpool keeps a count of the number of idle threads. It
+// uses this count to control the creation of additional threads.
+
+void threadpool_set_thread_busy(THREADPOOL);
+
+// Set the current thread idle
+
+void threadpool_set_thread_idle(THREADPOOL);
+
+// get the current number of threads
+
+int threadpool_get_current_threads(THREADPOOL);
diff --git a/storage/tokudb/ft-index/ft/worker-thread-benchmarks/worker-test.cc b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/worker-test.cc
new file mode 100644
index 00000000000..362a3ec5604
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/worker-test.cc
@@ -0,0 +1,261 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <toku_assert.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+
+int usage() {
+ printf("measure multi-thread work scheduling overhead\n");
+ printf("-nthreads N (number of worker threads, default 1)\n");
+ printf("-nworkitems N (number of work items, default 1)\n");
+ printf("-usleeptime N (work time, default 100)\n");
+ printf("-ntests N (number of test iterations, default 1)\n");
+ printf("-adaptive (use adaptive mutex locks, default no)\n");
+ return 1;
+}
+
+typedef struct workitem *WORKITEM;
+struct workitem {
+ struct workitem *next_wq;
+ int usleeptime;
+};
+
+#include "workqueue.h"
+#include "threadpool.h"
+
+int usleeptime = 100;
+
+void do_work(WORKITEM wi __attribute__((unused))) {
+#if 0
+ // sleep for usleeptime microseconds
+ usleep(usleeptime);
+#else
+ // busy wait for usleeptime loop interations
+ int n = wi->usleeptime;
+ volatile int i;
+ for (i=0; i<n; i++);
+#endif
+}
+
+// per thread argument that includes the work queues and locks
+struct runner_arg {
+ pthread_mutex_t *lock;
+ WORKQUEUE wq;
+ WORKQUEUE cq;
+};
+
+void *runner_thread(void *arg) {
+ int r;
+ struct runner_arg *runner = (struct runner_arg *)arg;
+ r = pthread_mutex_lock(runner->lock); assert(r == 0);
+ while (1) {
+ WORKITEM wi;
+ r = workqueue_deq(runner->wq, runner->lock, &wi);
+ if (r != 0) break;
+ r = pthread_mutex_unlock(runner->lock); assert(r == 0);
+ do_work(wi);
+ r = pthread_mutex_lock(runner->lock); assert(r == 0);
+ workqueue_enq(runner->cq, wi);
+ }
+ r = pthread_mutex_unlock(runner->lock); assert(r == 0);
+ return arg;
+}
+
+static inline void lockit(pthread_mutex_t *lock, int nthreads) {
+ if (nthreads > 0) {
+ int r = pthread_mutex_lock(lock); assert(r == 0);
+ }
+}
+
+static inline void unlockit(pthread_mutex_t *lock, int nthreads) {
+ if (nthreads > 0) {
+ int r = pthread_mutex_unlock(lock); assert(r == 0);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ int ntests = 1;
+ int nworkitems = 1;
+ int nthreads = 1;
+ int adaptive = 0;
+
+ int r;
+ int i;
+ for (i=1; i<argc; i++) {
+ char *arg = argv[i];
+ if (strcmp(arg, "-help") == 0) {
+ return usage();
+ }
+ if (strcmp(arg, "-ntests") == 0) {
+ assert(i+1 < argc);
+ ntests = atoi(argv[++i]);
+ }
+ if (strcmp(arg, "-nworkitems") == 0) {
+ assert(i+1 < argc);
+ nworkitems = atoi(argv[++i]);
+ }
+ if (strcmp(arg, "-nthreads") == 0) {
+ assert(i+1 < argc);
+ nthreads = atoi(argv[++i]);
+ }
+ if (strcmp(arg, "-usleeptime") == 0) {
+ assert(i+1 < argc);
+ usleeptime = atoi(argv[++i]);
+ }
+ if (strcmp(arg, "-adaptive") == 0) {
+ adaptive++;
+ }
+ }
+
+ pthread_mutex_t lock;
+ pthread_mutexattr_t mattr;
+ r = pthread_mutexattr_init(&mattr); assert(r == 0);
+ if (adaptive) {
+ r = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ADAPTIVE_NP); assert(r == 0);
+ }
+ r = pthread_mutex_init(&lock, &mattr); assert(r == 0);
+
+ struct workqueue wq;
+ workqueue_init(&wq);
+ struct workqueue cq;
+ workqueue_init(&cq);
+ THREADPOOL tp;
+ r = threadpool_create(&tp, nthreads); assert(r == 0);
+ struct runner_arg runner_arg;
+ runner_arg.lock = &lock;
+ runner_arg.wq = &wq;
+ runner_arg.cq = &cq;
+ for (i=0; i<nthreads; i++)
+ threadpool_maybe_add(tp, runner_thread, &runner_arg);
+ int t;
+ for (t=0; t<ntests; t++) {
+ struct workitem work[nworkitems];
+ if (nworkitems == 1) {
+ // single work items are run in the main thread
+ work[0].usleeptime = usleeptime;
+ do_work(&work[0]);
+ } else {
+ lockit(&lock, nthreads);
+ // put all the work on the work queue
+ int i;
+ for (i=0; i<nworkitems; i++) {
+ work[i].usleeptime = usleeptime;
+ workqueue_enq(&wq, &work[i]);
+ }
+ // run some of the work in the main thread
+ int ndone = 0;
+ while (!workqueue_empty(&wq)) {
+ WORKITEM wi;
+ workqueue_deq(&wq, &lock, &wi);
+ unlockit(&lock, nthreads);
+ do_work(wi);
+ lockit(&lock, nthreads);
+ ndone++;
+ }
+ // make sure all of the work has completed
+ for (i=ndone; i<nworkitems; i++) {
+ WORKITEM wi;
+ r = workqueue_deq(&cq, &lock, &wi);
+ assert(r == 0);
+ }
+ unlockit(&lock, nthreads);
+ }
+ }
+ workqueue_set_closed(&wq);
+ threadpool_destroy(&tp);
+ workqueue_destroy(&wq);
+ workqueue_destroy(&cq);
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/worker-thread-benchmarks/worker-test.cilk b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/worker-test.cilk
new file mode 100644
index 00000000000..77b2a5c58d0
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/worker-test.cilk
@@ -0,0 +1,74 @@
+#include <cilk-lib.cilkh>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+int usage() {
+ printf("measure multi-thread work scheduling overhead\n");
+ printf("-nworkitems N (number of work items, default 1)\n");
+ printf("-usleeptime N (work time, default 100)\n");
+ printf("-ntests N (number of test iterations, default 1)\n");
+ return 1;
+}
+
+typedef struct workitem *WORKITEM;
+struct workitem {
+ int usleeptime;
+};
+
+cilk void do_work(WORKITEM wi) {
+#if 0
+ // sleep for usleeptime microseconds
+ usleep(wi->usleeptime);
+#else
+ // busy wait for usleeptime loop interations
+ int n = wi->usleeptime;
+ volatile int i;
+ for (i=0; i<n; i++);
+#endif
+}
+
+cilk int main(int argc, char *argv[]) {
+ int ntests = 1;
+ int nworkitems = 1;
+ int usleeptime = 100;
+
+ int i;
+ int t;
+
+ struct workitem *work;
+
+ for (i=1; i<argc; i++) {
+ char *arg = argv[i];
+ if (strcmp(arg, "-help") == 0) {
+ return usage();
+ }
+ if (strcmp(arg, "-ntests") == 0) {
+ assert(i+1 < argc);
+ ntests = atoi(argv[++i]);
+ }
+ if (strcmp(arg, "-nworkitems") == 0) {
+ assert(i+1 < argc);
+ nworkitems = atoi(argv[++i]);
+ }
+ if (strcmp(arg, "-usleeptime") == 0) {
+ assert(i+1 < argc);
+ usleeptime = atoi(argv[++i]);
+ }
+ }
+
+ printf("ntests=%d nworkitems=%d usleeptime=%d\n", ntests, nworkitems, usleeptime);
+ work = (struct workitem *) calloc(nworkitems, sizeof (struct workitem));
+ for (t=0; t<ntests; t++) {
+ for (i=0; i<nworkitems; i++) {
+ work[i].usleeptime = usleeptime;
+ spawn do_work(&work[i]);
+ }
+ sync;
+ }
+ free(work);
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/worker-thread-benchmarks/workqueue.h b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/workqueue.h
new file mode 100644
index 00000000000..ab8f856a019
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/worker-thread-benchmarks/workqueue.h
@@ -0,0 +1,207 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+
+typedef struct workqueue *WORKQUEUE;
+struct workqueue {
+ WORKITEM head, tail; // head and tail of the linked list of work items
+ pthread_cond_t wait_read; // wait for read
+ int want_read; // number of threads waiting to read
+ pthread_cond_t wait_write; // wait for write
+ int want_write; // number of threads waiting to write
+ int ninq; // number of work items in the queue
+ char closed; // kicks waiting threads off of the write queue
+};
+
+// initialize a workqueue
+// expects: the workqueue is not initialized
+// effects: the workqueue is set to empty and the condition variable is initialized
+
+static void workqueue_init(WORKQUEUE wq) {
+ wq->head = wq->tail = 0;
+ int r;
+ r = pthread_cond_init(&wq->wait_read, 0); assert(r == 0);
+ wq->want_read = 0;
+ r = pthread_cond_init(&wq->wait_write, 0); assert(r == 0);
+ wq->want_write = 0;
+ wq->ninq = 0;
+ wq->closed = 0;
+}
+
+// destroy a workqueue
+// expects: the workqueue must be initialized and empty
+
+static void workqueue_destroy(WORKQUEUE wq) {
+ assert(wq->head == 0 && wq->tail == 0);
+ int r;
+ r = pthread_cond_destroy(&wq->wait_read); assert(r == 0);
+ r = pthread_cond_destroy(&wq->wait_write); assert(r == 0);
+}
+
+// close the workqueue
+// effects: signal any threads blocked in the workqueue
+
+static void workqueue_set_closed(WORKQUEUE wq) {
+ wq->closed = 1;
+ int r;
+ r = pthread_cond_broadcast(&wq->wait_read); assert(r == 0);
+ r = pthread_cond_broadcast(&wq->wait_write); assert(r == 0);
+}
+
+// determine whether or not the write queue is empty
+// return: 1 if the write queue is empty, otherwise 0
+
+static int workqueue_empty(WORKQUEUE wq) {
+ return wq->head == 0;
+}
+
+// put a work item at the tail of the write queue
+// expects: the mutex is locked
+// effects: append the workitem to the end of the write queue and signal
+// any readers
+
+static void workqueue_enq(WORKQUEUE wq, WORKITEM workitem) {
+ workitem->next_wq = 0;
+ if (wq->tail)
+ wq->tail->next_wq = workitem;
+ else
+ wq->head = workitem;
+ wq->tail = workitem;
+ wq->ninq++;
+ if (wq->want_read) {
+ int r = pthread_cond_signal(&wq->wait_read); assert(r == 0);
+ }
+}
+
+// get a workitem from the head of the write queue
+// expects: the mutex is locked
+// effects: wait until the workqueue is not empty, remove the first workitem from the
+// write queue and return it
+// returns: 0 if success, otherwise an error
+
+static int workqueue_deq(WORKQUEUE wq, pthread_mutex_t *mutex, WORKITEM *workitemptr) {
+ while (workqueue_empty(wq)) {
+ if (wq->closed)
+ return EINVAL;
+ wq->want_read++;
+ int r = pthread_cond_wait(&wq->wait_read, mutex); assert(r == 0);
+ wq->want_read--;
+ }
+ WORKITEM workitem = wq->head;
+ wq->head = workitem->next_wq;
+ if (wq->head == 0)
+ wq->tail = 0;
+ wq->ninq--;
+ workitem->next_wq = 0;
+ *workitemptr = workitem;
+ return 0;
+}
+
+#if 0
+
+// suspend the writer thread
+// expects: the mutex is locked
+
+static void workqueue_wait_write(WORKQUEUE wq, pthread_mutex_t *mutex) {
+ wq->want_write++;
+ int r = pthread_cond_wait(&wq->wait_write, mutex); assert(r == 0);
+ wq->want_write--;
+}
+
+// wakeup the writer threads
+// expects: the mutex is locked
+
+static void workqueue_wakeup_write(WORKQUEUE wq) {
+ if (wq->want_write) {
+ int r = pthread_cond_broadcast(&wq->wait_write); assert(r == 0);
+ }
+}
+
+#endif
diff --git a/storage/tokudb/ft-index/ft/x1764-speedup/x1764-speedup-test.cc b/storage/tokudb/ft-index/ft/x1764-speedup/x1764-speedup-test.cc
new file mode 100644
index 00000000000..e4f9d1c9b53
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/x1764-speedup/x1764-speedup-test.cc
@@ -0,0 +1,175 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+uint64_t x1764_simple (const uint64_t *buf, size_t len)
+{
+ uint64_t sum=0;
+ for (size_t i=0; i<len ;i++) {
+ sum = sum*17 + buf[i];
+ }
+ return sum;
+}
+
+uint64_t x1764_2x (const uint64_t *buf, size_t len)
+{
+ assert(len%2==0);
+ uint64_t suma=0, sumb=0;
+ for (size_t i=0; i<len ;i+=2) {
+ suma = suma*(17L*17L) + buf[i];
+ sumb = sumb*(17L*17L) + buf[i+1];
+ }
+ return suma*17+sumb;
+}
+
+uint64_t x1764_3x (const uint64_t *buf, size_t len)
+{
+ assert(len%3==0);
+ uint64_t suma=0, sumb=0, sumc=0;
+ for (size_t i=0; i<len ;i+=3) {
+ suma = suma*(17LL*17LL*17LL) + buf[i];
+ sumb = sumb*(17LL*17LL*17LL) + buf[i+1];
+ sumc = sumc*(17LL*17LL*17LL) + buf[i+2];
+ }
+ uint64_t r = suma*17L*17L + sumb*17L + sumc;
+ return r;
+}
+
+uint64_t x1764_4x (const uint64_t *buf, size_t len)
+{
+ assert(len%4==0);
+ uint64_t suma=0, sumb=0, sumc=0, sumd=0;
+ for (size_t i=0; i<len ;i+=4) {
+ suma = suma*(17LL*17LL*17LL*17LL) + buf[i];
+ sumb = sumb*(17LL*17LL*17LL*17LL) + buf[i+1];
+ sumc = sumc*(17LL*17LL*17LL*17LL) + buf[i+2];
+ sumd = sumd*(17LL*17LL*17LL*17LL) + buf[i+3];
+ }
+ return suma*17L*17L*17L + sumb*17L*17L + sumc*17L + sumd;
+
+}
+
+float tdiff (struct timeval *start, struct timeval *end) {
+ return (end->tv_sec-start->tv_sec) +1e-6*(end->tv_usec - start->tv_usec);
+}
+
+int main (int argc, char *argv[]) {
+ int size = 1024*1024*4 + 8*4;
+ char *data = malloc(size);
+ for (int j=0; j<4; j++) {
+ struct timeval start,end,end2,end3,end4;
+ for (int i=0; i<size; i++) data[i]=i*i+j;
+ gettimeofday(&start, 0);
+ uint64_t s = x1764_simple((uint64_t*)data, size/sizeof(uint64_t));
+ gettimeofday(&end, 0);
+ uint64_t s2 = x1764_2x((uint64_t*)data, size/sizeof(uint64_t));
+ gettimeofday(&end2, 0);
+ uint64_t s3 = x1764_3x((uint64_t*)data, size/sizeof(uint64_t));
+ gettimeofday(&end3, 0);
+ uint64_t s4 = x1764_4x((uint64_t*)data, size/sizeof(uint64_t));
+ gettimeofday(&end4, 0);
+ assert(s==s2);
+ assert(s==s3);
+ assert(s==s4);
+ double b1 = tdiff(&start, &end);
+ double b2 = tdiff(&end, &end2);
+ double b3 = tdiff(&end2, &end3);
+ double b4 = tdiff(&end3, &end4);
+ printf("s=%016llx t=%.6fs %.6fs (%4.2fx), %.6fs (%4.2fx), %.6fs (%4.2fx) [%5.2f MB/s]\n",
+ (unsigned long long)s,
+ b1, b2, b1/b2, b3, b1/b3, b4, b1/b4, (size/b4)/(1024*1024));
+ }
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/util/x1764.cc b/storage/tokudb/ft-index/ft/x1764.cc
index ef7e6576e4f..c95ff327560 100644
--- a/storage/tokudb/ft-index/util/x1764.cc
+++ b/storage/tokudb/ft-index/ft/x1764.cc
@@ -90,13 +90,13 @@ PATENT RIGHTS GRANT:
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#include <toku_stdlib.h>
-#include <portability/toku_portability.h>
+#include <toku_include/toku_portability.h>
#include "x1764.h"
#define PRINT 0
-uint32_t toku_x1764_memory_simple (const void *buf, int len)
+uint32_t x1764_memory_simple (const void *buf, int len)
{
const uint64_t *CAST_FROM_VOIDP(lbuf, buf);
uint64_t c=0;
@@ -118,7 +118,7 @@ uint32_t toku_x1764_memory_simple (const void *buf, int len)
return ~((c&0xFFFFFFFF) ^ (c>>32));
}
-uint32_t toku_x1764_memory (const void *vbuf, int len)
+uint32_t x1764_memory (const void *vbuf, int len)
{
const uint8_t *CAST_FROM_VOIDP(buf, vbuf);
int len_4_words = 4*sizeof(uint64_t);
@@ -149,13 +149,13 @@ uint32_t toku_x1764_memory (const void *vbuf, int len)
}
-void toku_x1764_init(struct x1764 *l) {
+void x1764_init(struct x1764 *l) {
l->sum=0;
l->input=0;
l->n_input_bytes=0;
}
-void toku_x1764_add (struct x1764 *l, const void *vbuf, int len) {
+void x1764_add (struct x1764 *l, const void *vbuf, int len) {
if (PRINT) printf("%d: n_input_bytes=%d len=%d\n", __LINE__, l->n_input_bytes, len);
int n_input_bytes = l->n_input_bytes;
const unsigned char *CAST_FROM_VOIDP(cbuf, vbuf);
@@ -287,7 +287,7 @@ void toku_x1764_add (struct x1764 *l, const void *vbuf, int len) {
l->input = input;
if (PRINT) printf("%d: n_input_bytes=%d\n", __LINE__, l->n_input_bytes);
}
-uint32_t toku_x1764_finish (struct x1764 *l) {
+uint32_t x1764_finish (struct x1764 *l) {
if (PRINT) printf("%d: n_input_bytes=%d\n", __LINE__, l->n_input_bytes);
int len = l->n_input_bytes;
if (len>0) {
diff --git a/storage/tokudb/ft-index/util/x1764.h b/storage/tokudb/ft-index/ft/x1764.h
index 1f87f50f09e..090167c8fc7 100644
--- a/storage/tokudb/ft-index/util/x1764.h
+++ b/storage/tokudb/ft-index/ft/x1764.h
@@ -99,11 +99,11 @@ PATENT RIGHTS GRANT:
// If any odd bytes numbers are left at the end, they are filled in at the low end.
-uint32_t toku_x1764_memory (const void *buf, int len);
+uint32_t x1764_memory (const void *buf, int len);
// Effect: Compute x1764 on the bytes of buf. Return the 32 bit answer.
-uint32_t toku_x1764_memory_simple (const void *buf, int len);
-// Effect: Same as toku_x1764_memory, but not highly optimized (more likely to be correct). Useful for testing the optimized version.
+uint32_t x1764_memory_simple (const void *buf, int len);
+// Effect: Same as x1764_memory, but not highly optimized (more likely to be correct). Useful for testing the optimized version.
// For incrementally computing an x1764, use the following interfaces.
@@ -113,13 +113,13 @@ struct x1764 {
int n_input_bytes;
};
-void toku_x1764_init(struct x1764 *l);
+void x1764_init(struct x1764 *l);
// Effect: Initialize *l.
-void toku_x1764_add (struct x1764 *l, const void *vbuf, int len);
+void x1764_add (struct x1764 *l, const void *vbuf, int len);
// Effect: Add more bytes to *l.
-uint32_t toku_x1764_finish (struct x1764 *l);
+uint32_t x1764_finish (struct x1764 *l);
// Effect: Return the final 32-bit result.
diff --git a/storage/tokudb/ft-index/ft/xids-internal.h b/storage/tokudb/ft-index/ft/xids-internal.h
index 6ceae6ee35e..f0e1b97c733 100644
--- a/storage/tokudb/ft-index/ft/xids-internal.h
+++ b/storage/tokudb/ft-index/ft/xids-internal.h
@@ -93,16 +93,26 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+
// Variable size list of transaction ids (known in design doc as xids<>).
// ids[0] is the outermost transaction.
// ids[num_xids - 1] is the innermost transaction.
// Should only be accessed by accessor functions xids_xxx, not directly.
// If the xids struct is unpacked, the compiler aligns the ids[] and we waste a lot of space
+#if TOKU_WINDOWS
+#pragma pack(push, 1)
+#endif
+
typedef struct __attribute__((__packed__)) xids_t {
uint8_t num_xids; // maximum value of MAX_TRANSACTION_RECORDS - 1 ...
// ... because transaction 0 is implicit
TXNID ids[];
} XIDS_S;
+#if TOKU_WINDOWS
+#pragma pack(pop)
+#endif
+
+
#endif
diff --git a/storage/tokudb/ft-index/ft/xids.h b/storage/tokudb/ft-index/ft/xids.h
index 45246785775..f7a7a87155d 100644
--- a/storage/tokudb/ft-index/ft/xids.h
+++ b/storage/tokudb/ft-index/ft/xids.h
@@ -104,10 +104,12 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include "x1764.h"
#include "rbuf.h"
#include "wbuf.h"
#include "tokuconst.h"
+
//Retrieve an XIDS representing the root transaction.
XIDS xids_get_root_xids(void);
diff --git a/storage/tokudb/ft-index/include/CMakeLists.txt b/storage/tokudb/ft-index/include/CMakeLists.txt
new file mode 100644
index 00000000000..f24f2bca4f9
--- /dev/null
+++ b/storage/tokudb/ft-index/include/CMakeLists.txt
@@ -0,0 +1,5 @@
+install(
+ FILES tdb-internal.h
+ DESTINATION include
+ COMPONENT tokukv_headers
+ )
diff --git a/storage/tokudb/ft-index/include/tdb-internal.h b/storage/tokudb/ft-index/include/tdb-internal.h
new file mode 100644
index 00000000000..42f63582871
--- /dev/null
+++ b/storage/tokudb/ft-index/include/tdb-internal.h
@@ -0,0 +1,110 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+#ifndef _TDB_INTERNAL_H
+#define _TDB_INTERNAL_H
+
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+
+#include "toku_list.h"
+// Included by db.h, defines some internal structures. These structures are inlined in some versions of db.h
+// the types DB_TXN and so forth have been defined.
+
+//// This list structure is repeated here (from toku_list.h) so that the db.h file will be standalone. Any code that depends on this list matching the structure in toku_list.h
+//// will get flagged by the compiler if someone changes one but not the other. See #2276.
+//struct toku_list {
+// struct toku_list *next, *prev;
+//};
+
+struct simple_dbt {
+ uint32_t len;
+ void *data;
+};
+
+// end of _TDB_INTERNAL_H:
+#endif
diff --git a/storage/tokudb/ft-index/locktree/lock_request.cc b/storage/tokudb/ft-index/locktree/lock_request.cc
index 2f43e8960db..362f9bfa98d 100644
--- a/storage/tokudb/ft-index/locktree/lock_request.cc
+++ b/storage/tokudb/ft-index/locktree/lock_request.cc
@@ -338,7 +338,7 @@ int lock_request::retry(void) {
}
void lock_request::retry_all_lock_requests(locktree *lt) {
- lt_lock_request_info *info = lt->get_lock_request_info();
+ locktree::lt_lock_request_info *info = lt->get_lock_request_info();
// if a thread reads this bit to be true, then it should go ahead and
// take the locktree mutex and retry lock requests. we use this bit
diff --git a/storage/tokudb/ft-index/locktree/lock_request.h b/storage/tokudb/ft-index/locktree/lock_request.h
index 0916a6529e0..48956826547 100644
--- a/storage/tokudb/ft-index/locktree/lock_request.h
+++ b/storage/tokudb/ft-index/locktree/lock_request.h
@@ -202,7 +202,7 @@ private:
// the lock request info state stored in the
// locktree that this lock request is for.
- struct lt_lock_request_info *m_info;
+ struct locktree::lt_lock_request_info *m_info;
// effect: tries again to acquire the lock described by this lock request
// returns: 0 if retrying the request succeeded and is now complete
diff --git a/storage/tokudb/ft-index/locktree/locktree.cc b/storage/tokudb/ft-index/locktree/locktree.cc
index 2deb8c2ad78..21b0aaa1426 100644
--- a/storage/tokudb/ft-index/locktree/locktree.cc
+++ b/storage/tokudb/ft-index/locktree/locktree.cc
@@ -116,9 +116,10 @@ namespace toku {
// but does nothing based on the value of the reference count - it is
// up to the user of the locktree to destroy it when it sees fit.
-void locktree::create(locktree_manager *mgr, DICTIONARY_ID dict_id,
- DESCRIPTOR desc, ft_compare_func cmp) {
- m_mgr = mgr;
+void locktree::create(manager::memory_tracker *mem_tracker, DICTIONARY_ID dict_id,
+ DESCRIPTOR desc, ft_compare_func cmp) {
+ m_mem_tracker = mem_tracker;
+ m_mgr = mem_tracker->get_manager();
m_dict_id = dict_id;
// the only reason m_cmp is malloc'd here is to prevent gdb from printing
@@ -163,18 +164,6 @@ void locktree::destroy(void) {
m_lock_request_info.pending_lock_requests.destroy();
}
-void locktree::add_reference(void) {
- (void) toku_sync_add_and_fetch(&m_reference_count, 1);
-}
-
-uint32_t locktree::release_reference(void) {
- return toku_sync_sub_and_fetch(&m_reference_count, 1);
-}
-
-uint32_t locktree::get_reference_count(void) {
- return m_reference_count;
-}
-
// a container for a range/txnid pair
struct row_lock {
keyrange range;
@@ -185,8 +174,9 @@ struct row_lock {
// storing each row lock into the given growable array. the
// caller does not own the range inside the returned row locks,
// so remove from the tree with care using them as keys.
-static void iterate_and_get_overlapping_row_locks(const concurrent_tree::locked_keyrange *lkr,
- GrowableArray<row_lock> *row_locks) {
+static void iterate_and_get_overlapping_row_locks(
+ const concurrent_tree::locked_keyrange *lkr,
+ GrowableArray<row_lock> *row_locks) {
struct copy_fn_obj {
GrowableArray<row_lock> *row_locks;
bool fn(const keyrange &range, TXNID txnid) {
@@ -203,7 +193,7 @@ static void iterate_and_get_overlapping_row_locks(const concurrent_tree::locked_
// which txnids are conflicting, and store them in the conflicts
// set, if given.
static bool determine_conflicting_txnids(const GrowableArray<row_lock> &row_locks,
- const TXNID &txnid, txnid_set *conflicts) {
+ const TXNID &txnid, txnid_set *conflicts) {
bool conflicts_exist = false;
const size_t num_overlaps = row_locks.get_size();
for (size_t i = 0; i < num_overlaps; i++) {
@@ -228,23 +218,19 @@ static uint64_t row_lock_size_in_tree(const row_lock &lock) {
// remove and destroy the given row lock from the locked keyrange,
// then notify the memory tracker of the newly freed lock.
static void remove_row_lock_from_tree(concurrent_tree::locked_keyrange *lkr,
- const row_lock &lock, locktree_manager *mgr) {
+ const row_lock &lock, locktree::manager::memory_tracker *mem_tracker) {
const uint64_t mem_released = row_lock_size_in_tree(lock);
lkr->remove(lock.range);
- if (mgr != nullptr) {
- mgr->note_mem_released(mem_released);
- }
+ mem_tracker->note_mem_released(mem_released);
}
// insert a row lock into the locked keyrange, then notify
// the memory tracker of this newly acquired lock.
static void insert_row_lock_into_tree(concurrent_tree::locked_keyrange *lkr,
- const row_lock &lock, locktree_manager *mgr) {
+ const row_lock &lock, locktree::manager::memory_tracker *mem_tracker) {
uint64_t mem_used = row_lock_size_in_tree(lock);
lkr->insert(lock.range, lock.txnid);
- if (mgr != nullptr) {
- mgr->note_mem_used(mem_used);
- }
+ mem_tracker->note_mem_used(mem_used);
}
void locktree::sto_begin(TXNID txnid) {
@@ -261,16 +247,12 @@ void locktree::sto_append(const DBT *left_key, const DBT *right_key) {
buffer_mem = m_sto_buffer.get_num_bytes();
m_sto_buffer.append(left_key, right_key);
delta = m_sto_buffer.get_num_bytes() - buffer_mem;
- if (m_mgr != nullptr) {
- m_mgr->note_mem_used(delta);
- }
+ m_mem_tracker->note_mem_used(delta);
}
void locktree::sto_end(void) {
uint64_t num_bytes = m_sto_buffer.get_num_bytes();
- if (m_mgr != nullptr) {
- m_mgr->note_mem_released(num_bytes);
- }
+ m_mem_tracker->note_mem_released(num_bytes);
m_sto_buffer.destroy();
m_sto_buffer.create();
m_sto_txnid = TXNID_NONE;
@@ -332,9 +314,8 @@ void locktree::sto_migrate_buffer_ranges_to_tree(void *prepared_lkr) {
invariant(!m_rangetree->is_empty());
}
-bool locktree::sto_try_acquire(void *prepared_lkr,
- TXNID txnid,
- const DBT *left_key, const DBT *right_key) {
+bool locktree::sto_try_acquire(void *prepared_lkr, TXNID txnid,
+ const DBT *left_key, const DBT *right_key) {
if (m_rangetree->is_empty() && m_sto_buffer.is_empty() && m_sto_score >= STO_SCORE_THRESHOLD) {
// We can do the optimization because the rangetree is empty, and
// we know its worth trying because the sto score is big enough.
@@ -363,10 +344,8 @@ bool locktree::sto_try_acquire(void *prepared_lkr,
// try to acquire a lock and consolidate it with existing locks if possible
// param: lkr, a prepared locked keyrange
// return: 0 on success, DB_LOCK_NOTGRANTED if conflicting locks exist.
-int locktree::acquire_lock_consolidated(void *prepared_lkr,
- TXNID txnid,
- const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts) {
+int locktree::acquire_lock_consolidated(void *prepared_lkr, TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts) {
int r = 0;
concurrent_tree::locked_keyrange *lkr;
@@ -382,8 +361,8 @@ int locktree::acquire_lock_consolidated(void *prepared_lkr,
size_t num_overlapping_row_locks = overlapping_row_locks.get_size();
// if any overlapping row locks conflict with this request, bail out.
- bool conflicts_exist = determine_conflicting_txnids(overlapping_row_locks,
- txnid, conflicts);
+ bool conflicts_exist = determine_conflicting_txnids(
+ overlapping_row_locks, txnid, conflicts);
if (!conflicts_exist) {
// there are no conflicts, so all of the overlaps are for the requesting txnid.
// so, we must consolidate all existing overlapping ranges and the requested
@@ -392,11 +371,11 @@ int locktree::acquire_lock_consolidated(void *prepared_lkr,
row_lock overlapping_lock = overlapping_row_locks.fetch_unchecked(i);
invariant(overlapping_lock.txnid == txnid);
requested_range.extend(m_cmp, overlapping_lock.range);
- remove_row_lock_from_tree(lkr, overlapping_lock, m_mgr);
+ remove_row_lock_from_tree(lkr, overlapping_lock, m_mem_tracker);
}
row_lock new_lock = { .range = requested_range, .txnid = txnid };
- insert_row_lock_into_tree(lkr, new_lock, m_mgr);
+ insert_row_lock_into_tree(lkr, new_lock, m_mem_tracker);
} else {
r = DB_LOCK_NOTGRANTED;
}
@@ -409,10 +388,8 @@ int locktree::acquire_lock_consolidated(void *prepared_lkr,
// acquire a lock in the given key range, inclusive. if successful,
// return 0. otherwise, populate the conflicts txnid_set with the set of
// transactions that conflict with this request.
-int locktree::acquire_lock(bool is_write_request,
- TXNID txnid,
- const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts) {
+int locktree::acquire_lock(bool is_write_request, TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts) {
int r = 0;
// we are only supporting write locks for simplicity
@@ -433,15 +410,9 @@ int locktree::acquire_lock(bool is_write_request,
return r;
}
-int locktree::try_acquire_lock(bool is_write_request,
- TXNID txnid,
- const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts, bool big_txn) {
- // All ranges in the locktree must have left endpoints <= right endpoints.
- // Range comparisons rely on this fact, so we make a paranoid invariant here.
- paranoid_invariant(m_cmp->compare(left_key, right_key) <= 0);
- int r = m_mgr == nullptr ? 0 :
- m_mgr->check_current_lock_constraints(big_txn);
+int locktree::try_acquire_lock(bool is_write_request, TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts, bool big_txn) {
+ int r = m_mgr->check_current_lock_constraints(big_txn);
if (r == 0) {
r = acquire_lock(is_write_request, txnid, left_key, right_key, conflicts);
}
@@ -449,19 +420,18 @@ int locktree::try_acquire_lock(bool is_write_request,
}
// the locktree silently upgrades read locks to write locks for simplicity
-int locktree::acquire_read_lock(TXNID txnid, const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts, bool big_txn) {
+int locktree::acquire_read_lock(TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts, bool big_txn) {
return acquire_write_lock(txnid, left_key, right_key, conflicts, big_txn);
}
-int locktree::acquire_write_lock(TXNID txnid, const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts, bool big_txn) {
+int locktree::acquire_write_lock(TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts, bool big_txn) {
return try_acquire_lock(true, txnid, left_key, right_key, conflicts, big_txn);
}
-void locktree::get_conflicts(bool is_write_request,
- TXNID txnid, const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts) {
+void locktree::get_conflicts(bool is_write_request, TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts) {
// because we only support write locks, ignore this bit for now.
(void) is_write_request;
@@ -510,8 +480,8 @@ void locktree::get_conflicts(bool is_write_request,
// whole lock [1,3]. Now, someone else can lock 2 before our txn gets
// around to unlocking 2, so we should not remove that lock.
void locktree::remove_overlapping_locks_for_txnid(TXNID txnid,
- const DBT *left_key,
- const DBT *right_key) {
+ const DBT *left_key, const DBT *right_key) {
+
keyrange release_range;
release_range.create(left_key, right_key);
@@ -531,7 +501,7 @@ void locktree::remove_overlapping_locks_for_txnid(TXNID txnid,
// If this isn't our lock, that's ok, just don't remove it.
// See rationale above.
if (lock.txnid == txnid) {
- remove_row_lock_from_tree(&lkr, lock, m_mgr);
+ remove_row_lock_from_tree(&lkr, lock, m_mem_tracker);
}
}
@@ -581,9 +551,6 @@ void locktree::release_locks(TXNID txnid, const range_buffer *ranges) {
while (iter.current(&rec)) {
const DBT *left_key = rec.get_left_key();
const DBT *right_key = rec.get_right_key();
- // All ranges in the locktree must have left endpoints <= right endpoints.
- // Range comparisons rely on this fact, so we make a paranoid invariant here.
- paranoid_invariant(m_cmp->compare(left_key, right_key) <= 0);
remove_overlapping_locks_for_txnid(txnid, left_key, right_key);
iter.next();
}
@@ -601,8 +568,8 @@ void locktree::release_locks(TXNID txnid, const range_buffer *ranges) {
// row locks, storing each one into the given array of size N,
// then removing each extracted lock from the locked keyrange.
static int extract_first_n_row_locks(concurrent_tree::locked_keyrange *lkr,
- locktree_manager *mgr,
- row_lock *row_locks, int num_to_extract) {
+ locktree::manager::memory_tracker *mem_tracker,
+ row_lock *row_locks, int num_to_extract) {
struct extract_fn_obj {
int num_extracted;
@@ -633,7 +600,7 @@ static int extract_first_n_row_locks(concurrent_tree::locked_keyrange *lkr,
int num_extracted = extract_fn.num_extracted;
invariant(num_extracted <= num_to_extract);
for (int i = 0; i < num_extracted; i++) {
- remove_row_lock_from_tree(lkr, row_locks[i], mgr);
+ remove_row_lock_from_tree(lkr, row_locks[i], mem_tracker);
}
return num_extracted;
@@ -665,7 +632,7 @@ struct txnid_range_buffer {
// approach works well. if there are many txnids and each
// has locks in a random/alternating order, then this does
// not work so well.
-void locktree::escalate(lt_escalate_cb after_escalate_callback, void *after_escalate_callback_extra) {
+void locktree::escalate(manager::lt_escalate_cb after_escalate_callback, void *after_escalate_callback_extra) {
omt<struct txnid_range_buffer, struct txnid_range_buffer *> range_buffers;
range_buffers.create();
@@ -691,9 +658,8 @@ void locktree::escalate(lt_escalate_cb after_escalate_callback, void *after_esca
// we always remove the "first" n because we are removing n
// each time we do an extraction. so this loops until its empty.
- while ((num_extracted =
- extract_first_n_row_locks(&lkr, m_mgr, extracted_buf,
- num_row_locks_per_batch)) > 0) {
+ while ((num_extracted = extract_first_n_row_locks(&lkr, m_mem_tracker,
+ extracted_buf, num_row_locks_per_batch)) > 0) {
int current_index = 0;
while (current_index < num_extracted) {
// every batch of extracted locks is in range-sorted order. search
@@ -761,7 +727,7 @@ void locktree::escalate(lt_escalate_cb after_escalate_callback, void *after_esca
keyrange range;
range.create(rec.get_left_key(), rec.get_right_key());
row_lock lock = { .range = range, .txnid = current_txnid };
- insert_row_lock_into_tree(&lkr, lock, m_mgr);
+ insert_row_lock_into_tree(&lkr, lock, m_mem_tracker);
iter.next();
}
@@ -776,7 +742,7 @@ void locktree::escalate(lt_escalate_cb after_escalate_callback, void *after_esca
lkr.release();
}
-void *locktree::get_userdata(void) const {
+void *locktree::get_userdata(void) {
return m_userdata;
}
@@ -784,7 +750,7 @@ void locktree::set_userdata(void *userdata) {
m_userdata = userdata;
}
-struct lt_lock_request_info *locktree::get_lock_request_info(void) {
+struct locktree::lt_lock_request_info *locktree::get_lock_request_info(void) {
return &m_lock_request_info;
}
@@ -792,11 +758,11 @@ void locktree::set_descriptor(DESCRIPTOR desc) {
m_cmp->set_descriptor(desc);
}
-locktree_manager *locktree::get_manager(void) const {
- return m_mgr;
+locktree::manager::memory_tracker *locktree::get_mem_tracker(void) const {
+ return m_mem_tracker;
}
-int locktree::compare(const locktree *lt) const {
+int locktree::compare(const locktree *lt) {
if (m_dict_id.dictid < lt->m_dict_id.dictid) {
return -1;
} else if (m_dict_id.dictid == lt->m_dict_id.dictid) {
diff --git a/storage/tokudb/ft-index/locktree/locktree.h b/storage/tokudb/ft-index/locktree/locktree.h
index 2f8dcef6668..a3c3b566fcf 100644
--- a/storage/tokudb/ft-index/locktree/locktree.h
+++ b/storage/tokudb/ft-index/locktree/locktree.h
@@ -89,7 +89,8 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-#pragma once
+#ifndef TOKU_LOCKTREE_H
+#define TOKU_LOCKTREE_H
#include <db.h>
#include <toku_time.h>
@@ -104,6 +105,11 @@ PATENT RIGHTS GRANT:
#include "wfg.h"
#include "range_buffer.h"
+#define TOKU_LOCKTREE_ESCALATOR_LAMBDA 0
+#if TOKU_LOCKTREE_ESCALATOR_LAMBDA
+#include <functional>
+#endif
+
enum {
LTM_SIZE_CURRENT = 0,
LTM_SIZE_LIMIT,
@@ -134,31 +140,70 @@ typedef struct {
namespace toku {
- class locktree;
- class locktree_manager;
- class lock_request;
- class memory_tracker;
- class concurrent_tree;
-
- typedef int (*lt_create_cb)(locktree *lt, void *extra);
- typedef void (*lt_destroy_cb)(locktree *lt);
- typedef void (*lt_escalate_cb)(TXNID txnid, const locktree *lt, const range_buffer &buffer, void *extra);
+class lock_request;
+class concurrent_tree;
+
+// A locktree represents the set of row locks owned by all transactions
+// over an open dictionary. Read and write ranges are represented as
+// a left and right key which are compared with the given descriptor
+// and comparison fn.
+//
+// Locktrees are not created and destroyed by the user. Instead, they are
+// referenced and released using the locktree manager.
+//
+// A sample workflow looks like this:
+// - Create a manager.
+// - Get a locktree by dictionaroy id from the manager.
+// - Perform read/write lock acquision on the locktree, add references to
+// the locktree using the manager, release locks, release references, etc.
+// - ...
+// - Release the final reference to the locktree. It will be destroyed.
+// - Destroy the manager.
+
+class locktree {
+public:
+
+ // effect: Attempts to grant a read lock for the range of keys between [left_key, right_key].
+ // returns: If the lock cannot be granted, return DB_LOCK_NOTGRANTED, and populate the
+ // given conflicts set with the txnids that hold conflicting locks in the range.
+ // If the locktree cannot create more locks, return TOKUDB_OUT_OF_LOCKS.
+ // note: Read locks cannot be shared between txnids, as one would expect.
+ // This is for simplicity since read locks are rare in MySQL.
+ int acquire_read_lock(TXNID txnid, const DBT *left_key, const DBT *right_key, txnid_set *conflicts, bool big_txn);
+
+ // effect: Attempts to grant a write lock for the range of keys between [left_key, right_key].
+ // returns: If the lock cannot be granted, return DB_LOCK_NOTGRANTED, and populate the
+ // given conflicts set with the txnids that hold conflicting locks in the range.
+ // If the locktree cannot create more locks, return TOKUDB_OUT_OF_LOCKS.
+ int acquire_write_lock(TXNID txnid, const DBT *left_key, const DBT *right_key, txnid_set *conflicts, bool big_txn);
+
+ // effect: populate the conflicts set with the txnids that would preventing
+ // the given txnid from getting a lock on [left_key, right_key]
+ void get_conflicts(bool is_write_request, TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts);
+
+ // effect: Release all of the lock ranges represented by the range buffer for a txnid.
+ void release_locks(TXNID txnid, const range_buffer *ranges);
+
+ // returns: The userdata associated with this locktree, or null if it has not been set.
+ void *get_userdata(void);
+
+ void set_userdata(void *userdata);
+
+ void set_descriptor(DESCRIPTOR desc);
+
+ int compare(const locktree *lt);
+
+ DICTIONARY_ID get_dict_id() const;
struct lt_counters {
uint64_t wait_count, wait_time;
uint64_t long_wait_count, long_wait_time;
uint64_t timeout_count;
-
- void add(const lt_counters &rhs) {
- wait_count += rhs.wait_count;
- wait_time += rhs.wait_time;
- long_wait_count += rhs.long_wait_count;
- long_wait_time += rhs.long_wait_time;
- timeout_count += rhs.timeout_count;
- }
};
- // Lock request state for some locktree
+ // The locktree stores some data for lock requests. It doesn't have to know
+ // how they work or even what a lock request object looks like.
struct lt_lock_request_info {
omt<lock_request *> pending_lock_requests;
toku_mutex_t mutex;
@@ -166,15 +211,46 @@ namespace toku {
lt_counters counters;
};
- // The locktree manager manages a set of locktrees, one for each open dictionary.
- // Locktrees are retrieved from the manager. When they are no longer needed, they
- // are be released by the user.
- class locktree_manager {
+ // Private info struct for storing pending lock request state.
+ // Only to be used by lock requests. We store it here as
+ // something less opaque than usual to strike a tradeoff between
+ // abstraction and code complexity. It is still fairly abstract
+ // since the lock_request object is opaque
+ struct lt_lock_request_info *get_lock_request_info(void);
+
+ class manager;
+
+ // the escalator coordinates escalation on a set of locktrees for a bunch of threads
+ class escalator {
+ public:
+ void create(void);
+ void destroy(void);
+#if TOKU_LOCKTREE_ESCALATOR_LAMBDA
+ void run(manager *mgr, std::function<void (void)> escalate_locktrees_fun);
+#else
+ void run(manager *mgr, void (*escalate_locktrees_fun)(void *extra), void *extra);
+#endif
+ private:
+ toku_mutex_t m_escalator_mutex;
+ toku_cond_t m_escalator_done;
+ bool m_escalator_running;
+ };
+ ENSURE_POD(escalator);
+
+ // The locktree manager manages a set of locktrees,
+ // one for each open dictionary. Locktrees are accessed through
+ // the manager, and when they are no longer needed, they can
+ // be released by the user.
+
+ class manager {
public:
- // param: create_cb, called just after a locktree is first created.
- // destroy_cb, called just before a locktree is destroyed.
- // escalate_cb, called after a locktree is escalated (with extra param)
- void create(lt_create_cb create_cb, lt_destroy_cb destroy_cb, lt_escalate_cb escalate_cb, void *extra);
+ typedef int (*lt_create_cb)(locktree *lt, void *extra);
+ typedef void (*lt_destroy_cb)(locktree *lt);
+ typedef void (*lt_escalate_cb)(TXNID txnid, const locktree *lt, const range_buffer &buffer, void *extra);
+
+ // note: create_cb is called just after a locktree is first created.
+ // destroy_cb is called just before a locktree is destroyed.
+ void create(lt_create_cb create_cb, lt_destroy_cb destroy_cb, lt_escalate_cb, void *extra);
void destroy(void);
@@ -185,9 +261,10 @@ namespace toku {
// effect: Get a locktree from the manager. If a locktree exists with the given
// dict_id, it is referenced and then returned. If one did not exist, it
// is created. It will use the given descriptor and comparison function
- // for comparing keys, and the on_create callback passed to locktree_manager::create()
+ // for comparing keys, and the on_create callback passed to manager::create()
// will be called with the given extra parameter.
- locktree *get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc, ft_compare_func cmp, void *on_create_extra);
+ locktree *get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc, ft_compare_func cmp,
+ void *on_create_extra);
void reference_lt(locktree *lt);
@@ -195,6 +272,54 @@ namespace toku {
// to zero, the on_destroy callback is called before it gets destroyed.
void release_lt(locktree *lt);
+ // The memory tracker is employed by the manager to take care of
+ // maintaining the current number of locks and lock memory and run
+ // escalation if necessary.
+ //
+ // To do this, the manager hands out a memory tracker reference to each
+ // locktree it creates, so that the locktrees can notify the memory
+ // tracker when locks are acquired and released.
+
+ class memory_tracker {
+ public:
+ void set_manager(manager *mgr);
+ manager *get_manager(void);
+
+ // effect: Determines if too many locks or too much memory is being used,
+ // Runs escalation on the manager if so.
+ // returns: 0 if there enough resources to create a new lock, or TOKUDB_OUT_OF_LOCKS
+ // if there are not enough resources and lock escalation failed to free up
+ // enough resources for a new lock.
+ int check_current_lock_constraints(void);
+
+ bool over_big_threshold(void);
+
+ void note_mem_used(uint64_t mem_used);
+
+ void note_mem_released(uint64_t mem_freed);
+
+ private:
+ manager *m_mgr;
+
+ // returns: true if the manager of this memory tracker currently
+ // has more locks or lock memory than it is allowed.
+ // note: this is a lock-less read, and it is ok for the caller to
+ // get false when they should have gotten true as long as
+ // a subsequent call gives the correct answer.
+ //
+ // in general, if the tracker says the manager is not out of
+ // locks, you are clear to add O(1) locks to the system.
+ bool out_of_locks(void) const;
+ };
+ ENSURE_POD(memory_tracker);
+
+ // effect: calls the private function run_escalation(), only ok to
+ // do for tests.
+ // rationale: to get better stress test coverage, we want a way to
+ // deterministicly trigger lock escalation.
+ void run_escalation_for_test(void);
+ void run_escalation(void);
+
void get_status(LTM_STATUS status);
// effect: calls the iterate function on each pending lock request
@@ -208,21 +333,10 @@ namespace toku {
void *extra);
int iterate_pending_lock_requests(lock_request_iterate_callback cb, void *extra);
- // effect: Determines if too many locks or too much memory is being used,
- // Runs escalation on the manager if so.
- // param: big_txn, if the current transaction is 'big' (has spilled rollback logs)
- // returns: 0 if there enough resources to create a new lock, or TOKUDB_OUT_OF_LOCKS
- // if there are not enough resources and lock escalation failed to free up
- // enough resources for a new lock.
int check_current_lock_constraints(bool big_txn);
- bool over_big_threshold(void);
-
- void note_mem_used(uint64_t mem_used);
-
- void note_mem_released(uint64_t mem_freed);
-
- bool out_of_locks(void) const;
+ // Escalate locktrees touched by a txn
+ void escalate_lock_trees_for_txn(TXNID, locktree *lt);
// Escalate all locktrees
void escalate_all_locktrees(void);
@@ -230,13 +344,6 @@ namespace toku {
// Escalate a set of locktrees
void escalate_locktrees(locktree **locktrees, int num_locktrees);
- // effect: calls the private function run_escalation(), only ok to
- // do for tests.
- // rationale: to get better stress test coverage, we want a way to
- // deterministicly trigger lock escalation.
- void run_escalation_for_test(void);
- void run_escalation(void);
-
// Add time t to the escalator's wait time statistics
void add_escalator_wait_time(uint64_t t);
@@ -246,7 +353,7 @@ namespace toku {
// tracks the current number of locks and lock memory
uint64_t m_max_lock_memory;
uint64_t m_current_lock_memory;
- memory_tracker *m_mem_tracker;
+ memory_tracker m_mem_tracker;
struct lt_counters m_lt_counters;
@@ -269,14 +376,22 @@ namespace toku {
void status_init(void);
- // Manage the set of open locktrees
+ // effect: Gets a locktree from the map.
+ // requires: Manager's mutex is held
locktree *locktree_map_find(const DICTIONARY_ID &dict_id);
+
+ // effect: Puts a locktree into the map.
+ // requires: Manager's mutex is held
void locktree_map_put(locktree *lt);
+
+ // effect: Removes a locktree from the map.
+ // requires: Manager's mutex is held
void locktree_map_remove(locktree *lt);
static int find_by_dict_id(locktree *const &lt, const DICTIONARY_ID &dict_id);
void escalator_init(void);
+
void escalator_destroy(void);
// statistics about lock escalation.
@@ -289,295 +404,214 @@ namespace toku {
uint64_t m_long_wait_escalation_count;
uint64_t m_long_wait_escalation_time;
- // the escalator coordinates escalation on a set of locktrees for a bunch of threads
- class locktree_escalator {
- public:
- void create(void);
- void destroy(void);
- void run(locktree_manager *mgr, void (*escalate_locktrees_fun)(void *extra), void *extra);
-
- private:
- toku_mutex_t m_escalator_mutex;
- toku_cond_t m_escalator_done;
- bool m_escalator_running;
- };
-
- locktree_escalator m_escalator;
+ escalator m_escalator;
friend class manager_unit_test;
};
+ ENSURE_POD(manager);
- // A locktree represents the set of row locks owned by all transactions
- // over an open dictionary. Read and write ranges are represented as
- // a left and right key which are compared with the given descriptor
- // and comparison fn.
- //
- // Locktrees are not created and destroyed by the user. Instead, they are
- // referenced and released using the locktree manager.
- //
- // A sample workflow looks like this:
- // - Create a manager.
- // - Get a locktree by dictionaroy id from the manager.
- // - Perform read/write lock acquision on the locktree, add references to
- // the locktree using the manager, release locks, release references, etc.
- // - ...
- // - Release the final reference to the locktree. It will be destroyed.
- // - Destroy the manager.
- class locktree {
- public:
- // effect: Creates a locktree that uses the given memory tracker
- // to report memory usage and honor memory constraints.
- void create(locktree_manager *mgr, DICTIONARY_ID dict_id,
- DESCRIPTOR desc, ft_compare_func cmp);
-
- void destroy(void);
-
- // For thread-safe, external reference counting
- void add_reference(void);
-
- // requires: the reference count is > 0
- // returns: the reference count, after decrementing it by one
- uint32_t release_reference(void);
-
- // returns: the current reference count
- uint32_t get_reference_count(void);
-
- // effect: Attempts to grant a read lock for the range of keys between [left_key, right_key].
- // returns: If the lock cannot be granted, return DB_LOCK_NOTGRANTED, and populate the
- // given conflicts set with the txnids that hold conflicting locks in the range.
- // If the locktree cannot create more locks, return TOKUDB_OUT_OF_LOCKS.
- // note: Read locks cannot be shared between txnids, as one would expect.
- // This is for simplicity since read locks are rare in MySQL.
- int acquire_read_lock(TXNID txnid, const DBT *left_key, const DBT *right_key, txnid_set *conflicts, bool big_txn);
-
- // effect: Attempts to grant a write lock for the range of keys between [left_key, right_key].
- // returns: If the lock cannot be granted, return DB_LOCK_NOTGRANTED, and populate the
- // given conflicts set with the txnids that hold conflicting locks in the range.
- // If the locktree cannot create more locks, return TOKUDB_OUT_OF_LOCKS.
- int acquire_write_lock(TXNID txnid, const DBT *left_key, const DBT *right_key, txnid_set *conflicts, bool big_txn);
+ manager::memory_tracker *get_mem_tracker(void) const;
- // effect: populate the conflicts set with the txnids that would preventing
- // the given txnid from getting a lock on [left_key, right_key]
- void get_conflicts(bool is_write_request, TXNID txnid,
- const DBT *left_key, const DBT *right_key, txnid_set *conflicts);
+private:
+ manager *m_mgr;
+ manager::memory_tracker *m_mem_tracker;
- // effect: Release all of the lock ranges represented by the range buffer for a txnid.
- void release_locks(TXNID txnid, const range_buffer *ranges);
+ DICTIONARY_ID m_dict_id;
- // effect: Runs escalation on this locktree
- void escalate(lt_escalate_cb after_escalate_callback, void *extra);
-
- // returns: The userdata associated with this locktree, or null if it has not been set.
- void *get_userdata(void) const;
-
- void set_userdata(void *userdata);
-
- locktree_manager *get_manager(void) const;
-
- void set_descriptor(DESCRIPTOR desc);
+ // use a comparator object that encapsulates an ft compare
+ // function and a descriptor in a fake db. this way we can
+ // pass it around for easy key comparisons.
+ //
+ // since this comparator will store a pointer to a descriptor,
+ // the user of the locktree needs to make sure that the descriptor
+ // is valid for as long as the locktree. this is currently
+ // implemented by opening an ft_handle for this locktree and
+ // storing it as userdata below.
+ comparator *m_cmp;
- int compare(const locktree *lt) const;
+ uint32_t m_reference_count;
- DICTIONARY_ID get_dict_id() const;
+ concurrent_tree *m_rangetree;
- // Private info struct for storing pending lock request state.
- // Only to be used by lock requests. We store it here as
- // something less opaque than usual to strike a tradeoff between
- // abstraction and code complexity. It is still fairly abstract
- // since the lock_request object is opaque
- struct lt_lock_request_info *get_lock_request_info(void);
+ void *m_userdata;
- private:
- locktree_manager *m_mgr;
- DICTIONARY_ID m_dict_id;
- uint32_t m_reference_count;
-
- // use a comparator object that encapsulates an ft compare
- // function and a descriptor in a fake db. this way we can
- // pass it around for easy key comparisons.
- //
- // since this comparator will store a pointer to a descriptor,
- // the user of the locktree needs to make sure that the descriptor
- // is valid for as long as the locktree. this is currently
- // implemented by opening an ft_handle for this locktree and
- // storing it as userdata below.
- comparator *m_cmp;
-
- concurrent_tree *m_rangetree;
-
- void *m_userdata;
- struct lt_lock_request_info m_lock_request_info;
-
- // The following fields and members prefixed with "sto_" are for
- // the single txnid optimization, intended to speed up the case
- // when only one transaction is using the locktree. If we know
- // the locktree has only one transaction, then acquiring locks
- // takes O(1) work and releasing all locks takes O(1) work.
- //
- // How do we know that the locktree only has a single txnid?
- // What do we do if it does?
- //
- // When a txn with txnid T requests a lock:
- // - If the tree is empty, the optimization is possible. Set the single
- // txnid to T, and insert the lock range into the buffer.
- // - If the tree is not empty, check if the single txnid is T. If so,
- // append the lock range to the buffer. Otherwise, migrate all of
- // the locks in the buffer into the rangetree on behalf of txnid T,
- // and invalid the single txnid.
- //
- // When a txn with txnid T releases its locks:
- // - If the single txnid is valid, it must be for T. Destroy the buffer.
- // - If it's not valid, release locks the normal way in the rangetree.
- //
- // To carry out the optimization we need to record a single txnid
- // and a range buffer for each locktree, each protected by the root
- // lock of the locktree's rangetree. The root lock for a rangetree
- // is grabbed by preparing a locked keyrange on the rangetree.
- TXNID m_sto_txnid;
- range_buffer m_sto_buffer;
-
- // The single txnid optimization speeds up the case when only one
- // transaction is using the locktree. But it has the potential to
- // hurt the case when more than one txnid exists.
- //
- // There are two things we need to do to make the optimization only
- // optimize the case we care about, and not hurt the general case.
- //
- // Bound the worst-case latency for lock migration when the
- // optimization stops working:
- // - Idea: Stop the optimization and migrate immediate if we notice
- // the single txnid has takes many locks in the range buffer.
- // - Implementation: Enforce a max size on the single txnid range buffer.
- // - Analysis: Choosing the perfect max value, M, is difficult to do
- // without some feedback from the field. Intuition tells us that M should
- // not be so small that the optimization is worthless, and it should not
- // be so big that it's unreasonable to have to wait behind a thread doing
- // the work of converting M buffer locks into rangetree locks.
- //
- // Prevent concurrent-transaction workloads from trying the optimization
- // in vain:
- // - Idea: Don't even bother trying the optimization if we think the
- // system is in a concurrent-transaction state.
- // - Implementation: Do something even simpler than detecting whether the
- // system is in a concurent-transaction state. Just keep a "score" value
- // and some threshold. If at any time the locktree is eligible for the
- // optimization, only do it if the score is at this threshold. When you
- // actually do the optimization but someone has to migrate locks in the buffer
- // (expensive), then reset the score back to zero. Each time a txn
- // releases locks, the score is incremented by 1.
- // - Analysis: If you let the threshold be "C", then at most 1 / C txns will
- // do the optimization in a concurrent-transaction system. Similarly, it
- // takes at most C txns to start using the single txnid optimzation, which
- // is good when the system transitions from multithreaded to single threaded.
- //
- // STO_BUFFER_MAX_SIZE:
- //
- // We choose the max value to be 1 million since most transactions are smaller
- // than 1 million and we can create a rangetree of 1 million elements in
- // less than a second. So we can be pretty confident that this threshold
- // enables the optimization almost always, and prevents super pathological
- // latency issues for the first lock taken by a second thread.
- //
- // STO_SCORE_THRESHOLD:
- //
- // A simple first guess at a good value for the score threshold is 100.
- // By our analysis, we'd end up doing the optimization in vain for
- // around 1% of all transactions, which seems reasonable. Further,
- // if the system goes single threaded, it ought to be pretty quick
- // for 100 transactions to go by, so we won't have to wait long before
- // we start doing the single txind optimzation again.
- static const int STO_BUFFER_MAX_SIZE = 50 * 1024;
- static const int STO_SCORE_THRESHOLD = 100;
- int m_sto_score;
-
- // statistics about time spent ending the STO early
- uint64_t m_sto_end_early_count;
- tokutime_t m_sto_end_early_time;
-
- // effect: begins the single txnid optimizaiton, setting m_sto_txnid
- // to the given txnid.
- // requires: m_sto_txnid is invalid
- void sto_begin(TXNID txnid);
-
- // effect: append a range to the sto buffer
- // requires: m_sto_txnid is valid
- void sto_append(const DBT *left_key, const DBT *right_key);
-
- // effect: ends the single txnid optimization, releaseing any memory
- // stored in the sto buffer, notifying the tracker, and
- // invalidating m_sto_txnid.
- // requires: m_sto_txnid is valid
- void sto_end(void);
-
- // params: prepared_lkr is a void * to a prepared locked keyrange. see below.
- // effect: ends the single txnid optimization early, migrating buffer locks
- // into the rangetree, calling sto_end(), and then setting the
- // sto_score back to zero.
- // requires: m_sto_txnid is valid
- void sto_end_early(void *prepared_lkr);
- void sto_end_early_no_accounting(void *prepared_lkr);
-
- // params: prepared_lkr is a void * to a prepared locked keyrange. we can't use
- // the real type because the compiler won't allow us to forward declare
- // concurrent_tree::locked_keyrange without including concurrent_tree.h,
- // which we cannot do here because it is a template implementation.
- // requires: the prepared locked keyrange is for the locktree's rangetree
- // requires: m_sto_txnid is valid
- // effect: migrates each lock in the single txnid buffer into the locktree's
- // rangetree, notifying the memory tracker as necessary.
- void sto_migrate_buffer_ranges_to_tree(void *prepared_lkr);
-
- // effect: If m_sto_txnid is valid, then release the txnid's locks
- // by ending the optimization.
- // requires: If m_sto_txnid is valid, it is equal to the given txnid
- // returns: True if locks were released for this txnid
- bool sto_try_release(TXNID txnid);
-
- // params: prepared_lkr is a void * to a prepared locked keyrange. see above.
- // requires: the prepared locked keyrange is for the locktree's rangetree
- // effect: If m_sto_txnid is valid and equal to the given txnid, then
- // append a range onto the buffer. Otherwise, if m_sto_txnid is valid
- // but not equal to this txnid, then migrate the buffer's locks
- // into the rangetree and end the optimization, setting the score
- // back to zero.
- // returns: true if the lock was acquired for this txnid
- bool sto_try_acquire(void *prepared_lkr, TXNID txnid,
- const DBT *left_key, const DBT *right_key);
-
- // Effect:
- // Provides a hook for a helgrind suppression.
- // Returns:
- // true if m_sto_txnid is not TXNID_NONE
- bool sto_txnid_is_valid_unsafe(void) const;
-
- // Effect:
- // Provides a hook for a helgrind suppression.
- // Returns:
- // m_sto_score
- int sto_get_score_unsafe(void )const;
-
- void remove_overlapping_locks_for_txnid(TXNID txnid,
- const DBT *left_key, const DBT *right_key);
-
- int acquire_lock_consolidated(void *prepared_lkr, TXNID txnid,
- const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts);
-
- int acquire_lock(bool is_write_request, TXNID txnid,
- const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts);
-
- int try_acquire_lock(bool is_write_request, TXNID txnid,
- const DBT *left_key, const DBT *right_key,
- txnid_set *conflicts, bool big_txn);
-
-
- friend class locktree_unit_test;
- friend class manager_unit_test;
- friend class lock_request_unit_test;
+ struct lt_lock_request_info m_lock_request_info;
- // engine status reaches into the locktree to read some stats
- friend void locktree_manager::get_status(LTM_STATUS status);
- };
+ // The following fields and members prefixed with "sto_" are for
+ // the single txnid optimization, intended to speed up the case
+ // when only one transaction is using the locktree. If we know
+ // the locktree has only one transaction, then acquiring locks
+ // takes O(1) work and releasing all locks takes O(1) work.
+ //
+ // How do we know that the locktree only has a single txnid?
+ // What do we do if it does?
+ //
+ // When a txn with txnid T requests a lock:
+ // - If the tree is empty, the optimization is possible. Set the single
+ // txnid to T, and insert the lock range into the buffer.
+ // - If the tree is not empty, check if the single txnid is T. If so,
+ // append the lock range to the buffer. Otherwise, migrate all of
+ // the locks in the buffer into the rangetree on behalf of txnid T,
+ // and invalid the single txnid.
+ //
+ // When a txn with txnid T releases its locks:
+ // - If the single txnid is valid, it must be for T. Destroy the buffer.
+ // - If it's not valid, release locks the normal way in the rangetree.
+ //
+ // To carry out the optimization we need to record a single txnid
+ // and a range buffer for each locktree, each protected by the root
+ // lock of the locktree's rangetree. The root lock for a rangetree
+ // is grabbed by preparing a locked keyrange on the rangetree.
+ TXNID m_sto_txnid;
+ range_buffer m_sto_buffer;
+
+ // The single txnid optimization speeds up the case when only one
+ // transaction is using the locktree. But it has the potential to
+ // hurt the case when more than one txnid exists.
+ //
+ // There are two things we need to do to make the optimization only
+ // optimize the case we care about, and not hurt the general case.
+ //
+ // Bound the worst-case latency for lock migration when the
+ // optimization stops working:
+ // - Idea: Stop the optimization and migrate immediate if we notice
+ // the single txnid has takes many locks in the range buffer.
+ // - Implementation: Enforce a max size on the single txnid range buffer.
+ // - Analysis: Choosing the perfect max value, M, is difficult to do
+ // without some feedback from the field. Intuition tells us that M should
+ // not be so small that the optimization is worthless, and it should not
+ // be so big that it's unreasonable to have to wait behind a thread doing
+ // the work of converting M buffer locks into rangetree locks.
+ //
+ // Prevent concurrent-transaction workloads from trying the optimization
+ // in vain:
+ // - Idea: Don't even bother trying the optimization if we think the
+ // system is in a concurrent-transaction state.
+ // - Implementation: Do something even simpler than detecting whether the
+ // system is in a concurent-transaction state. Just keep a "score" value
+ // and some threshold. If at any time the locktree is eligible for the
+ // optimization, only do it if the score is at this threshold. When you
+ // actually do the optimization but someone has to migrate locks in the buffer
+ // (expensive), then reset the score back to zero. Each time a txn
+ // releases locks, the score is incremented by 1.
+ // - Analysis: If you let the threshold be "C", then at most 1 / C txns will
+ // do the optimization in a concurrent-transaction system. Similarly, it
+ // takes at most C txns to start using the single txnid optimzation, which
+ // is good when the system transitions from multithreaded to single threaded.
+ //
+ // STO_BUFFER_MAX_SIZE:
+ //
+ // We choose the max value to be 1 million since most transactions are smaller
+ // than 1 million and we can create a rangetree of 1 million elements in
+ // less than a second. So we can be pretty confident that this threshold
+ // enables the optimization almost always, and prevents super pathological
+ // latency issues for the first lock taken by a second thread.
+ //
+ // STO_SCORE_THRESHOLD:
+ //
+ // A simple first guess at a good value for the score threshold is 100.
+ // By our analysis, we'd end up doing the optimization in vain for
+ // around 1% of all transactions, which seems reasonable. Further,
+ // if the system goes single threaded, it ought to be pretty quick
+ // for 100 transactions to go by, so we won't have to wait long before
+ // we start doing the single txind optimzation again.
+ static const int STO_BUFFER_MAX_SIZE = 50 * 1024;
+ static const int STO_SCORE_THRESHOLD = 100;
+ int m_sto_score;
+
+ // statistics about time spent ending the STO early
+ uint64_t m_sto_end_early_count;
+ tokutime_t m_sto_end_early_time;
+
+ // effect: begins the single txnid optimizaiton, setting m_sto_txnid
+ // to the given txnid.
+ // requires: m_sto_txnid is invalid
+ void sto_begin(TXNID txnid);
+
+ // effect: append a range to the sto buffer
+ // requires: m_sto_txnid is valid
+ void sto_append(const DBT *left_key, const DBT *right_key);
+
+ // effect: ends the single txnid optimization, releaseing any memory
+ // stored in the sto buffer, notifying the tracker, and
+ // invalidating m_sto_txnid.
+ // requires: m_sto_txnid is valid
+ void sto_end(void);
+
+ // params: prepared_lkr is a void * to a prepared locked keyrange. see below.
+ // effect: ends the single txnid optimization early, migrating buffer locks
+ // into the rangetree, calling sto_end(), and then setting the
+ // sto_score back to zero.
+ // requires: m_sto_txnid is valid
+ void sto_end_early(void *prepared_lkr);
+ void sto_end_early_no_accounting(void *prepared_lkr);
+
+ // params: prepared_lkr is a void * to a prepared locked keyrange. we can't use
+ // the real type because the compiler won't allow us to forward declare
+ // concurrent_tree::locked_keyrange without including concurrent_tree.h,
+ // which we cannot do here because it is a template implementation.
+ // requires: the prepared locked keyrange is for the locktree's rangetree
+ // requires: m_sto_txnid is valid
+ // effect: migrates each lock in the single txnid buffer into the locktree's
+ // rangetree, notifying the memory tracker as necessary.
+ void sto_migrate_buffer_ranges_to_tree(void *prepared_lkr);
+
+ // effect: If m_sto_txnid is valid, then release the txnid's locks
+ // by ending the optimization.
+ // requires: If m_sto_txnid is valid, it is equal to the given txnid
+ // returns: True if locks were released for this txnid
+ bool sto_try_release(TXNID txnid);
+
+ // params: prepared_lkr is a void * to a prepared locked keyrange. see above.
+ // requires: the prepared locked keyrange is for the locktree's rangetree
+ // effect: If m_sto_txnid is valid and equal to the given txnid, then
+ // append a range onto the buffer. Otherwise, if m_sto_txnid is valid
+ // but not equal to this txnid, then migrate the buffer's locks
+ // into the rangetree and end the optimization, setting the score
+ // back to zero.
+ // returns: true if the lock was acquired for this txnid
+ bool sto_try_acquire(void *prepared_lkr, TXNID txnid,
+ const DBT *left_key, const DBT *right_key);
+
+ // Effect:
+ // Provides a hook for a helgrind suppression.
+ // Returns:
+ // true if m_sto_txnid is not TXNID_NONE
+ bool sto_txnid_is_valid_unsafe(void) const;
+
+ // Effect:
+ // Provides a hook for a helgrind suppression.
+ // Returns:
+ // m_sto_score
+ int sto_get_score_unsafe(void )const;
+
+ // effect: Creates a locktree that uses the given memory tracker
+ // to report memory usage and honor memory constraints.
+ void create(manager::memory_tracker *mem_tracker, DICTIONARY_ID dict_id,
+ DESCRIPTOR desc, ft_compare_func cmp);
+
+ void destroy(void);
+
+ void remove_overlapping_locks_for_txnid(TXNID txnid,
+ const DBT *left_key, const DBT *right_key);
+
+ int acquire_lock_consolidated(void *prepared_lkr, TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts);
+
+ int acquire_lock(bool is_write_request, TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts);
+
+ int try_acquire_lock(bool is_write_request, TXNID txnid,
+ const DBT *left_key, const DBT *right_key, txnid_set *conflicts, bool big_txn);
+
+ void escalate(manager::lt_escalate_cb after_escalate_callback, void *extra);
+
+ friend class locktree_unit_test;
+ friend class manager_unit_test;
+ friend class lock_request_unit_test;
+};
+ENSURE_POD(locktree);
} /* namespace toku */
+
+#endif /* TOKU_LOCKTREE_H */
diff --git a/storage/tokudb/ft-index/locktree/manager.cc b/storage/tokudb/ft-index/locktree/manager.cc
index b1bc5da2fe9..8a70144e9e4 100644
--- a/storage/tokudb/ft-index/locktree/manager.cc
+++ b/storage/tokudb/ft-index/locktree/manager.cc
@@ -100,9 +100,10 @@ PATENT RIGHTS GRANT:
namespace toku {
-void locktree_manager::create(lt_create_cb create_cb, lt_destroy_cb destroy_cb, lt_escalate_cb escalate_cb, void *escalate_extra) {
+void locktree::manager::create(lt_create_cb create_cb, lt_destroy_cb destroy_cb, lt_escalate_cb escalate_cb, void *escalate_extra) {
m_max_lock_memory = DEFAULT_MAX_LOCK_MEMORY;
m_current_lock_memory = 0;
+ m_mem_tracker.set_manager(this);
m_locktree_map.create();
m_lt_create_callback = create_cb;
@@ -119,7 +120,7 @@ void locktree_manager::create(lt_create_cb create_cb, lt_destroy_cb destroy_cb,
escalator_init();
}
-void locktree_manager::destroy(void) {
+void locktree::manager::destroy(void) {
escalator_destroy();
invariant(m_current_lock_memory == 0);
invariant(m_locktree_map.size() == 0);
@@ -127,19 +128,19 @@ void locktree_manager::destroy(void) {
toku_mutex_destroy(&m_mutex);
}
-void locktree_manager::mutex_lock(void) {
+void locktree::manager::mutex_lock(void) {
toku_mutex_lock(&m_mutex);
}
-void locktree_manager::mutex_unlock(void) {
+void locktree::manager::mutex_unlock(void) {
toku_mutex_unlock(&m_mutex);
}
-size_t locktree_manager::get_max_lock_memory(void) {
+size_t locktree::manager::get_max_lock_memory(void) {
return m_max_lock_memory;
}
-int locktree_manager::set_max_lock_memory(size_t max_lock_memory) {
+int locktree::manager::set_max_lock_memory(size_t max_lock_memory) {
int r = 0;
mutex_lock();
if (max_lock_memory < m_current_lock_memory) {
@@ -151,39 +152,39 @@ int locktree_manager::set_max_lock_memory(size_t max_lock_memory) {
return r;
}
-int locktree_manager::find_by_dict_id(locktree *const &lt, const DICTIONARY_ID &dict_id) {
- if (lt->get_dict_id().dictid < dict_id.dictid) {
+int locktree::manager::find_by_dict_id(locktree *const &lt, const DICTIONARY_ID &dict_id) {
+ if (lt->m_dict_id.dictid < dict_id.dictid) {
return -1;
- } else if (lt->get_dict_id().dictid == dict_id.dictid) {
+ } else if (lt->m_dict_id.dictid == dict_id.dictid) {
return 0;
} else {
return 1;
}
}
-locktree *locktree_manager::locktree_map_find(const DICTIONARY_ID &dict_id) {
+locktree *locktree::manager::locktree_map_find(const DICTIONARY_ID &dict_id) {
locktree *lt;
int r = m_locktree_map.find_zero<DICTIONARY_ID, find_by_dict_id>(dict_id, &lt, nullptr);
return r == 0 ? lt : nullptr;
}
-void locktree_manager::locktree_map_put(locktree *lt) {
- int r = m_locktree_map.insert<DICTIONARY_ID, find_by_dict_id>(lt, lt->get_dict_id(), nullptr);
+void locktree::manager::locktree_map_put(locktree *lt) {
+ int r = m_locktree_map.insert<DICTIONARY_ID, find_by_dict_id>(lt, lt->m_dict_id, nullptr);
invariant_zero(r);
}
-void locktree_manager::locktree_map_remove(locktree *lt) {
+void locktree::manager::locktree_map_remove(locktree *lt) {
uint32_t idx;
locktree *found_lt;
int r = m_locktree_map.find_zero<DICTIONARY_ID, find_by_dict_id>(
- lt->get_dict_id(), &found_lt, &idx);
+ lt->m_dict_id, &found_lt, &idx);
invariant_zero(r);
invariant(found_lt == lt);
r = m_locktree_map.delete_at(idx);
invariant_zero(r);
}
-locktree *locktree_manager::get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc,
+locktree *locktree::manager::get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc,
ft_compare_func cmp, void *on_create_extra) {
// hold the mutex around searching and maybe
@@ -193,14 +194,15 @@ locktree *locktree_manager::get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc,
locktree *lt = locktree_map_find(dict_id);
if (lt == nullptr) {
XCALLOC(lt);
- lt->create(this, dict_id, desc, cmp);
+ lt->create(&m_mem_tracker, dict_id, desc, cmp);
+ invariant(lt->m_reference_count == 1);
// new locktree created - call the on_create callback
// and put it in the locktree map
if (m_lt_create_callback) {
int r = m_lt_create_callback(lt, on_create_extra);
if (r != 0) {
- lt->release_reference();
+ (void) toku_sync_sub_and_fetch(&lt->m_reference_count, 1);
lt->destroy();
toku_free(lt);
lt = nullptr;
@@ -218,7 +220,7 @@ locktree *locktree_manager::get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc,
return lt;
}
-void locktree_manager::reference_lt(locktree *lt) {
+void locktree::manager::reference_lt(locktree *lt) {
// increment using a sync fetch and add.
// the caller guarantees that the lt won't be
// destroyed while we increment the count here.
@@ -229,12 +231,20 @@ void locktree_manager::reference_lt(locktree *lt) {
// if the manager's mutex is held, it is ok for the
// reference count to transition from 0 to 1 (no race),
// since we're serialized with other opens and closes.
- lt->add_reference();
+ toku_sync_fetch_and_add(&lt->m_reference_count, 1);
}
-void locktree_manager::release_lt(locktree *lt) {
+static void add_lt_counters(locktree::lt_counters *x, locktree::lt_counters *y) {
+ x->wait_count += y->wait_count;
+ x->wait_time += y->wait_time;
+ x->long_wait_count += y->long_wait_count;
+ x->long_wait_time += y->long_wait_time;
+ x->timeout_count += y->timeout_count;
+}
+
+void locktree::manager::release_lt(locktree *lt) {
bool do_destroy = false;
- DICTIONARY_ID dict_id = lt->get_dict_id();
+ DICTIONARY_ID dict_id = lt->m_dict_id;
// Release a reference on the locktree. If the count transitions to zero,
// then we *may* need to do the cleanup.
@@ -264,7 +274,7 @@ void locktree_manager::release_lt(locktree *lt) {
// This way, if many threads transition the same locktree's reference count
// from 1 to zero and wait behind the manager's mutex, only one of them will
// do the actual destroy and the others will happily do nothing.
- uint32_t refs = lt->release_reference();
+ uint32_t refs = toku_sync_sub_and_fetch(&lt->m_reference_count, 1);
if (refs == 0) {
mutex_lock();
locktree *find_lt = locktree_map_find(dict_id);
@@ -274,12 +284,12 @@ void locktree_manager::release_lt(locktree *lt) {
// If the reference count is zero, it's our responsibility to remove
// it and do the destroy. Otherwise, someone still wants it.
invariant(find_lt == lt);
- if (lt->get_reference_count() == 0) {
+ if (lt->m_reference_count == 0) {
locktree_map_remove(lt);
do_destroy = true;
}
}
- m_lt_counters.add(lt->get_lock_request_info()->counters);
+ add_lt_counters(&m_lt_counters, &lt->m_lock_request_info.counters);
mutex_unlock();
}
@@ -293,22 +303,28 @@ void locktree_manager::release_lt(locktree *lt) {
}
}
-void locktree_manager::run_escalation(void) {
- struct escalation_fn {
- static void run(void *extra) {
- locktree_manager *mgr = (locktree_manager *) extra;
- mgr->escalate_all_locktrees();
- };
- };
- m_escalator.run(this, escalation_fn::run, this);
+// test-only version of lock escalation
+#if TOKU_LOCKTREE_ESCALATOR_LAMBDA
+void locktree::manager::run_escalation(void) {
+ m_escalator.run(this, [this] () -> void { escalate_all_locktrees(); });
+}
+#else
+static void manager_run_escalation_fun(void *extra) {
+ locktree::manager *thismanager = (locktree::manager *) extra;
+ thismanager->escalate_all_locktrees();
}
-// test-only version of lock escalation
-void locktree_manager::run_escalation_for_test(void) {
+void locktree::manager::run_escalation(void) {
+ m_escalator.run(this, manager_run_escalation_fun, this);
+}
+#endif
+
+void locktree::manager::run_escalation_for_test(void) {
run_escalation();
}
-void locktree_manager::escalate_all_locktrees(void) {
+void locktree::manager::escalate_all_locktrees(void) {
+ if (0) fprintf(stderr, "%d %s:%u\n", toku_os_gettid(), __PRETTY_FUNCTION__, __LINE__);
uint64_t t0 = toku_current_time_microsec();
// get all locktrees
@@ -331,25 +347,47 @@ void locktree_manager::escalate_all_locktrees(void) {
add_escalator_wait_time(t1 - t0);
}
-void locktree_manager::note_mem_used(uint64_t mem_used) {
- (void) toku_sync_fetch_and_add(&m_current_lock_memory, mem_used);
+void locktree::manager::memory_tracker::set_manager(manager *mgr) {
+ m_mgr = mgr;
+}
+
+locktree::manager *locktree::manager::memory_tracker::get_manager(void) {
+ return m_mgr;
+}
+
+int locktree::manager::memory_tracker::check_current_lock_constraints(void) {
+ int r = 0;
+ // check if we're out of locks without the mutex first. then, grab the
+ // mutex and check again. if we're still out of locks, run escalation.
+ // return an error if we're still out of locks after escalation.
+ if (out_of_locks()) {
+ m_mgr->run_escalation();
+ if (out_of_locks()) {
+ r = TOKUDB_OUT_OF_LOCKS;
+ }
+ }
+ return r;
+}
+
+void locktree::manager::memory_tracker::note_mem_used(uint64_t mem_used) {
+ (void) toku_sync_fetch_and_add(&m_mgr->m_current_lock_memory, mem_used);
}
-void locktree_manager::note_mem_released(uint64_t mem_released) {
- uint64_t old_mem_used = toku_sync_fetch_and_sub(&m_current_lock_memory, mem_released);
+void locktree::manager::memory_tracker::note_mem_released(uint64_t mem_released) {
+ uint64_t old_mem_used = toku_sync_fetch_and_sub(&m_mgr->m_current_lock_memory, mem_released);
invariant(old_mem_used >= mem_released);
}
-bool locktree_manager::out_of_locks(void) const {
- return m_current_lock_memory >= m_max_lock_memory;
+bool locktree::manager::memory_tracker::out_of_locks(void) const {
+ return m_mgr->m_current_lock_memory >= m_mgr->m_max_lock_memory;
}
-bool locktree_manager::over_big_threshold(void) {
- return m_current_lock_memory >= m_max_lock_memory / 2;
+bool locktree::manager::memory_tracker::over_big_threshold(void) {
+ return m_mgr->m_current_lock_memory >= m_mgr->m_max_lock_memory / 2;
}
-int locktree_manager::iterate_pending_lock_requests(lock_request_iterate_callback callback,
- void *extra) {
+int locktree::manager::iterate_pending_lock_requests(
+ lock_request_iterate_callback callback, void *extra) {
mutex_lock();
int r = 0;
size_t num_locktrees = m_locktree_map.size();
@@ -358,7 +396,7 @@ int locktree_manager::iterate_pending_lock_requests(lock_request_iterate_callbac
r = m_locktree_map.fetch(i, &lt);
invariant_zero(r);
- struct lt_lock_request_info *info = lt->get_lock_request_info();
+ struct lt_lock_request_info *info = &lt->m_lock_request_info;
toku_mutex_lock(&info->mutex);
size_t num_requests = info->pending_lock_requests.size();
@@ -366,7 +404,7 @@ int locktree_manager::iterate_pending_lock_requests(lock_request_iterate_callbac
lock_request *req;
r = info->pending_lock_requests.fetch(k, &req);
invariant_zero(r);
- r = callback(lt->get_dict_id(), req->get_txnid(),
+ r = callback(lt->m_dict_id, req->get_txnid(),
req->get_left_key(), req->get_right_key(),
req->get_conflicting_txnid(), req->get_start_time(), extra);
}
@@ -377,25 +415,21 @@ int locktree_manager::iterate_pending_lock_requests(lock_request_iterate_callbac
return r;
}
-int locktree_manager::check_current_lock_constraints(bool big_txn) {
+int locktree::manager::check_current_lock_constraints(bool big_txn) {
int r = 0;
- if (big_txn && over_big_threshold()) {
+ if (big_txn && m_mem_tracker.over_big_threshold()) {
run_escalation();
- if (over_big_threshold()) {
+ if (m_mem_tracker.over_big_threshold()) {
r = TOKUDB_OUT_OF_LOCKS;
}
}
- if (r == 0 && out_of_locks()) {
- run_escalation();
- if (out_of_locks()) {
- // return an error if we're still out of locks after escalation.
- r = TOKUDB_OUT_OF_LOCKS;
- }
+ if (r == 0) {
+ r = m_mem_tracker.check_current_lock_constraints();
}
return r;
}
-void locktree_manager::escalator_init(void) {
+void locktree::manager::escalator_init(void) {
ZERO_STRUCT(m_escalation_mutex);
toku_mutex_init(&m_escalation_mutex, nullptr);
m_escalation_count = 0;
@@ -408,12 +442,12 @@ void locktree_manager::escalator_init(void) {
m_escalator.create();
}
-void locktree_manager::escalator_destroy(void) {
+void locktree::manager::escalator_destroy(void) {
m_escalator.destroy();
toku_mutex_destroy(&m_escalation_mutex);
}
-void locktree_manager::add_escalator_wait_time(uint64_t t) {
+void locktree::manager::add_escalator_wait_time(uint64_t t) {
toku_mutex_lock(&m_escalation_mutex);
m_wait_escalation_count += 1;
m_wait_escalation_time += t;
@@ -424,7 +458,8 @@ void locktree_manager::add_escalator_wait_time(uint64_t t) {
toku_mutex_unlock(&m_escalation_mutex);
}
-void locktree_manager::escalate_locktrees(locktree **locktrees, int num_locktrees) {
+void locktree::manager::escalate_locktrees(locktree **locktrees, int num_locktrees) {
+ if (0) fprintf(stderr, "%d %s:%u %d\n", toku_os_gettid(), __PRETTY_FUNCTION__, __LINE__, num_locktrees);
// there are too many row locks in the system and we need to tidy up.
//
// a simple implementation of escalation does not attempt
@@ -446,32 +481,65 @@ void locktree_manager::escalate_locktrees(locktree **locktrees, int num_locktree
toku_mutex_unlock(&m_escalation_mutex);
}
+#if !TOKU_LOCKTREE_ESCALATOR_LAMBDA
struct escalate_args {
- locktree_manager *mgr;
+ locktree::manager *mgr;
locktree **locktrees;
int num_locktrees;
};
-void locktree_manager::locktree_escalator::create(void) {
+static void manager_escalate_locktrees(void *extra) {
+ escalate_args *args = (escalate_args *) extra;
+ args->mgr->escalate_locktrees(args->locktrees, args->num_locktrees);
+}
+#endif
+
+void locktree::manager::escalate_lock_trees_for_txn(TXNID txnid UU(), locktree *lt UU()) {
+ // get lock trees for txnid
+ const int num_locktrees = 1;
+ locktree *locktrees[1] = { lt };
+ reference_lt(lt);
+
+ // escalate these lock trees
+ locktree::escalator this_escalator;
+ this_escalator.create();
+#if TOKU_LOCKTREE_ESCALATOR_LAMBDA
+ this_escalator.run(this, [this,locktrees,num_locktrees] () -> void { escalate_locktrees(locktrees, num_locktrees); });
+#else
+ escalate_args args = { this, locktrees, num_locktrees };
+ this_escalator.run(this, manager_escalate_locktrees, &args);
+#endif
+ this_escalator.destroy();
+}
+
+void locktree::escalator::create(void) {
ZERO_STRUCT(m_escalator_mutex);
toku_mutex_init(&m_escalator_mutex, nullptr);
toku_cond_init(&m_escalator_done, nullptr);
m_escalator_running = false;
}
-void locktree_manager::locktree_escalator::destroy(void) {
+void locktree::escalator::destroy(void) {
toku_cond_destroy(&m_escalator_done);
toku_mutex_destroy(&m_escalator_mutex);
}
-void locktree_manager::locktree_escalator::run(locktree_manager *mgr, void (*escalate_locktrees_fun)(void *extra), void *extra) {
+#if TOKU_LOCKTREE_ESCALATOR_LAMBDA
+void locktree::escalator::run(locktree::manager *mgr, std::function<void (void)> escalate_locktrees_fun) {
+#else
+ void locktree::escalator::run(locktree::manager *mgr, void (*escalate_locktrees_fun)(void *extra), void *extra) {
+#endif
uint64_t t0 = toku_current_time_microsec();
toku_mutex_lock(&m_escalator_mutex);
if (!m_escalator_running) {
// run escalation on this thread
m_escalator_running = true;
toku_mutex_unlock(&m_escalator_mutex);
+#if TOKU_LOCKTREE_ESCALATOR_LAMBDA
+ escalate_locktrees_fun();
+#else
escalate_locktrees_fun(extra);
+#endif
toku_mutex_lock(&m_escalator_mutex);
m_escalator_running = false;
toku_cond_broadcast(&m_escalator_done);
@@ -485,7 +553,7 @@ void locktree_manager::locktree_escalator::run(locktree_manager *mgr, void (*esc
#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(status, k, c, t, "locktree: " l, inc)
-void locktree_manager::status_init(void) {
+void locktree::manager::status_init(void) {
STATUS_INIT(LTM_SIZE_CURRENT, LOCKTREE_MEMORY_SIZE, UINT64, "memory size", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(LTM_SIZE_LIMIT, LOCKTREE_MEMORY_SIZE_LIMIT, UINT64, "memory size limit", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(LTM_ESCALATION_COUNT, LOCKTREE_ESCALATION_NUM, UINT64, "number of times lock escalation ran", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
@@ -515,7 +583,7 @@ void locktree_manager::status_init(void) {
#define STATUS_VALUE(x) status.status[x].value.num
-void locktree_manager::get_status(LTM_STATUS statp) {
+void locktree::manager::get_status(LTM_STATUS statp) {
if (!status.initialized) {
status_init();
}
@@ -530,33 +598,33 @@ void locktree_manager::get_status(LTM_STATUS statp) {
STATUS_VALUE(LTM_LONG_WAIT_ESCALATION_COUNT) = m_long_wait_escalation_count;
STATUS_VALUE(LTM_LONG_WAIT_ESCALATION_TIME) = m_long_wait_escalation_time;
- mutex_lock();
-
uint64_t lock_requests_pending = 0;
uint64_t sto_num_eligible = 0;
uint64_t sto_end_early_count = 0;
tokutime_t sto_end_early_time = 0;
- struct lt_counters lt_counters = m_lt_counters;
-
- size_t num_locktrees = m_locktree_map.size();
- for (size_t i = 0; i < num_locktrees; i++) {
- locktree *lt;
- int r = m_locktree_map.fetch(i, &lt);
- invariant_zero(r);
-
- toku_mutex_lock(&lt->m_lock_request_info.mutex);
- lock_requests_pending += lt->m_lock_request_info.pending_lock_requests.size();
- lt_counters.add(lt->get_lock_request_info()->counters);
- toku_mutex_unlock(&lt->m_lock_request_info.mutex);
+ size_t num_locktrees = 0;
+ struct lt_counters lt_counters = {};
- sto_num_eligible += lt->sto_txnid_is_valid_unsafe() ? 1 : 0;
- sto_end_early_count += lt->m_sto_end_early_count;
- sto_end_early_time += lt->m_sto_end_early_time;
+ if (toku_mutex_trylock(&m_mutex) == 0) {
+ lt_counters = m_lt_counters;
+ num_locktrees = m_locktree_map.size();
+ for (size_t i = 0; i < num_locktrees; i++) {
+ locktree *lt;
+ int r = m_locktree_map.fetch(i, &lt);
+ invariant_zero(r);
+ if (toku_mutex_trylock(&lt->m_lock_request_info.mutex) == 0) {
+ lock_requests_pending += lt->m_lock_request_info.pending_lock_requests.size();
+ add_lt_counters(&lt_counters, &lt->m_lock_request_info.counters);
+ toku_mutex_unlock(&lt->m_lock_request_info.mutex);
+ }
+ sto_num_eligible += lt->sto_txnid_is_valid_unsafe() ? 1 : 0;
+ sto_end_early_count += lt->m_sto_end_early_count;
+ sto_end_early_time += lt->m_sto_end_early_time;
+ }
+ mutex_unlock();
}
- mutex_unlock();
-
STATUS_VALUE(LTM_NUM_LOCKTREES) = num_locktrees;
STATUS_VALUE(LTM_LOCK_REQUESTS_PENDING) = lock_requests_pending;
STATUS_VALUE(LTM_STO_NUM_ELIGIBLE) = sto_num_eligible;
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc b/storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc
index 18fcd873423..742165c59dc 100644
--- a/storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc
@@ -117,10 +117,13 @@ static int my_killed_callback(void) {
// make sure deadlocks are detected when a lock request starts
void lock_request_unit_test::test_wait_time_callback(void) {
int r;
- locktree lt;
+ locktree::manager mgr;
+ locktree *lt;
+
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
TXNID txnid_a = 1001;
lock_request request_a;
@@ -133,12 +136,12 @@ void lock_request_unit_test::test_wait_time_callback(void) {
const DBT *one = get_dbt(1);
// a locks 'one'
- request_a.set(&lt, txnid_a, one, one, lock_request::type::WRITE, false);
+ request_a.set(lt, txnid_a, one, one, lock_request::type::WRITE, false);
r = request_a.start();
assert_zero(r);
// b tries to lock 'one'
- request_b.set(&lt, txnid_b, one, one, lock_request::type::WRITE, false);
+ request_b.set(lt, txnid_b, one, one, lock_request::type::WRITE, false);
r = request_b.start();
assert(r == DB_LOCK_NOTGRANTED);
@@ -159,11 +162,11 @@ void lock_request_unit_test::test_wait_time_callback(void) {
request_b.destroy();
- release_lock_and_retry_requests(&lt, txnid_a, one, one);
+ release_lock_and_retry_requests(lt, txnid_a, one, one);
request_a.destroy();
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_not_killed.cc b/storage/tokudb/ft-index/locktree/tests/lock_request_not_killed.cc
index abee11052f4..e49b88f9d79 100644
--- a/storage/tokudb/ft-index/locktree/tests/lock_request_not_killed.cc
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_not_killed.cc
@@ -114,10 +114,13 @@ static int my_killed_callback(void) {
// make sure deadlocks are detected when a lock request starts
void lock_request_unit_test::test_wait_time_callback(void) {
int r;
- locktree lt;
+ locktree::manager mgr;
+ locktree *lt;
+
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
TXNID txnid_a = 1001;
lock_request request_a;
@@ -130,12 +133,12 @@ void lock_request_unit_test::test_wait_time_callback(void) {
const DBT *one = get_dbt(1);
// a locks 'one'
- request_a.set(&lt, txnid_a, one, one, lock_request::type::WRITE, false);
+ request_a.set(lt, txnid_a, one, one, lock_request::type::WRITE, false);
r = request_a.start();
assert_zero(r);
// b tries to lock 'one'
- request_b.set(&lt, txnid_b, one, one, lock_request::type::WRITE, false);
+ request_b.set(lt, txnid_b, one, one, lock_request::type::WRITE, false);
r = request_b.start();
assert(r == DB_LOCK_NOTGRANTED);
@@ -155,11 +158,11 @@ void lock_request_unit_test::test_wait_time_callback(void) {
request_b.destroy();
- release_lock_and_retry_requests(&lt, txnid_a, one, one);
+ release_lock_and_retry_requests(lt, txnid_a, one, one);
request_a.destroy();
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_start_deadlock.cc b/storage/tokudb/ft-index/locktree/tests/lock_request_start_deadlock.cc
index 4710e19551b..08bd4c14d20 100644
--- a/storage/tokudb/ft-index/locktree/tests/lock_request_start_deadlock.cc
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_start_deadlock.cc
@@ -96,13 +96,14 @@ namespace toku {
// make sure deadlocks are detected when a lock request starts
void lock_request_unit_test::test_start_deadlock(void) {
int r;
- locktree lt;
-
+ locktree::manager mgr;
+ locktree *lt;
// something short
const uint64_t lock_wait_time = 10;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
TXNID txnid_a = 1001;
TXNID txnid_b = 2001;
@@ -118,30 +119,30 @@ void lock_request_unit_test::test_start_deadlock(void) {
const DBT *two = get_dbt(2);
// start and succeed 1,1 for A and 2,2 for B.
- request_a.set(&lt, txnid_a, one, one, lock_request::type::WRITE, false);
+ request_a.set(lt, txnid_a, one, one, lock_request::type::WRITE, false);
r = request_a.start();
invariant_zero(r);
- request_b.set(&lt, txnid_b, two, two, lock_request::type::WRITE, false);
+ request_b.set(lt, txnid_b, two, two, lock_request::type::WRITE, false);
r = request_b.start();
invariant_zero(r);
// txnid A should not be granted a lock on 2,2, so it goes pending.
- request_a.set(&lt, txnid_a, two, two, lock_request::type::WRITE, false);
+ request_a.set(lt, txnid_a, two, two, lock_request::type::WRITE, false);
r = request_a.start();
invariant(r == DB_LOCK_NOTGRANTED);
// if txnid B wants a lock on 1,1 it should deadlock with A
- request_b.set(&lt, txnid_b, one, one, lock_request::type::WRITE, false);
+ request_b.set(lt, txnid_b, one, one, lock_request::type::WRITE, false);
r = request_b.start();
invariant(r == DB_LOCK_DEADLOCK);
// txnid C should not deadlock on either of these - it should just time out.
- request_c.set(&lt, txnid_c, one, one, lock_request::type::WRITE, false);
+ request_c.set(lt, txnid_c, one, one, lock_request::type::WRITE, false);
r = request_c.start();
invariant(r == DB_LOCK_NOTGRANTED);
r = request_c.wait(lock_wait_time);
invariant(r == DB_LOCK_NOTGRANTED);
- request_c.set(&lt, txnid_c, two, two, lock_request::type::WRITE, false);
+ request_c.set(lt, txnid_c, two, two, lock_request::type::WRITE, false);
r = request_c.start();
invariant(r == DB_LOCK_NOTGRANTED);
r = request_c.wait(lock_wait_time);
@@ -149,18 +150,17 @@ void lock_request_unit_test::test_start_deadlock(void) {
// release locks for A and B, then wait on A's request which should succeed
// since B just unlocked and should have completed A's pending request.
- release_lock_and_retry_requests(&lt, txnid_a, one, one);
- release_lock_and_retry_requests(&lt, txnid_b, two, two);
+ release_lock_and_retry_requests(lt, txnid_a, one, one);
+ release_lock_and_retry_requests(lt, txnid_b, two, two);
r = request_a.wait(lock_wait_time);
invariant_zero(r);
- release_lock_and_retry_requests(&lt, txnid_a, two, two);
+ release_lock_and_retry_requests(lt, txnid_a, two, two);
request_a.destroy();
request_b.destroy();
request_c.destroy();
-
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_start_pending.cc b/storage/tokudb/ft-index/locktree/tests/lock_request_start_pending.cc
index 54d630078ac..867d5fb1bd0 100644
--- a/storage/tokudb/ft-index/locktree/tests/lock_request_start_pending.cc
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_start_pending.cc
@@ -97,11 +97,13 @@ namespace toku {
// stored in the lock request set as pending.
void lock_request_unit_test::test_start_pending(void) {
int r;
- locktree lt;
+ locktree::manager mgr;
+ locktree *lt;
lock_request request;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
TXNID txnid_a = 1001;
TXNID txnid_b = 2001;
@@ -111,15 +113,15 @@ void lock_request_unit_test::test_start_pending(void) {
const DBT *two = get_dbt(2);
// take a range lock using txnid b
- r = lt.acquire_write_lock(txnid_b, zero, two, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, zero, two, nullptr, false);
invariant_zero(r);
- lt_lock_request_info *info = lt.get_lock_request_info();
+ locktree::lt_lock_request_info *info = lt->get_lock_request_info();
// start a lock request for 1,1
// it should fail. the request should be stored and in the pending state.
request.create();
- request.set(&lt, txnid_a, one, one, lock_request::type::WRITE, false);
+ request.set(lt, txnid_a, one, one, lock_request::type::WRITE, false);
r = request.start();
invariant(r == DB_LOCK_NOTGRANTED);
invariant(info->pending_lock_requests.size() == 1);
@@ -132,21 +134,20 @@ void lock_request_unit_test::test_start_pending(void) {
invariant(compare_dbts(nullptr, &request.m_right_key_copy, one) == 0);
// release the range lock for txnid b
- locktree_unit_test::locktree_test_release_lock(&lt, txnid_b, zero, two);
+ locktree_unit_test::locktree_test_release_lock(lt, txnid_b, zero, two);
// now retry the lock requests.
// it should transition the request to successfully complete.
- lock_request::retry_all_lock_requests(&lt);
+ lock_request::retry_all_lock_requests(lt);
invariant(info->pending_lock_requests.size() == 0);
invariant(request.m_state == lock_request::state::COMPLETE);
invariant(request.m_complete_r == 0);
- locktree_unit_test::locktree_test_release_lock(&lt, txnid_a, one, one);
+ locktree_unit_test::locktree_test_release_lock(lt, txnid_a, one, one);
request.destroy();
-
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_wait_time_callback.cc b/storage/tokudb/ft-index/locktree/tests/lock_request_wait_time_callback.cc
index bc67bac7465..e077d461399 100644
--- a/storage/tokudb/ft-index/locktree/tests/lock_request_wait_time_callback.cc
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_wait_time_callback.cc
@@ -98,10 +98,12 @@ static const uint64_t my_lock_wait_time = 10 * 1000; // 10 sec
// make sure deadlocks are detected when a lock request starts
void lock_request_unit_test::test_wait_time_callback(void) {
int r;
- locktree lt;
+ locktree::manager mgr;
+ locktree *lt;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
TXNID txnid_a = 1001;
lock_request request_a;
@@ -115,12 +117,12 @@ void lock_request_unit_test::test_wait_time_callback(void) {
const DBT *two = get_dbt(2);
// a locks 'one'
- request_a.set(&lt, txnid_a, one, one, lock_request::type::WRITE, false);
+ request_a.set(lt, txnid_a, one, one, lock_request::type::WRITE, false);
r = request_a.start();
assert_zero(r);
// b tries to lock 'one'
- request_b.set(&lt, txnid_b, one, two, lock_request::type::WRITE, false);
+ request_b.set(lt, txnid_b, one, two, lock_request::type::WRITE, false);
r = request_b.start();
assert(r == DB_LOCK_NOTGRANTED);
uint64_t t_start = toku_current_time_microsec();
@@ -132,11 +134,11 @@ void lock_request_unit_test::test_wait_time_callback(void) {
assert(t_delta >= my_lock_wait_time);
request_b.destroy();
- release_lock_and_retry_requests(&lt, txnid_a, one, one);
+ release_lock_and_retry_requests(lt, txnid_a, one, one);
request_a.destroy();
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc b/storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc
index 3eb7bd3c3d4..70f3a6249c4 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc
@@ -105,10 +105,11 @@ namespace toku {
// test write lock conflicts when read or write locks exist
// test read lock conflicts when write locks exist
void locktree_unit_test::test_conflicts(void) {
- locktree lt;
-
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+ DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
int r;
TXNID txnid_a = 1001;
@@ -124,8 +125,8 @@ void locktree_unit_test::test_conflicts(void) {
// test_run == 0 means test with read lock
// test_run == 1 means test with write lock
#define ACQUIRE_LOCK(txn, left, right, conflicts) \
- test_run == 0 ? lt.acquire_read_lock(txn, left, right, conflicts, false) \
- : lt.acquire_write_lock(txn, left, right, conflicts, false)
+ test_run == 0 ? lt->acquire_read_lock(txn, left, right, conflicts, false) \
+ : lt->acquire_write_lock(txn, left, right, conflicts, false)
// acquire some locks for txnid_a
r = ACQUIRE_LOCK(txnid_a, one, one, nullptr);
@@ -141,8 +142,8 @@ void locktree_unit_test::test_conflicts(void) {
// if test_run == 0, then read locks exist. only test write locks.
#define ACQUIRE_LOCK(txn, left, right, conflicts) \
sub_test_run == 0 && test_run == 1 ? \
- lt.acquire_read_lock(txn, left, right, conflicts, false) \
- : lt.acquire_write_lock(txn, left, right, conflicts, false)
+ lt->acquire_read_lock(txn, left, right, conflicts, false) \
+ : lt->acquire_write_lock(txn, left, right, conflicts, false)
// try to get point write locks for txnid_b, should fail
r = ACQUIRE_LOCK(txnid_b, one, one, nullptr);
invariant(r == DB_LOCK_NOTGRANTED);
@@ -161,13 +162,13 @@ void locktree_unit_test::test_conflicts(void) {
#undef ACQUIRE_LOCK
}
- lt.remove_overlapping_locks_for_txnid(txnid_a, one, one);
- lt.remove_overlapping_locks_for_txnid(txnid_a, three, four);
- invariant(no_row_locks(&lt));
+ lt->remove_overlapping_locks_for_txnid(txnid_a, one, one);
+ lt->remove_overlapping_locks_for_txnid(txnid_a, three, four);
+ invariant(no_row_locks(lt));
}
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_create_destroy.cc b/storage/tokudb/ft-index/locktree/tests/locktree_create_destroy.cc
index b3b1fb77629..bb3681d037a 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_create_destroy.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_create_destroy.cc
@@ -95,26 +95,27 @@ namespace toku {
// test simple create and destroy of the locktree
void locktree_unit_test::test_create_destroy(void) {
- locktree lt;
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+ DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
+ locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
-
- lt_lock_request_info *info = lt.get_lock_request_info();
+ locktree::lt_lock_request_info *info = lt->get_lock_request_info();
invariant_notnull(info);
toku_mutex_lock(&info->mutex);
toku_mutex_unlock(&info->mutex);
- invariant(lt.m_dict_id.dictid == dict_id.dictid);
- invariant(lt.m_reference_count == 1);
- invariant(lt.m_rangetree != nullptr);
- invariant(lt.m_userdata == nullptr);
+ invariant(lt->m_dict_id.dictid == dict_id.dictid);
+ invariant(lt->m_reference_count == 1);
+ invariant(lt->m_rangetree != nullptr);
+ invariant(lt->m_userdata == nullptr);
invariant(info->pending_lock_requests.size() == 0);
- invariant(lt.m_sto_end_early_count == 0);
- invariant(lt.m_sto_end_early_time == 0);
+ invariant(lt->m_sto_end_early_count == 0);
+ invariant(lt->m_sto_end_early_time == 0);
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_1big7lt_1small.cc b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_1big7lt_1small.cc
index 26e286eb8ca..7c4af67e6f8 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_1big7lt_1small.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_1big7lt_1small.cc
@@ -119,7 +119,21 @@ static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64
return lt->acquire_write_lock(txn_id, &left, &right, nullptr, big_txn);
}
-static void run_big_txn(locktree_manager *mgr UU(), locktree **lt, int n_lt, TXNID txn_id) {
+#if 0
+static locktree **big_txn_lt;
+static int n_big_txn_lt;
+
+static int get_locktrees_touched_by_txn(TXNID txn_id UU(), void *txn_extra UU(), locktree ***ret_locktrees, int *ret_num_locktrees) {
+ locktree **locktrees = (locktree **) toku_malloc(n_big_txn_lt * sizeof (locktree *));
+ for (int i = 0; i < n_big_txn_lt; i++)
+ locktrees[i] = big_txn_lt[i];
+ *ret_locktrees = locktrees;
+ *ret_num_locktrees = n_big_txn_lt;
+ return 0;
+}
+#endif
+
+static void run_big_txn(locktree::manager *mgr UU(), locktree **lt, int n_lt, TXNID txn_id) {
int64_t last_i = -1;
for (int64_t i = 0; !killed; i++) {
for (int j = 0; j < n_lt; j++) {
@@ -143,7 +157,7 @@ static void run_big_txn(locktree_manager *mgr UU(), locktree **lt, int n_lt, TXN
}
struct big_arg {
- locktree_manager *mgr;
+ locktree::manager *mgr;
locktree **lt;
int n_lt;
TXNID txn_id;
@@ -157,7 +171,7 @@ static void *big_f(void *_arg) {
return arg;
}
-static void run_small_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id, int64_t k) {
+static void run_small_txn(locktree::manager *mgr UU(), locktree *lt, TXNID txn_id, int64_t k) {
int64_t i;
for (i = 0; !killed; i++) {
uint64_t t_start = toku_current_time_microsec();
@@ -176,7 +190,7 @@ static void run_small_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id
}
struct small_arg {
- locktree_manager *mgr;
+ locktree::manager *mgr;
locktree *lt;
TXNID txn_id;
int64_t k;
@@ -195,7 +209,7 @@ static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buff
printf("%u %s %" PRIu64 " %p %d %p\n", toku_os_gettid(), __FUNCTION__, txnid, lt, buffer.get_num_ranges(), extra);
}
-static uint64_t get_escalation_count(locktree_manager &mgr) {
+static uint64_t get_escalation_count(locktree::manager &mgr) {
LTM_STATUS_S ltm_status;
mgr.get_status(&ltm_status);
@@ -237,7 +251,7 @@ int main(int argc, const char *argv[]) {
int r;
// create a manager
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, e_callback, nullptr);
mgr.set_max_lock_memory(max_lock_memory);
@@ -250,6 +264,11 @@ int main(int argc, const char *argv[]) {
big_lt[i] = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
}
+#if 0
+ big_txn_lt = big_lt;
+ n_big_txn_lt = n_big;
+#endif
+
dict_id = { next_dict_id }; next_dict_id++;
locktree *small_lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_1lt.cc b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_1lt.cc
index 8f6c697970e..ab1818d2fd3 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_1lt.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_1lt.cc
@@ -118,7 +118,7 @@ static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64
return lt->acquire_write_lock(txn_id, &left, &right, nullptr, big_txn);
}
-static void run_big_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id, int64_t start_i) {
+static void run_big_txn(locktree::manager *mgr UU(), locktree *lt, TXNID txn_id, int64_t start_i) {
fprintf(stderr, "%u run_big_txn %p %" PRIu64 " %" PRId64 "\n", toku_os_gettid(), lt, txn_id, start_i);
int64_t last_i = -1;
for (int64_t i = start_i; !killed; i++) {
@@ -141,7 +141,7 @@ static void run_big_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id,
}
struct arg {
- locktree_manager *mgr;
+ locktree::manager *mgr;
locktree *lt;
TXNID txn_id;
int64_t start_i;
@@ -158,7 +158,7 @@ static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buff
printf("%u %s %" PRIu64 " %p %d %p\n", toku_os_gettid(), __FUNCTION__, txnid, lt, buffer.get_num_ranges(), extra);
}
-static uint64_t get_escalation_count(locktree_manager &mgr) {
+static uint64_t get_escalation_count(locktree::manager &mgr) {
LTM_STATUS_S ltm_status;
mgr.get_status(&ltm_status);
@@ -205,7 +205,7 @@ int main(int argc, const char *argv[]) {
int r;
// create a manager
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, e_callback, nullptr);
mgr.set_max_lock_memory(max_lock_memory);
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_2lt.cc b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_2lt.cc
index 576208f1dcb..d9f62ca29f3 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_2lt.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_2lt.cc
@@ -118,7 +118,7 @@ static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64
return lt->acquire_write_lock(txn_id, &left, &right, nullptr, big_txn);
}
-static void run_big_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id, int64_t start_i) {
+static void run_big_txn(locktree::manager *mgr UU(), locktree *lt, TXNID txn_id, int64_t start_i) {
fprintf(stderr, "%u run_big_txn %p %" PRIu64 " %" PRId64 "\n", toku_os_gettid(), lt, txn_id, start_i);
int64_t last_i = -1;
for (int64_t i = start_i; !killed; i++) {
@@ -141,7 +141,7 @@ static void run_big_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id,
}
struct arg {
- locktree_manager *mgr;
+ locktree::manager *mgr;
locktree *lt;
TXNID txn_id;
int64_t start_i;
@@ -158,7 +158,7 @@ static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buff
printf("%u %s %" PRIu64 " %p %d %p\n", toku_os_gettid(), __FUNCTION__, txnid, lt, buffer.get_num_ranges(), extra);
}
-static uint64_t get_escalation_count(locktree_manager &mgr) {
+static uint64_t get_escalation_count(locktree::manager &mgr) {
LTM_STATUS_S ltm_status;
mgr.get_status(&ltm_status);
@@ -205,7 +205,7 @@ int main(int argc, const char *argv[]) {
int r;
// create a manager
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, e_callback, nullptr);
mgr.set_max_lock_memory(max_lock_memory);
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc
index 4ee79b4f573..cdee8b9d333 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc
@@ -123,7 +123,7 @@ static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buff
printf("%u %s %" PRIu64 " %p %d %p\n", toku_os_gettid(), __FUNCTION__, txnid, lt, buffer.get_num_ranges(), extra);
}
-static uint64_t get_escalation_count(locktree_manager &mgr) {
+static uint64_t get_escalation_count(locktree::manager &mgr) {
LTM_STATUS_S ltm_status;
mgr.get_status(&ltm_status);
@@ -159,7 +159,7 @@ int main(int argc, const char *argv[]) {
int r;
// create a manager
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, e_callback, nullptr);
mgr.set_max_lock_memory(max_lock_memory);
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc
index 4fd102e2d49..28ae88cb3a8 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc
@@ -126,7 +126,7 @@ static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64
return lt->acquire_write_lock(txn_id, &left, &right, nullptr, big_txn);
}
-static void run_big_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id) {
+static void run_big_txn(locktree::manager *mgr UU(), locktree *lt, TXNID txn_id) {
int64_t last_i = -1;
for (int64_t i = 0; !killed; i++) {
uint64_t t_start = toku_current_time_microsec();
@@ -144,7 +144,7 @@ static void run_big_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id)
locktree_release_lock(lt, txn_id, 0, last_i); // release the range 0 .. last_i
}
-static void run_small_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id, int64_t k) {
+static void run_small_txn(locktree::manager *mgr UU(), locktree *lt, TXNID txn_id, int64_t k) {
for (int64_t i = 0; !killed; i++) {
uint64_t t_start = toku_current_time_microsec();
int r = locktree_write_lock(lt, txn_id, k, k, false);
@@ -160,7 +160,7 @@ static void run_small_txn(locktree_manager *mgr UU(), locktree *lt, TXNID txn_id
}
struct arg {
- locktree_manager *mgr;
+ locktree::manager *mgr;
locktree *lt;
TXNID txn_id;
int64_t k;
@@ -183,7 +183,7 @@ static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buff
printf("%u %s %" PRIu64 " %p %d %p\n", toku_os_gettid(), __FUNCTION__, txnid, lt, buffer.get_num_ranges(), extra);
}
-static uint64_t get_escalation_count(locktree_manager &mgr) {
+static uint64_t get_escalation_count(locktree::manager &mgr) {
LTM_STATUS_S ltm_status;
mgr.get_status(&ltm_status);
@@ -223,7 +223,7 @@ int main(int argc, const char *argv[]) {
int r;
// create a manager
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, e_callback, nullptr);
mgr.set_max_lock_memory(max_lock_memory);
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc b/storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc
index b4e0d0765bc..142e50992a6 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc
@@ -95,10 +95,11 @@ namespace toku {
// test that ranges with infinite endpoints work
void locktree_unit_test::test_infinity(void) {
- locktree lt;
-
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+ DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
int r;
TXNID txnid_a = 1001;
@@ -111,60 +112,60 @@ void locktree_unit_test::test_infinity(void) {
const DBT max_int = max_dbt();
// txn A will lock -inf, 5.
- r = lt.acquire_write_lock(txnid_a, toku_dbt_negative_infinity(), five, nullptr, false);
+ r = lt->acquire_write_lock(txnid_a, toku_dbt_negative_infinity(), five, nullptr, false);
invariant(r == 0);
// txn B will fail to get any lock <= 5, even min_int
- r = lt.acquire_write_lock(txnid_b, five, five, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, five, five, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, zero, one, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, zero, one, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, &min_int, &min_int, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, &min_int, &min_int, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, toku_dbt_negative_infinity(), &min_int, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, toku_dbt_negative_infinity(), &min_int, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- lt.remove_overlapping_locks_for_txnid(txnid_a, toku_dbt_negative_infinity(), five);
+ lt->remove_overlapping_locks_for_txnid(txnid_a, toku_dbt_negative_infinity(), five);
// txn A will lock 1, +inf
- r = lt.acquire_write_lock(txnid_a, one, toku_dbt_positive_infinity(), nullptr, false);
+ r = lt->acquire_write_lock(txnid_a, one, toku_dbt_positive_infinity(), nullptr, false);
invariant(r == 0);
// txn B will fail to get any lock >= 1, even max_int
- r = lt.acquire_write_lock(txnid_b, one, one, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, one, one, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, two, five, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, two, five, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, &max_int, &max_int, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, &max_int, &max_int, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, &max_int, toku_dbt_positive_infinity(), nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, &max_int, toku_dbt_positive_infinity(), nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- lt.remove_overlapping_locks_for_txnid(txnid_a, toku_dbt_negative_infinity(), five);
+ lt->remove_overlapping_locks_for_txnid(txnid_a, toku_dbt_negative_infinity(), five);
// txn A will lock -inf, +inf
- r = lt.acquire_write_lock(txnid_a, toku_dbt_negative_infinity(), toku_dbt_positive_infinity(), nullptr, false);
+ r = lt->acquire_write_lock(txnid_a, toku_dbt_negative_infinity(), toku_dbt_positive_infinity(), nullptr, false);
invariant(r == 0);
// txn B will fail to get any lock
- r = lt.acquire_write_lock(txnid_b, zero, one, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, zero, one, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, two, five, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, two, five, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, &min_int, &min_int, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, &min_int, &min_int, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, &min_int, &max_int, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, &min_int, &max_int, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, &max_int, &max_int, nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, &max_int, &max_int, nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, toku_dbt_negative_infinity(), toku_dbt_negative_infinity(), nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, toku_dbt_negative_infinity(), toku_dbt_negative_infinity(), nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, toku_dbt_negative_infinity(), toku_dbt_positive_infinity(), nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, toku_dbt_negative_infinity(), toku_dbt_positive_infinity(), nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- r = lt.acquire_write_lock(txnid_b, toku_dbt_positive_infinity(), toku_dbt_positive_infinity(), nullptr, false);
+ r = lt->acquire_write_lock(txnid_b, toku_dbt_positive_infinity(), toku_dbt_positive_infinity(), nullptr, false);
invariant(r == DB_LOCK_NOTGRANTED);
- lt.remove_overlapping_locks_for_txnid(txnid_a, toku_dbt_negative_infinity(), toku_dbt_positive_infinity());
+ lt->remove_overlapping_locks_for_txnid(txnid_a, toku_dbt_negative_infinity(), toku_dbt_positive_infinity());
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_misc.cc b/storage/tokudb/ft-index/locktree/tests/locktree_misc.cc
index 72906cca983..5916914297d 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_misc.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_misc.cc
@@ -107,16 +107,18 @@ static int my_compare_dbts(DB *db, const DBT *a, const DBT *b) {
// test that get/set userdata works, and that get_manager() works
void locktree_unit_test::test_misc(void) {
- locktree lt;
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+ DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, my_compare_dbts);
+ locktree *lt = mgr.get_lt(dict_id, desc, my_compare_dbts, nullptr);
- invariant(lt.get_userdata() == nullptr);
+ invariant(lt->get_userdata() == nullptr);
int userdata;
- lt.set_userdata(&userdata);
- invariant(lt.get_userdata() == &userdata);
- lt.set_userdata(nullptr);
- invariant(lt.get_userdata() == nullptr);
+ lt->set_userdata(&userdata);
+ invariant(lt->get_userdata() == &userdata);
+ lt->set_userdata(nullptr);
+ invariant(lt->get_userdata() == nullptr);
int r;
DBT dbt_a, dbt_b;
@@ -126,17 +128,17 @@ void locktree_unit_test::test_misc(void) {
// make sure the comparator object has the correct
// descriptor when we set the locktree's descriptor
- lt.set_descriptor(&d1);
+ lt->set_descriptor(&d1);
expected_descriptor = &d1;
- r = lt.m_cmp->compare(&dbt_a, &dbt_b);
+ r = lt->m_cmp->compare(&dbt_a, &dbt_b);
invariant(r == expected_comparison_magic);
- lt.set_descriptor(&d2);
+ lt->set_descriptor(&d2);
expected_descriptor = &d2;
- r = lt.m_cmp->compare(&dbt_a, &dbt_b);
+ r = lt->m_cmp->compare(&dbt_a, &dbt_b);
invariant(r == expected_comparison_magic);
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc b/storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc
index 6b412f214b4..ecb710517e1 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc
@@ -98,10 +98,11 @@ namespace toku {
// write locks if overlapping and ensure that existing read
// or write locks are consolidated by overlapping relocks.
void locktree_unit_test::test_overlapping_relock(void) {
- locktree lt;
-
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+ DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
const DBT *zero = get_dbt(0);
const DBT *one = get_dbt(1);
@@ -120,15 +121,15 @@ void locktree_unit_test::test_overlapping_relock(void) {
// do something. at the end of the test, we release 100, 100.
const TXNID the_other_txnid = 9999;
const DBT *hundred = get_dbt(100);
- r = lt.acquire_write_lock(the_other_txnid, hundred, hundred, nullptr, false);
+ r = lt->acquire_write_lock(the_other_txnid, hundred, hundred, nullptr, false);
invariant(r == 0);
for (int test_run = 0; test_run < 2; test_run++) {
// test_run == 0 means test with read lock
// test_run == 1 means test with write lock
#define ACQUIRE_LOCK(txn, left, right, conflicts) \
- test_run == 0 ? lt.acquire_read_lock(txn, left, right, conflicts, false) \
- : lt.acquire_write_lock(txn, left, right, conflicts, false)
+ test_run == 0 ? lt->acquire_read_lock(txn, left, right, conflicts, false) \
+ : lt->acquire_write_lock(txn, left, right, conflicts, false)
// lock [1,1] and [2,2]. then lock [1,2].
// ensure only [1,2] exists in the tree
@@ -156,10 +157,10 @@ void locktree_unit_test::test_overlapping_relock(void) {
return true;
}
} verify_fn;
- verify_fn.cmp = lt.m_cmp;
+ verify_fn.cmp = lt->m_cmp;
#define do_verify() \
- do { verify_fn.saw_the_other = false; locktree_iterate<verify_fn_obj>(&lt, &verify_fn); } while (0)
+ do { verify_fn.saw_the_other = false; locktree_iterate<verify_fn_obj>(lt, &verify_fn); } while (0)
keyrange range;
range.create(one, two);
@@ -169,9 +170,9 @@ void locktree_unit_test::test_overlapping_relock(void) {
// unlocking [1,1] should remove the only range,
// the other unlocks shoudl do nothing.
- lt.remove_overlapping_locks_for_txnid(txnid_a, one, one);
- lt.remove_overlapping_locks_for_txnid(txnid_a, two, two);
- lt.remove_overlapping_locks_for_txnid(txnid_a, one, two);
+ lt->remove_overlapping_locks_for_txnid(txnid_a, one, one);
+ lt->remove_overlapping_locks_for_txnid(txnid_a, two, two);
+ lt->remove_overlapping_locks_for_txnid(txnid_a, one, two);
// try overlapping from the right
r = ACQUIRE_LOCK(txnid_a, one, three, nullptr);
@@ -196,16 +197,16 @@ void locktree_unit_test::test_overlapping_relock(void) {
do_verify();
// release one of the locks we acquired. this should clean up the whole range.
- lt.remove_overlapping_locks_for_txnid(txnid_a, zero, four);
+ lt->remove_overlapping_locks_for_txnid(txnid_a, zero, four);
#undef ACQUIRE_LOCK
}
// remove the other txnid's lock now
- lt.remove_overlapping_locks_for_txnid(the_other_txnid, hundred, hundred);
+ lt->remove_overlapping_locks_for_txnid(the_other_txnid, hundred, hundred);
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_simple_lock.cc b/storage/tokudb/ft-index/locktree/tests/locktree_simple_lock.cc
index 2a4de0f7b77..549a44a1479 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_simple_lock.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_simple_lock.cc
@@ -95,11 +95,11 @@ namespace toku {
// test simple, non-overlapping read locks and then write locks
void locktree_unit_test::test_simple_lock(void) {
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, nullptr, nullptr);
-
+ DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
- locktree *lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
+ locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
int r;
TXNID txnid_a = 1001;
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_single_txnid_optimization.cc b/storage/tokudb/ft-index/locktree/tests/locktree_single_txnid_optimization.cc
index 9da0eff51ce..6fdd7270f09 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_single_txnid_optimization.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_single_txnid_optimization.cc
@@ -98,10 +98,11 @@ namespace toku {
// write locks if overlapping and ensure that existing read
// or write locks are consolidated by overlapping relocks.
void locktree_unit_test::test_single_txnid_optimization(void) {
- locktree lt;
-
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+ DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
- lt.create(nullptr, dict_id, nullptr, compare_dbts);
+ locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
const DBT *zero = get_dbt(0);
const DBT *one = get_dbt(1);
@@ -123,13 +124,13 @@ void locktree_unit_test::test_single_txnid_optimization(void) {
buffer.create();
#define lock_and_append_point_for_txnid_a(key) \
- r = lt.acquire_write_lock(txnid_a, key, key, nullptr, false); \
+ r = lt->acquire_write_lock(txnid_a, key, key, nullptr, false); \
invariant_zero(r); \
buffer.append(key, key);
#define maybe_point_locks_for_txnid_b(i) \
if (where == i) { \
- r = lt.acquire_write_lock(txnid_b, one, one, nullptr, false); \
+ r = lt->acquire_write_lock(txnid_b, one, one, nullptr, false); \
invariant_zero(r); \
}
@@ -142,7 +143,7 @@ void locktree_unit_test::test_single_txnid_optimization(void) {
lock_and_append_point_for_txnid_a(zero);
maybe_point_locks_for_txnid_b(2);
- lt.release_locks(txnid_a, &buffer);
+ lt->release_locks(txnid_a, &buffer);
// txnid b does not take a lock on iteration 3
if (where != 3) {
@@ -157,21 +158,21 @@ void locktree_unit_test::test_single_txnid_optimization(void) {
return true;
}
} verify_fn;
- verify_fn.cmp = lt.m_cmp;
+ verify_fn.cmp = lt->m_cmp;
keyrange range;
range.create(one, one);
verify_fn.expected_txnid = txnid_b;
verify_fn.expected_range = &range;
- locktree_iterate<verify_fn_obj>(&lt, &verify_fn);
- lt.remove_overlapping_locks_for_txnid(txnid_b, one, one);
+ locktree_iterate<verify_fn_obj>(lt, &verify_fn);
+ lt->remove_overlapping_locks_for_txnid(txnid_b, one, one);
}
buffer.destroy();
}
- lt.release_reference();
- lt.destroy();
+ mgr.release_lt(lt);
+ mgr.destroy();
}
} /* namespace toku */
diff --git a/storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc b/storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc
index 5b4eef82b30..6f667c04a74 100644
--- a/storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc
+++ b/storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc
@@ -94,14 +94,17 @@ PATENT RIGHTS GRANT:
namespace toku {
void manager_unit_test::test_create_destroy(void) {
- locktree_manager mgr;
- lt_create_cb create_callback = (lt_create_cb) (long) 1;
- lt_destroy_cb destroy_callback = (lt_destroy_cb) (long) 2;
- lt_escalate_cb escalate_callback = (lt_escalate_cb) (long) 3;
+ locktree::manager mgr;
+ locktree::manager::lt_create_cb create_callback =
+ (locktree::manager::lt_create_cb) (long) 1;
+ locktree::manager::lt_destroy_cb destroy_callback =
+ (locktree::manager::lt_destroy_cb) (long) 2;
+ locktree::manager::lt_escalate_cb escalate_callback =
+ (locktree::manager::lt_escalate_cb) (long) 3;
void *extra = (void *) (long) 4;
mgr.create(create_callback, destroy_callback, escalate_callback, extra);
- invariant(mgr.m_max_lock_memory == locktree_manager::DEFAULT_MAX_LOCK_MEMORY);
+ invariant(mgr.m_max_lock_memory == locktree::manager::DEFAULT_MAX_LOCK_MEMORY);
invariant(mgr.m_current_lock_memory == 0);
invariant(mgr.m_escalation_count == 0);
invariant(mgr.m_escalation_time == 0);
diff --git a/storage/tokudb/ft-index/locktree/tests/manager_locktree_map.cc b/storage/tokudb/ft-index/locktree/tests/manager_locktree_map.cc
index bd35ba93fc9..1235f15f885 100644
--- a/storage/tokudb/ft-index/locktree/tests/manager_locktree_map.cc
+++ b/storage/tokudb/ft-index/locktree/tests/manager_locktree_map.cc
@@ -94,7 +94,7 @@ PATENT RIGHTS GRANT:
namespace toku {
void manager_unit_test::test_lt_map(void) {
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, nullptr, nullptr);
locktree aa;
diff --git a/storage/tokudb/ft-index/locktree/tests/manager_params.cc b/storage/tokudb/ft-index/locktree/tests/manager_params.cc
index 1fbaf2cf330..95642db5121 100644
--- a/storage/tokudb/ft-index/locktree/tests/manager_params.cc
+++ b/storage/tokudb/ft-index/locktree/tests/manager_params.cc
@@ -95,7 +95,7 @@ namespace toku {
void manager_unit_test::test_params(void) {
int r;
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, nullptr, nullptr);
uint64_t new_max_lock_memory = 15307752356;
diff --git a/storage/tokudb/ft-index/locktree/tests/manager_reference_release_lt.cc b/storage/tokudb/ft-index/locktree/tests/manager_reference_release_lt.cc
index 65a2ee478e8..9bf06f77840 100644
--- a/storage/tokudb/ft-index/locktree/tests/manager_reference_release_lt.cc
+++ b/storage/tokudb/ft-index/locktree/tests/manager_reference_release_lt.cc
@@ -108,7 +108,7 @@ static void destroy_cb(locktree *lt) {
}
void manager_unit_test::test_reference_release_lt(void) {
- locktree_manager mgr;
+ locktree::manager mgr;
mgr.create(create_cb, destroy_cb, nullptr, nullptr);
DICTIONARY_ID a = { 0 };
diff --git a/storage/tokudb/ft-index/locktree/tests/manager_status.cc b/storage/tokudb/ft-index/locktree/tests/manager_status.cc
index e73814d8169..6803b5a22b3 100644
--- a/storage/tokudb/ft-index/locktree/tests/manager_status.cc
+++ b/storage/tokudb/ft-index/locktree/tests/manager_status.cc
@@ -112,7 +112,8 @@ static void assert_status(LTM_STATUS ltm_status, const char *keyname, uint64_t v
}
void manager_unit_test::test_status(void) {
- locktree_manager mgr;
+
+ locktree::manager mgr;
mgr.create(nullptr, nullptr, nullptr, nullptr);
LTM_STATUS_S status;
diff --git a/storage/tokudb/ft-index/locktree/tests/range_buffer_test.cc b/storage/tokudb/ft-index/locktree/tests/range_buffer_test.cc
index 38ed2469b69..2fbc27e0d04 100644
--- a/storage/tokudb/ft-index/locktree/tests/range_buffer_test.cc
+++ b/storage/tokudb/ft-index/locktree/tests/range_buffer_test.cc
@@ -93,7 +93,7 @@ PATENT RIGHTS GRANT:
#include <string.h>
-#include <portability/memory.h>
+#include <toku_include/memory.h>
#include <locktree/range_buffer.h>
diff --git a/storage/tokudb/ft-index/portability/CMakeLists.txt b/storage/tokudb/ft-index/portability/CMakeLists.txt
index 93dcf1d1675..e4364357fb0 100644
--- a/storage/tokudb/ft-index/portability/CMakeLists.txt
+++ b/storage/tokudb/ft-index/portability/CMakeLists.txt
@@ -29,19 +29,10 @@ set_property(TARGET ${LIBTOKUPORTABILITY} tokuportability_static_conv APPEND PRO
set_property(SOURCE file memory os_malloc portability toku_assert toku_rwlock APPEND PROPERTY
COMPILE_DEFINITIONS TOKU_ALLOW_DEPRECATED=1)
-configure_file(toku_config.h.in toku_config.h)
-add_custom_target(generate_config_h DEPENDS
- "${CMAKE_CURRENT_BINARY_DIR}/toku_config.h")
-
# detect when we are being built as a subproject
if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
install(
- FILES toku_os_types.h toku_time.h toku_list.h toku_os.h
- DESTINATION include
- COMPONENT tokukv_headers
- )
- install(
- FILES "${CMAKE_CURRENT_BINARY_DIR}/toku_config.h"
+ FILES toku_os_types.h toku_time.h
DESTINATION include
COMPONENT tokukv_headers
)
diff --git a/storage/tokudb/ft-index/portability/huge_page_detection.cc b/storage/tokudb/ft-index/portability/huge_page_detection.cc
index 52f52c7120e..0d376ca521e 100644
--- a/storage/tokudb/ft-index/portability/huge_page_detection.cc
+++ b/storage/tokudb/ft-index/portability/huge_page_detection.cc
@@ -93,8 +93,11 @@ PATENT RIGHTS GRANT:
#include <stdio.h>
#include <string.h>
-#include <portability/toku_assert.h>
-#include <portability/toku_os.h>
+#include <toku_assert.h>
+
+#include "huge_page_detection.h"
+
+extern "C" {
static bool check_huge_pages_config_file(const char *fname)
// Effect: Return true if huge pages are there. If so, print diagnostics.
@@ -107,7 +110,7 @@ static bool check_huge_pages_config_file(const char *fname)
char *r = fgets(buf, sizeof(buf), f);
assert(r != NULL);
if (strstr(buf, "[always]")) {
- fprintf(stderr,"TokuDB: Transparent huge pages are enabled, according to %s. TokuDB will be disabled. To use TokuDB disable huge pages in your kernel or, for testing, set the environment variable TOKU_HUGE_PAGES_OK to 1\n", fname);
+ fprintf(stderr, "Transparent huge pages are enabled, according to %s\n", fname);
huge_pages_enabled = true;
} else {
huge_pages_enabled =false;
@@ -117,6 +120,20 @@ static bool check_huge_pages_config_file(const char *fname)
return huge_pages_enabled;
}
+/* struct mapinfo { */
+/* void *addr; */
+/* size_t size; */
+/* }; */
+
+/* static void* map_it(size_t size, struct mapinfo *mi, int *n_maps) { */
+/* void *r = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); */
+/* if ((long)r==-1) perror("mmap failed"); */
+/* mi[*n_maps].addr = r; */
+/* mi[*n_maps].size = size; */
+/* (*n_maps)++; */
+/* return r; */
+/* } */
+
static bool check_huge_pages_in_practice(void)
// Effect: Return true if huge pages appear to be defined in practice.
{
@@ -178,7 +195,7 @@ static bool check_huge_pages_in_practice(void)
#endif
}
-bool toku_os_huge_pages_enabled(void)
+bool complain_and_return_true_if_huge_pages_are_enabled(void)
// Effect: Return true if huge pages appear to be enabled. If so, print some diagnostics to stderr.
// If environment variable TOKU_HUGE_PAGES_OK is set, then don't complain.
{
@@ -192,3 +209,4 @@ bool toku_os_huge_pages_enabled(void)
return conf1|conf2|prac;
}
}
+}
diff --git a/storage/tokudb/ft-index/portability/huge_page_detection.h b/storage/tokudb/ft-index/portability/huge_page_detection.h
new file mode 100644
index 00000000000..7efcbb2fbfc
--- /dev/null
+++ b/storage/tokudb/ft-index/portability/huge_page_detection.h
@@ -0,0 +1,96 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+
+
+#pragma once
+
+extern "C" bool complain_and_return_true_if_huge_pages_are_enabled(void);
+// Effect: Return true if huge pages appear to be enabled. If so, print some diagnostics to stderr.
+// If environment variable TOKU_HUGE_PAGES_OK is set, then don't complain.
diff --git a/storage/tokudb/ft-index/portability/memory.cc b/storage/tokudb/ft-index/portability/memory.cc
index 6102aaf7c1a..885a94c508b 100644
--- a/storage/tokudb/ft-index/portability/memory.cc
+++ b/storage/tokudb/ft-index/portability/memory.cc
@@ -88,7 +88,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <toku_portability.h>
#include <string.h>
@@ -221,9 +221,6 @@ toku_memory_footprint(void * p, size_t touched) {
void *
toku_malloc(size_t size) {
- if (size > status.max_requested_size) {
- status.max_requested_size = size;
- }
void *p = t_malloc ? t_malloc(size) : os_malloc(size);
if (p) {
TOKU_ANNOTATE_NEW_MEMORY(p, size); // see #4671 and https://bugs.kde.org/show_bug.cgi?id=297147
@@ -236,15 +233,11 @@ toku_malloc(size_t size) {
}
} else {
toku_sync_add_and_fetch(&status.malloc_fail, 1);
- status.last_failed_size = size;
}
return p;
}
void *toku_malloc_aligned(size_t alignment, size_t size) {
- if (size > status.max_requested_size) {
- status.max_requested_size = size;
- }
void *p = t_malloc_aligned ? t_malloc_aligned(alignment, size) : os_malloc_aligned(alignment, size);
if (p) {
TOKU_ANNOTATE_NEW_MEMORY(p, size); // see #4671 and https://bugs.kde.org/show_bug.cgi?id=297147
@@ -257,7 +250,6 @@ void *toku_malloc_aligned(size_t alignment, size_t size) {
}
} else {
toku_sync_add_and_fetch(&status.malloc_fail, 1);
- status.last_failed_size = size;
}
return p;
}
@@ -272,9 +264,6 @@ toku_calloc(size_t nmemb, size_t size) {
void *
toku_realloc(void *p, size_t size) {
- if (size > status.max_requested_size) {
- status.max_requested_size = size;
- }
size_t used_orig = p ? my_malloc_usable_size(p) : 0;
void *q = t_realloc ? t_realloc(p, size) : os_realloc(p, size);
if (q) {
@@ -288,15 +277,11 @@ toku_realloc(void *p, size_t size) {
}
} else {
toku_sync_add_and_fetch(&status.realloc_fail, 1);
- status.last_failed_size = size;
}
return q;
}
void *toku_realloc_aligned(size_t alignment, void *p, size_t size) {
- if (size > status.max_requested_size) {
- status.max_requested_size = size;
- }
size_t used_orig = p ? my_malloc_usable_size(p) : 0;
void *q = t_realloc_aligned ? t_realloc_aligned(alignment, p, size) : os_realloc_aligned(alignment, p, size);
if (q) {
@@ -310,7 +295,6 @@ void *toku_realloc_aligned(size_t alignment, void *p, size_t size) {
}
} else {
toku_sync_add_and_fetch(&status.realloc_fail, 1);
- status.last_failed_size = size;
}
return q;
}
@@ -345,14 +329,9 @@ toku_free(void *p) {
void *
toku_xmalloc(size_t size) {
- if (size > status.max_requested_size) {
- status.max_requested_size = size;
- }
void *p = t_xmalloc ? t_xmalloc(size) : os_malloc(size);
- if (p == NULL) { // avoid function call in common case
- status.last_failed_size = size;
+ if (p == NULL) // avoid function call in common case
resource_assert(p);
- }
TOKU_ANNOTATE_NEW_MEMORY(p, size); // see #4671 and https://bugs.kde.org/show_bug.cgi?id=297147
if (toku_memory_do_stats) {
size_t used = my_malloc_usable_size(p);
@@ -369,14 +348,8 @@ void* toku_xmalloc_aligned(size_t alignment, size_t size)
// Fail with a resource_assert if the allocation fails (don't return an error code).
// Requires: alignment is a power of two.
{
- if (size > status.max_requested_size) {
- status.max_requested_size = size;
- }
void *p = t_xmalloc_aligned ? t_xmalloc_aligned(alignment, size) : os_malloc_aligned(alignment,size);
- if (p == NULL) {
- status.last_failed_size = size;
- resource_assert(p);
- }
+ resource_assert(p);
if (toku_memory_do_stats) {
size_t used = my_malloc_usable_size(p);
toku_sync_add_and_fetch(&status.malloc_count, 1);
@@ -397,15 +370,10 @@ toku_xcalloc(size_t nmemb, size_t size) {
void *
toku_xrealloc(void *v, size_t size) {
- if (size > status.max_requested_size) {
- status.max_requested_size = size;
- }
size_t used_orig = v ? my_malloc_usable_size(v) : 0;
void *p = t_xrealloc ? t_xrealloc(v, size) : os_realloc(v, size);
- if (p == 0) { // avoid function call in common case
- status.last_failed_size = size;
+ if (p == 0) // avoid function call in common case
resource_assert(p);
- }
if (toku_memory_do_stats) {
size_t used = my_malloc_usable_size(p);
toku_sync_add_and_fetch(&status.realloc_count, 1);
diff --git a/storage/tokudb/ft-index/portability/os_malloc.cc b/storage/tokudb/ft-index/portability/os_malloc.cc
index 6db71e958e9..ecc5ea9ca3c 100644
--- a/storage/tokudb/ft-index/portability/os_malloc.cc
+++ b/storage/tokudb/ft-index/portability/os_malloc.cc
@@ -89,7 +89,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <toku_portability.h>
#include <stdlib.h>
diff --git a/storage/tokudb/ft-index/portability/portability.cc b/storage/tokudb/ft-index/portability/portability.cc
index 8fdfb916d94..55437fdc886 100644
--- a/storage/tokudb/ft-index/portability/portability.cc
+++ b/storage/tokudb/ft-index/portability/portability.cc
@@ -88,7 +88,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "$Id$"
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <stdio.h>
#include <stdlib.h>
diff --git a/storage/tokudb/ft-index/portability/tests/test-cache-line-boundary-fails.cc b/storage/tokudb/ft-index/portability/tests/test-cache-line-boundary-fails.cc
index 6e900b15be8..bff4d1bfd18 100644
--- a/storage/tokudb/ft-index/portability/tests/test-cache-line-boundary-fails.cc
+++ b/storage/tokudb/ft-index/portability/tests/test-cache-line-boundary-fails.cc
@@ -89,17 +89,15 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-#include <portability/toku_config.h>
-#include <portability/toku_atomic.h>
-
+#include "toku_config.h"
#include <memory.h>
+#include <portability/toku_atomic.h>
+#include "test.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
-#include "test.h"
-
int verbose = 0;
static const size_t cachelinesize = 64;
diff --git a/storage/tokudb/ft-index/portability/tests/test-fsync.cc b/storage/tokudb/ft-index/portability/tests/test-fsync.cc
index efdfd0dd4f2..843a09b5dc9 100644
--- a/storage/tokudb/ft-index/portability/tests/test-fsync.cc
+++ b/storage/tokudb/ft-index/portability/tests/test-fsync.cc
@@ -221,6 +221,7 @@ time_fsyncs_many_files(int N, int bytes, int fds[/*N*/]) {
}
}
+#if !TOKU_WINDOWS
//sync() does not appear to have an analogue on windows.
static void
time_sync_fsyncs_many_files(int N, int bytes, int fds[/*N*/]) {
@@ -276,6 +277,7 @@ time_sync_fsyncs_many_files(int N, int bytes, int fds[/*N*/]) {
fflush(stdout);
}
}
+#endif
int test_main(int argc, char *const argv[]) {
int i;
@@ -318,7 +320,9 @@ int test_main(int argc, char *const argv[]) {
time_many_fsyncs_one_file(N, bytes, fds);
time_fsyncs_many_files(N, bytes, fds);
+#if !TOKU_WINDOWS
time_sync_fsyncs_many_files(N, bytes, fds);
+#endif
return 0;
}
diff --git a/storage/tokudb/ft-index/portability/tests/test-hugepage.cc b/storage/tokudb/ft-index/portability/tests/test-hugepage.cc
index 61adcac0a69..70a6784da8b 100644
--- a/storage/tokudb/ft-index/portability/tests/test-hugepage.cc
+++ b/storage/tokudb/ft-index/portability/tests/test-hugepage.cc
@@ -88,12 +88,12 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-
-#include <portability/toku_os.h>
-#include <portability/toku_assert.h>
+#include <stdio.h>
+#include <assert.h>
+#include <huge_page_detection.h>
int main(void) {
- bool enabled = toku_os_huge_pages_enabled();
- invariant(!enabled);
+ bool enabled = complain_and_return_true_if_huge_pages_are_enabled();
+ assert(!enabled);
return 0;
}
diff --git a/storage/tokudb/ft-index/portability/tests/test-xid.cc b/storage/tokudb/ft-index/portability/tests/test-xid.cc
index 140f335d0e5..c71b70d499f 100644
--- a/storage/tokudb/ft-index/portability/tests/test-xid.cc
+++ b/storage/tokudb/ft-index/portability/tests/test-xid.cc
@@ -88,7 +88,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <stdio.h>
#include <toku_stdint.h>
#include <unistd.h>
diff --git a/storage/tokudb/ft-index/portability/toku_assert.cc b/storage/tokudb/ft-index/portability/toku_assert.cc
index 860d11d83f4..f3eeba1b0f1 100644
--- a/storage/tokudb/ft-index/portability/toku_assert.cc
+++ b/storage/tokudb/ft-index/portability/toku_assert.cc
@@ -88,7 +88,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <toku_portability.h>
#include "toku_assert.h"
@@ -101,11 +101,16 @@ PATENT RIGHTS GRANT:
# include <sys/malloc.h>
#endif
#include <dlfcn.h>
+#if !TOKU_WINDOWS
#include <execinfo.h>
+#endif
-// These are statically allocated so that the backtrace can run without any calls to malloc()
+
+#if !TOKU_WINDOWS
#define N_POINTERS 1000
+// These are statically allocated so that the backtrace can run without any calls to malloc()
static void *backtrace_pointers[N_POINTERS];
+#endif
static uint64_t engine_status_num_rows = 0;
@@ -118,17 +123,14 @@ toku_assert_init(void)
malloc_stats_f = (malloc_stats_fun_t) dlsym(RTLD_DEFAULT, "malloc_stats");
}
-// Function pointers are zero by default so asserts can be used by ft-layer tests without an environment.
+// Function pointers are zero by default so asserts can be used by brt-layer tests without an environment.
static int (*toku_maybe_get_engine_status_text_p)(char* buff, int buffsize) = 0;
-static int (*toku_maybe_err_engine_status_p)(void) = 0;
static void (*toku_maybe_set_env_panic_p)(int code, const char* msg) = 0;
-void toku_assert_set_fpointers(int (*toku_maybe_get_engine_status_text_pointer)(char*, int),
- int (*toku_maybe_err_engine_status_pointer)(void),
+void toku_assert_set_fpointers(int (*toku_maybe_get_engine_status_text_pointer)(char*, int),
void (*toku_maybe_set_env_panic_pointer)(int, const char*),
uint64_t num_rows) {
toku_maybe_get_engine_status_text_p = toku_maybe_get_engine_status_text_pointer;
- toku_maybe_err_engine_status_p = toku_maybe_err_engine_status_pointer;
toku_maybe_set_env_panic_p = toku_maybe_set_env_panic_pointer;
engine_status_num_rows = num_rows;
}
@@ -136,66 +138,56 @@ void toku_assert_set_fpointers(int (*toku_maybe_get_engine_status_text_pointer)(
bool toku_gdb_dump_on_assert = false;
void (*do_assert_hook)(void) = NULL;
-void db_env_do_backtrace_errfunc(toku_env_err_func errfunc, const void *env) {
- // backtrace
- int n = backtrace(backtrace_pointers, N_POINTERS);
- errfunc(env, 0, "Backtrace: (Note: toku_do_assert=0x%p)\n", toku_do_assert);
- char **syms = backtrace_symbols(backtrace_pointers, n);
- if (syms) {
- for (char **symstr = syms; symstr != NULL && (symstr - syms) < n; ++symstr) {
- errfunc(env, 0, *symstr);
- }
- free(syms);
- }
-
- if (engine_status_num_rows && toku_maybe_err_engine_status_p) {
- toku_maybe_err_engine_status_p();
- } else {
- errfunc(env, 0, "Engine status function not available\n");
- }
- errfunc(env, 0, "Memory usage:\n");
- if (malloc_stats_f) {
- malloc_stats_f();
- }
+static void toku_do_backtrace_abort(void) __attribute__((noreturn));
- if (do_assert_hook) do_assert_hook();
- if (toku_gdb_dump_on_assert) {
- toku_try_gdb_stack_trace(nullptr);
- }
-}
+static void
+toku_do_backtrace_abort(void) {
-void db_env_do_backtrace(FILE *outf) {
// backtrace
+#if !TOKU_WINDOWS
int n = backtrace(backtrace_pointers, N_POINTERS);
- fprintf(outf, "Backtrace: (Note: toku_do_assert=0x%p)\n", toku_do_assert); fflush(outf);
- backtrace_symbols_fd(backtrace_pointers, n, fileno(outf));
+ fprintf(stderr, "Backtrace: (Note: toku_do_assert=0x%p)\n", toku_do_assert); fflush(stderr);
+ backtrace_symbols_fd(backtrace_pointers, n, fileno(stderr));
+#endif
- fflush(outf);
+ fflush(stderr);
if (engine_status_num_rows && toku_maybe_get_engine_status_text_p) {
int buffsize = engine_status_num_rows * 128; // assume 128 characters per row (gross overestimate, should be safe)
char buff[buffsize];
toku_maybe_get_engine_status_text_p(buff, buffsize);
- fprintf(outf, "Engine status:\n%s\n", buff);
- } else {
- fprintf(outf, "Engine status function not available\n");
+ fprintf(stderr, "Engine status:\n%s\n", buff);
}
- fprintf(outf, "Memory usage:\n");
- fflush(outf); // just in case malloc_stats() crashes, we still want engine status (and to know that malloc_stats() failed)
+ else
+ fprintf(stderr, "Engine status function not available\n");
+ fprintf(stderr, "Memory usage:\n");
+ fflush(stderr); // just in case malloc_stats() crashes, we still want engine status (and to know that malloc_stats() failed)
if (malloc_stats_f) {
malloc_stats_f();
}
- fflush(outf);
+ fflush(stderr);
if (do_assert_hook) do_assert_hook();
if (toku_gdb_dump_on_assert) {
toku_try_gdb_stack_trace(nullptr);
}
-}
-__attribute__((noreturn))
-static void toku_do_backtrace_abort(void) {
- db_env_do_backtrace(stderr);
+#if TOKU_WINDOWS
+ //Following commented methods will not always end the process (could hang).
+ //They could be unacceptable for other reasons as well (popups,
+ //flush buffers before quitting, etc)
+ // abort()
+ // assert(false) (assert.h assert)
+ // raise(SIGABRT)
+ // divide by 0
+ // null dereference
+ // _exit
+ // exit
+ // ExitProcess
+ TerminateProcess(GetCurrentProcess(), 134); //Only way found so far to unconditionally
+ //Terminate the process
+#endif
+
abort();
}
diff --git a/storage/tokudb/ft-index/portability/toku_atomic.h b/storage/tokudb/ft-index/portability/toku_atomic.h
index e897d0b7e4a..c24c7ab2607 100644
--- a/storage/tokudb/ft-index/portability/toku_atomic.h
+++ b/storage/tokudb/ft-index/portability/toku_atomic.h
@@ -91,9 +91,8 @@ PATENT RIGHTS GRANT:
#ifndef TOKU_ATOMIC_H
#define TOKU_ATOMIC_H
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <toku_assert.h>
-
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
diff --git a/storage/tokudb/ft-index/portability/toku_byteswap.h b/storage/tokudb/ft-index/portability/toku_byteswap.h
index 4ddeefe2c1b..8c26daf572f 100644
--- a/storage/tokudb/ft-index/portability/toku_byteswap.h
+++ b/storage/tokudb/ft-index/portability/toku_byteswap.h
@@ -91,7 +91,7 @@ PATENT RIGHTS GRANT:
#ifndef TOKU_BYTESWAP_H
#define TOKU_BYTESWAP_H
-#include <portability/toku_config.h>
+#include "toku_config.h"
#if defined(HAVE_BYTESWAP_H)
# include <byteswap.h>
diff --git a/storage/tokudb/ft-index/portability/toku_crash.h b/storage/tokudb/ft-index/portability/toku_crash.h
index 153ab26d460..bd45ee1a1a1 100644
--- a/storage/tokudb/ft-index/portability/toku_crash.h
+++ b/storage/tokudb/ft-index/portability/toku_crash.h
@@ -108,6 +108,9 @@ PATENT RIGHTS GRANT:
//
//Linux:
// abort() and both assert(false) cause FILE buffers to be flushed and written to disk: Unacceptable
+//Windows:
+// None of them cause file buffers to be flushed/written to disk, however
+// abort(), assert(false) <assert.h>, null dereference, and divide by 0 cause popups requiring user intervention during tests: Unacceptable
//
//kill -SIGKILL $pid is annoying (and so far untested)
//
@@ -115,7 +118,11 @@ PATENT RIGHTS GRANT:
//I'm choosing raise(SIGABRT), followed by divide by 0, followed by null dereference, followed by all the others just in case one gets caught.
static void __attribute__((unused, noreturn))
toku_hard_crash_on_purpose(void) {
+#if TOKU_WINDOWS
+ TerminateProcess(GetCurrentProcess(), 137);
+#else
raise(SIGKILL); //Does not flush buffers on linux; cannot be caught.
+#endif
{
int zero = 0;
int infinity = 1/zero;
diff --git a/storage/tokudb/ft-index/portability/toku_htonl.h b/storage/tokudb/ft-index/portability/toku_htonl.h
index 126ba932b87..8d275ebcd0f 100644
--- a/storage/tokudb/ft-index/portability/toku_htonl.h
+++ b/storage/tokudb/ft-index/portability/toku_htonl.h
@@ -95,6 +95,7 @@ PATENT RIGHTS GRANT:
//#error
#endif
+// TODO: This byte order stuff should all be in once place (ie: portability layer, not toku_include)
#include <toku_htod.h>
#include <arpa/inet.h>
diff --git a/storage/tokudb/ft-index/portability/toku_os_types.h b/storage/tokudb/ft-index/portability/toku_os_types.h
index 698bb9f2524..073021e474a 100644
--- a/storage/tokudb/ft-index/portability/toku_os_types.h
+++ b/storage/tokudb/ft-index/portability/toku_os_types.h
@@ -125,8 +125,10 @@ static inline bool toku_fileids_are_equal(struct fileid *a, struct fileid *b) {
typedef struct stat toku_struct_stat;
+// windows compat
#if !defined(O_BINARY)
#define O_BINARY 0
#endif
+
#endif
diff --git a/storage/tokudb/ft-index/portability/toku_pthread.cc b/storage/tokudb/ft-index/portability/toku_pthread.cc
index d023e9427ec..ce174b40705 100644
--- a/storage/tokudb/ft-index/portability/toku_pthread.cc
+++ b/storage/tokudb/ft-index/portability/toku_pthread.cc
@@ -89,7 +89,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#define _GNU_SOURCE 1
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <toku_pthread.h>
int toku_pthread_yield(void) {
diff --git a/storage/tokudb/ft-index/portability/toku_pthread.h b/storage/tokudb/ft-index/portability/toku_pthread.h
index 18edad7c1fa..4ec9dfa9634 100644
--- a/storage/tokudb/ft-index/portability/toku_pthread.h
+++ b/storage/tokudb/ft-index/portability/toku_pthread.h
@@ -213,6 +213,21 @@ toku_mutex_lock(toku_mutex_t *mutex) {
#endif
}
+static inline int
+toku_mutex_trylock(toku_mutex_t *mutex) {
+ int r = pthread_mutex_trylock(&mutex->pmutex);
+#if TOKU_PTHREAD_DEBUG
+ if (r == 0) {
+ invariant(mutex->valid);
+ invariant(!mutex->locked);
+ invariant(mutex->owner == 0);
+ mutex->locked = true;
+ mutex->owner = pthread_self();
+ }
+#endif
+ return r;
+}
+
static inline void
toku_mutex_unlock(toku_mutex_t *mutex) {
#if TOKU_PTHREAD_DEBUG
diff --git a/storage/tokudb/ft-index/portability/toku_random.h b/storage/tokudb/ft-index/portability/toku_random.h
index 956e73990a7..ab317eb6295 100644
--- a/storage/tokudb/ft-index/portability/toku_random.h
+++ b/storage/tokudb/ft-index/portability/toku_random.h
@@ -91,7 +91,7 @@ PATENT RIGHTS GRANT:
#ifndef TOKU_RANDOM_H
#define TOKU_RANDOM_H
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <toku_portability.h>
#include <toku_assert.h>
#include <stdlib.h>
diff --git a/storage/tokudb/ft-index/portability/toku_time.h b/storage/tokudb/ft-index/portability/toku_time.h
index 89b8dcb8524..6c522c5ad8d 100644
--- a/storage/tokudb/ft-index/portability/toku_time.h
+++ b/storage/tokudb/ft-index/portability/toku_time.h
@@ -92,11 +92,11 @@ PATENT RIGHTS GRANT:
#define TOKU_TIME_H
#include "toku_config.h"
-
#include <time.h>
#include <sys/time.h>
#include <stdint.h>
+
static inline float toku_tdiff (struct timeval *a, struct timeval *b) {
return (float)((a->tv_sec - b->tv_sec) + 1e-6 * (a->tv_usec - b->tv_usec));
}
diff --git a/storage/tokudb/ft-index/scripts/run.stress-tests.py b/storage/tokudb/ft-index/scripts/run.stress-tests.py
index d4245a7c4b4..fbbf5ee6472 100755
--- a/storage/tokudb/ft-index/scripts/run.stress-tests.py
+++ b/storage/tokudb/ft-index/scripts/run.stress-tests.py
@@ -735,7 +735,6 @@ if __name__ == '__main__':
'test_stress6.tdb',
'test_stress7.tdb',
'test_stress_hot_indexing.tdb',
- 'test_stress_with_verify.tdb',
'test_stress_openclose.tdb']
default_recover_testnames = ['recover-test_stress1.tdb',
'recover-test_stress2.tdb',
@@ -767,8 +766,8 @@ if __name__ == '__main__':
help="skip the tests that don't involve upgrade [default=False]")
upgrade_group.add_option('--double_upgrade', action='store_true', dest='double_upgrade', default=False,
help='run the upgrade tests twice in a row [default=False]')
- upgrade_group.add_option('--add_old_version', action='append', type='choice', dest='old_versions', choices=['4.2.0', '5.0.8', '5.2.7', '6.0.0', '6.1.0', '6.5.1', '6.6.3', '7.1.6'],
- help='which old versions to use for running the stress tests in upgrade mode. can be specified multiple times [options=4.2.0, 5.0.8, 5.2.7, 6.0.0, 6.1.0, 6.5.1, 6.6.3, 7.1.6]')
+ upgrade_group.add_option('--add_old_version', action='append', type='choice', dest='old_versions', choices=['4.2.0', '5.0.8', '5.2.7', '6.0.0', '6.1.0', '6.5.1', '6.6.3'],
+ help='which old versions to use for running the stress tests in upgrade mode. can be specified multiple times [options=4.2.0, 5.0.8, 5.2.7, 6.0.0, 6.1.0, 6.5.1, 6.6.3]')
upgrade_group.add_option('--old_environments_dir', type='string', dest='old_environments_dir',
default=('%s/old-stress-test-envs' % default_tokudb_data),
help='directory containing old version environments (should contain 5.0.8/, 5.2.7/, etc, and the environments should be in those) [default=../../tokudb.data/stress_environments]')
diff --git a/storage/tokudb/ft-index/scripts/watch.stress-tests.bash b/storage/tokudb/ft-index/scripts/watch.stress-tests.bash
index 9dccbe2bbf5..86d8e495a1a 100755
--- a/storage/tokudb/ft-index/scripts/watch.stress-tests.bash
+++ b/storage/tokudb/ft-index/scripts/watch.stress-tests.bash
@@ -1,3 +1,3 @@
#!/bin/bash
-watch "date ; awk '{ print \$1, \$3 }' < /tmp/stress-tests-log | sort -k 2 | uniq -c | sort -k 3 -r -s | head -n10; echo ; echo; echo 'Failing tests:'; grep FAILED /tmp/stress-tests-log | sort -k 3 -r -s"
+watch "date ; awk '{ print \$1, \$3 }' < /tmp/run.stress-tests.log | tail -n 100 | sort -k 2 | uniq -c | sort -k 3 -r -s | head -n10; echo ; echo; echo 'Failing tests:'; grep FAILED /tmp/run.stress-tests.log | sort -k 3 -r -s"
diff --git a/storage/tokudb/ft-index/src/indexer-undo-do.cc b/storage/tokudb/ft-index/src/indexer-undo-do.cc
index 559dfef7291..2201c4f37e3 100644
--- a/storage/tokudb/ft-index/src/indexer-undo-do.cc
+++ b/storage/tokudb/ft-index/src/indexer-undo-do.cc
@@ -581,8 +581,8 @@ indexer_find_prev_xr(DB_INDEXER *UU(indexer), ULEHANDLE ule, uint64_t xrindex, u
return prev_found;
}
-// inject "delete" message into ft with logging in recovery and rollback logs,
-// and making assocation between txn and ft
+// inject "delete" message into brt with logging in recovery and rollback logs,
+// and making assocation between txn and brt
static int
indexer_ft_delete_provisional(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xids, TOKUTXN txn) {
int result = 0;
@@ -630,8 +630,8 @@ indexer_ft_delete_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xi
return result;
}
-// inject "insert" message into ft with logging in recovery and rollback logs,
-// and making assocation between txn and ft
+// inject "insert" message into brt with logging in recovery and rollback logs,
+// and making assocation between txn and brt
static int
indexer_ft_insert_provisional(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, DBT *hotval, XIDS xids, TOKUTXN txn) {
int result = 0;
@@ -650,7 +650,7 @@ indexer_ft_insert_provisional(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, DBT *
}
// send an insert message into the tree without rollback or recovery logging
-// and without associating the txn and the ft
+// and without associating the txn and the brt
static int
indexer_ft_insert_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, DBT *hotval, XIDS xids) {
int result = 0;
diff --git a/storage/tokudb/ft-index/src/loader.cc b/storage/tokudb/ft-index/src/loader.cc
index 62b4f0b6cef..53db4da092d 100644
--- a/storage/tokudb/ft-index/src/loader.cc
+++ b/storage/tokudb/ft-index/src/loader.cc
@@ -323,15 +323,15 @@ toku_loader_create_loader(DB_ENV *env,
for (int i = 0; i < N; i++) {
new_inames_in_env[i] = nullptr;
}
- FT_HANDLE *XMALLOC_N(N, fts);
+ FT_HANDLE *XMALLOC_N(N, brts);
for (int i=0; i<N; i++) {
- fts[i] = dbs[i]->i->ft_handle;
+ brts[i] = dbs[i]->i->ft_handle;
}
LSN load_lsn;
rval = locked_load_inames(env, loader_txn, N, dbs, new_inames_in_env, &load_lsn, puts_allowed);
if ( rval!=0 ) {
free_inames(new_inames_in_env, N);
- toku_free(fts);
+ toku_free(brts);
goto create_exit;
}
TOKUTXN ttxn = loader_txn ? db_txn_struct_i(loader_txn)->tokutxn : NULL;
@@ -340,7 +340,7 @@ toku_loader_create_loader(DB_ENV *env,
env->i->generate_row_for_put,
src_db,
N,
- fts, dbs,
+ brts, dbs,
(const char **)new_inames_in_env,
compare_functions,
loader->i->temp_file_template,
@@ -352,12 +352,12 @@ toku_loader_create_loader(DB_ENV *env,
puts_allowed);
if ( rval!=0 ) {
free_inames(new_inames_in_env, N);
- toku_free(fts);
+ toku_free(brts);
goto create_exit;
}
loader->i->inames_in_env = new_inames_in_env;
- toku_free(fts);
+ toku_free(brts);
if (!puts_allowed) {
rval = ft_loader_close_and_redirect(loader);
diff --git a/storage/tokudb/ft-index/src/tests/CMakeLists.txt b/storage/tokudb/ft-index/src/tests/CMakeLists.txt
index 366d392143a..c37db9539b9 100644
--- a/storage/tokudb/ft-index/src/tests/CMakeLists.txt
+++ b/storage/tokudb/ft-index/src/tests/CMakeLists.txt
@@ -20,6 +20,9 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
file(GLOB transparent_upgrade_srcs RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" upgrade*.cc)
+ file(GLOB tdb_dontrun_srcs RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" bdb-simple-deadlock*.cc)
+ string(REGEX REPLACE "\\.cc(;|$)" "\\1" tdb_dontrun_tests "${tdb_dontrun_srcs}")
+
file(GLOB srcs RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" *.cc)
list(REMOVE_ITEM srcs ${transparent_upgrade_srcs})
@@ -33,10 +36,332 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
string(REGEX REPLACE "\\.cc(;|$)" ".tdb\\1" stress_tests "${stress_test_srcs}")
set(tdb_srcs ${srcs})
+ list(REMOVE_ITEM tdb_srcs ${tdb_dontrun_srcs})
string(REGEX REPLACE "\\.cc(;|$)" ".tdb\\1" tdb_bins "${tdb_srcs}")
list(REMOVE_ITEM tdb_srcs ${abortrecover_srcs} ${loader_srcs})
string(REGEX REPLACE "\\.cc(;|$)" ".tdb\\1" tdb_tests "${tdb_srcs}")
+ if(BDB_FOUND)
+ set(bdb_dontrun_srcs
+ backwards_10_each_le_and_msg
+ bigtxn27
+ blackhole
+ blocking-prelock-range
+ blocking-set-range-reverse-0
+ blocking-table-lock
+ bug1381
+ bug627
+ cachetable-race
+ checkpoint_callback
+ checkpoint_stress
+ cursor-isolation
+ cursor-set-del-rmw
+ cursor-set-range-rmw
+ db-put-simple-deadlock
+ del-simple
+ del-multiple
+ del-multiple-huge-primary-row
+ del-multiple-srcdb
+ directory_lock
+ diskfull
+ dump-env
+ env_loader_memory
+ env-put-multiple
+ env_nproc
+ env_startup
+ execute-updates
+ filesize
+ get_key_after_bytes_unit
+ get_last_key
+ helgrind1
+ helgrind2
+ helgrind3
+ hotindexer-bw
+ hotindexer-error-callback
+ hotindexer-insert-committed-optimized
+ hotindexer-insert-committed
+ hotindexer-insert-provisional
+ hotindexer-lock-test
+ hotindexer-multiclient
+ hotindexer-nested-insert-committed
+ hotindexer-put-abort
+ hotindexer-put-commit
+ hotindexer-put-multiple
+ hotindexer-simple-abort
+ hotindexer-simple-abort-put
+ hotindexer-undo-do-test
+ hotindexer-with-queries
+ hot-optimize-table-tests
+ insert-dup-prelock
+ isolation
+ isolation-read-committed
+ keyrange
+ keyrange-merge
+ last-verify-time
+ loader-cleanup-test
+ loader-create-abort
+ loader-create-close
+ loader-create-commit-nproc-limit
+ loader-dup-test
+ loader-no-puts
+ loader-nproc-close
+ loader-nproc-create
+ loader-reference-test
+ loader-stress-del
+ loader-stress-test
+ loader-tpch-load
+ locktree_escalation_stalls
+ lock-pressure
+ manyfiles
+ maxsize-for-loader
+ multiprocess
+ mvcc-create-table
+ mvcc-many-committed
+ mvcc-read-committed
+ openlimit17
+ openlimit17-locktree
+ openlimit17-metafiles
+ perf_checkpoint_var
+ perf_child_txn
+ perf_cursor_nop
+ perf_iibench
+ perf_insert
+ perf_insert_multiple
+ perf_malloc_free
+ perf_nop
+ perf_ptquery
+ perf_ptquery2
+ perf_rangequery
+ perf_read_txn
+ perf_read_txn_single_thread
+ perf_read_write
+ perf_txn_single_thread
+ perf_xmalloc_free
+ prelock-read-read
+ prelock-read-write
+ prelock-write-read
+ prelock-write-write
+ print_engine_status
+ powerfail
+ preload-db
+ preload-db-nested
+ progress
+ put-del-multiple-array-indexing
+ put-multiple
+ queries_with_deletes
+ recover-2483
+ recover-3113
+ recover-5146
+ recover-child-rollback
+ recover-compare-db
+ recover-compare-db-descriptor
+ recover-del-multiple
+ recover-del-multiple-abort
+ recover-del-multiple-srcdb-fdelete-all
+ recover-delboth-after-checkpoint
+ recover-delboth-checkpoint
+ recover-descriptor
+ recover-descriptor2
+ recover-descriptor3
+ recover-descriptor4
+ recover-descriptor5
+ recover-descriptor6
+ recover-descriptor7
+ recover-descriptor8
+ recover-descriptor9
+ recover-descriptor10
+ recover-descriptor11
+ recover-descriptor12
+ recover-fclose-in-checkpoint
+ recover-fcreate-basementnodesize
+ recover-flt1
+ recover-flt2
+ recover-flt3
+ recover-flt4
+ recover-flt5
+ recover-flt6
+ recover-flt7
+ recover-flt8
+ recover-flt9
+ recover-flt10
+ recover-hotindexer-simple-abort-put
+ recover-loader-test
+ recover-lsn-filter-multiple
+ recover-put-multiple
+ recover-put-multiple-abort
+ recover-put-multiple-fdelete-all
+ recover-put-multiple-fdelete-some
+ recover-put-multiple-srcdb-fdelete-all
+ recover-split-checkpoint
+ recover-tablelock
+ recover-test-logsuppress
+ recover-test-logsuppress-put
+ recover-test_stress1
+ recover-test_stress2
+ recover-test_stress3
+ recover-test_stress_openclose
+ recover-upgrade-db-descriptor-multihandle
+ recover-upgrade-db-descriptor
+ recover-update-multiple
+ recover-update-multiple-abort
+ recover-update_aborts
+ recover-update_aborts_before_checkpoint
+ recover-update_aborts_before_close
+ recover-update_changes_values
+ recover-update_changes_values_before_checkpoint
+ recover-update_changes_values_before_close
+ recover-update_broadcast_aborts
+ recover-update_broadcast_aborts2
+ recover-update_broadcast_aborts3
+ recover-update_broadcast_aborts_before_checkpoint
+ recover-update_broadcast_aborts_before_close
+ recover-update_broadcast_changes_values
+ recover-update_broadcast_changes_values2
+ recover-update_broadcast_changes_values3
+ recover-update_broadcast_changes_values_before_checkpoint
+ recover-update_broadcast_changes_values_before_close
+ recover-update_changes_values_before_close
+ recovery_fileops_stress
+ recovery_fileops_unit
+ recovery_stress
+ redirect
+ replace-into-write-lock
+ root_fifo_2
+ root_fifo_32
+ root_fifo_41
+ seqinsert
+ shutdown-3344
+ stat64
+ stat64-create-modify-times
+ stat64_flatten
+ stat64-null-txn
+ stat64-root-changes
+ stress-gc
+ stress-gc2
+ test-xa-prepare
+ test1324
+ test1572
+ test3219
+ test3522
+ test3522b
+ test3529
+ test_3645
+ test_3529_insert_2
+ test_3529_table_lock
+ test_3755
+ test_4015
+ test_4368
+ test_4657
+ test_5015
+ test_5469
+ test-5138
+ test938c
+ test_abort1
+ test_abort4
+ test_abort5
+ test_bad_implicit_promotion
+ test_blobs_leaf_split
+ test_bulk_fetch
+ test_compression_methods
+ test_cmp_descriptor
+ test_cursor_interrupt
+ test_cursor_with_read_txn
+ test_db_change_pagesize
+ test_db_change_xxx
+ test_cursor_delete_2119
+ test_db_descriptor
+ test_db_descriptor_named_db
+ test_db_txn_locks_read_uncommitted
+ test_get_max_row_size
+ test_insert_many_gc
+ test_iterate_live_transactions
+ test_iterate_pending_lock_requests
+ test_large_update_broadcast_small_cachetable
+ test_lock_timeout_callback
+ test_locking_with_read_txn
+ test_locktree_close
+ test_logflush
+ test_multiple_checkpoints_block_commit
+ test_query
+ test_read_txn_invalid_ops
+ test_redirect_func
+ test_restrict
+ test_row_size_supported
+ test_simple_read_txn
+ test_stress0
+ test_stress1
+ test_stress2
+ test_stress3
+ test_stress4
+ test_stress5
+ test_stress6
+ test_stress7
+ test_stress_openclose
+ test_stress_with_verify
+ test_stress_hot_indexing
+ test_transactional_descriptor
+ test_trans_desc_during_chkpt
+ test_trans_desc_during_chkpt2
+ test_trans_desc_during_chkpt3
+ test_trans_desc_during_chkpt4
+ test_txn_abort6
+ test_txn_abort8
+ test_txn_abort9
+ test_txn_close_open_commit
+ test_txn_commit8
+ test_txn_nested1
+ test_txn_nested2
+ test_txn_nested3
+ test_txn_nested4
+ test_txn_nested5
+ test_update_abort_works
+ test_update_calls_back
+ test_update_can_delete_elements
+ test_update_changes_values
+ test_update_nonexistent_keys
+ test_update_previously_deleted
+ test_update_stress
+ test_update_txn_snapshot_works_concurrently
+ test_update_txn_snapshot_works_correctly_with_deletes
+ test_update_broadcast_abort_works
+ test_update_broadcast_calls_back
+ test_update_broadcast_can_delete_elements
+ test_update_broadcast_changes_values
+ test_update_broadcast_previously_deleted
+ test_update_broadcast_stress
+ test_update_broadcast_update_fun_has_choices
+ test_update_broadcast_with_empty_table
+ test_update_broadcast_indexer
+ test_update_broadcast_loader
+ test_update_broadcast_nested_updates
+ test_update_nested_updates
+ test_update_with_empty_table
+ test_updates_single_key
+ txn-ignore
+ transactional_fileops
+ update-multiple-data-diagonal
+ update-multiple-key0
+ update-multiple-nochange
+ update-multiple-with-indexer
+ update-multiple-with-indexer-array
+ update
+ upgrade_simple
+ upgrade-test-1
+ upgrade-test-2
+ upgrade-test-3
+ upgrade-test-4
+ upgrade-test-5
+ upgrade-test-6
+ upgrade-test-7
+ zombie_db
+ )
+ set(bdb_srcs ${srcs})
+ string(REGEX REPLACE "\\.cc(;|$)" "\\1" bdb_testbases "${bdb_srcs}")
+ list(REMOVE_ITEM bdb_testbases ${bdb_dontrun_srcs})
+ string(REGEX REPLACE "(.)(;|$)" "\\1.bdb\\2" bdb_tests "${bdb_testbases}")
+ set(bdb_bins ${bdb_tests})
+ endif()
+
set(tdb_tests_that_should_fail
test_db_no_env.tdb
test_log8.recover
@@ -50,7 +375,9 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
## #5138 only reproduces when using the static library.
list(REMOVE_ITEM tdb_bins test-5138.tdb)
add_executable(test-5138.tdb test-5138.cc)
- target_link_libraries(test-5138.tdb ${LIBTOKUDB}_static ${ZLIB_LIBRARY} ${LIBTOKUPORTABILITY}_static ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_SYSTEM_LIBS})
+ target_link_libraries(test-5138.tdb ${LIBTOKUDB}_static z ${LIBTOKUPORTABILITY}_static ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_SYSTEM_LIBS})
+ set_property(TARGET test-5138.tdb APPEND PROPERTY
+ COMPILE_DEFINITIONS "USE_TDB;IS_TDB=1;TOKUDB=1")
add_space_separated_property(TARGET test-5138.tdb COMPILE_FLAGS -fvisibility=hidden)
add_ydb_test(test-5138.tdb)
@@ -63,9 +390,25 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
# We link the test with util directly so that the test code itself can use
# some of those things (i.e. kibbutz in the threaded tests).
target_link_libraries(${base}.tdb util ${LIBTOKUDB} ${LIBTOKUPORTABILITY})
+ set_property(TARGET ${base}.tdb APPEND PROPERTY
+ COMPILE_DEFINITIONS "USE_TDB;IS_TDB=1;TOKUDB=1")
add_space_separated_property(TARGET ${base}.tdb COMPILE_FLAGS -fvisibility=hidden)
endforeach(bin)
+ if(BDB_FOUND)
+ foreach(bin ${bdb_bins})
+ get_filename_component(base ${bin} NAME_WE)
+
+ add_executable(${base}.bdb ${base}.cc)
+ set_property(TARGET ${base}.bdb APPEND PROPERTY
+ COMPILE_DEFINITIONS "USE_BDB;IS_TDB=0;TOKU_ALLOW_DEPRECATED")
+ set_target_properties(${base}.bdb PROPERTIES
+ INCLUDE_DIRECTORIES "${BDB_INCLUDE_DIR};${CMAKE_CURRENT_BINARY_DIR}/../../toku_include;${CMAKE_CURRENT_SOURCE_DIR}/../../toku_include;${CMAKE_CURRENT_SOURCE_DIR}/../../portability;${CMAKE_CURRENT_SOURCE_DIR}/../..")
+ target_link_libraries(${base}.bdb ${LIBTOKUPORTABILITY} ${BDB_LIBRARIES})
+ add_space_separated_property(TARGET ${base}.bdb COMPILE_FLAGS -fvisibility=hidden)
+ endforeach(bin)
+ endif()
+
foreach(bin loader-cleanup-test.tdb diskfull.tdb)
set_property(TARGET ${bin} APPEND PROPERTY
COMPILE_DEFINITIONS DONT_DEPRECATE_WRITES)
@@ -78,6 +421,22 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
endmacro(declare_custom_tests)
declare_custom_tests(test1426.tdb)
+ if(BDB_FOUND)
+ macro(declare_custom_bdb_tests)
+ foreach(test ${ARGN})
+ list(REMOVE_ITEM bdb_tests ${test})
+ endforeach(test)
+ endmacro(declare_custom_bdb_tests)
+
+ declare_custom_bdb_tests(test1426.bdb)
+ configure_file(run_test1426.sh . COPYONLY)
+ add_test(NAME ydb/test1426.tdb
+ COMMAND run_test1426.sh
+ $<TARGET_FILE:test1426.tdb> $<TARGET_FILE:test1426.bdb>
+ "test1426.tdb.ctest-data" "test1426.bdb.ctest-data"
+ $<TARGET_FILE:tokudb_dump> "${BDB_INCLUDE_DIR}/../bin/db_dump")
+ add_dependencies(test1426.tdb tokudb_dump)
+ endif()
string(REGEX REPLACE "\\.cc(;|$)" ".tdb\\1" recover_would_be_tdb_tests "${recover_srcs}")
declare_custom_tests(${recover_would_be_tdb_tests})
@@ -384,7 +743,7 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
setup_toku_test_properties(ydb/${test} ${test})
endforeach()
- foreach(test ${tdb_tests})
+ foreach(test ${tdb_tests} ${bdb_tests})
add_ydb_test(${test})
endforeach(test)
@@ -466,6 +825,16 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
ydb/test_txn_nested5.tdb
ydb/test_update_broadcast_stress.tdb
)
+ if (BDB_FOUND)
+ list(APPEND long_tests
+ ydb/root_fifo_1.bdb
+ ydb/root_fifo_31.bdb
+ ydb/rowsize.bdb
+ ydb/test_log10.bdb
+ ydb/test_log7.bdb
+ ydb/test_logmax.bdb
+ )
+ endif (BDB_FOUND)
set_tests_properties(${long_tests} PROPERTIES TIMEOUT 3600)
## some take even longer, with valgrind
set(extra_long_tests
@@ -481,6 +850,11 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
ydb/test3039.tdb
ydb/test_update_stress.tdb
)
+ if (BDB_FOUND)
+ list(APPEND extra_long_tests
+ ydb/test_groupcommit_count.bdb
+ )
+ endif (BDB_FOUND)
set_tests_properties(${extra_long_tests} PROPERTIES TIMEOUT 7200)
## these really take a long time with valgrind
set(phenomenally_long_tests
@@ -490,5 +864,10 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
ydb/recover_stress.tdb
ydb/test3529.tdb
)
+ if (BDB_FOUND)
+ list(APPEND phenomenally_long_tests
+ ydb/test1426.tdb
+ )
+ endif (BDB_FOUND)
set_tests_properties(${phenomenally_long_tests} PROPERTIES TIMEOUT 14400)
endif(BUILD_TESTING OR BUILD_SRC_TESTS)
diff --git a/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-detect.cc b/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-detect.cc
new file mode 100644
index 00000000000..ce0dcab38a3
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-detect.cc
@@ -0,0 +1,300 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+// verify that the BDB locker can detect deadlocks on the fly and allow
+// the deadlock to be unwound by the deadlocked threads. the main thread
+// polls for deadlocks with the lock_detect function.
+//
+// A write locks L
+// B write locks M
+// A tries to write lock M && B tries to write lock L
+// One of A or B gets the DEADLOCK error, the other waits
+// A and B release their locks
+
+#include "test.h"
+#include "toku_pthread.h"
+#include <portability/toku_atomic.h>
+
+struct test_seq {
+ int state;
+ toku_mutex_t lock;
+ toku_cond_t cv;
+};
+
+static void test_seq_init(struct test_seq *seq) {
+ seq->state = 0;
+ toku_mutex_init(&seq->lock, NULL);
+ toku_cond_init(&seq->cv, NULL);
+}
+
+static void test_seq_destroy(struct test_seq *seq) {
+ toku_mutex_destroy(&seq->lock);
+ toku_cond_destroy(&seq->cv);
+}
+
+static void test_seq_sleep(struct test_seq *seq, int new_state) {
+ toku_mutex_lock(&seq->lock);
+ while (seq->state != new_state) {
+ toku_cond_wait(&seq->cv, &seq->lock);
+ }
+ toku_mutex_unlock(&seq->lock);
+}
+
+static void test_seq_next_state(struct test_seq *seq) {
+ toku_mutex_lock(&seq->lock);
+ seq->state++;
+ toku_cond_broadcast(&seq->cv);
+ toku_mutex_unlock(&seq->lock);
+}
+
+struct locker_args {
+ DB_ENV *db_env;
+ struct test_seq *test_seq;
+ int *deadlock_count;
+};
+
+static void *run_locker_a(void *arg) {
+ struct locker_args *locker_args = (struct locker_args *) arg;
+ DB_ENV *db_env = locker_args->db_env;
+ struct test_seq *test_seq = locker_args->test_seq;
+ int r;
+
+ uint32_t locker_a;
+ r = db_env->lock_id(db_env, &locker_a); assert(r == 0);
+
+ DBT object_l = { .data = (char *) "L", .size = 1 };
+ DBT object_m = { .data = (char *) "M", .size = 1 };
+
+ test_seq_sleep(test_seq, 0);
+ DB_LOCK lock_a_l;
+ r = db_env->lock_get(db_env, locker_a, DB_LOCK_NOWAIT, &object_l, DB_LOCK_WRITE, &lock_a_l); assert(r == 0);
+ test_seq_next_state(test_seq);
+
+ test_seq_sleep(test_seq, 2);
+ DB_LOCK lock_a_m;
+ bool m_locked = false;
+ r = db_env->lock_get(db_env, locker_a, 0, &object_m, DB_LOCK_WRITE, &lock_a_m);
+ assert(r == 0 || r == DB_LOCK_DEADLOCK);
+ if (r == 0)
+ m_locked = true;
+
+ r = db_env->lock_put(db_env, &lock_a_l); assert(r == 0);
+
+ if (m_locked) {
+ r = db_env->lock_put(db_env, &lock_a_m); assert(r == 0);
+ } else {
+ (void) toku_sync_fetch_and_add(locker_args->deadlock_count, 1);
+ if (verbose) printf("%s:%u m deadlock\n", __FUNCTION__, __LINE__);
+ }
+
+ r = db_env->lock_id_free(db_env, locker_a); assert(r == 0);
+
+ return arg;
+}
+
+static void *run_locker_b(void *arg) {
+ struct locker_args *locker_args = (struct locker_args *) arg;
+ DB_ENV *db_env = locker_args->db_env;
+ struct test_seq *test_seq = locker_args->test_seq;
+ int r;
+
+ uint32_t locker_b;
+ r = db_env->lock_id(db_env, &locker_b); assert(r == 0);
+
+ DBT object_l = { .data = (char *) "L", .size = 1 };
+ DBT object_m = { .data = (char *) "M", .size = 1 };
+
+ test_seq_sleep(test_seq, 1);
+ DB_LOCK lock_b_m;
+ r = db_env->lock_get(db_env, locker_b, DB_LOCK_NOWAIT, &object_m, DB_LOCK_WRITE, &lock_b_m); assert(r == 0);
+ test_seq_next_state(test_seq);
+
+ test_seq_sleep(test_seq, 2);
+ DB_LOCK lock_b_l;
+ bool l_locked = false;
+ r = db_env->lock_get(db_env, locker_b, 0, &object_l, DB_LOCK_WRITE, &lock_b_l);
+ assert(r == 0 || r == DB_LOCK_DEADLOCK);
+ if (r == 0)
+ l_locked = true;
+
+ r = db_env->lock_put(db_env, &lock_b_m); assert(r == 0);
+
+ if (l_locked) {
+ r = db_env->lock_put(db_env, &lock_b_l); assert(r == 0);
+ } else {
+ (void) toku_sync_fetch_and_add(locker_args->deadlock_count, 1);
+ if (verbose) printf("%s:%u l deadlock\n", __FUNCTION__, __LINE__);
+ }
+
+ r = db_env->lock_id_free(db_env, locker_b); assert(r == 0);
+
+ return arg;
+}
+
+static void simple_deadlock(DB_ENV *db_env) {
+ int r;
+
+ struct test_seq test_seq; ZERO_STRUCT(test_seq); test_seq_init(&test_seq);
+
+ int deadlock_count = 0 ;
+
+ toku_pthread_t tid_a;
+ struct locker_args args_a = { db_env, &test_seq, &deadlock_count };
+ r = toku_pthread_create(&tid_a, NULL, run_locker_a, &args_a); assert(r == 0);
+
+ toku_pthread_t tid_b;
+ struct locker_args args_b = { db_env, &test_seq, &deadlock_count };
+ r = toku_pthread_create(&tid_b, NULL, run_locker_b, &args_b); assert(r == 0);
+
+ while (1) {
+ sleep(10);
+ int rejected = 0;
+ r = db_env->lock_detect(db_env, 0, DB_LOCK_YOUNGEST, &rejected); assert(r == 0);
+ if (verbose)
+ printf("%s %d\n", __FUNCTION__, rejected);
+ if (rejected == 0)
+ break;
+ }
+
+ void *ret = NULL;
+ r = toku_pthread_join(tid_a, &ret); assert(r == 0);
+ r = toku_pthread_join(tid_b, &ret); assert(r == 0);
+
+ assert(deadlock_count == 1);
+
+ test_seq_destroy(&test_seq);
+}
+
+int test_main(int argc, char * const argv[]) {
+ uint64_t cachesize = 0;
+ int do_txn = 1;
+ const char *db_env_dir = TOKU_TEST_FILENAME;
+ int db_env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_THREAD;
+
+ // parse_args(argc, argv);
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0) {
+ if (verbose > 0)
+ verbose--;
+ continue;
+ }
+ assert(0);
+ }
+
+ // setup env
+ int r;
+ char rm_cmd[strlen(db_env_dir) + strlen("rm -rf ") + 1];
+ snprintf(rm_cmd, sizeof(rm_cmd), "rm -rf %s", db_env_dir);
+ r = system(rm_cmd); assert(r == 0);
+
+ r = toku_os_mkdir(db_env_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); assert(r == 0);
+
+ DB_ENV *db_env = NULL;
+ r = db_env_create(&db_env, 0); assert(r == 0);
+ if (cachesize) {
+ const uint64_t gig = 1 << 30;
+ r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
+ }
+ if (!do_txn)
+ db_env_open_flags &= ~(DB_INIT_TXN | DB_INIT_LOG);
+ r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+
+ // run test
+ simple_deadlock(db_env);
+
+ // close env
+ r = db_env->close(db_env, 0); assert(r == 0); db_env = NULL;
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-nowait.cc b/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-nowait.cc
new file mode 100644
index 00000000000..036fb8d0115
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-nowait.cc
@@ -0,0 +1,177 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+// verify that a simle write lock deadlock is detected by the BDB locker
+// A write locks L
+// B write locks M
+// A tries to write lock M, gets DB_LOCK_NOTGRANTED
+// B tries to write lock L, gets DB_LOCK_NOTGRANTED
+
+#include "test.h"
+
+static void simple_deadlock(DB_ENV *db_env) {
+ int r;
+
+ uint32_t locker_a;
+ r = db_env->lock_id(db_env, &locker_a); assert(r == 0);
+ uint32_t locker_b;
+ r = db_env->lock_id(db_env, &locker_b); assert(r == 0);
+
+ DBT object_l = { .data = (char *) "L", .size = 1 };
+ DBT object_m = { .data = (char *) "M", .size = 1 };
+
+ DB_LOCK lock_a_l;
+ r = db_env->lock_get(db_env, locker_a, DB_LOCK_NOWAIT, &object_l, DB_LOCK_WRITE, &lock_a_l); assert(r == 0);
+
+ DB_LOCK lock_b_m;
+ r = db_env->lock_get(db_env, locker_b, DB_LOCK_NOWAIT, &object_m, DB_LOCK_WRITE, &lock_b_m); assert(r == 0);
+
+ DB_LOCK lock_a_m;
+ r = db_env->lock_get(db_env, locker_a, DB_LOCK_NOWAIT, &object_m, DB_LOCK_WRITE, &lock_a_m); assert(r == DB_LOCK_NOTGRANTED);
+
+ DB_LOCK lock_b_l;
+ r = db_env->lock_get(db_env, locker_b, DB_LOCK_NOWAIT, &object_l, DB_LOCK_WRITE, &lock_b_l); assert(r == DB_LOCK_NOTGRANTED);
+
+ r = db_env->lock_put(db_env, &lock_a_l); assert(r == 0);
+ r = db_env->lock_put(db_env, &lock_b_m); assert(r == 0);
+
+ r = db_env->lock_id_free(db_env, locker_a); assert(r == 0);
+ r = db_env->lock_id_free(db_env, locker_b); assert(r == 0);
+}
+
+int test_main(int argc, char * const argv[]) {
+ uint64_t cachesize = 0;
+ int do_txn = 1;
+ const char *db_env_dir = TOKU_TEST_FILENAME;
+ int db_env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_THREAD;
+
+ // parse_args(argc, argv);
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0) {
+ if (verbose > 0)
+ verbose--;
+ continue;
+ }
+ assert(0);
+ }
+
+ // setup env
+ int r;
+ char rm_cmd[strlen(db_env_dir) + strlen("rm -rf ") + 1];
+ snprintf(rm_cmd, sizeof(rm_cmd), "rm -rf %s", db_env_dir);
+ r = system(rm_cmd); assert(r == 0);
+
+ r = toku_os_mkdir(db_env_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); assert(r == 0);
+
+ DB_ENV *db_env = NULL;
+ r = db_env_create(&db_env, 0); assert(r == 0);
+ if (cachesize) {
+ const uint64_t gig = 1 << 30;
+ r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
+ }
+ if (!do_txn)
+ db_env_open_flags &= ~(DB_INIT_TXN | DB_INIT_LOG);
+ r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if 0 && defined(USE_BDB)
+ r = db_env->set_lk_detect(db_env, DB_LOCK_YOUNGEST); assert(r == 0);
+#endif
+
+ // run test
+ simple_deadlock(db_env);
+
+ // close env
+ r = db_env->close(db_env, 0); assert(r == 0); db_env = NULL;
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-on-the-fly.cc b/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-on-the-fly.cc
new file mode 100644
index 00000000000..12386e173c3
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/bdb-simple-deadlock-on-the-fly.cc
@@ -0,0 +1,292 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+// verify that the BDB locker can detect deadlocks on the fly and allow
+// the deadlock to be unwound by the deadlocked threads. we use the
+// set_lk_detect function to force the locker to check for deadlocks.
+//
+// A write locks L
+// B write locks M
+// A tries to write lock M && B tries to write lock L
+// One of A or B should get the DEADLOCK error, the other waits
+// A and B release their locks
+
+#include "test.h"
+#include "toku_pthread.h"
+#include <portability/toku_atomic.h>
+
+struct test_seq {
+ int state;
+ toku_mutex_t lock;
+ toku_cond_t cv;
+};
+
+static void test_seq_init(struct test_seq *seq) {
+ seq->state = 0;
+ toku_mutex_init(&seq->lock, NULL);
+ toku_cond_init(&seq->cv, NULL);
+}
+
+static void test_seq_destroy(struct test_seq *seq) {
+ toku_mutex_destroy(&seq->lock);
+ toku_cond_destroy(&seq->cv);
+}
+
+static void test_seq_sleep(struct test_seq *seq, int new_state) {
+ toku_mutex_lock(&seq->lock);
+ while (seq->state != new_state) {
+ toku_cond_wait(&seq->cv, &seq->lock);
+ }
+ toku_mutex_unlock(&seq->lock);
+}
+
+static void test_seq_next_state(struct test_seq *seq) {
+ toku_mutex_lock(&seq->lock);
+ seq->state++;
+ toku_cond_broadcast(&seq->cv);
+ toku_mutex_unlock(&seq->lock);
+}
+
+struct locker_args {
+ DB_ENV *db_env;
+ struct test_seq *test_seq;
+ int *deadlock_count;
+};
+
+static void *run_locker_a(void *arg) {
+ struct locker_args *locker_args = (struct locker_args *) arg;
+ DB_ENV *db_env = locker_args->db_env;
+ struct test_seq *test_seq = locker_args->test_seq;
+ int r;
+
+ uint32_t locker_a;
+ r = db_env->lock_id(db_env, &locker_a); assert(r == 0);
+
+ DBT object_l = { .data = (char *) "L", .size = 1 };
+ DBT object_m = { .data = (char *) "M", .size = 1 };
+
+ test_seq_sleep(test_seq, 0);
+ DB_LOCK lock_a_l;
+ r = db_env->lock_get(db_env, locker_a, DB_LOCK_NOWAIT, &object_l, DB_LOCK_WRITE, &lock_a_l); assert(r == 0);
+ test_seq_next_state(test_seq);
+
+ test_seq_sleep(test_seq, 2);
+ DB_LOCK lock_a_m;
+ bool m_locked = false;
+ r = db_env->lock_get(db_env, locker_a, 0, &object_m, DB_LOCK_WRITE, &lock_a_m);
+ assert(r == 0 || r == DB_LOCK_DEADLOCK);
+ if (r == 0)
+ m_locked = true;
+
+ r = db_env->lock_put(db_env, &lock_a_l); assert(r == 0);
+
+ if (m_locked) {
+ r = db_env->lock_put(db_env, &lock_a_m); assert(r == 0);
+ } else {
+ (void) toku_sync_fetch_and_add(locker_args->deadlock_count, 1);
+ if (verbose) printf("%s:%u m deadlock\n", __FUNCTION__, __LINE__);
+ }
+
+ r = db_env->lock_id_free(db_env, locker_a); assert(r == 0);
+
+ return arg;
+}
+
+static void *run_locker_b(void *arg) {
+ struct locker_args *locker_args = (struct locker_args *) arg;
+ DB_ENV *db_env = locker_args->db_env;
+ struct test_seq *test_seq = locker_args->test_seq;
+ int r;
+
+ uint32_t locker_b;
+ r = db_env->lock_id(db_env, &locker_b); assert(r == 0);
+
+ DBT object_l = { .data = (char *) "L", .size = 1 };
+ DBT object_m = { .data = (char *) "M", .size = 1 };
+
+ test_seq_sleep(test_seq, 1);
+ DB_LOCK lock_b_m;
+ r = db_env->lock_get(db_env, locker_b, DB_LOCK_NOWAIT, &object_m, DB_LOCK_WRITE, &lock_b_m); assert(r == 0);
+ test_seq_next_state(test_seq);
+
+ test_seq_sleep(test_seq, 2);
+ DB_LOCK lock_b_l;
+ bool l_locked = false;
+ r = db_env->lock_get(db_env, locker_b, 0, &object_l, DB_LOCK_WRITE, &lock_b_l);
+ assert(r == 0 || r == DB_LOCK_DEADLOCK);
+ if (r == 0)
+ l_locked = true;
+
+ r = db_env->lock_put(db_env, &lock_b_m); assert(r == 0);
+
+ if (l_locked) {
+ r = db_env->lock_put(db_env, &lock_b_l); assert(r == 0);
+ } else {
+ (void) toku_sync_fetch_and_add(locker_args->deadlock_count, 1);
+ if (verbose) printf("%s:%u l deadlock\n", __FUNCTION__, __LINE__);
+ }
+
+ r = db_env->lock_id_free(db_env, locker_b); assert(r == 0);
+
+ return arg;
+}
+
+static void simple_deadlock(DB_ENV *db_env) {
+ int r;
+ int deadlock_count = 0;
+
+ struct test_seq test_seq; ZERO_STRUCT(test_seq); test_seq_init(&test_seq);
+
+ toku_pthread_t tid_a;
+ struct locker_args args_a = { db_env, &test_seq, &deadlock_count };
+ r = toku_pthread_create(&tid_a, NULL, run_locker_a, &args_a); assert(r == 0);
+
+ toku_pthread_t tid_b;
+ struct locker_args args_b = { db_env, &test_seq, &deadlock_count };
+ r = toku_pthread_create(&tid_b, NULL, run_locker_b, &args_b); assert(r == 0);
+
+ void *ret = NULL;
+ r = toku_pthread_join(tid_a, &ret); assert(r == 0);
+ r = toku_pthread_join(tid_b, &ret); assert(r == 0);
+
+ assert(deadlock_count == 1);
+
+ test_seq_destroy(&test_seq);
+}
+
+int test_main(int argc, char * const argv[]) {
+ uint64_t cachesize = 0;
+ int do_txn = 1;
+ const char *db_env_dir = TOKU_TEST_FILENAME;
+ int db_env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_THREAD;
+
+ // parse_args(argc, argv);
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0) {
+ if (verbose > 0)
+ verbose--;
+ continue;
+ }
+ assert(0);
+ }
+
+ // setup env
+ int r;
+ char rm_cmd[strlen(db_env_dir) + strlen("rm -rf ") + 1];
+ snprintf(rm_cmd, sizeof(rm_cmd), "rm -rf %s", db_env_dir);
+ r = system(rm_cmd); assert(r == 0);
+
+ r = toku_os_mkdir(db_env_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); assert(r == 0);
+
+ DB_ENV *db_env = NULL;
+ r = db_env_create(&db_env, 0); assert(r == 0);
+ if (cachesize) {
+ const uint64_t gig = 1 << 30;
+ r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
+ }
+ if (!do_txn)
+ db_env_open_flags &= ~(DB_INIT_TXN | DB_INIT_LOG);
+ r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if defined(USE_BDB)
+ r = db_env->set_lk_detect(db_env, DB_LOCK_YOUNGEST); assert(r == 0);
+#endif
+
+ // run test
+ simple_deadlock(db_env);
+
+ // close env
+ r = db_env->close(db_env, 0); assert(r == 0); db_env = NULL;
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/bdb.suppressions b/storage/tokudb/ft-index/src/tests/bdb.suppressions
new file mode 100644
index 00000000000..5e06d9a84e7
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/bdb.suppressions
@@ -0,0 +1,87 @@
+{
+ bdb_writes_undefined_data_to_disk
+ Memcheck:Param
+ pwrite64(buf)
+ fun:pwrite64
+ fun:__os_io
+ obj:/lib/libdb-4.3.so
+ fun:__memp_bhwrite
+ fun:__memp_sync_int
+ fun:__memp_fsync
+ fun:__db_sync
+ fun:__db_refresh
+ fun:__db_close
+ fun:__fop_subdb_setup
+ fun:__db_open
+ fun:__db_open_pp
+}
+
+{
+ bdb_leaks_db_home_strdup
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:__os_malloc
+ fun:__os_strdup
+ fun:__db_open_pp
+ fun:main
+}
+
+{
+ bdb_leaks_in_db_create
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:__os_malloc
+ fun:__os_calloc
+ fun:__bam_db_create
+ fun:db_create
+ fun:main
+}
+
+{
+ bdb_leaks_if_you_open_twice
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:__os_malloc
+ fun:__os_strdup
+ fun:__db_open_pp
+}
+
+{
+ bdb_leaks_again
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:__os_malloc
+ fun:__os_strdup
+ fun:__db_home
+ obj:/lib/libdb-4.3.so
+ fun:__dbenv_open
+}
+
+{
+ <bdb_leaks>
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:__os_malloc
+ fun:__os_calloc
+ fun:__bam_db_create
+ fun:db_create
+}
+
+{
+ <bdb_leaks>
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:__os_malloc
+ fun:__os_calloc
+ fun:__bam_db_create
+ fun:db_create
+}
+
+{
+ <bdb_leaks>
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:__os_malloc
+ fun:__os_calloc
+ fun:db_create
+}
diff --git a/storage/tokudb/ft-index/src/tests/big-nested-abort-abort.cc b/storage/tokudb/ft-index/src/tests/big-nested-abort-abort.cc
index 882c3441a8f..0707773d6b5 100644
--- a/storage/tokudb/ft-index/src/tests/big-nested-abort-abort.cc
+++ b/storage/tokudb/ft-index/src/tests/big-nested-abort-abort.cc
@@ -175,7 +175,11 @@ setup (void) {
r=db_env_create(&env, 0); CKERR(r);
+#ifndef TOKUDB
+ r=env->set_lk_max_objects(env, N); CKERR(r);
+#else
r=env->set_redzone(env, 0); CKERR(r);
+#endif
env->set_errfile(env, stderr);
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/big-nested-abort-commit.cc b/storage/tokudb/ft-index/src/tests/big-nested-abort-commit.cc
index 98dde05cfde..711f235275e 100644
--- a/storage/tokudb/ft-index/src/tests/big-nested-abort-commit.cc
+++ b/storage/tokudb/ft-index/src/tests/big-nested-abort-commit.cc
@@ -174,6 +174,9 @@ setup (void) {
r=db_env_create(&env, 0); CKERR(r);
+#ifndef TOKUDB
+ r=env->set_lk_max_objects(env, N); CKERR(r);
+#endif
env->set_errfile(env, stderr);
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/big-nested-commit-abort.cc b/storage/tokudb/ft-index/src/tests/big-nested-commit-abort.cc
index ec8707530fa..0469867396d 100644
--- a/storage/tokudb/ft-index/src/tests/big-nested-commit-abort.cc
+++ b/storage/tokudb/ft-index/src/tests/big-nested-commit-abort.cc
@@ -169,6 +169,9 @@ setup (void) {
r=db_env_create(&env, 0); CKERR(r);
+#ifndef TOKUDB
+ r=env->set_lk_max_objects(env, N); CKERR(r);
+#endif
env->set_errfile(env, stderr);
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/big-nested-commit-commit.cc b/storage/tokudb/ft-index/src/tests/big-nested-commit-commit.cc
index 189bc97769f..ad25b5e90e8 100644
--- a/storage/tokudb/ft-index/src/tests/big-nested-commit-commit.cc
+++ b/storage/tokudb/ft-index/src/tests/big-nested-commit-commit.cc
@@ -168,8 +168,13 @@ setup (void) {
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
r=env->set_redzone(env, 0); CKERR(r);
+#endif
+#ifndef TOKUDB
+ r=env->set_lk_max_objects(env, N); CKERR(r);
+#endif
env->set_errfile(env, stderr);
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/blocking-first-empty.cc b/storage/tokudb/ft-index/src/tests/blocking-first-empty.cc
index 6ccf879005d..72267437a4a 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-first-empty.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-first-empty.cc
@@ -98,6 +98,7 @@ struct my_callback_context {
DBT val;
};
+#if TOKUDB
static int blocking_first_callback(DBT const *a UU(), DBT const *b UU(), void *e UU()) {
DBT const *found_key = a;
DBT const *found_val = b;
@@ -106,6 +107,7 @@ static int blocking_first_callback(DBT const *a UU(), DBT const *b UU(), void *e
copy_dbt(&context->val, found_val);
return 0;
}
+#endif
static void blocking_first(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptime) {
int r;
@@ -120,7 +122,11 @@ static void blocking_first(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptim
DBC *cursor = NULL;
r = db->cursor(db, txn, &cursor, 0); assert(r == 0); // get a write lock on -inf +inf
+#if TOKUDB
r = cursor->c_getf_first(cursor, DB_RMW, blocking_first_callback, &context); assert(r == DB_NOTFOUND);
+#else
+ r = cursor->c_get(cursor, &context.key, &context.val, DB_FIRST + DB_RMW); assert(r == DB_NOTFOUND);
+#endif
usleep(sleeptime);
@@ -213,7 +219,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-first.cc b/storage/tokudb/ft-index/src/tests/blocking-first.cc
index 6d255023274..1bd414a90aa 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-first.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-first.cc
@@ -116,6 +116,7 @@ struct my_callback_context {
DBT val;
};
+#if TOKUDB
static int blocking_first_callback(DBT const *a UU(), DBT const *b UU(), void *e UU()) {
DBT const *found_key = a;
DBT const *found_val = b;
@@ -124,6 +125,7 @@ static int blocking_first_callback(DBT const *a UU(), DBT const *b UU(), void *e
copy_dbt(&context->val, found_val);
return 0;
}
+#endif
static void blocking_first(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptime) {
int r;
@@ -138,7 +140,11 @@ static void blocking_first(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptim
DBC *cursor = NULL;
r = db->cursor(db, txn, &cursor, 0); assert(r == 0); // get a write lock on -inf ... 0
+#if TOKUDB
r = cursor->c_getf_first(cursor, DB_RMW, blocking_first_callback, &context); assert(r == 0);
+#else
+ r = cursor->c_get(cursor, &context.key, &context.val, DB_FIRST + DB_RMW); assert(r == 0);
+#endif
usleep(sleeptime);
r = cursor->c_close(cursor); assert(r == 0);
@@ -230,7 +236,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-last.cc b/storage/tokudb/ft-index/src/tests/blocking-last.cc
index 403f31bca61..5ca6ce5ec6a 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-last.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-last.cc
@@ -116,6 +116,7 @@ struct my_callback_context {
DBT val;
};
+#if TOKUDB
static int blocking_last_callback(DBT const *a UU(), DBT const *b UU(), void *e UU()) {
DBT const *found_key = a;
DBT const *found_val = b;
@@ -124,6 +125,7 @@ static int blocking_last_callback(DBT const *a UU(), DBT const *b UU(), void *e
copy_dbt(&context->val, found_val);
return 0;
}
+#endif
static void blocking_last(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptime) {
int r;
@@ -138,7 +140,11 @@ static void blocking_last(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptime
DBC *cursor = NULL;
r = db->cursor(db, txn, &cursor, 0); assert(r == 0); // get a write lock on -inf ... 0
+#if TOKUDB
r = cursor->c_getf_last(cursor, DB_RMW, blocking_last_callback, &context); assert(r == 0);
+#else
+ r = cursor->c_get(cursor, &context.key, &context.val, DB_LAST + DB_RMW); assert(r == 0);
+#endif
usleep(sleeptime);
r = cursor->c_close(cursor); assert(r == 0);
@@ -230,7 +236,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-next-prev-deadlock.cc b/storage/tokudb/ft-index/src/tests/blocking-next-prev-deadlock.cc
index f71c89aa3e7..fb591feff28 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-next-prev-deadlock.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-next-prev-deadlock.cc
@@ -124,6 +124,7 @@ struct my_callback_context {
DBT val;
};
+#if TOKUDB
static int blocking_next_callback(DBT const *a UU(), DBT const *b UU(), void *e UU()) {
DBT const *found_key = a;
DBT const *found_val = b;
@@ -132,6 +133,7 @@ static int blocking_next_callback(DBT const *a UU(), DBT const *b UU(), void *e
copy_dbt(&context->val, found_val);
return 0;
}
+#endif
static void blocking_next(DB_ENV *db_env, DB *db, uint64_t nrows UU(), long sleeptime) {
int r;
@@ -148,7 +150,11 @@ static void blocking_next(DB_ENV *db_env, DB *db, uint64_t nrows UU(), long slee
uint64_t i;
for (i = 0; ; i++) {
+#if TOKUDB
r = cursor->c_getf_next(cursor, DB_RMW, blocking_next_callback, &context);
+#else
+ r = cursor->c_get(cursor, &context.key, &context.val, DB_NEXT + DB_RMW);
+#endif
if (r != 0)
break;
if (verbose)
@@ -190,7 +196,11 @@ static void blocking_prev(DB_ENV *db_env, DB *db, uint64_t nrows UU(), long slee
uint64_t i;
for (i = 0; ; i++) {
+#if TOKUDB
r = cursor->c_getf_prev(cursor, DB_RMW, blocking_next_callback, &context);
+#else
+ r = cursor->c_get(cursor, &context.key, &context.val, DB_PREV + DB_RMW);
+#endif
if (r != 0)
break;
if (verbose)
@@ -295,7 +305,11 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#else
+ r = db_env->set_lk_detect(db_env, DB_LOCK_YOUNGEST); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-next-prev.cc b/storage/tokudb/ft-index/src/tests/blocking-next-prev.cc
index ec1ae8ff340..86644a13cf5 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-next-prev.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-next-prev.cc
@@ -123,6 +123,7 @@ struct my_callback_context {
DBT val;
};
+#if TOKUDB
static int blocking_next_callback(DBT const *a UU(), DBT const *b UU(), void *e UU()) {
DBT const *found_key = a;
DBT const *found_val = b;
@@ -131,6 +132,7 @@ static int blocking_next_callback(DBT const *a UU(), DBT const *b UU(), void *e
copy_dbt(&context->val, found_val);
return 0;
}
+#endif
static void blocking_next(DB_ENV *db_env, DB *db, uint64_t nrows UU(), long sleeptime) {
int r;
@@ -147,7 +149,11 @@ static void blocking_next(DB_ENV *db_env, DB *db, uint64_t nrows UU(), long slee
uint64_t i;
for (i = 0; ; i++) {
+#if TOKUDB
r = cursor->c_getf_next(cursor, 0, blocking_next_callback, &context);
+#else
+ r = cursor->c_get(cursor, &context.key, &context.val, DB_NEXT);
+#endif
if (r != 0)
break;
if (verbose)
@@ -193,7 +199,11 @@ static void blocking_prev(DB_ENV *db_env, DB *db, uint64_t nrows UU(), long slee
uint64_t i;
for (i = 0; ; i++) {
+#if TOKUDB
r = cursor->c_getf_prev(cursor, 0, blocking_next_callback, &context);
+#else
+ r = cursor->c_get(cursor, &context.key, &context.val, DB_PREV);
+#endif
if (r != 0)
break;
if (verbose)
diff --git a/storage/tokudb/ft-index/src/tests/blocking-prelock-range.cc b/storage/tokudb/ft-index/src/tests/blocking-prelock-range.cc
index 15065dcf244..cece47cbeec 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-prelock-range.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-prelock-range.cc
@@ -181,7 +181,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-put-timeout.cc b/storage/tokudb/ft-index/src/tests/blocking-put-timeout.cc
index b91198a4438..c43bcfad5f0 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-put-timeout.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-put-timeout.cc
@@ -156,7 +156,11 @@ static void t_b(DB_ENV *db_env, DB *db, struct test_seq *seq) {
DBT key = { .data = &k, .size = sizeof k };
DBT val = { .data = &k, .size = sizeof k };
r = db->put(db, txn_b, &key, &val, 0);
+#if USE_BDB
+ assert(r == DB_LOCK_DEADLOCK);
+#else
assert(r == DB_LOCK_NOTGRANTED);
+#endif
r = txn_b->abort(txn_b); assert(r == 0);
}
@@ -208,12 +212,31 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if USE_BDB
+ db_timeout_t t;
+ r = db_env->get_timeout(db_env, &t, DB_SET_LOCK_TIMEOUT); assert(r == 0);
+ if (verbose) printf("lock %d\n", t);
+ r = db_env->get_timeout(db_env, &t, DB_SET_TXN_TIMEOUT); assert(r == 0);
+ if (verbose) printf("txn %d\n", t);
+
+ r = db_env->set_timeout(db_env, 5000000, DB_SET_LOCK_TIMEOUT); assert(r == 0);
+ r = db_env->set_timeout(db_env, 5000000, DB_SET_TXN_TIMEOUT); assert(r == 0);
+
+ r = db_env->get_timeout(db_env, &t, DB_SET_LOCK_TIMEOUT); assert(r == 0);
+ if (verbose) printf("lock %d\n", t);
+ r = db_env->get_timeout(db_env, &t, DB_SET_TXN_TIMEOUT); assert(r == 0);
+ if (verbose) printf("txn %d\n", t);
+
+ r = db_env->set_lk_detect(db_env, DB_LOCK_EXPIRE); assert(r == 0);
+#endif
+#if USE_TDB
uint64_t lock_timeout_msec;
r = db_env->get_lock_timeout(db_env, &lock_timeout_msec); assert(r == 0);
if (verbose) printf("lock timeout: %" PRIu64 "\n", lock_timeout_msec);
r = db_env->set_lock_timeout(db_env, 5000, nullptr); assert(r == 0);
r = db_env->get_lock_timeout(db_env, &lock_timeout_msec); assert(r == 0);
if (verbose) printf("lock timeout: %" PRIu64 "\n", lock_timeout_msec);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-put-wakeup.cc b/storage/tokudb/ft-index/src/tests/blocking-put-wakeup.cc
index 06c51b6fede..9c8ad60787b 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-put-wakeup.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-put-wakeup.cc
@@ -208,7 +208,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-put.cc b/storage/tokudb/ft-index/src/tests/blocking-put.cc
index 8100862881a..afd083986d8 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-put.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-put.cc
@@ -180,7 +180,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-set-range-0.cc b/storage/tokudb/ft-index/src/tests/blocking-set-range-0.cc
index 896d4a82e12..8d2dad831a2 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-set-range-0.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-set-range-0.cc
@@ -117,6 +117,7 @@ struct my_callback_context {
DBT val;
};
+#if TOKUDB
static int blocking_set_range_callback(DBT const *a UU(), DBT const *b UU(), void *e UU()) {
DBT const *found_key = a;
DBT const *found_val = b;
@@ -125,6 +126,7 @@ static int blocking_set_range_callback(DBT const *a UU(), DBT const *b UU(), voi
copy_dbt(&context->val, found_val);
return 0;
}
+#endif
static void blocking_set_range(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptime, uint64_t the_key) {
int r;
@@ -142,7 +144,11 @@ static void blocking_set_range(DB_ENV *db_env, DB *db, uint64_t nrows, long slee
uint64_t k = htonl(the_key);
DBT key = { .data = &k, .size = sizeof k };
+#if TOKUDB
r = cursor->c_getf_set_range(cursor, DB_RMW, &key, blocking_set_range_callback, &context); assert(r == 0);
+#else
+ r = cursor->c_get(cursor, &key, &context.val, DB_SET_RANGE + DB_RMW); assert(r == 0);
+#endif
uint64_t v;
assert(context.val.size == sizeof v);
memcpy(&v, context.val.data, context.val.size);
@@ -240,7 +246,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-set-range-n.cc b/storage/tokudb/ft-index/src/tests/blocking-set-range-n.cc
index 841809fadbe..838d18ed6d5 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-set-range-n.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-set-range-n.cc
@@ -117,6 +117,7 @@ struct my_callback_context {
DBT val;
};
+#if TOKUDB
static int blocking_set_range_callback(DBT const *a UU(), DBT const *b UU(), void *e UU()) {
DBT const *found_key = a;
DBT const *found_val = b;
@@ -125,6 +126,7 @@ static int blocking_set_range_callback(DBT const *a UU(), DBT const *b UU(), voi
copy_dbt(&context->val, found_val);
return 0;
}
+#endif
static void blocking_set_range(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptime, uint64_t the_key) {
int r;
@@ -142,7 +144,11 @@ static void blocking_set_range(DB_ENV *db_env, DB *db, uint64_t nrows, long slee
uint64_t k = htonl(the_key);
DBT key = { .data = &k, .size = sizeof k };
+#if TOKUDB
r = cursor->c_getf_set_range(cursor, DB_RMW, &key, blocking_set_range_callback, &context); assert(r == DB_NOTFOUND);
+#else
+ r = cursor->c_get(cursor, &key, &context.val, DB_SET_RANGE + DB_RMW); assert(r == DB_NOTFOUND);
+#endif
usleep(sleeptime);
r = cursor->c_close(cursor); assert(r == 0);
@@ -235,7 +241,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-set-range-reverse-0.cc b/storage/tokudb/ft-index/src/tests/blocking-set-range-reverse-0.cc
index f63bb3c0e5b..7d06dc4c9e0 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-set-range-reverse-0.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-set-range-reverse-0.cc
@@ -142,7 +142,11 @@ static void blocking_set_range(DB_ENV *db_env, DB *db, uint64_t nrows, long slee
uint64_t k = htonl(the_key);
DBT key = { .data = &k, .size = sizeof k };
+#if TOKUDB
r = cursor->c_getf_set_range_reverse(cursor, 0, &key, blocking_set_range_callback, &context); assert(r == 0);
+#else
+ r = cursor->c_get(cursor, &key, &context.val, DB_SET_RANGE_REVERSE); assert(r == 0);
+#endif
uint64_t v;
assert(context.val.size == sizeof v);
memcpy(&v, context.val.data, context.val.size);
@@ -240,7 +244,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-set.cc b/storage/tokudb/ft-index/src/tests/blocking-set.cc
index dd0196ff276..d229321aa43 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-set.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-set.cc
@@ -112,6 +112,7 @@ static void populate(DB_ENV *db_env, DB *db, uint64_t nrows) {
r = txn->commit(txn, 0); assert(r == 0);
}
+#if TOKUDB
static int blocking_set_callback(DBT const *a UU(), DBT const *b UU(), void *e UU()) {
// DBT const *found_key = a;
DBT const *found_val = b;
@@ -122,6 +123,7 @@ static int blocking_set_callback(DBT const *a UU(), DBT const *b UU(), void *e U
memcpy(my_val->data, found_val->data, found_val->size);
return 0;
}
+#endif
static void blocking_set(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptime) {
int r;
@@ -138,7 +140,11 @@ static void blocking_set(DB_ENV *db_env, DB *db, uint64_t nrows, long sleeptime)
uint64_t k = htonl(0); // set to key 0
DBT key = { .data = &k, .size = sizeof k };
+#if TOKUDB
r = cursor->c_getf_set(cursor, DB_RMW, &key, blocking_set_callback, &val); assert(r == 0);
+#else
+ r = cursor->c_get(cursor, &key, &val, DB_SET + DB_RMW); assert(r == 0);
+#endif
uint64_t v;
assert(val.size == sizeof v);
memcpy(&v, val.data, val.size);
@@ -220,7 +226,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/blocking-table-lock.cc b/storage/tokudb/ft-index/src/tests/blocking-table-lock.cc
index 42e824debbf..2ae82319a7e 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-table-lock.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-table-lock.cc
@@ -174,7 +174,9 @@ int test_main(int argc, char * const argv[]) {
r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert(r == 0);
}
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/checkpoint1.cc b/storage/tokudb/ft-index/src/tests/checkpoint1.cc
index 9fe56cdbc36..3620b9006a8 100644
--- a/storage/tokudb/ft-index/src/tests/checkpoint1.cc
+++ b/storage/tokudb/ft-index/src/tests/checkpoint1.cc
@@ -118,7 +118,9 @@ checkpoint1 (void)
toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
r = db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
r = env->set_redzone(env, 0); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/checkpoint_fairness.cc b/storage/tokudb/ft-index/src/tests/checkpoint_fairness.cc
index 03d5c47f4e5..c94e1f4b1ab 100644
--- a/storage/tokudb/ft-index/src/tests/checkpoint_fairness.cc
+++ b/storage/tokudb/ft-index/src/tests/checkpoint_fairness.cc
@@ -147,7 +147,9 @@ int test_main(int argc, char * const argv[]) {
// try to starve the checkpoint
{ int chk_r = db_env_create(&env, 0); CKERR(chk_r); }
+#ifdef USE_TDB
{ int chk_r = env->set_redzone(env, 0); CKERR(chk_r); }
+#endif
{
const int size = 10+strlen(env_dir);
char cmd[size];
diff --git a/storage/tokudb/ft-index/src/tests/checkpoint_stress.cc b/storage/tokudb/ft-index/src/tests/checkpoint_stress.cc
index 976ba8e8555..ebbaf4085fc 100644
--- a/storage/tokudb/ft-index/src/tests/checkpoint_stress.cc
+++ b/storage/tokudb/ft-index/src/tests/checkpoint_stress.cc
@@ -272,10 +272,13 @@ random_acts(void * d) {
}
}
+
+#if IS_TDB && !TOKU_WINDOWS
return intothevoid;
+#endif
}
-uint64_t max_cachesize = 256 << 20;
+uint64_t max_windows_cachesize = 256 << 20;
static void
run_test (int iter, int die) {
@@ -293,7 +296,7 @@ run_test (int iter, int die) {
const int32_t K256 = 256 * 1024;
uint64_t cachebytes = 0;
cachebytes = K256 * (iter + 1) - (128 * 1024);
- if (cachebytes > max_cachesize)
+ if (cachebytes > max_windows_cachesize)
cachebytes = 0;
if (iter & 2) cachebytes = 0; // use default cachesize half the time
diff --git a/storage/tokudb/ft-index/src/tests/cilktests/bar2.cilk b/storage/tokudb/ft-index/src/tests/cilktests/bar2.cilk
new file mode 100644
index 00000000000..3939cee64bc
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/cilktests/bar2.cilk
@@ -0,0 +1,22 @@
+#include <cilk.h>
+#include <stdio.h>
+#include "foo2.h"
+
+extern "Cilk++"
+int foo2 (int i) {
+ return i+1;
+}
+
+int foo (int i) {
+ int r;
+ r = cilk_spawn foo2 (i+1);
+ cilk_sync;
+ return r+1;
+}
+
+extern "C++"
+void do_foo (void) {
+ printf("Running cilk\n");
+ int r = cilk::run(&foo, 3);
+ printf("Done r =%d\n", r);
+}
diff --git a/storage/tokudb/ft-index/src/tests/cilktests/foo.cilk b/storage/tokudb/ft-index/src/tests/cilktests/foo.cilk
new file mode 100644
index 00000000000..dfc5540db4b
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/cilktests/foo.cilk
@@ -0,0 +1,41 @@
+#include <pthread.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+
+pthread_t pt[2];
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+extern "C" void* start (void *extra __attribute__((__unused__))) {
+ { int r = pthread_mutex_lock(&mutex); assert(r==0); }
+ printf("T%lx got lock\n", pthread_self());
+ sleep(1);
+ printf("T%lx releasing lock\n", pthread_self());
+ { int r = pthread_mutex_unlock(&mutex); assert(r==0); }
+ return 0;
+}
+
+void create_pthread(void) {
+ for (int i=0; i<2; i++) {
+ int r = pthread_create(&pt[i], 0, start, NULL);
+ assert(r==0);
+ }
+}
+
+void join_pthread (void) {
+ for (int i=0; i<2; i++) {
+ int r = pthread_join(pt[i], NULL);
+ assert(r==0);
+ }
+}
+
+void foo (void) {
+}
+
+int cilk_main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+ create_pthread();
+ cilk_spawn foo();
+ cilk_sync;
+ join_pthread();
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/cilktests/foo2.cpp b/storage/tokudb/ft-index/src/tests/cilktests/foo2.cpp
new file mode 100644
index 00000000000..edc8e7f8cf0
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/cilktests/foo2.cpp
@@ -0,0 +1,131 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: expandtab:ts=8:sw=4:softtabstop=4:
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+
+#include <pthread.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+#include "foo2.h"
+#include "cilk.h"
+
+pthread_t pt[2];
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+extern "C" void* start (void *extra __attribute__((__unused__))) {
+ { int r = pthread_mutex_lock(&mutex); assert(r==0); }
+ printf("T%lx got lock\n", pthread_self());
+ sleep(1);
+ printf("T%lx releasing lock\n", pthread_self());
+ { int r = pthread_mutex_unlock(&mutex); assert(r==0); }
+ return 0;
+}
+
+void create_pthread(void) {
+ for (int i=0; i<2; i++) {
+ int r = pthread_create(&pt[i], 0, start, NULL);
+ assert(r==0);
+ }
+}
+
+void join_pthread (void) {
+ for (int i=0; i<2; i++) {
+ int r = pthread_join(pt[i], NULL);
+ assert(r==0);
+ }
+}
+
+int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+ __cilkscreen_disable_instrumentation();
+ create_pthread();
+ __cilkscreen_enable_instrumentation();
+ do_foo();
+ join_pthread();
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/cilktests/get.cilk b/storage/tokudb/ft-index/src/tests/cilktests/get.cilk
new file mode 100644
index 00000000000..810ab332581
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/cilktests/get.cilk
@@ -0,0 +1,27 @@
+/* Perform a DB->get in a cilk thread */
+
+#include <assert.h>
+#include <db.h>
+#include <stdlib.h>
+#include <toku_os.h>
+
+#define DIR __FILE__ ".dir"
+
+DB_ENV *env;
+
+void foo (void) {
+ printf("foo\n");
+}
+
+const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE;
+
+int cilk_main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+ system("rm -rf " DIR);
+ toku_os_mkdir(DIR, 0777);
+ { int r = db_env_create(&env, 0); assert(r==0); }
+ { int r = env->open(env, DIR, envflags,S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0); }
+ cilk_spawn foo();
+ cilk_sync;
+ { int r = env->close(env, 0); assert(r==0); }
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/cilktests/measurecilkrun.cilk b/storage/tokudb/ft-index/src/tests/cilktests/measurecilkrun.cilk
new file mode 100644
index 00000000000..b6949b7e989
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/cilktests/measurecilkrun.cilk
@@ -0,0 +1,106 @@
+#include <pthread.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+#include "cilk.h"
+#include <sys/time.h>
+
+int foo (int i) {
+ return i+1;
+}
+
+int fooi (void* iv) {
+ int *ip=(int*)iv;
+ return foo(*ip);
+}
+
+extern "C++" {
+
+int N = 1000;
+
+double tdiff (struct timeval *after, struct timeval *before)
+{
+ return after->tv_sec - before->tv_sec + (1e-6)*(after->tv_usec - before->tv_usec);
+}
+
+
+void do_cilkrun (void) {
+ cilk::run(&foo, 0);
+}
+
+static cilk::context *ctx;
+void do_cilkcxt (void) {
+ int i = 0;
+ int j __attribute__((__unused__)) = ctx->run(&fooi, (void*)&i);
+}
+
+void do_N_cilkcxt (void) {
+ struct timeval start,end;
+ gettimeofday(&start, 0);
+ cilk::context ctx;
+ int r=0;
+ for (int i=0; i<N; i++) {
+ int j=ctx.run(&fooi, (void*)&i);
+ r+=j;
+ }
+ gettimeofday(&end, 0);
+ printf("%.3fus per ctx.run (tot=%d)\n", 1e6*tdiff(&end, &start)/N, 0);
+}
+
+
+extern "Cilk++" int cilk_in_pt (int i) {
+ assert(i==0);
+ return 0;
+}
+
+pthread_t pt_for_cilk;
+extern void* do_pt_for_cilk(void *extra __attribute__((__unused__))) {
+ cilk::run(&cilk_in_pt, 0);
+ return 0;
+}
+
+void setup_cilk_in_pthread (void) {
+ int r = pthread_create(&pt_for_cilk, 0, do_pt_for_cilk, NULL);
+ assert(r==0);
+}
+
+void do_cilk_in_pthread (void) {
+}
+
+void* do_something (void *extra __attribute__((__unused__))) {
+ return 0;
+}
+
+void do_pthread(void) {
+ pthread_t pt;
+ {int r = pthread_create(&pt, 0, do_something, NULL); assert(r==0);}
+ {int r = pthread_join(pt, NULL); assert(r==0);}
+}
+
+void measure(void (*f)(void), const char *string) {
+ const int maxiter=4;
+ for (int j=0; j<maxiter; j++) {
+ int M = (j+1==maxiter) ? N : 1<<j;
+ struct timeval start,end;
+ gettimeofday(&start, 0);
+ for (int i=0; i<M; i++) {
+ f();
+ }
+ gettimeofday(&end, 0);
+ printf("%9.3fus per call (%d calls) for %s\n", 1e6*tdiff(&end, &start)/M, M, string);
+ }
+ printf("\n");
+}
+
+int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
+ measure(do_pthread, "pthread");
+ measure(do_cilkrun, "cilkrun");
+
+ ctx = new cilk::context;
+ measure(do_cilkcxt, "cilkcxt");
+ delete ctx;
+
+ return 0;
+}
+
+} /* end extern "C" */
diff --git a/storage/tokudb/ft-index/src/tests/create-datadir.cc b/storage/tokudb/ft-index/src/tests/create-datadir.cc
index ecd0b032897..bcf37621780 100644
--- a/storage/tokudb/ft-index/src/tests/create-datadir.cc
+++ b/storage/tokudb/ft-index/src/tests/create-datadir.cc
@@ -114,9 +114,13 @@ static void run_test (void) {
r = db_create(&db, env, 0); CKERR(r);
r = db->open(db, NULL, "bdir/b.db", NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666);
+#if USE_TDB
CKERR(r); //Success, so need a new handle
r = db->close(db, 0); CKERR(r);
r = db_create(&db, env, 0); CKERR(r);
+#else
+ assert(r != 0);
+#endif
char path[TOKU_PATH_MAX+1];
r = toku_os_mkdir(toku_path_join(path, 2, TOKU_TEST_FILENAME, "bdir"), 0777); assert(r == 0);
r = db->open(db, NULL, "bdir/b.db", NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
@@ -133,6 +137,13 @@ static void run_test (void) {
r = db->open(db, NULL, "c.db", NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
r = db->close(db, 0); CKERR(r);
+#if 0
+ // test fname with absolute path
+ r = db_create(&db, env, 0); CKERR(r);
+ r = db->open(db, NULL, "/tmp/d.db", NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
+ r = db->close(db, 0); CKERR(r);
+#endif
+
r = env->close(env, 0); CKERR(r);
}
diff --git a/storage/tokudb/ft-index/src/tests/cursor-more-than-a-leaf-provdel.cc b/storage/tokudb/ft-index/src/tests/cursor-more-than-a-leaf-provdel.cc
index 2927bb7c5ff..5b3ba8a37cb 100644
--- a/storage/tokudb/ft-index/src/tests/cursor-more-than-a-leaf-provdel.cc
+++ b/storage/tokudb/ft-index/src/tests/cursor-more-than-a-leaf-provdel.cc
@@ -104,14 +104,22 @@ setup (void) {
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
r=env->set_redzone(env, 0); CKERR(r);
r=env->set_default_bt_compare(env, int_dbt_cmp); CKERR(r);
+#endif
env->set_errfile(env, stderr);
+#ifdef USE_BDB
+ r=env->set_lk_max_objects(env, 2*num_insert); CKERR(r);
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
+#ifdef USE_BDB
+ r=db->set_bt_compare(db, int_dbt_cmp); CKERR(r);
+#endif
r=db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=txn->commit(txn, 0); assert(r==0);
}
diff --git a/storage/tokudb/ft-index/src/tests/db-put-simple-deadlock-threads.cc b/storage/tokudb/ft-index/src/tests/db-put-simple-deadlock-threads.cc
index d60725c4966..004a7aad12d 100644
--- a/storage/tokudb/ft-index/src/tests/db-put-simple-deadlock-threads.cc
+++ b/storage/tokudb/ft-index/src/tests/db-put-simple-deadlock-threads.cc
@@ -184,6 +184,9 @@ static void simple_deadlock(DB_ENV *db_env, DB *db, int do_txn, int n) {
}
uint32_t txn_flags = 0;
+#if USE_BDB
+ txn_flags = DB_TXN_NOWAIT; // force no wait for BDB to avoid a bug described below
+#endif
DB_TXN *txn_a = NULL;
if (do_txn) {
@@ -206,6 +209,7 @@ static void simple_deadlock(DB_ENV *db_env, DB *db, int do_txn, int n) {
test_seq_next_state(&test_seq);
test_seq_sleep(&test_seq, 2);
+ // BDB does not time out this lock request, so the test hangs. it looks like a bug in bdb's __lock_get_internal.
insert_row(db, txn_a, htonl(n-1), n-1, DB_LOCK_NOTGRANTED);
test_seq_next_state(&test_seq);
@@ -264,8 +268,16 @@ int test_main(int argc, char * const argv[]) {
}
if (!do_txn)
db_env_open_flags &= ~(DB_INIT_TXN | DB_INIT_LOG);
+#if USE_BDB
+ r = db_env->set_flags(db_env, DB_TIME_NOTGRANTED, 1); assert(r == 0); // force DB_LOCK_DEADLOCK to DB_LOCK_NOTGRANTED
+#endif
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if defined(USE_TDB)
r = db_env->set_lock_timeout(db_env, 0, nullptr); assert(r == 0); // no wait
+#elif defined(USE_BDB)
+ r = db_env->set_lk_detect(db_env, DB_LOCK_YOUNGEST); assert(r == 0);
+ r = db_env->set_timeout(db_env, 10000, DB_SET_LOCK_TIMEOUT); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/db-put-simple-deadlock.cc b/storage/tokudb/ft-index/src/tests/db-put-simple-deadlock.cc
index acc841b8d78..d373752994a 100644
--- a/storage/tokudb/ft-index/src/tests/db-put-simple-deadlock.cc
+++ b/storage/tokudb/ft-index/src/tests/db-put-simple-deadlock.cc
@@ -88,7 +88,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-// this test demonstrates that a simple deadlock with 2 transactions on a single thread works with tokudb
+// this test demonstrates that a simple deadlock with 2 transactions on a single thread works with tokudb, hangs with bdb
#include "test.h"
@@ -115,6 +115,9 @@ static void simple_deadlock(DB_ENV *db_env, DB *db, int do_txn, int n) {
}
uint32_t txn_flags = 0;
+#if USE_BDB
+ txn_flags = DB_TXN_NOWAIT; // force no wait for BDB to avoid a bug described below
+#endif
DB_TXN *txn_a = NULL;
if (do_txn) {
@@ -130,6 +133,7 @@ static void simple_deadlock(DB_ENV *db_env, DB *db, int do_txn, int n) {
insert_row(db, txn_b, htonl(n-1), n-1, 0);
+ // if the txn_flags is 0, then BDB does not time out this lock request, so the test hangs. it looks like a bug in bdb's __lock_get_internal.
insert_row(db, txn_a, htonl(n-1), n-1, DB_LOCK_NOTGRANTED);
insert_row(db, txn_b, htonl(0), 0, DB_LOCK_NOTGRANTED);
@@ -144,7 +148,7 @@ int test_main(int argc, char * const argv[]) {
uint64_t cachesize = 0;
uint32_t pagesize = 0;
int do_txn = 1;
- int nrows = 1000;
+ int nrows = 1000; // for BDB, insert enough rows to create a tree with more than one page in it. this avoids a page locking conflict.
const char *db_env_dir = TOKU_TEST_FILENAME;
const char *db_filename = "simple_deadlock";
int db_env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_THREAD;
@@ -183,7 +187,14 @@ int test_main(int argc, char * const argv[]) {
}
if (!do_txn)
db_env_open_flags &= ~(DB_INIT_TXN | DB_INIT_LOG);
+#if USE_BDB
+ r = db_env->set_flags(db_env, DB_TIME_NOTGRANTED, 1); assert(r == 0); // force DB_LOCK_DEADLOCK to DB_LOCK_NOTGRANTED
+#endif
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if defined(USE_BDB)
+ r = db_env->set_lk_detect(db_env, DB_LOCK_YOUNGEST); assert(r == 0);
+ r = db_env->set_timeout(db_env, 1000, DB_SET_LOCK_TIMEOUT); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
r = db_create(&db, db_env, 0); assert(r == 0);
diff --git a/storage/tokudb/ft-index/src/tests/db-put-simple-lockwait.cc b/storage/tokudb/ft-index/src/tests/db-put-simple-lockwait.cc
index e459652101d..54682db81af 100644
--- a/storage/tokudb/ft-index/src/tests/db-put-simple-lockwait.cc
+++ b/storage/tokudb/ft-index/src/tests/db-put-simple-lockwait.cc
@@ -213,7 +213,11 @@ int test_main(int argc, char * const argv[]) {
if (!do_txn)
db_env_open_flags &= ~(DB_INIT_TXN | DB_INIT_LOG);
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if TOKUDB
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#else
+ r = db_env->set_lk_detect(db_env, DB_LOCK_YOUNGEST); assert(r == 0);
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/db-put-update-deadlock.cc b/storage/tokudb/ft-index/src/tests/db-put-update-deadlock.cc
index ddd2893cae0..1a546825fc4 100644
--- a/storage/tokudb/ft-index/src/tests/db-put-update-deadlock.cc
+++ b/storage/tokudb/ft-index/src/tests/db-put-update-deadlock.cc
@@ -91,6 +91,7 @@ PATENT RIGHTS GRANT:
// for all i: T(i) reads 0, gets a read lock on 0
// for all i: T(i) writes 0, enters a deadlock
// tokudb detects deadlock on the fly
+// bdb detects deadlock on the fly or uses a deadlock detector
// --poll runs the deadlock detector until all the txns are resolved
#include "test.h"
@@ -200,6 +201,18 @@ static void update_deadlock(DB_ENV *db_env, DB *db, int do_txn, int nrows, int n
}
#endif
+#if defined(USE_BDB)
+ // check for deadlocks
+ if (poll_deadlock) {
+ while (n_txns > 0) {
+ sleep(10);
+ int rejected = 0;
+ r = db_env->lock_detect(db_env, 0, DB_LOCK_YOUNGEST, &rejected); assert(r == 0);
+ printf("%s rejected %d\n", __FUNCTION__, rejected);
+ }
+ }
+#endif
+
// cleanup
for (int i = 0; i < ntxns; i++) {
void *ret = NULL;
@@ -261,7 +274,14 @@ int test_main(int argc, char * const argv[]) {
if (!do_txn)
db_env_open_flags &= ~(DB_INIT_TXN | DB_INIT_LOG);
r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0);
+#if defined(TOKUDB)
r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
+#endif
+#if defined(USE_BDB)
+ if (!poll_deadlock) {
+ r = db_env->set_lk_detect(db_env, DB_LOCK_YOUNGEST); assert(r == 0);
+ }
+#endif
// create the db
DB *db = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/dump-env.cc b/storage/tokudb/ft-index/src/tests/dump-env.cc
index 8348c25f2bd..9e1459b80ec 100644
--- a/storage/tokudb/ft-index/src/tests/dump-env.cc
+++ b/storage/tokudb/ft-index/src/tests/dump-env.cc
@@ -106,14 +106,22 @@ setup (void) {
}
r=db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
r=env->set_redzone(env, 0); CKERR(r);
r=env->set_default_bt_compare(env, int_dbt_cmp); CKERR(r);
+#endif
env->set_errfile(env, stderr);
+#ifdef USE_BDB
+ r=env->set_lk_max_objects(env, 2*num_insert); CKERR(r);
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
+#ifdef USE_BDB
+ r=db->set_bt_compare(db, int_dbt_cmp); CKERR(r);
+#endif
r=db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=txn->commit(txn, 0); assert(r==0);
}
diff --git a/storage/tokudb/ft-index/src/tests/filesize.cc b/storage/tokudb/ft-index/src/tests/filesize.cc
index b47be955efd..c1b7ad2df30 100644
--- a/storage/tokudb/ft-index/src/tests/filesize.cc
+++ b/storage/tokudb/ft-index/src/tests/filesize.cc
@@ -196,7 +196,11 @@ delete_n (uint32_t ah)
ndelete_notfound++;
else
ndelete_failed++;
+#ifdef USE_BDB
+ assert(r==0 || r==DB_NOTFOUND);
+#else
CKERR(r);
+#endif
}
static void
diff --git a/storage/tokudb/ft-index/src/tests/hotindexer-undo-do-test.cc b/storage/tokudb/ft-index/src/tests/hotindexer-undo-do-test.cc
index 51f60652d14..e1a2070a036 100644
--- a/storage/tokudb/ft-index/src/tests/hotindexer-undo-do-test.cc
+++ b/storage/tokudb/ft-index/src/tests/hotindexer-undo-do-test.cc
@@ -97,13 +97,13 @@ PATENT RIGHTS GRANT:
#include <ft/tokuconst.h>
#include <ft/fttypes.h>
+#include <ft/omt.h>
#include <ft/leafentry.h>
#include <ft/ule.h>
#include <ft/ule-internal.h>
#include <ft/le-cursor.h>
-#include <ft/xids-internal.h>
-
#include "indexer-internal.h"
+#include <ft/xids-internal.h>
struct txn {
TXNID xid;
diff --git a/storage/tokudb/ft-index/src/tests/inflate.cc b/storage/tokudb/ft-index/src/tests/inflate.cc
index 8311b591c86..5a727544be5 100644
--- a/storage/tokudb/ft-index/src/tests/inflate.cc
+++ b/storage/tokudb/ft-index/src/tests/inflate.cc
@@ -165,7 +165,11 @@ delete_n (uint32_t ah)
DBT key;
dbt_init(&key, &an, 4);
int r = db->del(db, NULL, &key, DB_DELETE_ANY);
+#ifdef USE_BDB
+ assert(r==0 || r==DB_NOTFOUND);
+#else
CKERR(r);
+#endif
}
static void
diff --git a/storage/tokudb/ft-index/src/tests/inflate2.cc b/storage/tokudb/ft-index/src/tests/inflate2.cc
index e5b8b6f270f..2bb930446a2 100644
--- a/storage/tokudb/ft-index/src/tests/inflate2.cc
+++ b/storage/tokudb/ft-index/src/tests/inflate2.cc
@@ -179,7 +179,11 @@ delete_n_now (uint32_t ah)
DBT key;
dbt_init(&key, &an, 4);
int r = db->del(db, NULL, &key, DB_DELETE_ANY);
+#ifdef USE_BDB
+ assert(r==0 || r==DB_NOTFOUND);
+#else
CKERR(r);
+#endif
get_n(ah, DB_NOTFOUND);
}
diff --git a/storage/tokudb/ft-index/src/tests/loader-blobs-create-leaf.c.notyet b/storage/tokudb/ft-index/src/tests/loader-blobs-create-leaf.c.notyet
new file mode 100644
index 00000000000..04a26a5cc25
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/loader-blobs-create-leaf.c.notyet
@@ -0,0 +1,149 @@
+// verify that the loader can deal with blobs larger than the node size
+
+#include "test.h"
+
+static int my_bt_compare(DB *db, const DBT *a, const DBT *b) {
+ db = db;
+ assert(a->size == 8 && b->size == 8);
+ return memcmp(a->data, b->data, 8);
+}
+
+static int my_row_generate(DB *dest_db, DB *src_db, DBT *dest_key, DBT *dest_val, const DBT *src_key, const DBT *src_val) {
+ dest_db = dest_db; src_db = src_db; dest_key = dest_key; dest_val = dest_val; src_key = src_key; src_val = src_val;
+ assert(dest_key->flags == DB_DBT_REALLOC);
+ dest_key->data = toku_realloc(dest_key->data, src_key->size);
+ memcpy(dest_key->data, src_key->data, src_key->size);
+ dest_key->size = src_key->size;
+ assert(dest_val->flags == DB_DBT_REALLOC);
+ dest_val->data = toku_realloc(dest_val->data, src_val->size);
+ memcpy(dest_val->data, src_val->data, src_val->size);
+ dest_val->size = src_val->size;
+ return 0;
+}
+
+static void insert(DB_LOADER *loader, int k, int val_size) {
+ int r;
+
+ // generate the key
+ char key_buffer[8];
+ memset(key_buffer, 0, sizeof key_buffer);
+ int newa = htonl(k);
+ memcpy(key_buffer, &newa, sizeof newa);
+
+ // generate the value
+ char *val_buffer = toku_malloc(val_size); assert(val_buffer);
+ memset(val_buffer, 0, val_size);
+
+ DBT key = { .data = key_buffer, .size = sizeof key_buffer };
+ DBT value = { .data = val_buffer, .size = val_size };
+ r = loader->put(loader, &key, &value);
+ if (DISALLOW_PUTS) {
+ assert(r == EINVAL);
+ }
+ else {
+ assert_zero(r);
+ }
+
+ toku_free(val_buffer);
+}
+
+int test_main(int argc, char * const argv[]) {
+ uint32_t loader_flags = 0;
+#if defined(TOKUDB)
+ char *db_env_dir = "blobs.leafsplit.env.tokudb";
+#else
+ char *db_env_dir = "blobs.leafsplit.env.bdb";
+#endif
+ int db_env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG;
+ char *db_filename = "blobs.db";
+ int do_txn = 1;
+ u_int64_t cachesize = 0;
+ u_int32_t pagesize = 0;
+
+ int i;
+ for (i = 1; i < argc; i++) {
+ char *arg = argv[i];
+ if (strcmp(arg, "-v") == 0 || strcmp(arg, "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(arg, "-q") == 0) {
+ if (verbose > 0) verbose--;
+ continue;
+ }
+ if (strcmp(arg, "-z") == 0) {
+ loader_flags |= LOADER_COMPRESS_INTERMEDIATES;
+ continue;
+ }
+ if (strcmp(arg, "-p") == 0) {
+ loader_flags |= LOADER_DISALLOW_PUTS;
+ continue;
+ }
+ if (strcmp(arg, "--txn") == 0 && i+1 < argc) {
+ do_txn = atoi(argv[++i]);
+ continue;
+ }
+ if (strcmp(arg, "--pagesize") == 0 && i+1 < argc) {
+ pagesize = atoi(argv[++i]);
+ continue;
+ }
+ if (strcmp(arg, "--cachesize") == 0 && i+1 < argc) {
+ cachesize = atol(argv[++i]);
+ continue;
+ }
+
+ assert(0);
+ }
+
+ int r;
+ char rm_cmd[strlen(db_env_dir) + strlen("rm -rf ") + 1];
+ snprintf(rm_cmd, sizeof(rm_cmd), "rm -rf %s", db_env_dir);
+ r = system(rm_cmd); assert_zero(r);
+
+ r = toku_os_mkdir(db_env_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); assert_zero(r);
+
+ // create and open the env
+ DB_ENV *db_env = NULL;
+ r = db_env_create(&db_env, 0); assert_zero(r);
+ if (cachesize) {
+ const u_int64_t gig = 1 << 30;
+ r = db_env->set_cachesize(db_env, cachesize / gig, cachesize % gig, 1); assert_zero(r);
+ }
+ r = db_env->set_generate_row_callback_for_put(db_env, my_row_generate); assert_zero(r);
+ r = db_env->set_default_bt_compare(db_env, my_bt_compare); assert_zero(r);
+ if (!do_txn)
+ db_env_open_flags &= ~(DB_INIT_TXN | DB_INIT_LOG);
+ r = db_env->open(db_env, db_env_dir, db_env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert_zero(r);
+
+ // create the db
+ DB *db = NULL;
+ r = db_create(&db, db_env, 0); assert_zero(r);
+ DB_TXN *create_txn = NULL;
+ if (do_txn) {
+ r = db_env->txn_begin(db_env, NULL, &create_txn, 0); assert_zero(r);
+ }
+ if (pagesize) {
+ r = db->set_pagesize(db, pagesize); assert_zero(r);
+ }
+ r = db->open(db, create_txn, db_filename, NULL, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert_zero(r);
+
+ DB_LOADER *loader = NULL;
+ uint32_t db_flags = 0;
+ uint32_t dbt_flags = 0;
+ r = db_env->create_loader(db_env, create_txn, &loader, db, 1, &db, &db_flags, &dbt_flags, loader_flags); assert_zero(r);
+
+ insert(loader, 1, 8000000);
+ insert(loader, 2, 1);
+
+ r = loader->close(loader); assert_zero(r);
+
+ if (do_txn) {
+ r = create_txn->commit(create_txn, 0); assert_zero(r);
+ }
+
+ // shutdown
+ r = db->close(db, 0); assert_zero(r); db = NULL;
+ r = db_env->close(db_env, 0); assert_zero(r); db_env = NULL;
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/loader-create-commit-nproc-limit.cc b/storage/tokudb/ft-index/src/tests/loader-create-commit-nproc-limit.cc
index 091809a8551..c918c4bfd8c 100644
--- a/storage/tokudb/ft-index/src/tests/loader-create-commit-nproc-limit.cc
+++ b/storage/tokudb/ft-index/src/tests/loader-create-commit-nproc-limit.cc
@@ -88,10 +88,6 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2010-2013 Tokutek Inc. All rights reserved."
#ident "$Id$"
-// This test crashes if a failed loader creation causes the db to be corrupted by unlinking
-// the underlying fractal tree files. This unlinking occurs because the txn that logs the
-// load log entries is committed rather than aborted.
-
#include "test.h"
#include <db.h>
#include <sys/resource.h>
diff --git a/storage/tokudb/ft-index/src/tests/loader-close-nproc-limit.cc b/storage/tokudb/ft-index/src/tests/loader-nproc-close.cc
index 3ef2b0541f7..3ef2b0541f7 100644
--- a/storage/tokudb/ft-index/src/tests/loader-close-nproc-limit.cc
+++ b/storage/tokudb/ft-index/src/tests/loader-nproc-close.cc
diff --git a/storage/tokudb/ft-index/src/tests/loader-create-nproc-limit.cc b/storage/tokudb/ft-index/src/tests/loader-nproc-create.cc
index 7a61fce7799..7a61fce7799 100644
--- a/storage/tokudb/ft-index/src/tests/loader-create-nproc-limit.cc
+++ b/storage/tokudb/ft-index/src/tests/loader-nproc-create.cc
diff --git a/storage/tokudb/ft-index/src/tests/medium-nested-commit-commit.cc b/storage/tokudb/ft-index/src/tests/medium-nested-commit-commit.cc
index 48d9102d523..e1c815695cc 100644
--- a/storage/tokudb/ft-index/src/tests/medium-nested-commit-commit.cc
+++ b/storage/tokudb/ft-index/src/tests/medium-nested-commit-commit.cc
@@ -177,6 +177,9 @@ test_setup (void) {
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_env_create(&env, 0); CKERR(r);
+#ifndef TOKUDB
+ r=env->set_lk_max_objects(env, N); CKERR(r);
+#endif
env->set_errfile(env, stderr);
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/recover-compare-db-descriptor.cc b/storage/tokudb/ft-index/src/tests/recover-compare-db-descriptor.cc
index 58ae0b007e3..8da0e58af8d 100644
--- a/storage/tokudb/ft-index/src/tests/recover-compare-db-descriptor.cc
+++ b/storage/tokudb/ft-index/src/tests/recover-compare-db-descriptor.cc
@@ -100,6 +100,8 @@ const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG
const char *namea="a.db";
const char *nameb="b.db";
+#if USE_TDB
+
static int my_compare(DB *UU(db), const DBT *a, const DBT *b) {
assert(db);
assert(db->cmp_descriptor);
@@ -110,13 +112,17 @@ static int my_compare(DB *UU(db), const DBT *a, const DBT *b) {
return memcmp(a->data, b->data, a->size);
}
+#endif
+
static void
change_descriptor(DB_ENV* env, DB* db) {
+#if USE_TDB
DBT descriptor;
dbt_init(&descriptor, descriptor_contents, sizeof(descriptor_contents));
IN_TXN_COMMIT(env, NULL, txn_desc, 0, {
{ int chk_r = db->change_descriptor(db, txn_desc, &descriptor, DB_UPDATE_CMP_DESCRIPTOR); CKERR(chk_r); }
});
+#endif
}
static void
@@ -130,7 +136,9 @@ do_x1_shutdown (bool do_commit, bool do_abort) {
DB *dba, *dbb;
r = db_env_create(&env, 0); CKERR(r);
r = env->set_data_dir(env, "data"); CKERR(r);
+#if USE_TDB
r = env->set_default_bt_compare(env, my_compare); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
@@ -173,7 +181,9 @@ do_x1_recover (bool did_commit) {
r = toku_os_mkdir(datadir, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_env_create(&env, 0); CKERR(r);
r = env->set_data_dir(env, "data"); CKERR(r);
+#if USE_TDB
r = env->set_default_bt_compare(env, my_compare); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/recover-compare-db.cc b/storage/tokudb/ft-index/src/tests/recover-compare-db.cc
index 7e1de1ef3fe..0102a36db6a 100644
--- a/storage/tokudb/ft-index/src/tests/recover-compare-db.cc
+++ b/storage/tokudb/ft-index/src/tests/recover-compare-db.cc
@@ -98,12 +98,16 @@ const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG
const char *namea="a.db";
const char *nameb="b.db";
+#if USE_TDB
+
static int my_compare(DB *UU(db), const DBT *a, const DBT *b) {
assert(db);
assert(a->size == b->size);
return memcmp(a->data, b->data, a->size);
}
+#endif
+
static void
do_x1_shutdown (bool do_commit, bool do_abort) {
int r;
@@ -112,7 +116,9 @@ do_x1_shutdown (bool do_commit, bool do_abort) {
DB_ENV *env;
DB *dba, *dbb;
r = db_env_create(&env, 0); CKERR(r);
+#if USE_TDB
r = env->set_default_bt_compare(env, my_compare); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
@@ -149,7 +155,9 @@ do_x1_recover (bool did_commit) {
DB *dba, *dbb;
int r;
r = db_env_create(&env, 0); CKERR(r);
+#if USE_TDB
r = env->set_default_bt_compare(env, my_compare); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/recover-fcreate-basementnodesize.cc b/storage/tokudb/ft-index/src/tests/recover-fcreate-basementnodesize.cc
index 228528a5327..2297a095e69 100644
--- a/storage/tokudb/ft-index/src/tests/recover-fcreate-basementnodesize.cc
+++ b/storage/tokudb/ft-index/src/tests/recover-fcreate-basementnodesize.cc
@@ -99,6 +99,7 @@ static const char *namea="a.db"; uint32_t nodesizea = 0;
static const char *nameb="b.db"; uint32_t nodesizeb = 32*1024;
static void do_remove(DB_ENV *env, const char *filename) {
+#if TOKUDB
int r;
DBT dname;
DBT iname;
@@ -111,6 +112,12 @@ static void do_remove(DB_ENV *env, const char *filename) {
toku_path_join(rmpath, 2, TOKU_TEST_FILENAME, iname.data);
toku_os_recursive_delete(rmpath);
toku_free(iname.data);
+#else
+ (void) env;
+ char rmpath[TOKU_PATH_MAX+1];
+ toku_path_join(rmpath, 2, TOKU_TEST_FILENAME, filename);
+ toku_os_recursive_delete(rmpath);
+#endif
}
static void run_test (void) {
diff --git a/storage/tokudb/ft-index/src/tests/recover-fcreate-nodesize.cc b/storage/tokudb/ft-index/src/tests/recover-fcreate-nodesize.cc
index 619704efcf2..d0a695b16ad 100644
--- a/storage/tokudb/ft-index/src/tests/recover-fcreate-nodesize.cc
+++ b/storage/tokudb/ft-index/src/tests/recover-fcreate-nodesize.cc
@@ -100,6 +100,7 @@ static const char *namea="a.db"; uint32_t nodesizea = 0;
static const char *nameb="b.db"; uint32_t nodesizeb = 64*1024;
static void do_remove(DB_ENV *env, const char *filename) {
+#if TOKUDB
int r;
DBT dname;
DBT iname;
@@ -112,6 +113,12 @@ static void do_remove(DB_ENV *env, const char *filename) {
toku_path_join(rmpath, 2, TOKU_TEST_FILENAME, iname.data);
toku_os_recursive_delete(rmpath);
toku_free(iname.data);
+#else
+ (void) env;
+ char rmpath[TOKU_PATH_MAX+1];
+ toku_path_join(rmpath, 2, TOKU_TEST_FILENAME, filename);
+ toku_os_recursive_delete(rmpath);
+#endif
}
static void run_test (void) {
diff --git a/storage/tokudb/ft-index/src/tests/recover-missing-dbfile-2.cc b/storage/tokudb/ft-index/src/tests/recover-missing-dbfile-2.cc
index 59f963ef503..777fb3499e6 100644
--- a/storage/tokudb/ft-index/src/tests/recover-missing-dbfile-2.cc
+++ b/storage/tokudb/ft-index/src/tests/recover-missing-dbfile-2.cc
@@ -109,7 +109,9 @@ static void run_test (void) {
DB_ENV *env;
r = db_env_create(&env, 0); CKERR(r);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
DB *dba;
@@ -158,7 +160,9 @@ static void run_recover (void) {
CKERR(r);
r = db_env_create(&env, 0); CKERR(r);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO);
assert(r == DB_RUNRECOVERY);
@@ -180,7 +184,9 @@ static void run_no_recover (void) {
int r;
r = db_env_create(&env, 0); CKERR(r);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags & ~DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = env->close(env, 0); CKERR(r);
exit(0);
diff --git a/storage/tokudb/ft-index/src/tests/recover-missing-dbfile.cc b/storage/tokudb/ft-index/src/tests/recover-missing-dbfile.cc
index a71f91d7417..1287ac71c18 100644
--- a/storage/tokudb/ft-index/src/tests/recover-missing-dbfile.cc
+++ b/storage/tokudb/ft-index/src/tests/recover-missing-dbfile.cc
@@ -109,7 +109,9 @@ static void run_test (void) {
DB *dba;
r = db_env_create(&env, 0); CKERR(r);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
@@ -149,7 +151,9 @@ static void run_recover (void) {
CKERR(r);
r = db_env_create(&env, 0); CKERR(r);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO);
CKERR2(r, DB_RUNRECOVERY);
@@ -171,7 +175,9 @@ static void run_no_recover (void) {
int r;
r = db_env_create(&env, 0); CKERR(r);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags & ~DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = env->close(env, 0); CKERR(r);
exit(0);
diff --git a/storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor-multihandle.cc b/storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor-multihandle.cc
index 3914badda0b..67ffd36560f 100644
--- a/storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor-multihandle.cc
+++ b/storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor-multihandle.cc
@@ -105,6 +105,8 @@ const char *namea="a.db";
int verified = 0;
uint32_t forced_version = 2;
+#if USE_TDB
+
static int my_compare(DB *UU(db), const DBT *a, const DBT *b) {
assert(db);
assert(db->cmp_descriptor);
@@ -119,14 +121,18 @@ static int my_compare(DB *UU(db), const DBT *a, const DBT *b) {
return memcmp(a->data, b->data, a->size);
}
+#endif
+
static void
change_descriptor(DB* db, int which, DB_ENV* env) {
+#if USE_TDB
DBT descriptor;
size_t len = strlen(descriptor_contents[which])+1;
dbt_init(&descriptor, descriptor_contents[which], len);
IN_TXN_COMMIT(env, NULL, txn_desc, 0, {
{ int chk_r = db->change_descriptor(db, txn_desc, &descriptor, DB_UPDATE_CMP_DESCRIPTOR); CKERR(chk_r); }
});
+#endif
}
static void
@@ -140,7 +146,9 @@ do_x1_shutdown (bool do_commit, bool do_abort) {
DB *dba, *dbb;
r = db_env_create(&env, 0); CKERR(r);
r = env->set_data_dir(env, "data"); CKERR(r);
+#if USE_TDB
r = env->set_default_bt_compare(env, my_compare); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
@@ -186,7 +194,9 @@ do_x1_recover (bool did_commit) {
r = toku_os_mkdir(datadir, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_env_create(&env, 0); CKERR(r);
r = env->set_data_dir(env, "data"); CKERR(r);
+#if USE_TDB
r = env->set_default_bt_compare(env, my_compare); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor.cc b/storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor.cc
index 5bf6e1be049..31cacc9d354 100644
--- a/storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor.cc
+++ b/storage/tokudb/ft-index/src/tests/recover-upgrade-db-descriptor.cc
@@ -105,6 +105,8 @@ const char *namea="a.db";
int verified = 0;
uint32_t forced_version = 2;
+#if USE_TDB
+
static int my_compare(DB *UU(db), const DBT *a, const DBT *b) {
assert(db);
assert(db->cmp_descriptor);
@@ -119,14 +121,18 @@ static int my_compare(DB *UU(db), const DBT *a, const DBT *b) {
return memcmp(a->data, b->data, a->size);
}
+#endif
+
static void
change_descriptor(DB* db, int which, DB_ENV* env) {
+#if USE_TDB
DBT descriptor;
size_t len = strlen(descriptor_contents[which])+1;
dbt_init(&descriptor, descriptor_contents[which], len);
IN_TXN_COMMIT(env, NULL, txn_desc, 0, {
{ int chk_r = db->change_descriptor(db, txn_desc, &descriptor, DB_UPDATE_CMP_DESCRIPTOR); CKERR(chk_r); }
});
+#endif
}
static void
@@ -140,7 +146,9 @@ do_x1_shutdown (bool do_commit, bool do_abort) {
DB *dba;
r = db_env_create(&env, 0); CKERR(r);
r = env->set_data_dir(env, "data"); CKERR(r);
+#if USE_TDB
r = env->set_default_bt_compare(env, my_compare); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
@@ -189,7 +197,9 @@ do_x1_recover (bool did_commit) {
r = toku_os_mkdir(datadir, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_env_create(&env, 0); CKERR(r);
r = env->set_data_dir(env, "data"); CKERR(r);
+#if USE_TDB
r = env->set_default_bt_compare(env, my_compare); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, envflags|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = db_create(&dba, env, 0); CKERR(r);
r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/recovery_stress.cc b/storage/tokudb/ft-index/src/tests/recovery_stress.cc
index 9e6b3117031..26190bae824 100644
--- a/storage/tokudb/ft-index/src/tests/recovery_stress.cc
+++ b/storage/tokudb/ft-index/src/tests/recovery_stress.cc
@@ -95,7 +95,7 @@ PATENT RIGHTS GRANT:
#include "checkpoint_test.h"
-static const uint64_t max_cachesize = 256 << 20;
+static const uint64_t max_windows_cachesize = 256 << 20;
static const int NUM_DICTIONARIES = 1;
static const int OPER_STEPS = 6;
@@ -495,7 +495,7 @@ static void run_test (int iter) {
uint64_t cachebytes = 0; // 0 => use default size
const int32_t K256 = 256 * 1024;
cachebytes = K256 * (iter + 1) - (128 * 1024);
- if (cachebytes > max_cachesize)
+ if (cachebytes > max_windows_cachesize)
cachebytes = 0;
if (iter & 2) cachebytes = 0; // use default cachesize half the time
diff --git a/storage/tokudb/ft-index/src/tests/root_fifo_2.cc b/storage/tokudb/ft-index/src/tests/root_fifo_2.cc
index b8d3ac63f27..98f209bf769 100644
--- a/storage/tokudb/ft-index/src/tests/root_fifo_2.cc
+++ b/storage/tokudb/ft-index/src/tests/root_fifo_2.cc
@@ -184,7 +184,11 @@ static void root_fifo_2(int n, int create_outside) {
// cleanup
r = env->close(env, 0);
+#if TOKUDB
assert(r == 0); env = null_env;
+#else
+ printf("%s:%d env close r=%d\n", __FUNCTION__, __LINE__, r);
+#endif
}
int test_main(int argc, char *const argv[]) {
diff --git a/storage/tokudb/ft-index/src/tests/rowsize.cc b/storage/tokudb/ft-index/src/tests/rowsize.cc
index 0965231e621..38232321915 100644
--- a/storage/tokudb/ft-index/src/tests/rowsize.cc
+++ b/storage/tokudb/ft-index/src/tests/rowsize.cc
@@ -102,7 +102,9 @@ static void setup_env (void) {
{int r = toku_os_mkdir(envdir, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); }
{int r = db_env_create(&env, 0); CKERR(r); }
//env->set_errfile(env, stderr);
+#ifdef TOKUDB
CKERR(env->set_redzone(env, 0));
+#endif
{ int r = env->open(env, envdir, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); }
{ int r = db_create(&db, env, 0); CKERR(r); }
{ int r = db->open(db, NULL, "foo.db", 0, DB_BTREE, DB_CREATE | DB_AUTO_COMMIT, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); }
@@ -117,11 +119,14 @@ static void put (const char *keystring, int size, bool should_work) {
DBT k, v;
dbt_init(&k, keystring, 1+strlen(keystring));
dbt_init(&v, toku_xcalloc(size, 1), size);
+#ifdef USE_BDB
+#define DB_YES_OVERWRITE 0
+#endif
static DB_TXN *txn = NULL;
{ int r = env->txn_begin(env, 0, &txn, 0); CKERR(r); }
{
int r = db->put(db, NULL, &k, &v, 0);
- if (should_work) {
+ if (!IS_TDB || should_work) {
CKERR(r);
} else {
assert(r!=0);
diff --git a/storage/tokudb/ft-index/src/tests/simple.cc b/storage/tokudb/ft-index/src/tests/simple.cc
index d51cf446f4c..ed55a1e847e 100644
--- a/storage/tokudb/ft-index/src/tests/simple.cc
+++ b/storage/tokudb/ft-index/src/tests/simple.cc
@@ -136,7 +136,9 @@ test_main (int argc, char * const argv[]) {
parse_args(argc, argv);
setup(FLAGS_LOG);
env->txn_checkpoint(env, 0, 0, 0);
+#ifdef USE_TDB
print_engine_status(env);
+#endif
test_shutdown();
return 0;
}
diff --git a/storage/tokudb/ft-index/src/tests/test-prepare.cc b/storage/tokudb/ft-index/src/tests/test-prepare.cc
index ea3949cf6fe..a29241596f0 100644
--- a/storage/tokudb/ft-index/src/tests/test-prepare.cc
+++ b/storage/tokudb/ft-index/src/tests/test-prepare.cc
@@ -103,7 +103,9 @@ static void clean_env (const char *envdir) {
static void setup_env (DB_ENV **envp, const char *envdir) {
{ int chk_r = db_env_create(envp, 0); CKERR(chk_r); }
(*envp)->set_errfile(*envp, stderr);
+#ifdef TOKUDB
{ int chk_r = (*envp)->set_redzone(*envp, 0); CKERR(chk_r); }
+#endif
{ int chk_r = (*envp)->open(*envp, envdir, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
}
diff --git a/storage/tokudb/ft-index/src/tests/test-prepare2.cc b/storage/tokudb/ft-index/src/tests/test-prepare2.cc
index eb79a1e8e18..ce4cf4869ef 100644
--- a/storage/tokudb/ft-index/src/tests/test-prepare2.cc
+++ b/storage/tokudb/ft-index/src/tests/test-prepare2.cc
@@ -105,7 +105,9 @@ static void clean_env (const char *envdir) {
static void setup_env (DB_ENV **envp, const char *envdir) {
{ int chk_r = db_env_create(envp, 0); CKERR(chk_r); }
(*envp)->set_errfile(*envp, stderr);
+#ifdef TOKUDB
{ int chk_r = (*envp)->set_redzone(*envp, 0); CKERR(chk_r); }
+#endif
{ int chk_r = (*envp)->open(*envp, envdir, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
}
diff --git a/storage/tokudb/ft-index/src/tests/test-prepare3.cc b/storage/tokudb/ft-index/src/tests/test-prepare3.cc
index 352518b8579..4cd13050310 100644
--- a/storage/tokudb/ft-index/src/tests/test-prepare3.cc
+++ b/storage/tokudb/ft-index/src/tests/test-prepare3.cc
@@ -105,7 +105,9 @@ static void clean_env (const char *envdir) {
static void setup_env (DB_ENV **envp, const char *envdir) {
{ int chk_r = db_env_create(envp, 0); CKERR(chk_r); }
(*envp)->set_errfile(*envp, stderr);
+#ifdef TOKUDB
{ int chk_r = (*envp)->set_redzone(*envp, 0); CKERR(chk_r); }
+#endif
{ int chk_r = (*envp)->open(*envp, envdir, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
}
diff --git a/storage/tokudb/ft-index/src/tests/test-xa-prepare.cc b/storage/tokudb/ft-index/src/tests/test-xa-prepare.cc
index d409eefb382..751589c5d91 100644
--- a/storage/tokudb/ft-index/src/tests/test-xa-prepare.cc
+++ b/storage/tokudb/ft-index/src/tests/test-xa-prepare.cc
@@ -103,7 +103,9 @@ static void clean_env (const char *envdir) {
static void setup_env (DB_ENV **envp, const char *envdir) {
{ int chk_r = db_env_create(envp, 0); CKERR(chk_r); }
(*envp)->set_errfile(*envp, stderr);
+#ifdef TOKUDB
{ int chk_r = (*envp)->set_redzone(*envp, 0); CKERR(chk_r); }
+#endif
{ int chk_r = (*envp)->open(*envp, envdir, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
}
diff --git a/storage/tokudb/ft-index/src/tests/test.h b/storage/tokudb/ft-index/src/tests/test.h
index 4cbfcf426d6..b5ab33ccfee 100644
--- a/storage/tokudb/ft-index/src/tests/test.h
+++ b/storage/tokudb/ft-index/src/tests/test.h
@@ -107,13 +107,17 @@ PATENT RIGHTS GRANT:
#include "toku_assert.h"
#include <signal.h>
#include <time.h>
-
+#if defined(USE_TDB)
#include "ydb.h"
//TDB uses DB_NOTFOUND for c_del and DB_CURRENT errors.
#ifdef DB_KEYEMPTY
#error
#endif
#define DB_KEYEMPTY DB_NOTFOUND
+#endif
+#ifndef DB_DELETE_ANY
+#define DB_DELETE_ANY 0
+#endif
// Certain tests fail when row locks taken for read are not shared.
// This switch prevents them from failing so long as read locks are not shared.
@@ -140,6 +144,13 @@ int verbose=0;
fflush(stderr); \
} while (0)
+// If the error code depends on BDB vs TDB use this
+#ifdef USE_TDB
+#define CKERR_depending(r,tdbexpect,bdbexpect) CKERR2(r,tdbexpect)
+#else
+#define CKERR_depending(r,tdbexpect,bdbexpect) CKERR2(r,bdbexpect)
+#endif
+
static __attribute__((__unused__)) void
parse_args (int argc, char * const argv[]) {
const char *argv0=argv[0];
@@ -163,6 +174,7 @@ parse_args (int argc, char * const argv[]) {
}
}
+#ifdef USE_TDB
static __attribute__((__unused__)) void
print_engine_status(DB_ENV * UU(env)) {
if (verbose) { // verbose declared statically in this file
@@ -175,7 +187,9 @@ print_engine_status(DB_ENV * UU(env)) {
printf("%s", buff);
}
}
+#endif
+#ifdef USE_TDB
static __attribute__((__unused__)) uint64_t
get_engine_status_val(DB_ENV * UU(env), const char * keyname) {
uint64_t rval = 0;
@@ -199,6 +213,7 @@ get_engine_status_val(DB_ENV * UU(env), const char * keyname) {
CKERR2(found, 1);
return rval;
}
+#endif
static __attribute__((__unused__)) DBT *
dbt_init(DBT *dbt, const void *data, uint32_t size) {
@@ -278,8 +293,13 @@ uint_dbt_cmp (DB *db, const DBT *a, const DBT *b) {
return 0;
}
+#ifdef USE_TDB
#define SET_TRACE_FILE(x) toku_set_trace_file(x)
#define CLOSE_TRACE_FILE(x) toku_close_trace_file()
+#else
+#define SET_TRACE_FILE(x) ((void)0)
+#define CLOSE_TRACE_FILE(x) ((void)0)
+#endif
#include <memory.h>
@@ -341,11 +361,19 @@ void print_time_now(void) {
static void UU()
multiply_locks_for_n_dbs(DB_ENV *env, int num_dbs) {
+#ifdef USE_TDB
uint64_t current_max_lock_memory;
int r = env->get_lk_max_memory(env, &current_max_lock_memory);
CKERR(r);
r = env->set_lk_max_memory(env, current_max_lock_memory * num_dbs);
CKERR(r);
+#else
+ uint32_t current_max_locks;
+ int r = env->get_lk_max_locks(env, &current_max_locks);
+ CKERR(r);
+ r = env->set_lk_max_locks(env, current_max_locks * num_dbs);
+ CKERR(r);
+#endif
}
static inline void
@@ -374,6 +402,7 @@ static void copy_dbt(DBT *dest, const DBT *src) {
}
// DBT_ARRAY is a toku-specific type
+#ifdef USE_TDB
UU()
static int
env_update_multiple_test_no_array(
@@ -478,6 +507,7 @@ static int env_del_multiple_test_no_array(
}
return r;
}
+#endif
/* Some macros for evaluating blocks or functions within the scope of a
* transaction. */
@@ -505,8 +535,20 @@ main(int argc, char * const argv[])
#endif
{
int r;
+#if IS_TDB && TOKU_WINDOWS
+ int rinit = toku_ydb_init();
+ CKERR(rinit);
+#endif
+#if !IS_TDB && DB_VERSION_MINOR==4 && DB_VERSION_MINOR == 7
+ db_env_set_func_malloc(toku_malloc);
+ db_env_set_func_free(toku_free);
+ db_env_set_func_realloc(toku_realloc);
+#endif
toku_os_initialize_settings(1);
r = test_main(argc, argv);
+#if IS_TDB && TOKU_WINDOWS
+ toku_ydb_destroy();
+#endif
return r;
}
diff --git a/storage/tokudb/ft-index/src/tests/test1426.cc b/storage/tokudb/ft-index/src/tests/test1426.cc
new file mode 100644
index 00000000000..40ca1dee345
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/test1426.cc
@@ -0,0 +1,196 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#include "test.h"
+/* Test for #1426. Make sure deletes and inserts in a FIFO work. */
+/* This test is run using a special makefile rule that runs the TDB version and the BDB version, dumps their outputs, and compares them */
+
+#include <db.h>
+#include <memory.h>
+#include <fcntl.h>
+
+// |DB_INIT_TXN| DB_INIT_LOG | DB_RECOVER
+const int envflags = DB_CREATE|DB_INIT_MPOOL|DB_INIT_LOCK |DB_THREAD |DB_PRIVATE;
+
+DB_ENV *env;
+DB *db;
+DB_TXN * const null_txn = NULL;
+
+static void
+empty_cachetable (void)
+// Make all the cachetable entries clean.
+// Brute force it by closing and reopening everything.
+{
+ int r;
+ r = db->close(db, 0); CKERR(r);
+ r = env->close(env, 0); CKERR(r);
+ r = db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
+ r = env->set_cachesize(env, 0, 10000000, 1); CKERR(r);
+#endif
+ r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
+ r = db_create(&db, env, 0); CKERR(r);
+ r = db->open(db, null_txn, "main", 0, DB_BTREE, 0, 0666); CKERR(r);
+}
+
+static void
+do_insert_delete_fifo (void)
+{
+ int r;
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+
+ r = db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
+ r = env->set_cachesize(env, 0, 10000000, 1); CKERR(r);
+#endif
+ r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
+ r = db_create(&db, env, 0); CKERR(r);
+ r = db->set_pagesize(db, 4096); CKERR(r);
+ r = db->open(db, null_txn, "main", 0, DB_BTREE, DB_CREATE, 0666); CKERR(r);
+ {
+ uint64_t i;
+ uint64_t n_deleted = 0;
+ uint64_t N=20000; // total number to insert
+ uint64_t M= 5000; // size of rolling fifo
+ uint64_t D= 200; // number to delete at once
+ for (i=0; i<N; i++) {
+ {
+ char k[100],v[100];
+ int keylen = snprintf(k, sizeof k, "%016" PRIu64 "key", i);
+ uint32_t rand1 = myrandom();
+ uint32_t rand2 = myrandom();
+ uint32_t rand3 = myrandom();
+ int vallen = snprintf(v, sizeof v, "%016" PRIu64 "val%08x%08x%08x", i, rand1, rand2, rand3);
+ DBT kt, vt;
+ r = db->put(db, null_txn, dbt_init(&kt, k, keylen) , dbt_init(&vt, v, vallen), 0); CKERR(r);
+ }
+ if (i%D==0) {
+ // Once every D steps, delete everything until there are only M things left.
+ // Flush the data down the tree for all the values we will do
+ {
+ uint64_t peek_here = n_deleted;
+ while (peek_here + M < i) {
+ char k[100];
+ int keylen = snprintf(k, sizeof k, "%016" PRIu64 "key", peek_here);
+ DBT kt;
+ DBT vt;
+ memset(&vt, 0, sizeof(vt));
+ vt.flags = DB_DBT_MALLOC;
+ r = db->get(db, null_txn, dbt_init(&kt, k, keylen), &vt, 0); CKERR(r);
+ peek_here++;
+ toku_free(vt.data);
+ }
+ }
+ empty_cachetable();
+ while (n_deleted + M < i) {
+ char k[100];
+ int keylen = snprintf(k, sizeof k, "%016" PRIu64 "key", n_deleted);
+ DBT kt;
+ r = db->del(db, null_txn, dbt_init(&kt, k, keylen), 0);
+ if (r!=0) printf("error %d %s", r, db_strerror(r));
+ CKERR(r);
+ n_deleted++;
+ empty_cachetable();
+ }
+ }
+ }
+ }
+ r = db->close(db, 0); CKERR(r);
+ r = env->close(env, 0); CKERR(r);
+}
+
+int
+test_main (int argc, char *const argv[])
+{
+ parse_args(argc, argv);
+ do_insert_delete_fifo();
+ return 0;
+}
+
diff --git a/storage/tokudb/ft-index/src/tests/test1753.cc b/storage/tokudb/ft-index/src/tests/test1753.cc
index d4d09ecaf79..1eee0977f06 100644
--- a/storage/tokudb/ft-index/src/tests/test1753.cc
+++ b/storage/tokudb/ft-index/src/tests/test1753.cc
@@ -99,6 +99,10 @@ DB_TXN *null_txn=0;
static void do_test1753 (int do_create_on_reopen) {
+ if (IS_TDB==0 && DB_VERSION_MAJOR==4 && DB_VERSION_MINOR<7 && do_create_on_reopen==0) {
+ return; // do_create_on_reopen==0 segfaults in 4.6
+ }
+
int r;
toku_os_recursive_delete(TOKU_TEST_FILENAME);
toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
diff --git a/storage/tokudb/ft-index/src/tests/test1842.cc b/storage/tokudb/ft-index/src/tests/test1842.cc
index 43702da5694..f5fccfb54bc 100644
--- a/storage/tokudb/ft-index/src/tests/test1842.cc
+++ b/storage/tokudb/ft-index/src/tests/test1842.cc
@@ -137,7 +137,9 @@ setup_db (uint32_t dup_mode) {
toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
r = db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
r = env->set_default_bt_compare(env, int_dbt_cmp); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, DB_INIT_MPOOL | DB_INIT_LOG | DB_INIT_LOCK | DB_INIT_TXN | DB_PRIVATE | DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
CKERR(r);
@@ -146,6 +148,9 @@ setup_db (uint32_t dup_mode) {
r = env->txn_begin(env, 0, &txn, 0); CKERR(r);
r = db_create(&db, env, 0); CKERR(r);
+#ifndef TOKUDB
+ r=db->set_bt_compare(db, int_dbt_cmp); CKERR(r);
+#endif
r = db->set_flags(db, dup_mode); assert(r == 0); CKERR(r);
r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = txn->commit(txn, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test3039.cc b/storage/tokudb/ft-index/src/tests/test3039.cc
index aaaeebc7c36..e944eb0cd00 100644
--- a/storage/tokudb/ft-index/src/tests/test3039.cc
+++ b/storage/tokudb/ft-index/src/tests/test3039.cc
@@ -112,7 +112,11 @@ static DB_ENV *env = NULL;
static DB *db;
// BDB cannot handle big transactions by default (runs out of locks).
+#ifdef TOKUDB
#define N_PER_XACTION 10000
+#else
+#define N_PER_XACTION 1000
+#endif
static void create_db (uint64_t N) {
n_rows = N;
@@ -120,7 +124,9 @@ static void create_db (uint64_t N) {
toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
{ int r = db_env_create(&env, 0); CKERR(r); }
env->set_errfile(env, stderr);
+#ifdef TOKUDB
env->set_redzone(env, 0);
+#endif
{ int r = env->set_cachesize(env, 0, 400*4096, 1); CKERR(r); }
{ int r = env->open(env, TOKU_TEST_FILENAME, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); }
DB_TXN *txn;
diff --git a/storage/tokudb/ft-index/src/tests/test3219.cc b/storage/tokudb/ft-index/src/tests/test3219.cc
index 95bff0f445d..523b3548271 100644
--- a/storage/tokudb/ft-index/src/tests/test3219.cc
+++ b/storage/tokudb/ft-index/src/tests/test3219.cc
@@ -92,7 +92,7 @@ PATENT RIGHTS GRANT:
// This test, when run under helgrind, should detect the race problem documented in #3219.
// The test:
// checkpointing runs (in one thread)
-// another thread does an ft lookup.
+// another thread does a brt lookup.
// We expect to see a lock-acquisition error.
diff --git a/storage/tokudb/ft-index/src/tests/test4573-logtrim.cc b/storage/tokudb/ft-index/src/tests/test4573-logtrim.cc
index a439f886103..a7a121b5d9e 100644
--- a/storage/tokudb/ft-index/src/tests/test4573-logtrim.cc
+++ b/storage/tokudb/ft-index/src/tests/test4573-logtrim.cc
@@ -92,7 +92,7 @@ PATENT RIGHTS GRANT:
const int envflags = DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|DB_RECOVER;
-const int my_lg_max = 100;
+const int my_lg_max = IS_TDB ? 100 : (4096*2);
int test_main (int UU(argc), char UU(*const argv[])) {
int r;
diff --git a/storage/tokudb/ft-index/src/tests/test5092.cc b/storage/tokudb/ft-index/src/tests/test5092.cc
index 6572c4df246..5cfc0557496 100644
--- a/storage/tokudb/ft-index/src/tests/test5092.cc
+++ b/storage/tokudb/ft-index/src/tests/test5092.cc
@@ -103,7 +103,9 @@ static void clean_env (const char *envdir) {
static void setup_env (DB_ENV **envp, const char *envdir) {
{ int chk_r = db_env_create(envp, 0); CKERR(chk_r); }
(*envp)->set_errfile(*envp, stderr);
+#ifdef TOKUDB
{ int chk_r = (*envp)->set_redzone(*envp, 0); CKERR(chk_r); }
+#endif
{ int chk_r = (*envp)->open(*envp, envdir, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(chk_r); }
}
diff --git a/storage/tokudb/ft-index/src/tests/test938.cc b/storage/tokudb/ft-index/src/tests/test938.cc
index bb4b9464a2d..5f7af0b618e 100644
--- a/storage/tokudb/ft-index/src/tests/test938.cc
+++ b/storage/tokudb/ft-index/src/tests/test938.cc
@@ -215,7 +215,9 @@ test_main(int argc, char *const argv[]) {
DB_TXN *txn;
{
r = db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
r = env->set_redzone(env, 0); CKERR(r);
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
env->set_errfile(env, stderr);
r=env->txn_begin(env, 0, &txn, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test938c.cc b/storage/tokudb/ft-index/src/tests/test938c.cc
index f3914ccb302..6d3d0a6b6e6 100644
--- a/storage/tokudb/ft-index/src/tests/test938c.cc
+++ b/storage/tokudb/ft-index/src/tests/test938c.cc
@@ -153,7 +153,9 @@ test_main(int argc, char *const argv[]) {
DB_TXN *txn;
{
r = db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
r = env->set_redzone(env, 0); CKERR(r);
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
env->set_errfile(env, stderr);
r=env->txn_begin(env, 0, &txn, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_abort1.cc b/storage/tokudb/ft-index/src/tests/test_abort1.cc
index 27f5d68348c..456f5811b73 100644
--- a/storage/tokudb/ft-index/src/tests/test_abort1.cc
+++ b/storage/tokudb/ft-index/src/tests/test_abort1.cc
@@ -113,6 +113,20 @@ test_db_open_aborts (void) {
r=db_env_create(&env, 0); assert(r==0);
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_PRIVATE|DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
+#if 0
+ {
+ DB_TXN *tid;
+ r=env->txn_begin(env, 0, &tid, 0); assert(r==0);
+ r=db->open(db, tid, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
+ r=tid->abort(tid); assert(r==0);
+ }
+ {
+ toku_struct_stat buf;
+ r=toku_stat(ENVDIR "/foo.db", &buf);
+ assert(r!=0);
+ assert(errno==ENOENT);
+ }
+#endif
{
DB_TXN *tid;
r=env->txn_begin(env, 0, &tid, 0); assert(r==0);
@@ -128,6 +142,7 @@ test_db_open_aborts (void) {
r=tid->abort(tid); assert(r==0);
}
{
+#if USE_TDB
{
DBT dname;
DBT iname;
@@ -137,6 +152,7 @@ test_db_open_aborts (void) {
r = env->get_iname(env, &dname, &iname);
CKERR2(r, DB_NOTFOUND);
}
+#endif
toku_struct_stat statbuf;
char filename[TOKU_PATH_MAX+1];
r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), &statbuf);
@@ -193,6 +209,7 @@ test_db_put_aborts (void) {
// The database should exist
{
char *filename;
+#if USE_TDB
{
DBT dname;
DBT iname;
@@ -204,6 +221,9 @@ test_db_put_aborts (void) {
CAST_FROM_VOIDP(filename, iname.data);
assert(filename);
}
+#else
+ filename = toku_xstrdup("foo.db");
+#endif
toku_struct_stat statbuf;
char fullfile[TOKU_PATH_MAX+1];
r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf);
diff --git a/storage/tokudb/ft-index/src/tests/test_abort2.cc b/storage/tokudb/ft-index/src/tests/test_abort2.cc
index e8beb73dcf2..6c63717a99d 100644
--- a/storage/tokudb/ft-index/src/tests/test_abort2.cc
+++ b/storage/tokudb/ft-index/src/tests/test_abort2.cc
@@ -149,6 +149,13 @@ do_test_abort2 (void) {
r=db_create(&db, env, 0); CKERR(r);
r=env->txn_begin(env, 0, &txn, 0); CKERR(r);
r=db->open(db, txn, "foo.db", 0, DB_BTREE, 0, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
+#ifndef TOKUDB
+ {
+ uint32_t ps;
+ r=db->get_pagesize(db, &ps); CKERR(r);
+ assert(ps==4096);
+ }
+#endif
r=txn->commit(txn, 0); assert(r==0);
r=env->txn_begin(env, 0, &txn, 0); assert(r==0);
diff --git a/storage/tokudb/ft-index/src/tests/test_abort3.cc b/storage/tokudb/ft-index/src/tests/test_abort3.cc
index 705ae5cfce2..05f810efe45 100644
--- a/storage/tokudb/ft-index/src/tests/test_abort3.cc
+++ b/storage/tokudb/ft-index/src/tests/test_abort3.cc
@@ -120,7 +120,11 @@ static void op_delete (int i) {
int r = db->del(db, txn,
dbt_init(&key, hello, strlen(hello)+1),
DB_DELETE_ANY);
+#ifdef TOKUDB
assert(r==0);
+#else
+ assert(r==DB_NOTFOUND || r==0);
+#endif
}
static void lookup (int i, int expect, int expectj) {
diff --git a/storage/tokudb/ft-index/src/tests/test_abort4.cc b/storage/tokudb/ft-index/src/tests/test_abort4.cc
index 0d575c78b12..73b82d78c40 100644
--- a/storage/tokudb/ft-index/src/tests/test_abort4.cc
+++ b/storage/tokudb/ft-index/src/tests/test_abort4.cc
@@ -200,6 +200,7 @@ verify_and_tear_down(int close_first) {
int r;
{
char *filename;
+#if USE_TDB
{
DBT dname;
DBT iname;
@@ -211,6 +212,9 @@ verify_and_tear_down(int close_first) {
CAST_FROM_VOIDP(filename, iname.data);
assert(filename);
}
+#else
+ filename = toku_xstrdup("foo.db");
+#endif
toku_struct_stat statbuf;
char fullfile[TOKU_PATH_MAX+1];
r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf);
diff --git a/storage/tokudb/ft-index/src/tests/test_abort5.cc b/storage/tokudb/ft-index/src/tests/test_abort5.cc
index 803e0c4fa22..d8837238dd3 100644
--- a/storage/tokudb/ft-index/src/tests/test_abort5.cc
+++ b/storage/tokudb/ft-index/src/tests/test_abort5.cc
@@ -231,6 +231,7 @@ verify_and_tear_down(int close_first) {
int r;
{
char *filename;
+#if USE_TDB
{
DBT dname;
DBT iname;
@@ -242,6 +243,9 @@ verify_and_tear_down(int close_first) {
CAST_FROM_VOIDP(filename, iname.data);
assert(filename);
}
+#else
+ filename = toku_xstrdup("foo.db");
+#endif
toku_struct_stat statbuf;
char fullfile[TOKU_PATH_MAX+1];
r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf);
diff --git a/storage/tokudb/ft-index/src/tests/test_abort_delete_first.cc b/storage/tokudb/ft-index/src/tests/test_abort_delete_first.cc
index ff55cb2e3ae..721414c90dd 100644
--- a/storage/tokudb/ft-index/src/tests/test_abort_delete_first.cc
+++ b/storage/tokudb/ft-index/src/tests/test_abort_delete_first.cc
@@ -205,12 +205,12 @@ do_abort_delete_first_or_last(int N,
r=db->close(db, 0); CKERR(r);
r=env->close(env, 0); CKERR(r);
-
- // Oh man, this is gross.
- char cmd[sizeof("../../tools/tokudb_dump -h foo.db >") + 2 * TOKU_PATH_MAX];
- snprintf(cmd, sizeof(cmd), "../../tools/tokudb_dump -h %s foo.db > %s", TOKU_TEST_FILENAME, DEV_NULL_FILE);
+#if defined(TOKUDB) && defined(__unix__)
+ char cmd[sizeof("../../utils/tokudb_dump -h foo.db >") + 2 * TOKU_PATH_MAX];
+ snprintf(cmd, sizeof(cmd), "../../utils/tokudb_dump -h %s foo.db > %s", TOKU_TEST_FILENAME, DEV_NULL_FILE);
r=system(cmd);
CKERR(r);
+#endif
}
int
diff --git a/storage/tokudb/ft-index/src/tests/test_archive1.cc b/storage/tokudb/ft-index/src/tests/test_archive1.cc
index 8aa045b061e..1a6f521854f 100644
--- a/storage/tokudb/ft-index/src/tests/test_archive1.cc
+++ b/storage/tokudb/ft-index/src/tests/test_archive1.cc
@@ -135,7 +135,14 @@ test_main (int argc, char *const argv[]) {
CKERR(r);
//this test no longer produces a list with any entries for TDB
// - txn_checkpoint trims unused logfiles
+#if IS_TDB
assert(list == 0);
+#else
+ assert(list);
+ assert(list[0]);
+ if (verbose) printf("file[0]=%s\n", list[0]);
+ toku_free(list);
+#endif
}
r=db->close(db, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_blobs_leaf_split.cc b/storage/tokudb/ft-index/src/tests/test_blobs_leaf_split.cc
index e567e4d58a8..dca73400644 100644
--- a/storage/tokudb/ft-index/src/tests/test_blobs_leaf_split.cc
+++ b/storage/tokudb/ft-index/src/tests/test_blobs_leaf_split.cc
@@ -112,7 +112,11 @@ static void insert(DB *db, DB_TXN *txn, int k, int val_size) {
}
int test_main(int argc, char * const argv[]) {
+#if defined(TOKUDB)
const char *db_env_dir = "dir.blobs.leafsplit.env.tdb";
+#else
+ const char *db_env_dir = "dir.blobs.leafsplit.env.bdb";
+#endif
int db_env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG;
const char *db_filename = "blobs.db";
int do_txn = 1;
diff --git a/storage/tokudb/ft-index/src/tests/test_cachesize.cc b/storage/tokudb/ft-index/src/tests/test_cachesize.cc
index 2af678ff53a..2c3357b584b 100644
--- a/storage/tokudb/ft-index/src/tests/test_cachesize.cc
+++ b/storage/tokudb/ft-index/src/tests/test_cachesize.cc
@@ -101,6 +101,10 @@ PATENT RIGHTS GRANT:
static uint64_t
size_from (uint32_t gbytes, uint32_t bytes) {
+#ifdef USE_BDB
+ if (sizeof (intptr_t) == 4 && gbytes == 4 && bytes == 0)
+ return 0xffffffff;
+#endif
return ((uint64_t)gbytes << 30) + bytes;
}
@@ -115,6 +119,11 @@ expect_le (uint64_t a, uint32_t gbytes, uint32_t bytes) {
uint64_t b = size_from(gbytes, bytes);
if (a != b && verbose)
printf("WARNING: expect %" PRIu64 " got %" PRIu64 "\n", a, b);
+#ifdef USE_BDB
+ if (a > b) {
+ assert(a == 4ULL<<30 && b == a-1); return;
+ }
+#endif
assert(a <= b);
}
diff --git a/storage/tokudb/ft-index/src/tests/test_cursor_delete2.cc b/storage/tokudb/ft-index/src/tests/test_cursor_delete2.cc
index 73a7182e2fd..bb326c80fc5 100644
--- a/storage/tokudb/ft-index/src/tests/test_cursor_delete2.cc
+++ b/storage/tokudb/ft-index/src/tests/test_cursor_delete2.cc
@@ -125,7 +125,7 @@ test_cursor_delete2 (void) {
r = txn->commit(txn, 0); CKERR(r);
r = dbenv->txn_begin(dbenv, 0, &txn, 0); CKERR(r);
- r = db->del(db, txn, dbt_init(&key, "a", 2), DB_DELETE_ANY); CKERR(r);
+ r = db->del(db, txn, dbt_init(&key, "a", 2), DB_DELETE_ANY); CKERR_depending(r,0,DB_NOTFOUND);
r = txn->commit(txn, 0); CKERR(r);
r = dbenv->txn_begin(dbenv, 0, &txn, 0); CKERR(r);
@@ -139,7 +139,7 @@ test_cursor_delete2 (void) {
r = dbenv->txn_begin(dbenv, 0, &txn, 0); CKERR(r);
r = db->del(db, txn, dbt_init(&key, "a", 2), 0); CKERR(r);
- r = db->del(db, txn, dbt_init(&key, "a", 2), DB_DELETE_ANY); CKERR(r);
+ r = db->del(db, txn, dbt_init(&key, "a", 2), DB_DELETE_ANY); CKERR_depending(r,0,DB_NOTFOUND);
r = txn->commit(txn, 0); CKERR(r);
r = db->close(db, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_db_dbt_mem_behavior.cc b/storage/tokudb/ft-index/src/tests/test_db_dbt_mem_behavior.cc
index eb5d7f87893..36ff6ca45eb 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_dbt_mem_behavior.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_dbt_mem_behavior.cc
@@ -223,12 +223,14 @@ test_main(int argc, char *const argv[]) {
assert(!was_truncated);
bool ulen_should_change = false;
+#if defined(USE_TDB)
if (flags[j] == DB_DBT_REALLOC) {
ulen_should_change = (bool)(old_ulen < sizeof(DATA));
}
else if (flags[j] == DB_DBT_MALLOC) {
ulen_should_change = (bool)(old_ulen != sizeof(DATA)*2);
}
+#endif
assert(ulen_should_change == (bool)ulen_changed);
assert(size_full);
assert(doclone == !small_buffer);
diff --git a/storage/tokudb/ft-index/src/tests/test_db_delete.cc b/storage/tokudb/ft-index/src/tests/test_db_delete.cc
index 66fc506d44b..8b4337bae85 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_delete.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_delete.cc
@@ -136,7 +136,9 @@ test_db_delete (int n, int dup_mode) {
/* create the dup database file */
DB_ENV *env;
r = db_env_create(&env, 0); assert(r == 0);
+#ifdef TOKUDB
r = env->set_redzone(env, 0); assert(r == 0);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, DB_CREATE+DB_PRIVATE+DB_INIT_MPOOL, 0); assert(r == 0);
DB *db;
@@ -177,7 +179,16 @@ test_db_delete (int n, int dup_mode) {
}
expect_db_del(db, htonl(n), 0, DB_NOTFOUND);
+#if defined(USE_TDB)
expect_db_del(db, htonl(n), DB_DELETE_ANY, 0);
+#endif
+#if defined(USE_BDB) && defined(DB_DELETE_ANY)
+ #if DB_DELETE_ANY == 0
+ expect_db_del(db, htonl(n), DB_DELETE_ANY, DB_NOTFOUND);
+ #else
+ expect_db_del(db, htonl(n), DB_DELETE_ANY, EINVAL);
+ #endif
+#endif
r = db->close(db, 0); assert(r == 0);
r = env->close(env, 0); assert(r == 0);
@@ -197,7 +208,9 @@ test_db_get_datasize0 (void) {
/* create the dup database file */
DB_ENV *env;
r = db_env_create(&env, 0); assert(r == 0);
+#ifdef TOKUDB
r = env->set_redzone(env, 0); assert(r == 0);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, DB_CREATE+DB_PRIVATE+DB_INIT_MPOOL, 0); assert(r == 0);
DB *db;
diff --git a/storage/tokudb/ft-index/src/tests/test_db_env_open_nocreate.cc b/storage/tokudb/ft-index/src/tests/test_db_env_open_nocreate.cc
index a690a4f33a9..be3deef6c6d 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_env_open_nocreate.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_env_open_nocreate.cc
@@ -117,7 +117,11 @@ test_main(int argc, char *const argv[]) {
int do_private;
for (do_private=0; do_private<2; do_private++) {
+#ifdef USE_TDB
if (do_private==0) continue; // See #208.
+#else
+ if (do_private==1) continue; // See #530. BDB 4.6.21 segfaults if DB_PRIVATE is passed when no environment previously exists.
+#endif
int private_flags = do_private ? (DB_CREATE|DB_PRIVATE) : 0;
toku_os_recursive_delete(TOKU_TEST_FILENAME);
@@ -132,12 +136,37 @@ test_main(int argc, char *const argv[]) {
r = db_env_create(&dbenv, 0);
CKERR(r);
r = dbenv->open(dbenv, TOKU_TEST_FILENAME, private_flags|DB_INIT_MPOOL, 0);
+#ifdef USE_TDB
// TokuDB has no trouble opening an environment if the directory exists.
CKERR(r);
assert(r==0);
+#else
+ if (r!=ENOENT) printf("%s:%d %d: %s\n", __FILE__, __LINE__, r,db_strerror(r));
+ assert(r==ENOENT);
+#endif
dbenv->close(dbenv,0); // free memory
}
+#ifndef USE_TDB
+ // Now make sure that if we have a non-private DB that we can tell if it opened or not.
+ DB *db;
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+ r = db_env_create(&dbenv, 0);
+ CKERR(r);
+ r = dbenv->open(dbenv, TOKU_TEST_FILENAME, DB_CREATE|DB_INIT_MPOOL, 0);
+ CKERR(r);
+ r=db_create(&db, dbenv, 0);
+ CKERR(r);
+ db->close(db, 0);
+ dbenv->close(dbenv,0); // free memory
+ r = db_env_create(&dbenv, 0);
+ CKERR(r);
+ r = dbenv->open(dbenv, TOKU_TEST_FILENAME, DB_INIT_MPOOL, 0);
+ CKERR(r);
+ dbenv->close(dbenv,0); // free memory
+#endif
+
return 0;
}
diff --git a/storage/tokudb/ft-index/src/tests/test_db_env_open_open_close.cc b/storage/tokudb/ft-index/src/tests/test_db_env_open_open_close.cc
index d9336a8b48e..58030826b30 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_env_open_open_close.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_env_open_open_close.cc
@@ -117,7 +117,18 @@ test_main(int argc, char*const* argv) {
r = dbenv->open(dbenv, TOKU_TEST_FILENAME, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0666);
if (verbose) printf("r=%d\n", r);
+#ifdef USE_TDB
assert(r == EINVAL);
+#elif USE_BDB
+#if DB_VERSION_MAJOR >= 5
+ assert(r == EINVAL);
+#else
+ if (verbose) printf("test_db_env_open_open_close.bdb skipped. (BDB apparently does not follow the spec).\n");
+ assert(r == 0);
+#endif
+#else
+#error
+#endif
r = dbenv->close(dbenv, 0);
assert(r == 0);
diff --git a/storage/tokudb/ft-index/src/tests/test_db_env_set_lg_dir.cc b/storage/tokudb/ft-index/src/tests/test_db_env_set_lg_dir.cc
index ffdaf5cb833..bdc1b6ef91a 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_env_set_lg_dir.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_env_set_lg_dir.cc
@@ -121,8 +121,13 @@ test_main(int argc, char *const argv[]) {
r = dbenv->open(dbenv, TOKU_TEST_FILENAME, DB_INIT_TXN|DB_INIT_LOG|DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0);
CKERR(r);
+#ifdef USE_TDB
+ // According to the BDB man page, you may not call set_lg_dir after doing the open.
+ // Some versions of BDB don't actually check this or complain
r = dbenv->set_lg_dir(dbenv, ".");
assert(r == EINVAL);
+#endif
+
r = dbenv->close(dbenv, 0);
assert(r == 0);
diff --git a/storage/tokudb/ft-index/src/tests/test_db_env_set_tmp_dir.cc b/storage/tokudb/ft-index/src/tests/test_db_env_set_tmp_dir.cc
index 150b0b29049..f9e47e7add0 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_env_set_tmp_dir.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_env_set_tmp_dir.cc
@@ -121,8 +121,13 @@ test_main(int argc, char *const argv[]) {
r = dbenv->open(dbenv, TOKU_TEST_FILENAME, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0);
CKERR(r);
+#ifdef USE_TDB
+ // According to the BDB man page, you may not call set_tmp_dir after doing the open.
+ // Some versions of BDB don't actually check this or complain
r = dbenv->set_tmp_dir(dbenv, ".");
assert(r == EINVAL);
+#endif
+
r = dbenv->close(dbenv, 0);
assert(r == 0);
diff --git a/storage/tokudb/ft-index/src/tests/test_db_env_strdup_null.cc b/storage/tokudb/ft-index/src/tests/test_db_env_strdup_null.cc
index 1f65f7a54ed..aa9d50c424f 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_env_strdup_null.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_env_strdup_null.cc
@@ -108,10 +108,13 @@ test_main (int UU(argc), char UU(*const argv[])) {
toku_os_recursive_delete(TOKU_TEST_FILENAME);
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
r=db_env_create(&env, 0); assert(r==0);
+// None of this stuff works with BDB. TDB does more error checking.
+#ifdef USE_TDB
r=env->set_data_dir(env, NULL); assert(r==EINVAL);
r=env->open(env, TOKU_TEST_FILENAME, DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
env->set_errpfx(env, NULL); assert(1); //Did not crash.
r=env->set_tmp_dir(env, NULL); assert(r==EINVAL);
+#endif
r=env->close(env, 0); assert(r==0);
return 0;
}
diff --git a/storage/tokudb/ft-index/src/tests/test_db_get_put_flags.cc b/storage/tokudb/ft-index/src/tests/test_db_get_put_flags.cc
index bb5403732b5..328436b4cd3 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_get_put_flags.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_get_put_flags.cc
@@ -136,7 +136,9 @@ setup (uint32_t flags) {
toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
/* Open/create primary */
r = db_env_create(&dbenv, 0); assert(r == 0);
+#ifdef USE_TDB
r = dbenv->set_redzone(dbenv, 0); CKERR(r);
+#endif
r = dbenv->open(dbenv, TOKU_TEST_FILENAME, DB_CREATE+DB_PRIVATE+DB_INIT_MPOOL, 0); assert(r == 0);
r = db_create(&dbp, dbenv, 0); CKERR(r);
dbp->set_errfile(dbp,0); // Turn off those annoying errors
@@ -180,6 +182,13 @@ get_bad_flags (DB* db, uint32_t flags, int r_expect, int keyint, int dataint) {
assert(*(int*)data.data == dataint);
}
+#ifdef USE_TDB
+#define EINVAL_FOR_TDB_OK_FOR_BDB EINVAL
+#else
+#define EINVAL_FOR_TDB_OK_FOR_BDB 0
+#endif
+
+
PUT_TEST put_tests[] = {
{0, DB_NODUPDATA, EINVAL, 0, 0}, //r_expect must change to 0, once implemented.
{0, 0, 0, 0, 0},
diff --git a/storage/tokudb/ft-index/src/tests/test_db_remove.cc b/storage/tokudb/ft-index/src/tests/test_db_remove.cc
index 7c5009a703d..f254fbee17c 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_remove.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_remove.cc
@@ -114,7 +114,11 @@ static void test_db_remove (void) {
// Now remove it, while it is open.
r = env->dbremove(env, NULL, fname, 0, 0);
+#ifdef USE_TDB
assert(r!=0);
+#else
+ assert(r==0);
+#endif
r = db1->close(db1, 0); assert(r==0);
r = env->close(env, 0); assert(r == 0);
diff --git a/storage/tokudb/ft-index/src/tests/test_db_txn_locks_nonheaviside.cc b/storage/tokudb/ft-index/src/tests/test_db_txn_locks_nonheaviside.cc
index 9451b107e1a..f0eb79d5527 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_txn_locks_nonheaviside.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_txn_locks_nonheaviside.cc
@@ -236,8 +236,10 @@ setup_dbs (void) {
/* Open/create primary */
r = db_env_create(&dbenv, 0);
CKERR(r);
+#ifdef TOKUDB
r = dbenv->set_default_bt_compare(dbenv, int_dbt_cmp);
CKERR(r);
+#endif
uint32_t env_txn_flags = DB_INIT_TXN | DB_INIT_LOCK;
uint32_t env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL;
r = dbenv->open(dbenv, TOKU_TEST_FILENAME, env_open_flags | env_txn_flags, 0600);
@@ -245,6 +247,10 @@ setup_dbs (void) {
r = db_create(&db, dbenv, 0);
CKERR(r);
+#ifndef TOKUDB
+ r = db->set_bt_compare( db, int_dbt_cmp);
+ CKERR(r);
+#endif
char a;
for (a = 'a'; a <= 'z'; a++) init_txn(a);
@@ -659,6 +665,16 @@ test (void) {
int
test_main(int argc, char *const argv[]) {
parse_args(argc, argv);
- test();
+ if (!IS_TDB) {
+ if (verbose) {
+ printf("Warning: " __FILE__" does not work in BDB.\n");
+ }
+ } else {
+ test();
+ /*
+ test_abort(0);
+ test_abort(DB_DUP | DB_DUPSORT);
+ */
+ }
return 0;
}
diff --git a/storage/tokudb/ft-index/src/tests/test_db_txn_locks_read_uncommitted.cc b/storage/tokudb/ft-index/src/tests/test_db_txn_locks_read_uncommitted.cc
index 277fbaee8be..5e9a947b9e6 100644
--- a/storage/tokudb/ft-index/src/tests/test_db_txn_locks_read_uncommitted.cc
+++ b/storage/tokudb/ft-index/src/tests/test_db_txn_locks_read_uncommitted.cc
@@ -178,8 +178,10 @@ setup_dbs (void) {
/* Open/create primary */
r = db_env_create(&dbenv, 0);
CKERR(r);
+#ifdef TOKUDB
r = dbenv->set_default_bt_compare(dbenv, int_dbt_cmp);
CKERR(r);
+#endif
uint32_t env_txn_flags = DB_INIT_TXN | DB_INIT_LOCK;
uint32_t env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL;
r = dbenv->open(dbenv, TOKU_TEST_FILENAME, env_open_flags | env_txn_flags, 0600);
@@ -187,6 +189,10 @@ setup_dbs (void) {
r = db_create(&db, dbenv, 0);
CKERR(r);
+#ifndef TOKUDB
+ r = db->set_bt_compare( db, int_dbt_cmp);
+ CKERR(r);
+#endif
char a;
for (a = 'a'; a <= 'z'; a++) init_txn(a, 0);
@@ -250,9 +256,28 @@ table_scan(char txn, bool success) {
static void
table_prelock(char txn, bool success) {
int r;
+#if defined USE_TDB && USE_TDB
r = db->pre_acquire_table_lock(db, txns[(int)txn]);
if (success) CKERR(r);
else CKERR2s(r, DB_LOCK_NOTGRANTED, DB_LOCK_DEADLOCK);
+#else
+ DBT key;
+ DBT data;
+
+ assert(txns[(int)txn] && cursors[(int)txn]);
+ r = cursors[(int)txn]->c_get(cursors[(int)txn],
+ dbt_init(&key, 0, 0),
+ dbt_init(&data, 0, 0),
+ DB_FIRST | DB_RMW);
+ while (r==0) {
+ r = cursors[(int)txn]->c_get(cursors[(int)txn],
+ dbt_init(&key, 0, 0),
+ dbt_init(&data, 0, 0),
+ DB_NEXT | DB_RMW);
+ }
+ if (success) CKERR2(r, DB_NOTFOUND);
+ else CKERR2s(r, DB_LOCK_NOTGRANTED, DB_LOCK_DEADLOCK);
+#endif
}
static void
diff --git a/storage/tokudb/ft-index/src/tests/test_env_close_flags.cc b/storage/tokudb/ft-index/src/tests/test_env_close_flags.cc
index 50fcd3fa50a..b393c5e1399 100644
--- a/storage/tokudb/ft-index/src/tests/test_env_close_flags.cc
+++ b/storage/tokudb/ft-index/src/tests/test_env_close_flags.cc
@@ -114,7 +114,12 @@ test_main (int argc __attribute__((__unused__)), char *const argv[] __attribute
r=db_env_create(&env, 0); assert(r==0);
env->set_errfile(env,0); // Turn off those annoying errors
r=env->close (env, 1);
+ //BDB does not check this in some versions
+#if defined(USE_TDB) || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
assert(r==EINVAL);
+#else
+ assert(r==0);
+#endif
toku_os_recursive_delete(TOKU_TEST_FILENAME);
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
@@ -130,6 +135,11 @@ test_main (int argc __attribute__((__unused__)), char *const argv[] __attribute
env->set_errfile(env,0); // Turn off those annoying errors
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_PRIVATE|DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=env->close (env, 1);
+ //BDB does not check this.
+#if defined(USE_TDB) || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
assert(r==EINVAL);
+#else
+ assert(r==0);
+#endif
return 0;
}
diff --git a/storage/tokudb/ft-index/src/tests/test_env_create_db_create.cc b/storage/tokudb/ft-index/src/tests/test_env_create_db_create.cc
index 8e706ebf04e..0425b2191d4 100644
--- a/storage/tokudb/ft-index/src/tests/test_env_create_db_create.cc
+++ b/storage/tokudb/ft-index/src/tests/test_env_create_db_create.cc
@@ -104,7 +104,13 @@ test_main (int UU(argc), char UU(*const argv[])) {
r = db_env_create(&env, 0);
assert(r == 0);
r = db_create(&db, env, 0);
+// BDB doesnt' actually barf on this case.
+#ifdef USE_TDB
assert(r != 0);
+#else
+ r = db->close(db, 0);
+ assert(r == 0);
+#endif
r = env->close(env, 0);
assert(r == 0);
return 0;
diff --git a/storage/tokudb/ft-index/src/tests/test_env_open_flags.cc b/storage/tokudb/ft-index/src/tests/test_env_open_flags.cc
index 8d9b147e46d..7bded023a29 100644
--- a/storage/tokudb/ft-index/src/tests/test_env_open_flags.cc
+++ b/storage/tokudb/ft-index/src/tests/test_env_open_flags.cc
@@ -125,19 +125,25 @@ test_main(int argc, char *const argv[]) {
toku_os_recursive_delete(TOKU_TEST_FILENAME);
toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+#ifdef USE_TDB
char tracefile[TOKU_PATH_MAX+1];
toku_set_trace_file(toku_path_join(tracefile, 2, TOKU_TEST_FILENAME, "trace.tktrace"));
+#endif
/* test flags */
test_env_open_flags(0, ENOENT);
+#ifdef TOKUDB
// This one segfaults in BDB 4.6.21
test_env_open_flags(DB_PRIVATE, ENOENT);
+#endif
test_env_open_flags(DB_PRIVATE+DB_CREATE, 0);
test_env_open_flags(DB_PRIVATE+DB_CREATE+DB_INIT_MPOOL, 0);
test_env_open_flags(DB_PRIVATE+DB_RECOVER, EINVAL);
test_env_open_flags(DB_PRIVATE+DB_CREATE+DB_INIT_MPOOL+DB_RECOVER, EINVAL);
+#ifdef USE_TDB
toku_close_trace_file();
+#endif
return 0;
}
diff --git a/storage/tokudb/ft-index/src/tests/test_groupcommit_count.cc b/storage/tokudb/ft-index/src/tests/test_groupcommit_count.cc
index c24efb5562f..acf0d5f7076 100644
--- a/storage/tokudb/ft-index/src/tests/test_groupcommit_count.cc
+++ b/storage/tokudb/ft-index/src/tests/test_groupcommit_count.cc
@@ -101,7 +101,12 @@ DB_ENV *env;
DB *db;
int do_sync=1;
+#ifdef TOKUDB
#define NITER 100
+#else
+// BDB is slow. Reduce the work.
+#define NITER 25
+#endif
static void *start_a_thread (void *i_p) {
int *CAST_FROM_VOIDP(which_thread_p, i_p);
@@ -209,7 +214,12 @@ do_test (int N) {
}
}
+#ifdef TOKUDB
int log_max_n_threads_over_10 = 3;
+#else
+// BDB is slow. Reduce the work.
+int log_max_n_threads_over_10 = 2;
+#endif
static void
my_parse_args (int argc, char *const argv[]) {
@@ -257,7 +267,9 @@ test_main (int argc, char *const argv[]) {
prev_count=0;
db_env_set_func_fsync(do_fsync);
+#if TOKUDB
db_env_set_num_bucket_mutexes(32);
+#endif
toku_os_recursive_delete(env_path);
{ int r=toku_os_mkdir(env_path, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0); }
diff --git a/storage/tokudb/ft-index/src/tests/test_locktree_close.cc b/storage/tokudb/ft-index/src/tests/test_locktree_close.cc
index 10efefd0b62..f3d220059b6 100644
--- a/storage/tokudb/ft-index/src/tests/test_locktree_close.cc
+++ b/storage/tokudb/ft-index/src/tests/test_locktree_close.cc
@@ -106,7 +106,7 @@ test_cursor (void) {
DB_ENV * env;
DB *db;
DB_TXN * const null_txn = 0;
- const char * const fname = "test.cursor.ft";
+ const char * const fname = "test.cursor.brt";
int r;
/* create the dup database file */
diff --git a/storage/tokudb/ft-index/src/tests/test_log1.cc b/storage/tokudb/ft-index/src/tests/test_log1.cc
index 3c03249c845..11e402d7be9 100644
--- a/storage/tokudb/ft-index/src/tests/test_log1.cc
+++ b/storage/tokudb/ft-index/src/tests/test_log1.cc
@@ -123,6 +123,7 @@ static void make_db (bool close_env) {
CKERR(r);
}
char *filename;
+#if USE_TDB
{
DBT dname;
DBT iname;
@@ -134,6 +135,10 @@ static void make_db (bool close_env) {
CAST_FROM_VOIDP(filename, iname.data);
assert(filename);
}
+#else
+ filename = toku_xstrdup("foo.db");
+#endif
+
r=tid->commit(tid, 0); assert(r==0);
r=db->close(db, 0); assert(r==0);
diff --git a/storage/tokudb/ft-index/src/tests/test_log10.cc b/storage/tokudb/ft-index/src/tests/test_log10.cc
index 599eb16d3ae..48535f1871a 100644
--- a/storage/tokudb/ft-index/src/tests/test_log10.cc
+++ b/storage/tokudb/ft-index/src/tests/test_log10.cc
@@ -120,7 +120,9 @@ static void insert_some (int outeri, bool close_env) {
DB *db;
DB_TXN *tid;
r=db_env_create(&env, 0); assert(r==0);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|create_flag, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
@@ -146,6 +148,13 @@ static void insert_some (int outeri, bool close_env) {
key.data = hello; key.size=strlen(hello)+1;
data.data = there; data.size=strlen(there)+1;
r=db->put(db, tid, &key, &data, 0); CKERR(r);
+#ifndef TOKUDB
+ // BDB cannot handle such a big txn.
+ if (i%1000==999) {
+ r=tid->commit(tid, 0); assert(r==0);
+ r=env->txn_begin(env, 0, &tid, 0); assert(r==0);
+ }
+#endif
}
r=tid->commit(tid, 0); assert(r==0);
r=db->close(db, 0); assert(r==0);
@@ -164,7 +173,9 @@ static void make_db (bool close_env) {
toku_os_recursive_delete(TOKU_TEST_FILENAME);
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
r=db_env_create(&env, 0); assert(r==0);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_log1_abort.cc b/storage/tokudb/ft-index/src/tests/test_log1_abort.cc
index f1f8269239e..4cc37daec28 100644
--- a/storage/tokudb/ft-index/src/tests/test_log1_abort.cc
+++ b/storage/tokudb/ft-index/src/tests/test_log1_abort.cc
@@ -129,7 +129,15 @@ test_main (int UU(argc), char UU(*const argv[])) {
r=tid->abort(tid);
assert(r==0);
r=env->close(env, 0);
+#ifdef USE_BDB
+#if DB_VERSION_MAJOR >= 5
assert(r==0);
+#else
+ assert(r==ENOENT);
+#endif
+#else
+ assert(r==0);
+#endif
{
toku_struct_stat statbuf;
char filename[TOKU_PATH_MAX+1];
diff --git a/storage/tokudb/ft-index/src/tests/test_log7.cc b/storage/tokudb/ft-index/src/tests/test_log7.cc
index ca5eb168028..cc38ae92ae3 100644
--- a/storage/tokudb/ft-index/src/tests/test_log7.cc
+++ b/storage/tokudb/ft-index/src/tests/test_log7.cc
@@ -122,6 +122,9 @@ static void make_db (bool close_env) {
toku_os_recursive_delete(TOKU_TEST_FILENAME);
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
r=db_env_create(&env, 0); assert(r==0);
+#ifdef TOKUDB
+
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
r=env->txn_begin(env, 0, &tid, 0); assert(r==0);
@@ -144,11 +147,13 @@ static void make_db (bool close_env) {
key.data = hello; key.size=strlen(hello)+1;
data.data = there; data.size=strlen(there)+1;
r=db->put(db, tid, &key, &data, 0); assert(r==0);
+#ifndef TOKUDB
// BDB cannot handle this huge transaction even with a lot of locks.
if (i%1000==599) {
r=tid->commit(tid, 0); assert(r==0);
r=env->txn_begin(env, 0, &tid, 0); assert(r==0);
}
+#endif
}
r=tid->commit(tid, 0); assert(r==0);
r=db->close(db, 0); assert(r==0);
diff --git a/storage/tokudb/ft-index/src/tests/test_log8.cc b/storage/tokudb/ft-index/src/tests/test_log8.cc
index bf6cad4c66b..a2c59400013 100644
--- a/storage/tokudb/ft-index/src/tests/test_log8.cc
+++ b/storage/tokudb/ft-index/src/tests/test_log8.cc
@@ -119,7 +119,9 @@ static void insert_some (int outeri, bool close_env) {
DB *db;
DB_TXN *tid;
r=db_env_create(&env, 0); assert(r==0);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|create_flag, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
@@ -164,7 +166,9 @@ static void make_db (bool close_env) {
toku_os_recursive_delete(TOKU_TEST_FILENAME);
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
r=db_env_create(&env, 0); assert(r==0);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_log9.cc b/storage/tokudb/ft-index/src/tests/test_log9.cc
index 302eaefb976..c61312f90d2 100644
--- a/storage/tokudb/ft-index/src/tests/test_log9.cc
+++ b/storage/tokudb/ft-index/src/tests/test_log9.cc
@@ -119,7 +119,9 @@ static void insert_some (int outeri, bool close_env) {
DB *db;
DB_TXN *tid;
r=db_env_create(&env, 0); assert(r==0);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE|create_flag, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
@@ -163,7 +165,9 @@ static void make_db (bool close_env) {
toku_os_recursive_delete(TOKU_TEST_FILENAME);
r=toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
r=db_env_create(&env, 0); assert(r==0);
+#if IS_TDB
db_env_enable_engine_status(0); // disable engine status on crash because test is expected to fail
+#endif
r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_CREATE|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r=db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_logflush.cc b/storage/tokudb/ft-index/src/tests/test_logflush.cc
index 0c813d4b131..f7870bee5ce 100644
--- a/storage/tokudb/ft-index/src/tests/test_logflush.cc
+++ b/storage/tokudb/ft-index/src/tests/test_logflush.cc
@@ -96,7 +96,11 @@ PATENT RIGHTS GRANT:
// Return the offset
static int
grep_for_in_logs (const char *str) {
+#ifdef TOKUDB
#define lfname "log000000000000.tokulog[0-9]*"
+#else
+#define lfname "log.0000000001"
+#endif
#define COMMAND "grep -F -q"
char lname[TOKU_PATH_MAX+1];
toku_path_join(lname, 2, TOKU_TEST_FILENAME, lfname);
diff --git a/storage/tokudb/ft-index/src/tests/test_logmax.cc b/storage/tokudb/ft-index/src/tests/test_logmax.cc
index 6c8b5a43ee2..2ff773a043a 100644
--- a/storage/tokudb/ft-index/src/tests/test_logmax.cc
+++ b/storage/tokudb/ft-index/src/tests/test_logmax.cc
@@ -152,7 +152,11 @@ test_logmax (int logmax) {
int effective_max;
if (logmax>0) effective_max = logmax;
else {
+#ifdef TOKUDB
effective_max = 100<<20;
+#else
+ effective_max = 10<<20;
+#endif
}
r=env->txn_begin(env, 0, &tid, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_reverse_compare_fun.cc b/storage/tokudb/ft-index/src/tests/test_reverse_compare_fun.cc
index 774a78d23b1..7d569c5bf97 100644
--- a/storage/tokudb/ft-index/src/tests/test_reverse_compare_fun.cc
+++ b/storage/tokudb/ft-index/src/tests/test_reverse_compare_fun.cc
@@ -155,8 +155,10 @@ test_reverse_compare (int n) {
/* create the dup database file */
DB_ENV *env;
r = db_env_create(&env, 0); assert(r == 0);
+#ifdef TOKUDB
r = env->set_default_bt_compare(env, reverse_compare);
CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, DB_CREATE+DB_PRIVATE+DB_INIT_MPOOL, 0); assert(r == 0);
DB *db;
@@ -164,6 +166,10 @@ test_reverse_compare (int n) {
CKERR(r);
r = db->set_pagesize(db, 4096);
CKERR(r);
+#ifndef TOKUDB
+ r = db->set_bt_compare(db, reverse_compare);
+ CKERR(r);
+#endif
r = db->open(db, null_txn, fname, "main", DB_BTREE, DB_CREATE, 0666);
CKERR(r);
@@ -186,6 +192,10 @@ test_reverse_compare (int n) {
CKERR(r);
r = db->set_pagesize(db, 4096);
CKERR(r);
+#ifndef TOKUDB
+ r = db->set_bt_compare(db, reverse_compare);
+ CKERR(r);
+#endif
r = db->open(db, null_txn, fname, "main", DB_BTREE, 0, 0666);
CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_set_func_malloc.cc b/storage/tokudb/ft-index/src/tests/test_set_func_malloc.cc
index 8efa786b7fd..eea9a913c1c 100644
--- a/storage/tokudb/ft-index/src/tests/test_set_func_malloc.cc
+++ b/storage/tokudb/ft-index/src/tests/test_set_func_malloc.cc
@@ -153,6 +153,7 @@ test1 (void)
db_env_set_func_realloc(brealloc);
db_env_set_func_free(bfree);
+#ifdef USE_TDB
// toku_malloc isn't affected by calling the BDB set_fun_malloc calls.
malloc_counter = realloc_counter = free_counter = 0;
@@ -165,6 +166,8 @@ test1 (void)
db_env_set_func_malloc(NULL);
db_env_set_func_realloc(NULL);
db_env_set_func_free(NULL);
+
+#endif
}
int
diff --git a/storage/tokudb/ft-index/src/tests/test_txn_abort7.cc b/storage/tokudb/ft-index/src/tests/test_txn_abort7.cc
index 8832e950310..144591ca650 100644
--- a/storage/tokudb/ft-index/src/tests/test_txn_abort7.cc
+++ b/storage/tokudb/ft-index/src/tests/test_txn_abort7.cc
@@ -119,6 +119,7 @@ test_abort_create (void) {
{
char *filename;
+#if USE_TDB
{
DBT dname;
DBT iname;
@@ -130,6 +131,9 @@ test_abort_create (void) {
CAST_FROM_VOIDP(filename, iname.data);
assert(filename);
}
+#else
+ filename = toku_xstrdup("test.db");
+#endif
toku_struct_stat statbuf;
char fullfile[TOKU_PATH_MAX+1];
r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf);
@@ -141,6 +145,7 @@ test_abort_create (void) {
r = txn->abort(txn); assert(r == 0);
{
+#if USE_TDB
{
DBT dname;
DBT iname;
@@ -150,6 +155,7 @@ test_abort_create (void) {
r = env->get_iname(env, &dname, &iname);
CKERR2(r, DB_NOTFOUND);
}
+#endif
toku_struct_stat statbuf;
char fullfile[TOKU_PATH_MAX+1];
r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf);
diff --git a/storage/tokudb/ft-index/src/tests/test_equal_keys_with_different_bytes.cc b/storage/tokudb/ft-index/src/tests/test_txn_abort8.cc
index 6567822c929..176b5544c78 100644
--- a/storage/tokudb/ft-index/src/tests/test_equal_keys_with_different_bytes.cc
+++ b/storage/tokudb/ft-index/src/tests/test_txn_abort8.cc
@@ -30,7 +30,7 @@ COPYING CONDITIONS NOTICE:
COPYRIGHT NOTICE:
TokuDB, Tokutek Fractal Tree Indexing Library.
- Copyright (C) 2014 Tokutek, Inc.
+ Copyright (C) 2007-2013 Tokutek, Inc.
DISCLAIMER:
@@ -86,64 +86,71 @@ PATENT RIGHTS GRANT:
under this License.
*/
-#ident "Copyright (c) 2014 Tokutek Inc. All rights reserved."
-
-#include <string>
-
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#include "test.h"
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <memory.h>
+#include <sys/stat.h>
+#include <db.h>
+
+//
+static void
+test_abort_close (void) {
+
+#ifndef USE_TDB
+#if DB_VERSION_MAJOR==4 && DB_VERSION_MINOR==3
+ if (verbose) fprintf(stderr, "%s does not work for BDB %d.%d. Not running\n", __FILE__, DB_VERSION_MAJOR, DB_VERSION_MINOR);
+ return;
+#else
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
-static int compare_strings_case_insensitive(DB *db, const DBT *a, const DBT *b) {
- invariant_notnull(db);
- return strcasecmp(reinterpret_cast<char *>(a->data),
- reinterpret_cast<char *>(b->data));
-}
-
-static void test_equal_keys_with_different_bytes(void) {
int r;
-
DB_ENV *env;
- r = db_env_create(&env, 0); CKERR(r);
- r = env->set_default_bt_compare(env, compare_strings_case_insensitive);
- r = env->open(env, TOKU_TEST_FILENAME, DB_CREATE+DB_PRIVATE+DB_INIT_MPOOL+DB_INIT_TXN, 0); CKERR(r);
-
- DB *db;
- r = db_create(&db, env, 0); CKERR(r);
- r = db->open(db, NULL, "db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(r);
-
- DBT key;
+ r = db_env_create(&env, 0); assert(r == 0);
+ r = env->set_data_dir(env, TOKU_TEST_FILENAME);
+ r = env->set_lg_dir(env, TOKU_TEST_FILENAME);
+ env->set_errfile(env, stdout);
+ r = env->open(env, 0, DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ if (r != 0) printf("%s:%d:%d:%s\n", __FILE__, __LINE__, r, db_strerror(r));
+ assert(r == 0);
- // put 'key'
- dbt_init(&key, "key", sizeof("key"));
- r = db->put(db, NULL, &key, &key, 0); CKERR(r);
+ DB_TXN *txn = 0;
+ r = env->txn_begin(env, 0, &txn, 0); assert(r == 0);
- // del 'KEY' - should match 'key'
- dbt_init(&key, "KEY", sizeof("KEY"));
- r = db->del(db, NULL, &key, 0); CKERR(r);
-
- DBT val;
- char val_buf[10];
- dbt_init(&val, val_buf, sizeof(val_buf));
-
- // search should fail for 'key'
- dbt_init(&key, "key", sizeof("key"));
- r = db->get(db, NULL, &key, &val, 0); CKERR2(r, DB_NOTFOUND);
-
- // search should fail for 'KEY'
- dbt_init(&key, "KEY", sizeof("KEY"));
- r = db->get(db, NULL, &key, &val, 0); CKERR2(r, DB_NOTFOUND);
-
- r = db->close(db, 0); CKERR(r);
- r = env->close(env, 0); CKERR(r);
+ DB *db;
+ r = db_create(&db, env, 0); assert(r == 0);
+ r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0);
+
+ {
+ toku_struct_stat statbuf;
+ char fullfile[TOKU_PATH_MAX+1];
+ r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf);
+ assert(r==0);
+ }
+
+ // Close before abort.
+ r = db->close(db, 0);
+
+ r = txn->abort(txn); assert(r == 0);
+
+ r = env->close(env, 0); assert(r == 0);
+
+ {
+ toku_struct_stat statbuf;
+ char fullfile[TOKU_PATH_MAX+1];
+ r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf);
+ assert(r!=0);
+ }
+#endif
+#endif
}
int
-test_main(int argc, char *const argv[]) {
- parse_args(argc, argv);
-
- toku_os_recursive_delete(TOKU_TEST_FILENAME);
- int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
-
- test_equal_keys_with_different_bytes();
-
+test_main(int UU(argc), char UU(*const argv[])) {
+ test_abort_close();
return 0;
}
diff --git a/storage/tokudb/ft-index/src/tests/test_txn_abort9.cc b/storage/tokudb/ft-index/src/tests/test_txn_abort9.cc
new file mode 100644
index 00000000000..48c4ae120e8
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/test_txn_abort9.cc
@@ -0,0 +1,162 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#include "test.h"
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <memory.h>
+#include <sys/stat.h>
+#include <db.h>
+
+//
+static void
+test_abort_close (void) {
+
+#ifndef USE_TDB
+#if DB_VERSION_MAJOR==4 && DB_VERSION_MINOR==3
+ if (verbose) fprintf(stderr, "%s does not work for BDB %d.%d. Not running\n", __FILE__, DB_VERSION_MAJOR, DB_VERSION_MINOR);
+ return;
+#else
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+
+ int r;
+ DB_ENV *env;
+ r = db_env_create(&env, 0); assert(r == 0);
+ r = env->set_data_dir(env, TOKU_TEST_FILENAME);
+ r = env->set_lg_dir(env, TOKU_TEST_FILENAME);
+ env->set_errfile(env, stdout);
+ r = env->open(env, 0, DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ if (r != 0) printf("%s:%d:%d:%s\n", __FILE__, __LINE__, r, db_strerror(r));
+ assert(r == 0);
+
+ DB_TXN *txn = 0;
+ r = env->txn_begin(env, 0, &txn, 0); assert(r == 0);
+
+ DB *db;
+ r = db_create(&db, env, 0); assert(r == 0);
+ r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0);
+
+ {
+ toku_struct_stat statbuf;
+ char fullfile[TOKU_PATH_MAX+1];
+ r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf);
+ assert(r==0);
+ }
+
+ // Close before commit.
+ r = db->close(db, 0);
+ r = txn->commit(txn, 0); CKERR(r);
+
+ // Now reopen it
+ r = env->txn_begin(env, 0, &txn, 0); CKERR(r);
+ r = db_create(&db, env, 0); assert(r == 0);
+ r = db->open(db, txn, "test.db", 0, DB_BTREE, 0, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0);
+
+ DBT k,v;
+ r = db->put(db, txn, dbt_init(&k, "hello", 6), dbt_init(&v, "there", 6), 0);
+ CKERR(r);
+
+ r = db->close(db, 0);
+
+ r = txn->abort(txn); assert(r == 0);
+
+ r = env->close(env, 0); CKERR(r);
+
+#endif
+#endif
+}
+
+int
+test_main(int UU(argc), char UU(*const argv[])) {
+ test_abort_close();
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/test_txn_close_open_commit.cc b/storage/tokudb/ft-index/src/tests/test_txn_close_open_commit.cc
new file mode 100644
index 00000000000..4f5060b3871
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/test_txn_close_open_commit.cc
@@ -0,0 +1,168 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#include "test.h"
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <memory.h>
+#include <sys/stat.h>
+#include <db.h>
+
+// Recreate a mysqld crash by closing and opening a db within a transaction.
+// The crash occurs when writing a dirty cachetable pair, so we insert one
+// row.
+static void
+test_txn_close_open_commit (void) {
+
+#ifndef USE_TDB
+#if DB_VERSION_MAJOR==4 && DB_VERSION_MINOR==3
+ if (verbose) fprintf(stderr, "%s does not work for BDB %d.%d. Not running\n", __FILE__, DB_VERSION_MAJOR, DB_VERSION_MINOR);
+ return;
+#else
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+
+ int r;
+ DB_ENV *env;
+ r = db_env_create(&env, 0); assert(r == 0);
+ r = env->set_data_dir(env, TOKU_TEST_FILENAME);
+ r = env->set_lg_dir(env, TOKU_TEST_FILENAME);
+ env->set_errfile(env, stdout);
+ r = env->open(env, 0, DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ if (r != 0) printf("%s:%d:%d:%s\n", __FILE__, __LINE__, r, db_strerror(r));
+ assert(r == 0);
+
+ DB_TXN *txn = 0;
+ r = env->txn_begin(env, 0, &txn, 0); assert(r == 0);
+
+ DB *db;
+ r = db_create(&db, env, 0); assert(r == 0);
+ r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0);
+
+ {
+ toku_struct_stat statbuf;
+ char fullfile[TOKU_PATH_MAX+1];
+ r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf);
+ assert(r==0);
+ }
+
+ DBT key, val;
+ int k = 1, v = 1;
+ r = db->put(db, txn, dbt_init(&key, &k, sizeof k), dbt_init(&val, &v, sizeof v), 0);
+ assert(r == 0);
+
+ // Close before commit
+ r = db->close(db, 0); assert(r == 0);
+
+ r = db_create(&db, env, 0); assert(r == 0);
+ r = db->open(db, txn, "test.db", 0, DB_UNKNOWN, 0, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0);
+
+ r = txn->commit(txn, 0); assert(r == 0);
+
+ r = db->close(db, 0); assert(r == 0);
+
+ r = env->close(env, 0); assert(r == 0);
+
+ {
+ toku_struct_stat statbuf;
+ char fullfile[TOKU_PATH_MAX+1];
+ r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf);
+ assert(r==0);
+ }
+#endif
+#endif
+}
+
+int
+test_main(int UU(argc), char UU(*const argv[])) {
+ test_txn_close_open_commit();
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/test_txn_commit8.cc b/storage/tokudb/ft-index/src/tests/test_txn_commit8.cc
new file mode 100644
index 00000000000..4f4d732dc8b
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/test_txn_commit8.cc
@@ -0,0 +1,156 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#include "test.h"
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <memory.h>
+#include <sys/stat.h>
+#include <db.h>
+
+// like test_txn_abort8.c except commit
+static void
+test_abort_close (void) {
+
+#ifndef USE_TDB
+#if DB_VERSION_MAJOR==4 && DB_VERSION_MINOR==3
+ if (verbose) fprintf(stderr, "%s does not work for BDB %d.%d. Not running\n", __FILE__, DB_VERSION_MAJOR, DB_VERSION_MINOR);
+ return;
+#else
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+
+ int r;
+ DB_ENV *env;
+ r = db_env_create(&env, 0); assert(r == 0);
+ r = env->set_data_dir(env, TOKU_TEST_FILENAME);
+ r = env->set_lg_dir(env, TOKU_TEST_FILENAME);
+ env->set_errfile(env, stdout);
+ r = env->open(env, 0, DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ if (r != 0) printf("%s:%d:%d:%s\n", __FILE__, __LINE__, r, db_strerror(r));
+ assert(r == 0);
+
+ DB_TXN *txn = 0;
+ r = env->txn_begin(env, 0, &txn, 0); assert(r == 0);
+
+ DB *db;
+ r = db_create(&db, env, 0); assert(r == 0);
+ r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0);
+
+ {
+ toku_struct_stat statbuf;
+ char fullfile[TOKU_PATH_MAX+1];
+ r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf);
+ assert(r==0);
+ }
+
+ // Close before commit
+ r = db->close(db, 0);
+
+ r = txn->commit(txn, 0); assert(r == 0);
+
+ r = env->close(env, 0); assert(r == 0);
+
+ {
+ toku_struct_stat statbuf;
+ char fullfile[TOKU_PATH_MAX+1];
+ r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf);
+ assert(r==0);
+ }
+#endif
+#endif
+}
+
+int
+test_main(int UU(argc), char UU(*const argv[])) {
+ test_abort_close();
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/test_txn_cursor_last.cc b/storage/tokudb/ft-index/src/tests/test_txn_cursor_last.cc
index 62cb3984b79..62813ab86c3 100644
--- a/storage/tokudb/ft-index/src/tests/test_txn_cursor_last.cc
+++ b/storage/tokudb/ft-index/src/tests/test_txn_cursor_last.cc
@@ -291,10 +291,12 @@ test_main(int argc, char *const argv[]) {
parse_args(argc, argv);
- test_txn_cursor_last_1(0);
- test_txn_cursor_last_1(1);
- test_txn_cursor_last_2(0);
- test_txn_cursor_last_2(1);
+ if (IS_TDB) {
+ test_txn_cursor_last_1(0);
+ test_txn_cursor_last_1(1);
+ test_txn_cursor_last_2(0);
+ test_txn_cursor_last_2(1);
+ }
return 0;
}
diff --git a/storage/tokudb/ft-index/src/tests/test_txn_nested1.cc b/storage/tokudb/ft-index/src/tests/test_txn_nested1.cc
index d25e7c61ce2..a5ba6afdfb1 100644
--- a/storage/tokudb/ft-index/src/tests/test_txn_nested1.cc
+++ b/storage/tokudb/ft-index/src/tests/test_txn_nested1.cc
@@ -125,7 +125,9 @@ setup_db (void) {
toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
r = db_env_create(&env, 0); CKERR(r);
+#ifdef TOKUDB
r = env->set_default_bt_compare(env, int_dbt_cmp); CKERR(r);
+#endif
r = env->open(env, TOKU_TEST_FILENAME, DB_INIT_MPOOL | DB_INIT_LOG | DB_INIT_LOCK | DB_INIT_TXN | DB_PRIVATE | DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
CKERR(r);
@@ -134,6 +136,9 @@ setup_db (void) {
r = env->txn_begin(env, 0, &txn, 0); CKERR(r);
r = db_create(&db, env, 0); CKERR(r);
+#ifndef TOKUDB
+ r = db->set_bt_compare(db, int_dbt_cmp); CKERR(r);
+#endif
r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
r = txn->commit(txn, 0); CKERR(r);
}
@@ -214,6 +219,74 @@ test_txn_nesting (int depth) {
}
}
+
+#if 0
+static void
+test_txn_abort (int insert, int secondnum) {
+ if (verbose) { fprintf(stderr, "%s (%s):%d [%d,%d]\n", __FILE__, __FUNCTION__, __LINE__, insert, secondnum); fflush(stderr); }
+ setup_db();
+
+ DBT key, val;
+ int r;
+
+
+ DB_TXN *parent = NULL, *child = NULL;
+
+ int i = 1;
+ r = env->txn_begin(env, 0, &parent, 0); CKERR(r);
+
+ //Insert something as a child
+ r = env->txn_begin(env, parent, &child, 0); CKERR(r);
+ i = 1;
+ r = db->put(db, child, dbt_init(&key, &i, sizeof i), dbt_init(&val, &i, sizeof i), 0);
+ CKERR(r);
+ r = child->commit(child,DB_TXN_NOSYNC);
+ child = NULL;
+
+
+ //delete it as a child
+ r = env->txn_begin(env, parent, &child, 0); CKERR(r);
+ i = secondnum;
+ if (insert) {
+ r = db->put(db, child, dbt_init(&key, &i, sizeof i), dbt_init(&val, &i, sizeof i), 0);
+ CKERR(r);
+ }
+ else { // delete
+ r = db->del(db, child, dbt_init(&key, &i, sizeof i), DB_DELETE_ANY);
+ if (IS_TDB) {
+ CKERR(r);
+ } else {
+ CKERR2(r, (secondnum==1 ? 0 : DB_NOTFOUND));
+ }
+ }
+ r = child->commit(child,DB_TXN_NOSYNC);
+ child = NULL;
+
+ r = parent->abort(parent);
+ CKERR(r);
+ parent = NULL;
+
+
+ {
+ DB_TXN *txn = NULL;
+ /* walk the db, should be empty */
+ r = env->txn_begin(env, 0, &txn, 0); CKERR(r);
+ DBC *cursor;
+ r = db->cursor(db, txn, &cursor, 0); CKERR(r);
+ memset(&key, 0, sizeof key);
+ memset(&val, 0, sizeof val);
+ r = cursor->c_get(cursor, &key, &val, DB_FIRST);
+ CKERR2(r, DB_NOTFOUND);
+ r = cursor->c_close(cursor); CKERR(r);
+ r = txn->commit(txn, 0);
+ }
+ r=db->close(db, 0); CKERR(r);
+ r=env->close(env, 0); CKERR(r);
+
+}
+
+#endif
+
int
test_main(int argc, char *const argv[]) {
parse_args(argc, argv);
diff --git a/storage/tokudb/ft-index/src/tests/test_txn_nested_abort4.cc b/storage/tokudb/ft-index/src/tests/test_txn_nested_abort4.cc
index 164f1c26d11..729c5ed44dd 100644
--- a/storage/tokudb/ft-index/src/tests/test_txn_nested_abort4.cc
+++ b/storage/tokudb/ft-index/src/tests/test_txn_nested_abort4.cc
@@ -160,7 +160,11 @@ test_txn_abort (int insert, int secondnum) {
}
else { // delete
r = db->del(db, child, dbt_init(&key, &i, sizeof i), DB_DELETE_ANY);
+ if (IS_TDB) {
CKERR(r);
+ } else {
+ CKERR2(r, (secondnum==1 ? 0 : DB_NOTFOUND));
+ }
}
r = child->commit(child,DB_TXN_NOSYNC);
child = NULL;
diff --git a/storage/tokudb/ft-index/src/tests/test_weakxaction.cc b/storage/tokudb/ft-index/src/tests/test_weakxaction.cc
index 3e9e1f25234..b1ca7e19ba3 100644
--- a/storage/tokudb/ft-index/src/tests/test_weakxaction.cc
+++ b/storage/tokudb/ft-index/src/tests/test_weakxaction.cc
@@ -128,6 +128,9 @@ test_autotxn (uint32_t env_flags, uint32_t db_flags) {
DB_TXN *x1, *x2 = NULL;
r = env->txn_begin(env, 0, &x1, DB_TXN_NOWAIT); CKERR(r);
+ #ifdef USE_BDB
+ r = env->txn_begin(env, 0, &x2, DB_TXN_NOWAIT); CKERR(r);
+ #endif
DBT k1,k2,v1,v2;
dbt_init(&k1, "hello", sizeof "hello");
dbt_init(&k2, "hello", sizeof "hello");
@@ -138,6 +141,9 @@ test_autotxn (uint32_t env_flags, uint32_t db_flags) {
r = db->put(db, x1, &k1, &v1, 0); CKERR(r);
r = db->get(db, x2, &k2, &v2, 0); assert(r==DB_LOCK_DEADLOCK || r==DB_LOCK_NOTGRANTED);
r = x1->commit(x1, 0); CKERR(r);
+ #ifdef USE_BDB
+ r = x2->commit(x2, 0); assert(r==0);
+ #endif
r = db->close(db, 0); CKERR(r);
r = env->close(env, 0); assert(r==0);
}
diff --git a/storage/tokudb/ft-index/src/tests/upgrade-test-1.cc b/storage/tokudb/ft-index/src/tests/upgrade-test-1.cc
index ef638e3fa8c..7897f9eb2e3 100644
--- a/storage/tokudb/ft-index/src/tests/upgrade-test-1.cc
+++ b/storage/tokudb/ft-index/src/tests/upgrade-test-1.cc
@@ -117,7 +117,7 @@ char *db_v4_dir = OLDDATADIR "env_preload.4.2.0.cleanshutdown";
char *db_v4_dir_node4k = OLDDATADIR "env_preload.4.2.0.node4k.cleanshutdown";
char *db_v4_dir_flat = OLDDATADIR "env_preload.4.2.0.flat.cleanshutdown";
-// HACK: Newer versions of the database/ft to use with this old
+// HACK: Newer versions of the database/brt to use with this old
// upgrade test code.
char *db_v6_dir = OLDDATADIR "env_preload.5.0.8.cleanshutdown";
char *db_v6_dir_node4k = OLDDATADIR "env_preload.5.0.8.node4k.cleanshutdown";
diff --git a/storage/tokudb/ft-index/src/tests/xa-dirty-commit.cc b/storage/tokudb/ft-index/src/tests/xa-dirty-commit.cc
new file mode 100644
index 00000000000..03850b2b026
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/xa-dirty-commit.cc
@@ -0,0 +1,193 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include "test.h"
+
+// Verify that a commit of a prepared txn in recovery retains a db that was created by it.
+// The rollback file is dirty when the environment is closed.
+
+static void create_foo(DB_ENV *env, DB_TXN *txn) {
+ int r;
+ DB *db;
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+ r = db->close(db, 0);
+ CKERR(r);
+}
+
+static void check_foo(DB_ENV *env) {
+ int r;
+ DB *db;
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->open(db, nullptr, "foo.db", 0, DB_BTREE, 0, 0);
+ CKERR(r);
+ r = db->close(db, 0);
+ CKERR(r);
+}
+
+static void create_prepared_txn(void) {
+ int r;
+
+ DB_ENV *env = nullptr;
+ r = db_env_create(&env, 0);
+ CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME,
+ DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE,
+ S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ DB_TXN *txn = nullptr;
+ r = env->txn_begin(env, nullptr, &txn, 0);
+ CKERR(r);
+
+ create_foo(env, txn);
+
+ TOKU_XA_XID xid = { 0x1234, 8, 9 };
+ for (int i = 0; i < 8+9; i++) {
+ xid.data[i] = i;
+ }
+ r = txn->xa_prepare(txn, &xid);
+ CKERR(r);
+
+ // discard the txn so that we can close the env and run xa recovery later
+ r = txn->discard(txn, 0);
+ CKERR(r);
+
+ r = env->close(env, TOKUFT_DIRTY_SHUTDOWN);
+ CKERR(r);
+}
+
+static void run_xa_recovery(void) {
+ int r;
+
+ DB_ENV *env;
+ r = db_env_create(&env, 0);
+ CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME,
+ DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE | DB_RECOVER,
+ S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ // get prepared xid
+ long count;
+ TOKU_XA_XID xid;
+ r = env->txn_xa_recover(env, &xid, 1, &count, DB_FIRST);
+ CKERR(r);
+
+ // commit it
+ DB_TXN *txn = nullptr;
+ r = env->get_txn_from_xid(env, &xid, &txn);
+ CKERR(r);
+ r = txn->commit(txn, 0);
+ CKERR(r);
+
+ check_foo(env);
+
+ r = env->close(env, 0);
+ CKERR(r);
+}
+
+int test_main (int argc, char *const argv[]) {
+ default_parse_args(argc, argv);
+
+ // init the env directory
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ // run the test
+ create_prepared_txn();
+ run_xa_recovery();
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/xa-dirty-rollback.cc b/storage/tokudb/ft-index/src/tests/xa-dirty-rollback.cc
new file mode 100644
index 00000000000..8d28e8a762f
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/xa-dirty-rollback.cc
@@ -0,0 +1,193 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include "test.h"
+
+// Verify that an abort of a prepared txn in recovery deletes a db created by it.
+// The rollback file is dirty when the environment is closed.
+
+static void create_foo(DB_ENV *env, DB_TXN *txn) {
+ int r;
+ DB *db;
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+ r = db->close(db, 0);
+ CKERR(r);
+}
+
+static void check_foo(DB_ENV *env) {
+ int r;
+ DB *db;
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->open(db, nullptr, "foo.db", 0, DB_BTREE, 0, 0);
+ CKERR2(r, ENOENT);
+ r = db->close(db, 0);
+ CKERR(r);
+}
+
+static void create_prepared_txn(void) {
+ int r;
+
+ DB_ENV *env = nullptr;
+ r = db_env_create(&env, 0);
+ CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME,
+ DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE,
+ S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ DB_TXN *txn = nullptr;
+ r = env->txn_begin(env, nullptr, &txn, 0);
+ CKERR(r);
+
+ create_foo(env, txn);
+
+ TOKU_XA_XID xid = { 0x1234, 8, 9 };
+ for (int i = 0; i < 8+9; i++) {
+ xid.data[i] = i;
+ }
+ r = txn->xa_prepare(txn, &xid);
+ CKERR(r);
+
+ // discard the txn so that we can close the env and run xa recovery later
+ r = txn->discard(txn, 0);
+ CKERR(r);
+
+ r = env->close(env, TOKUFT_DIRTY_SHUTDOWN);
+ CKERR(r);
+}
+
+static void run_xa_recovery(void) {
+ int r;
+
+ DB_ENV *env;
+ r = db_env_create(&env, 0);
+ CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME,
+ DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE | DB_RECOVER,
+ S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ // get prepared xid
+ long count;
+ TOKU_XA_XID xid;
+ r = env->txn_xa_recover(env, &xid, 1, &count, DB_FIRST);
+ CKERR(r);
+
+ // abort it
+ DB_TXN *txn = nullptr;
+ r = env->get_txn_from_xid(env, &xid, &txn);
+ CKERR(r);
+ r = txn->abort(txn);
+ CKERR(r);
+
+ check_foo(env);
+
+ r = env->close(env, 0);
+ CKERR(r);
+}
+
+int test_main (int argc, char *const argv[]) {
+ default_parse_args(argc, argv);
+
+ // init the env directory
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ // run the test
+ create_prepared_txn();
+ run_xa_recovery();
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/xa-txn-discard-abort.cc b/storage/tokudb/ft-index/src/tests/xa-txn-discard-abort.cc
new file mode 100644
index 00000000000..3b71f807d44
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/xa-txn-discard-abort.cc
@@ -0,0 +1,195 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include "test.h"
+
+// Verify that an abort of a prepared txn in recovery removes a db created by it.
+// A checkpoint is taken between the db creation and the txn prepare.
+
+static void create_foo(DB_ENV *env, DB_TXN *txn) {
+ int r;
+ DB *db;
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+ r = db->close(db, 0);
+ CKERR(r);
+}
+
+static void check_foo(DB_ENV *env) {
+ int r;
+ DB *db;
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->open(db, nullptr, "foo.db", 0, DB_BTREE, 0, 0);
+ CKERR2(r, ENOENT);
+ r = db->close(db, 0);
+ CKERR(r);
+}
+
+static void create_prepared_txn(void) {
+ int r;
+
+ DB_ENV *env = nullptr;
+ r = db_env_create(&env, 0);
+ CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME,
+ DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE,
+ S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ DB_TXN *txn = nullptr;
+ r = env->txn_begin(env, nullptr, &txn, 0);
+ CKERR(r);
+
+ create_foo(env, txn);
+ r = env->txn_checkpoint(env, 0, 0, 0);
+ CKERR(r);
+
+ TOKU_XA_XID xid = { 0x1234, 8, 9 };
+ for (int i = 0; i < 8+9; i++) {
+ xid.data[i] = i;
+ }
+ r = txn->xa_prepare(txn, &xid);
+ CKERR(r);
+
+ // discard the txn so that we can close the env and run xa recovery later
+ r = txn->discard(txn, 0);
+ CKERR(r);
+
+ r = env->close(env, TOKUFT_DIRTY_SHUTDOWN);
+ CKERR(r);
+}
+
+static void run_xa_recovery(void) {
+ int r;
+
+ DB_ENV *env;
+ r = db_env_create(&env, 0);
+ CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME,
+ DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE | DB_RECOVER,
+ S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ // get prepared xid
+ long count;
+ TOKU_XA_XID xid;
+ r = env->txn_xa_recover(env, &xid, 1, &count, DB_FIRST);
+ CKERR(r);
+
+ // abort it
+ DB_TXN *txn = nullptr;
+ r = env->get_txn_from_xid(env, &xid, &txn);
+ CKERR(r);
+ r = txn->abort(txn);
+ CKERR(r);
+
+ check_foo(env);
+
+ r = env->close(env, 0);
+ CKERR(r);
+}
+
+int test_main (int argc, char *const argv[]) {
+ default_parse_args(argc, argv);
+
+ // init the env directory
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ // run the test
+ create_prepared_txn();
+ run_xa_recovery();
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/xa-txn-discard-commit.cc b/storage/tokudb/ft-index/src/tests/xa-txn-discard-commit.cc
new file mode 100644
index 00000000000..51b2d0670cd
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/xa-txn-discard-commit.cc
@@ -0,0 +1,196 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include "test.h"
+
+// Verify that a commit of a prepared txn in recovery retains a db created by it.
+// A checkpoint is taken between the db creation and the txn prepare.
+
+static void create_foo(DB_ENV *env, DB_TXN *txn) {
+ int r;
+ DB *db;
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->open(db, txn, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+ r = db->close(db, 0);
+ CKERR(r);
+}
+
+static void check_foo(DB_ENV *env) {
+ int r;
+ DB *db;
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->open(db, nullptr, "foo.db", 0, DB_BTREE, 0, 0);
+ CKERR(r);
+ r = db->close(db, 0);
+ CKERR(r);
+}
+
+static void create_prepared_txn(void) {
+ int r;
+
+ DB_ENV *env = nullptr;
+ r = db_env_create(&env, 0);
+ CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME,
+ DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE,
+ S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ DB_TXN *txn = nullptr;
+ r = env->txn_begin(env, nullptr, &txn, 0);
+ CKERR(r);
+
+ create_foo(env, txn);
+
+ r = env->txn_checkpoint(env, 0, 0, 0);
+ CKERR(r);
+
+ TOKU_XA_XID xid = { 0x1234, 8, 9 };
+ for (int i = 0; i < 8+9; i++) {
+ xid.data[i] = i;
+ }
+ r = txn->xa_prepare(txn, &xid);
+ CKERR(r);
+
+ // discard the txn so that we can close the env and run xa recovery later
+ r = txn->discard(txn, 0);
+ CKERR(r);
+
+ r = env->close(env, TOKUFT_DIRTY_SHUTDOWN);
+ CKERR(r);
+}
+
+static void run_xa_recovery(void) {
+ int r;
+
+ DB_ENV *env;
+ r = db_env_create(&env, 0);
+ CKERR(r);
+ r = env->open(env, TOKU_TEST_FILENAME,
+ DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE | DB_RECOVER,
+ S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ // get prepared xid
+ long count;
+ TOKU_XA_XID xid;
+ r = env->txn_xa_recover(env, &xid, 1, &count, DB_FIRST);
+ CKERR(r);
+
+ // commit it
+ DB_TXN *txn = nullptr;
+ r = env->get_txn_from_xid(env, &xid, &txn);
+ CKERR(r);
+ r = txn->commit(txn, 0);
+ CKERR(r);
+
+ check_foo(env);
+
+ r = env->close(env, 0);
+ CKERR(r);
+}
+
+int test_main (int argc, char *const argv[]) {
+ default_parse_args(argc, argv);
+
+ // init the env directory
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+ CKERR(r);
+
+ // run the test
+ create_prepared_txn();
+ run_xa_recovery();
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/ydb-internal.h b/storage/tokudb/ft-index/src/ydb-internal.h
index 085a4dd0334..f8c10975d5a 100644
--- a/storage/tokudb/ft-index/src/ydb-internal.h
+++ b/storage/tokudb/ft-index/src/ydb-internal.h
@@ -97,6 +97,8 @@ PATENT RIGHTS GRANT:
#include <ft/fttypes.h>
#include <ft/ft-ops.h>
#include <ft/minicron.h>
+// TODO: remove vanilla omt in favor of templated one
+#include <ft/omt.h>
#include <util/growable_array.h>
#include <util/omt.h>
@@ -150,13 +152,14 @@ struct __toku_db_env_internal {
unsigned long cachetable_size;
CACHETABLE cachetable;
TOKULOGGER logger;
- toku::locktree_manager ltm;
+ toku::locktree::manager ltm;
lock_timeout_callback lock_wait_timeout_callback; // Called when a lock request times out waiting for a lock.
DB *directory; // Maps dnames to inames
DB *persistent_environment; // Stores environment settings, can be used for upgrade
- toku::omt<DB *> *open_dbs_by_dname; // Stores open db handles, sorted first by dname and then by numerical value of pointer to the db (arbitrarily assigned memory location)
- toku::omt<DB *> *open_dbs_by_dict_id; // Stores open db handles, sorted by dictionary id and then by numerical value of pointer to the db (arbitrarily assigned memory location)
+ // TODO: toku::omt<DB *>
+ OMT open_dbs_by_dname; // Stores open db handles, sorted first by dname and then by numerical value of pointer to the db (arbitrarily assigned memory location)
+ OMT open_dbs_by_dict_id; // Stores open db handles, sorted by dictionary id and then by numerical value of pointer to the db (arbitrarily assigned memory location)
toku_pthread_rwlock_t open_dbs_rwlock; // rwlock that protects the OMT of open dbs.
char *real_data_dir; // data dir used when the env is opened (relative to cwd, or absolute with leading /)
@@ -189,7 +192,7 @@ struct __toku_db_env_internal {
// test-only environment function for running lock escalation
static inline void toku_env_run_lock_escalation_for_test(DB_ENV *env) {
- toku::locktree_manager *mgr = &env->i->ltm;
+ toku::locktree::manager *mgr = &env->i->ltm;
mgr->run_escalation_for_test();
}
diff --git a/storage/tokudb/ft-index/src/ydb.cc b/storage/tokudb/ft-index/src/ydb.cc
index df4fd6baf87..5108f325e15 100644
--- a/storage/tokudb/ft-index/src/ydb.cc
+++ b/storage/tokudb/ft-index/src/ydb.cc
@@ -233,7 +233,6 @@ static DB_ENV * volatile most_recent_env; // most recently opened env, used fo
static int env_get_iname(DB_ENV* env, DBT* dname_dbt, DBT* iname_dbt);
static int toku_maybe_get_engine_status_text (char* buff, int buffsize); // for use by toku_assert
-static int toku_maybe_err_engine_status (void);
static void toku_maybe_set_env_panic(int code, const char * msg); // for use by toku_assert
int
@@ -477,7 +476,7 @@ needs_recovery (DB_ENV *env) {
static int toku_env_txn_checkpoint(DB_ENV * env, uint32_t kbyte, uint32_t min, uint32_t flags);
// Instruct db to use the default (built-in) key comparison function
-// by setting the flag bits in the db and ft structs
+// by setting the flag bits in the db and brt structs
static int
db_use_builtin_key_cmp(DB *db) {
HANDLE_PANICKED_DB(db);
@@ -853,12 +852,6 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
goto cleanup;
}
- if (toku_os_huge_pages_enabled()) {
- r = toku_ydb_do_error(env, TOKUDB_HUGE_PAGES_ENABLED,
- "Huge pages are enabled, disable them before continuing\n");
- goto cleanup;
- }
-
most_recent_env = NULL;
assert(sizeof(time_t) == sizeof(uint64_t));
@@ -1115,7 +1108,7 @@ cleanup:
most_recent_env = env;
uint64_t num_rows;
env_get_engine_status_num_rows(env, &num_rows);
- toku_assert_set_fpointers(toku_maybe_get_engine_status_text, toku_maybe_err_engine_status, toku_maybe_set_env_panic, num_rows);
+ toku_assert_set_fpointers(toku_maybe_get_engine_status_text, toku_maybe_set_env_panic, num_rows);
}
return r;
}
@@ -1124,6 +1117,12 @@ static int
env_close(DB_ENV * env, uint32_t flags) {
int r = 0;
const char * err_msg = NULL;
+ bool clean_shutdown = true;
+
+ if (flags & TOKUFT_DIRTY_SHUTDOWN) {
+ clean_shutdown = false;
+ flags &= ~TOKUFT_DIRTY_SHUTDOWN;
+ }
most_recent_env = NULL; // Set most_recent_env to NULL so that we don't have a dangling pointer (and if there's an error, the toku assert code would try to look at the env.)
@@ -1138,7 +1137,7 @@ env_close(DB_ENV * env, uint32_t flags) {
goto panic_and_quit_early;
}
if (env->i->open_dbs_by_dname) { //Verify that there are no open dbs.
- if (env->i->open_dbs_by_dname->size() > 0) {
+ if (toku_omt_size(env->i->open_dbs_by_dname) > 0) {
err_msg = "Cannot close environment due to open DBs\n";
r = toku_ydb_do_error(env, EINVAL, "%s", err_msg);
goto panic_and_quit_early;
@@ -1164,22 +1163,27 @@ env_close(DB_ENV * env, uint32_t flags) {
if (env->i->cachetable) {
toku_cachetable_minicron_shutdown(env->i->cachetable);
if (env->i->logger) {
- CHECKPOINTER cp = toku_cachetable_get_checkpointer(env->i->cachetable);
- r = toku_checkpoint(cp, env->i->logger, NULL, NULL, NULL, NULL, SHUTDOWN_CHECKPOINT);
- if (r) {
- err_msg = "Cannot close environment (error during checkpoint)\n";
- toku_ydb_do_error(env, r, "%s", err_msg);
- goto panic_and_quit_early;
+ CHECKPOINTER cp = nullptr;
+ if (clean_shutdown) {
+ cp = toku_cachetable_get_checkpointer(env->i->cachetable);
+ r = toku_checkpoint(cp, env->i->logger, NULL, NULL, NULL, NULL, SHUTDOWN_CHECKPOINT);
+ if (r) {
+ err_msg = "Cannot close environment (error during checkpoint)\n";
+ toku_ydb_do_error(env, r, "%s", err_msg);
+ goto panic_and_quit_early;
+ }
}
- toku_logger_close_rollback(env->i->logger);
- //Do a second checkpoint now that the rollback cachefile is closed.
- r = toku_checkpoint(cp, env->i->logger, NULL, NULL, NULL, NULL, SHUTDOWN_CHECKPOINT);
- if (r) {
- err_msg = "Cannot close environment (error during checkpoint)\n";
- toku_ydb_do_error(env, r, "%s", err_msg);
- goto panic_and_quit_early;
+ toku_logger_close_rollback_check_empty(env->i->logger, clean_shutdown);
+ if (clean_shutdown) {
+ //Do a second checkpoint now that the rollback cachefile is closed.
+ r = toku_checkpoint(cp, env->i->logger, NULL, NULL, NULL, NULL, SHUTDOWN_CHECKPOINT);
+ if (r) {
+ err_msg = "Cannot close environment (error during checkpoint)\n";
+ toku_ydb_do_error(env, r, "%s", err_msg);
+ goto panic_and_quit_early;
+ }
+ toku_logger_shutdown(env->i->logger);
}
- toku_logger_shutdown(env->i->logger);
}
toku_cachetable_close(&env->i->cachetable);
}
@@ -1214,14 +1218,10 @@ env_close(DB_ENV * env, uint32_t flags) {
toku_free(env->i->real_log_dir);
if (env->i->real_tmp_dir)
toku_free(env->i->real_tmp_dir);
- if (env->i->open_dbs_by_dname) {
- env->i->open_dbs_by_dname->destroy();
- toku_free(env->i->open_dbs_by_dname);
- }
- if (env->i->open_dbs_by_dict_id) {
- env->i->open_dbs_by_dict_id->destroy();
- toku_free(env->i->open_dbs_by_dict_id);
- }
+ if (env->i->open_dbs_by_dname)
+ toku_omt_destroy(&env->i->open_dbs_by_dname);
+ if (env->i->open_dbs_by_dict_id)
+ toku_omt_destroy(&env->i->open_dbs_by_dict_id);
if (env->i->dir)
toku_free(env->i->dir);
toku_pthread_rwlock_destroy(&env->i->open_dbs_rwlock);
@@ -1845,15 +1845,13 @@ fs_get_status(DB_ENV * env, fs_redzone_state * redzone_state) {
// Local status struct used to get information from memory.c
typedef enum {
MEMORY_MALLOC_COUNT = 0,
- MEMORY_FREE_COUNT,
+ MEMORY_FREE_COUNT,
MEMORY_REALLOC_COUNT,
- MEMORY_MALLOC_FAIL,
- MEMORY_REALLOC_FAIL,
- MEMORY_REQUESTED,
- MEMORY_USED,
- MEMORY_FREED,
- MEMORY_MAX_REQUESTED_SIZE,
- MEMORY_LAST_FAILED_SIZE,
+ MEMORY_MALLOC_FAIL,
+ MEMORY_REALLOC_FAIL,
+ MEMORY_REQUESTED,
+ MEMORY_USED,
+ MEMORY_FREED,
MEMORY_MAX_IN_USE,
MEMORY_MALLOCATOR_VERSION,
MEMORY_MMAP_THRESHOLD,
@@ -1881,8 +1879,6 @@ memory_status_init(void) {
STATUS_INIT(MEMORY_REQUESTED, nullptr, UINT64, "number of bytes requested", TOKU_ENGINE_STATUS);
STATUS_INIT(MEMORY_USED, nullptr, UINT64, "number of bytes used (requested + overhead)", TOKU_ENGINE_STATUS);
STATUS_INIT(MEMORY_FREED, nullptr, UINT64, "number of bytes freed", TOKU_ENGINE_STATUS);
- STATUS_INIT(MEMORY_MAX_REQUESTED_SIZE, nullptr, UINT64, "largest attempted allocation size", TOKU_ENGINE_STATUS);
- STATUS_INIT(MEMORY_LAST_FAILED_SIZE, nullptr, UINT64, "size of the last failed allocation attempt", TOKU_ENGINE_STATUS);
STATUS_INIT(MEMORY_MAX_IN_USE, MEM_ESTIMATED_MAXIMUM_MEMORY_FOOTPRINT, UINT64, "estimated maximum memory footprint", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(MEMORY_MALLOCATOR_VERSION, nullptr, CHARSTR, "mallocator version", TOKU_ENGINE_STATUS);
STATUS_INIT(MEMORY_MMAP_THRESHOLD, nullptr, UINT64, "mmap threshold", TOKU_ENGINE_STATUS);
@@ -2240,83 +2236,6 @@ env_get_engine_status_text(DB_ENV * env, char * buff, int bufsiz) {
return r;
}
-// prints engine status using toku_env_err line-by-line
-static int
-env_err_engine_status(DB_ENV * env) {
- uint32_t stringsize = 1024;
- uint64_t panic;
- char panicstring[stringsize];
- uint64_t num_rows;
- uint64_t max_rows;
- fs_redzone_state redzone_state;
-
- toku_env_err(env, 0, "BUILD_ID = %d", BUILD_ID);
-
- (void) env_get_engine_status_num_rows (env, &max_rows);
- TOKU_ENGINE_STATUS_ROW_S mystat[max_rows];
- int r = env->get_engine_status (env, mystat, max_rows, &num_rows, &redzone_state, &panic, panicstring, stringsize, TOKU_ENGINE_STATUS);
-
- if (r) {
- toku_env_err(env, 0, "Engine status not available: ");
- if (!env) {
- toku_env_err(env, 0, "no environment");
- }
- else if (!(env->i)) {
- toku_env_err(env, 0, "environment internal struct is null");
- }
- else if (!env_opened(env)) {
- toku_env_err(env, 0, "environment is not open");
- }
- }
- else {
- if (panic) {
- toku_env_err(env, 0, "Env panic code: %" PRIu64, panic);
- if (strlen(panicstring)) {
- invariant(strlen(panicstring) <= stringsize);
- toku_env_err(env, 0, "Env panic string: %s", panicstring);
- }
- }
-
- for (uint64_t row = 0; row < num_rows; row++) {
- switch (mystat[row].type) {
- case FS_STATE:
- toku_env_err(env, 0, "%s: %" PRIu64, mystat[row].legend, mystat[row].value.num);
- break;
- case UINT64:
- toku_env_err(env, 0, "%s: %" PRIu64, mystat[row].legend, mystat[row].value.num);
- break;
- case CHARSTR:
- toku_env_err(env, 0, "%s: %s", mystat[row].legend, mystat[row].value.str);
- break;
- case UNIXTIME:
- {
- char tbuf[26];
- format_time((time_t*)&mystat[row].value.num, tbuf);
- toku_env_err(env, 0, "%s: %s", mystat[row].legend, tbuf);
- }
- break;
- case TOKUTIME:
- {
- double t = tokutime_to_seconds(mystat[row].value.num);
- toku_env_err(env, 0, "%s: %.6f", mystat[row].legend, t);
- }
- break;
- case PARCOUNT:
- {
- uint64_t v = read_partitioned_counter(mystat[row].value.parcount);
- toku_env_err(env, 0, "%s: %" PRIu64, mystat[row].legend, v);
- }
- break;
- default:
- toku_env_err(env, 0, "%s: UNKNOWN STATUS TYPE: %d", mystat[row].legend, mystat[row].type);
- break;
- }
- }
- }
-
- return r;
-}
-
// intended for use by toku_assert logic, when env is not known
static int
toku_maybe_get_engine_status_text (char * buff, int buffsize) {
@@ -2332,19 +2251,6 @@ toku_maybe_get_engine_status_text (char * buff, int buffsize) {
return r;
}
-static int
-toku_maybe_err_engine_status (void) {
- DB_ENV * env = most_recent_env;
- int r;
- if (engine_status_enable && env != NULL) {
- r = env_err_engine_status(env);
- }
- else {
- r = EOPNOTSUPP;
- }
- return r;
-}
-
// Set panic code and panic string if not already panicked,
// intended for use by toku_assert when about to abort().
static void
@@ -2397,8 +2303,10 @@ struct ltm_iterate_requests_callback_extra {
};
static int
-find_db_by_dict_id(DB *const &db, const DICTIONARY_ID &dict_id_find) {
+find_db_by_dict_id(OMTVALUE v, void *dict_id_v) {
+ DB *db = (DB *) v;
DICTIONARY_ID dict_id = db->i->dict_id;
+ DICTIONARY_ID dict_id_find = *(DICTIONARY_ID *) dict_id_v;
if (dict_id.dictid < dict_id_find.dictid) {
return -1;
} else if (dict_id.dictid > dict_id_find.dictid) {
@@ -2410,9 +2318,10 @@ find_db_by_dict_id(DB *const &db, const DICTIONARY_ID &dict_id_find) {
static DB *
locked_get_db_by_dict_id(DB_ENV *env, DICTIONARY_ID dict_id) {
- DB *db;
- int r = env->i->open_dbs_by_dict_id->find_zero<DICTIONARY_ID, find_db_by_dict_id>(dict_id, &db, nullptr);
- return r == 0 ? db : nullptr;
+ OMTVALUE dbv;
+ int r = toku_omt_find_zero(env->i->open_dbs_by_dict_id, find_db_by_dict_id,
+ (void *) &dict_id, &dbv, nullptr);
+ return r == 0 ? (DB *) dbv : nullptr;
}
static int ltm_iterate_requests_callback(DICTIONARY_ID dict_id, TXNID txnid,
@@ -2443,7 +2352,7 @@ env_iterate_pending_lock_requests(DB_ENV *env,
return EINVAL;
}
- toku::locktree_manager *mgr = &env->i->ltm;
+ toku::locktree::manager *mgr = &env->i->ltm;
ltm_iterate_requests_callback_extra e(env, callback, extra);
return mgr->iterate_pending_lock_requests(ltm_iterate_requests_callback, &e);
}
@@ -2562,17 +2471,6 @@ static void env_set_killed_callback(DB_ENV *env, uint64_t default_killed_time_ms
env->i->killed_callback = killed_callback;
}
-static void env_do_backtrace(DB_ENV *env) {
- if (env->i->errcall) {
- db_env_do_backtrace_errfunc((toku_env_err_func) toku_env_err, (const void *) env);
- }
- if (env->i->errfile) {
- db_env_do_backtrace((FILE *) env->i->errfile);
- } else {
- db_env_do_backtrace(stderr);
- }
-}
-
static int
toku_env_create(DB_ENV ** envp, uint32_t flags) {
int r = ENOSYS;
@@ -2649,7 +2547,6 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) {
USENV(set_loader_memory_size);
USENV(get_loader_memory_size);
USENV(set_killed_callback);
- USENV(do_backtrace);
#undef USENV
// unlocked methods
@@ -2678,18 +2575,18 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) {
result->i->bt_compare = toku_builtin_compare_fun;
r = toku_logger_create(&result->i->logger);
- invariant_zero(r);
- invariant_notnull(result->i->logger);
+ if (r!=0) goto cleanup; // In particular, logger_create can return the huge page error.
+ assert(result->i->logger);
// Create the locktree manager, passing in the create/destroy/escalate callbacks.
// The extra parameter for escalation is simply a pointer to this environment.
// The escalate callback will need it to translate txnids to DB_TXNs
result->i->ltm.create(toku_db_lt_on_create_callback, toku_db_lt_on_destroy_callback, toku_db_txn_escalate_callback, result);
- XMALLOC(result->i->open_dbs_by_dname);
- result->i->open_dbs_by_dname->create();
- XMALLOC(result->i->open_dbs_by_dict_id);
- result->i->open_dbs_by_dict_id->create();
+ r = toku_omt_create(&result->i->open_dbs_by_dname);
+ assert_zero(r);
+ r = toku_omt_create(&result->i->open_dbs_by_dict_id);
+ assert_zero(r);
toku_pthread_rwlock_init(&result->i->open_dbs_rwlock, NULL);
*envp = result;
@@ -2715,7 +2612,9 @@ DB_ENV_CREATE_FUN (DB_ENV ** envp, uint32_t flags) {
// return <0 if v is earlier in omt than dbv
// return >0 if v is later in omt than dbv
static int
-find_db_by_db_dname(DB *const &db, DB *const &dbfind) {
+find_db_by_db_dname(OMTVALUE v, void *dbv) {
+ DB *db = (DB *) v; // DB* that is stored in the omt
+ DB *dbfind = (DB *) dbv; // extra, to be compared to v
int cmp;
const char *dname = db->i->dname;
const char *dnamefind = dbfind->i->dname;
@@ -2727,7 +2626,9 @@ find_db_by_db_dname(DB *const &db, DB *const &dbfind) {
}
static int
-find_db_by_db_dict_id(DB *const &db, DB *const &dbfind) {
+find_db_by_db_dict_id(OMTVALUE v, void *dbv) {
+ DB *db = (DB *) v;
+ DB *dbfind = (DB *) dbv;
DICTIONARY_ID dict_id = db->i->dict_id;
DICTIONARY_ID dict_id_find = dbfind->i->dict_id;
if (dict_id.dictid < dict_id_find.dictid) {
@@ -2750,18 +2651,20 @@ env_note_db_opened(DB_ENV *env, DB *db) {
assert(db->i->dname); // internal (non-user) dictionary has no dname
int r;
+ OMTVALUE v;
uint32_t idx;
-
- r = env->i->open_dbs_by_dname->find_zero<DB *, find_db_by_db_dname>(db, nullptr, &idx);
+ r = toku_omt_find_zero(env->i->open_dbs_by_dname, find_db_by_db_dname,
+ db, &v, &idx);
assert(r == DB_NOTFOUND);
- r = env->i->open_dbs_by_dname->insert_at(db, idx);
+ r = toku_omt_insert_at(env->i->open_dbs_by_dname, db, idx);
assert_zero(r);
- r = env->i->open_dbs_by_dict_id->find_zero<DB *, find_db_by_db_dict_id>(db, nullptr, &idx);
+ r = toku_omt_find_zero(env->i->open_dbs_by_dict_id, find_db_by_db_dict_id,
+ db, &v, &idx);
assert(r == DB_NOTFOUND);
- r = env->i->open_dbs_by_dict_id->insert_at(db, idx);
+ r = toku_omt_insert_at(env->i->open_dbs_by_dict_id, db, idx);
assert_zero(r);
- STATUS_VALUE(YDB_LAYER_NUM_OPEN_DBS) = env->i->open_dbs_by_dname->size();
+ STATUS_VALUE(YDB_LAYER_NUM_OPEN_DBS) = toku_omt_size(env->i->open_dbs_by_dname);
STATUS_VALUE(YDB_LAYER_NUM_DB_OPEN)++;
if (STATUS_VALUE(YDB_LAYER_NUM_OPEN_DBS) > STATUS_VALUE(YDB_LAYER_MAX_OPEN_DBS)) {
STATUS_VALUE(YDB_LAYER_MAX_OPEN_DBS) = STATUS_VALUE(YDB_LAYER_NUM_OPEN_DBS);
@@ -2774,44 +2677,58 @@ void
env_note_db_closed(DB_ENV *env, DB *db) {
toku_pthread_rwlock_wrlock(&env->i->open_dbs_rwlock);
assert(db->i->dname); // internal (non-user) dictionary has no dname
- assert(env->i->open_dbs_by_dname->size() > 0);
- assert(env->i->open_dbs_by_dict_id->size() > 0);
+ assert(toku_omt_size(env->i->open_dbs_by_dname) > 0);
+ assert(toku_omt_size(env->i->open_dbs_by_dict_id) > 0);
int r;
+ OMTVALUE v;
uint32_t idx;
-
- r = env->i->open_dbs_by_dname->find_zero<DB *, find_db_by_db_dname>(db, nullptr, &idx);
+ r = toku_omt_find_zero(env->i->open_dbs_by_dname, find_db_by_db_dname,
+ db, &v, &idx);
assert_zero(r);
- r = env->i->open_dbs_by_dname->delete_at(idx);
+ r = toku_omt_delete_at(env->i->open_dbs_by_dname, idx);
assert_zero(r);
- r = env->i->open_dbs_by_dict_id->find_zero<DB *, find_db_by_db_dict_id>(db, nullptr, &idx);
+ r = toku_omt_find_zero(env->i->open_dbs_by_dict_id, find_db_by_db_dict_id,
+ db, &v, &idx);
assert_zero(r);
- r = env->i->open_dbs_by_dict_id->delete_at(idx);
+ r = toku_omt_delete_at(env->i->open_dbs_by_dict_id, idx);
assert_zero(r);
STATUS_VALUE(YDB_LAYER_NUM_DB_CLOSE)++;
- STATUS_VALUE(YDB_LAYER_NUM_OPEN_DBS) = env->i->open_dbs_by_dname->size();
+ STATUS_VALUE(YDB_LAYER_NUM_OPEN_DBS) = toku_omt_size(env->i->open_dbs_by_dname);
toku_pthread_rwlock_wrunlock(&env->i->open_dbs_rwlock);
}
static int
-find_open_db_by_dname(DB *const &db, const char *const &dnamefind) {
- return strcmp(db->i->dname, dnamefind);
+find_open_db_by_dname (OMTVALUE v, void *dnamev) {
+ DB *db = (DB *) v; // DB* that is stored in the omt
+ int cmp;
+ const char *dname = db->i->dname;
+ const char *dnamefind = (char *) dnamev;
+ cmp = strcmp(dname, dnamefind);
+ return cmp;
}
// return true if there is any db open with the given dname
static bool
env_is_db_with_dname_open(DB_ENV *env, const char *dname) {
- DB *db;
+ int r;
+ bool rval;
+ OMTVALUE dbv;
+ uint32_t idx;
toku_pthread_rwlock_rdlock(&env->i->open_dbs_rwlock);
- int r = env->i->open_dbs_by_dname->find_zero<const char *, find_open_db_by_dname>(dname, &db, nullptr);
- if (r == 0) {
- invariant(strcmp(dname, db->i->dname) == 0);
- } else {
- invariant(r == DB_NOTFOUND);
+ r = toku_omt_find_zero(env->i->open_dbs_by_dname, find_open_db_by_dname, (void*)dname, &dbv, &idx);
+ if (r==0) {
+ DB *db = (DB *) dbv;
+ assert(strcmp(dname, db->i->dname) == 0);
+ rval = true;
+ }
+ else {
+ assert(r==DB_NOTFOUND);
+ rval = false;
}
toku_pthread_rwlock_rdunlock(&env->i->open_dbs_rwlock);
- return r == 0 ? true : false;
+ return rval;
}
//We do not (yet?) support deleting subdbs by deleting the enclosing 'fname'
@@ -3129,7 +3046,7 @@ env_get_iname(DB_ENV* env, DBT* dname_dbt, DBT* iname_dbt) {
// TODO 2216: Patch out this (dangerous) function when loader is working and
// we don't need to test the low-level redirect anymore.
-// for use by test programs only, just a wrapper around ft call:
+// for use by test programs only, just a wrapper around brt call:
int
toku_test_db_redirect_dictionary(DB * db, const char * dname_of_new_file, DB_TXN *dbtxn) {
int r;
@@ -3137,7 +3054,7 @@ toku_test_db_redirect_dictionary(DB * db, const char * dname_of_new_file, DB_TXN
DBT iname_dbt;
char * new_iname_in_env;
- FT_HANDLE ft_handle = db->i->ft_handle;
+ FT_HANDLE brt = db->i->ft_handle;
TOKUTXN tokutxn = db_txn_struct_i(dbtxn)->tokutxn;
toku_fill_dbt(&dname_dbt, dname_of_new_file, strlen(dname_of_new_file)+1);
@@ -3147,7 +3064,7 @@ toku_test_db_redirect_dictionary(DB * db, const char * dname_of_new_file, DB_TXN
new_iname_in_env = (char *) iname_dbt.data;
toku_multi_operation_client_lock(); //Must hold MO lock for dictionary_redirect.
- r = toku_dictionary_redirect(new_iname_in_env, ft_handle, tokutxn);
+ r = toku_dictionary_redirect(new_iname_in_env, brt, tokutxn);
toku_multi_operation_client_unlock();
toku_free(new_iname_in_env);
diff --git a/storage/tokudb/ft-index/src/ydb_cursor.cc b/storage/tokudb/ft-index/src/ydb_cursor.cc
index aa236ab0324..58e13b9e50a 100644
--- a/storage/tokudb/ft-index/src/ydb_cursor.cc
+++ b/storage/tokudb/ft-index/src/ydb_cursor.cc
@@ -313,7 +313,7 @@ c_getf_first_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, bytevec val,
r = context->r_user_callback;
}
- //Give ft-layer an error (if any) to return from toku_ft_cursor_first
+ //Give brt-layer an error (if any) to return from toku_ft_cursor_first
return r;
}
@@ -364,7 +364,7 @@ c_getf_last_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, bytevec val, v
r = context->r_user_callback;
}
- //Give ft-layer an error (if any) to return from toku_ft_cursor_last
+ //Give brt-layer an error (if any) to return from toku_ft_cursor_last
return r;
}
@@ -423,7 +423,7 @@ c_getf_next_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, bytevec val, v
r = context->r_user_callback;
}
- //Give ft-layer an error (if any) to return from toku_ft_cursor_next
+ //Give brt-layer an error (if any) to return from toku_ft_cursor_next
return r;
}
@@ -481,7 +481,7 @@ c_getf_prev_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, bytevec val, v
r = context->r_user_callback;
}
- //Give ft-layer an error (if any) to return from toku_ft_cursor_prev
+ //Give brt-layer an error (if any) to return from toku_ft_cursor_prev
return r;
}
@@ -518,7 +518,7 @@ c_getf_current_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, bytevec val
r = 0;
}
- //Give ft-layer an error (if any) to return from toku_ft_cursor_current
+ //Give brt-layer an error (if any) to return from toku_ft_cursor_current
return r;
}
@@ -571,7 +571,7 @@ c_getf_set_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, bytevec val, vo
r = context->r_user_callback;
}
- //Give ft-layer an error (if any) to return from toku_ft_cursor_set
+ //Give brt-layer an error (if any) to return from toku_ft_cursor_set
return r;
}
@@ -627,7 +627,7 @@ c_getf_set_range_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, bytevec v
r = context->r_user_callback;
}
- //Give ft-layer an error (if any) to return from toku_ft_cursor_set_range
+ //Give brt-layer an error (if any) to return from toku_ft_cursor_set_range
return r;
}
@@ -704,7 +704,7 @@ c_getf_set_range_reverse_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, b
r = context->r_user_callback;
}
- //Give ft-layer an error (if any) to return from toku_ft_cursor_set_range_reverse
+ //Give brt-layer an error (if any) to return from toku_ft_cursor_set_range_reverse
return r;
}
@@ -767,6 +767,7 @@ c_set_check_interrupt_callback(DBC* dbc, bool (*interrupt_callback)(void*), void
int
toku_c_get(DBC* c, DBT* key, DBT* val, uint32_t flag) {
+ //This function exists for legacy (test compatibility) purposes/parity with bdb.
HANDLE_PANICKED_DB(c->dbp);
HANDLE_CURSOR_ILLEGAL_WORKING_PARENT_TXN(c);
@@ -897,7 +898,7 @@ toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC ** c, uint32_t flags, int is_
);
assert(r == 0 || r == TOKUDB_MVCC_DICTIONARY_TOO_NEW);
if (r == 0) {
- // Set the is_temporary_cursor boolean inside the ftnode so
+ // Set the is_temporary_cursor boolean inside the brt node so
// that a query only needing one cursor will not perform
// unecessary malloc calls.
if (is_temporary_cursor) {
diff --git a/storage/tokudb/ft-index/src/ydb_db.cc b/storage/tokudb/ft-index/src/ydb_db.cc
index b9fa32eb4a0..5a06f61eeab 100644
--- a/storage/tokudb/ft-index/src/ydb_db.cc
+++ b/storage/tokudb/ft-index/src/ydb_db.cc
@@ -1048,7 +1048,7 @@ toku_db_verify_with_progress(DB *db, int (*progress_callback)(void *extra, float
return r;
}
-int toku_setup_db_internal (DB **dbp, DB_ENV *env, uint32_t flags, FT_HANDLE ft_handle, bool is_open) {
+int toku_setup_db_internal (DB **dbp, DB_ENV *env, uint32_t flags, FT_HANDLE brt, bool is_open) {
if (flags || env == NULL)
return EINVAL;
@@ -1067,7 +1067,7 @@ int toku_setup_db_internal (DB **dbp, DB_ENV *env, uint32_t flags, FT_HANDLE ft_
return ENOMEM;
}
memset(result->i, 0, sizeof *result->i);
- result->i->ft_handle = ft_handle;
+ result->i->ft_handle = brt;
result->i->opened = is_open;
*dbp = result;
return 0;
@@ -1082,10 +1082,10 @@ toku_db_create(DB ** db, DB_ENV * env, uint32_t flags) {
return EINVAL;
- FT_HANDLE ft_handle;
- toku_ft_handle_create(&ft_handle);
+ FT_HANDLE brt;
+ toku_ft_handle_create(&brt);
- int r = toku_setup_db_internal(db, env, flags, ft_handle, false);
+ int r = toku_setup_db_internal(db, env, flags, brt, false);
if (r != 0) return r;
DB *result=*db;
@@ -1162,7 +1162,7 @@ toku_db_create(DB ** db, DB_ENV * env, uint32_t flags) {
// The new inames are returned to the caller.
// It is the caller's responsibility to free them.
// If "mark_as_loader" is true, then include a mark in the iname
-// to indicate that the file is created by the ft loader.
+// to indicate that the file is created by the brt loader.
// Return 0 on success (could fail if write lock not available).
static int
load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[/*N*/], const char * new_inames_in_env[/*N*/], LSN *load_lsn, bool mark_as_loader) {
@@ -1207,13 +1207,13 @@ load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[/*N*/], const char * new
int do_fsync = 0;
LSN *get_lsn = NULL;
for (i = 0; i < N; i++) {
- FT_HANDLE ft_handle = dbs[i]->i->ft_handle;
+ FT_HANDLE brt = dbs[i]->i->ft_handle;
//Fsync is necessary for the last one only.
if (i==N-1) {
do_fsync = 1; //We only need a single fsync of logs.
get_lsn = load_lsn; //Set pointer to capture the last lsn.
}
- toku_ft_load(ft_handle, ttxn, new_inames_in_env[i], do_fsync, get_lsn);
+ toku_ft_load(brt, ttxn, new_inames_in_env[i], do_fsync, get_lsn);
}
}
return rval;
diff --git a/storage/tokudb/ft-index/src/ydb_db.h b/storage/tokudb/ft-index/src/ydb_db.h
index 54f0d178731..5f87fadc3e3 100644
--- a/storage/tokudb/ft-index/src/ydb_db.h
+++ b/storage/tokudb/ft-index/src/ydb_db.h
@@ -139,7 +139,7 @@ int toku_db_pre_acquire_table_lock(DB *db, DB_TXN *txn);
int toku_db_get (DB * db, DB_TXN * txn, DBT * key, DBT * data, uint32_t flags);
int toku_db_create(DB ** db, DB_ENV * env, uint32_t flags);
int toku_db_close(DB * db);
-int toku_setup_db_internal (DB **dbp, DB_ENV *env, uint32_t flags, FT_HANDLE ft_handle, bool is_open);
+int toku_setup_db_internal (DB **dbp, DB_ENV *env, uint32_t flags, FT_HANDLE brt, bool is_open);
int db_getf_set(DB *db, DB_TXN *txn, uint32_t flags, DBT *key, YDB_CALLBACK_FUNCTION f, void *extra);
int autotxn_db_get(DB* db, DB_TXN* txn, DBT* key, DBT* data, uint32_t flags);
diff --git a/storage/tokudb/ft-index/src/ydb_lib.cc b/storage/tokudb/ft-index/src/ydb_lib.cc
index 11847788661..5c0e539909d 100644
--- a/storage/tokudb/ft-index/src/ydb_lib.cc
+++ b/storage/tokudb/ft-index/src/ydb_lib.cc
@@ -109,4 +109,37 @@ static void __attribute__((destructor)) libtokudb_destroy(void) {
toku_ydb_destroy();
}
-#endif // __GNUC__
+#endif
+
+#if TOKU_WINDOWS
+#include <windows.h>
+#define UNUSED(x) x=x
+
+bool WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID reserved) {
+ UNUSED(h); UNUSED(reserved);
+ // printf("%s:%lu\n", __FUNCTION__, reason);
+ int r = 0;
+ switch(reason) {
+ case DLL_PROCESS_ATTACH:
+ r = toku_ydb_init();
+ break;
+ case DLL_PROCESS_DETACH:
+ toku_ydb_destroy();
+ break;
+ case DLL_THREAD_ATTACH:
+ //TODO: Any new thread code if necessary, i.e. allocate per-thread
+ // storage.
+ break;
+ case DLL_THREAD_DETACH:
+ //TODO: Any cleanup thread code if necessary, i.e. free per-thread
+ // storage.
+ break;
+ default:
+ break;
+ }
+ assert(r==0);
+ return true;
+}
+
+#endif
+
diff --git a/storage/tokudb/ft-index/src/ydb_load.h b/storage/tokudb/ft-index/src/ydb_load.h
index 6496a92eeec..f5ffeab528e 100644
--- a/storage/tokudb/ft-index/src/ydb_load.h
+++ b/storage/tokudb/ft-index/src/ydb_load.h
@@ -104,7 +104,7 @@ PATENT RIGHTS GRANT:
// The new inames are returned to the caller.
// It is the caller's responsibility to free them.
// If "mark_as_loader" is true, then include a mark in the iname
-// to indicate that the file is created by the ft loader.
+// to indicate that the file is created by the brt loader.
// Return 0 on success (could fail if write lock not available).
int locked_load_inames(DB_ENV * env,
DB_TXN * txn,
diff --git a/storage/tokudb/ft-index/src/ydb_row_lock.cc b/storage/tokudb/ft-index/src/ydb_row_lock.cc
index db5548a00c3..f7cdcbb563c 100644
--- a/storage/tokudb/ft-index/src/ydb_row_lock.cc
+++ b/storage/tokudb/ft-index/src/ydb_row_lock.cc
@@ -137,7 +137,7 @@ static void db_txn_note_row_lock(DB *db, DB_TXN *txn, const DBT *left_key, const
map->insert_at(ranges, idx);
// let the manager know we're referencing this lt
- toku::locktree_manager *ltm = &txn->mgrp->i->ltm;
+ toku::locktree::manager *ltm = &txn->mgrp->i->ltm;
ltm->reference_lt(ranges.lt);
} else {
invariant_zero(r);
@@ -148,7 +148,7 @@ static void db_txn_note_row_lock(DB *db, DB_TXN *txn, const DBT *left_key, const
ranges.buffer->append(left_key, right_key);
size_t new_num_bytes = ranges.buffer->get_num_bytes();
invariant(new_num_bytes > old_num_bytes);
- lt->get_manager()->note_mem_used(new_num_bytes - old_num_bytes);
+ lt->get_mem_tracker()->note_mem_used(new_num_bytes - old_num_bytes);
toku_mutex_unlock(&db_txn_struct_i(txn)->txn_mutex);
}
@@ -201,7 +201,7 @@ void toku_db_txn_escalate_callback(TXNID txnid, const toku::locktree *lt, const
//
// We could theoretically steal the memory from the caller instead of copying
// it, but it's simpler to have a callback API that doesn't transfer memory ownership.
- lt->get_manager()->note_mem_released(ranges.buffer->get_num_bytes());
+ lt->get_mem_tracker()->note_mem_released(ranges.buffer->get_num_bytes());
ranges.buffer->destroy();
ranges.buffer->create();
toku::range_buffer::iterator iter;
@@ -211,7 +211,7 @@ void toku_db_txn_escalate_callback(TXNID txnid, const toku::locktree *lt, const
ranges.buffer->append(rec.get_left_key(), rec.get_right_key());
iter.next();
}
- lt->get_manager()->note_mem_used(ranges.buffer->get_num_bytes());
+ lt->get_mem_tracker()->note_mem_used(ranges.buffer->get_num_bytes());
} else {
// In rare cases, we may not find the associated locktree, because we are
// racing with the transaction trying to add this locktree to the lt map
@@ -315,7 +315,7 @@ void toku_db_release_lt_key_ranges(DB_TXN *txn, txn_lt_key_ranges *ranges) {
// release all of the locks this txn has ever successfully
// acquired and stored in the range buffer for this locktree
lt->release_locks(txnid, ranges->buffer);
- lt->get_manager()->note_mem_released(ranges->buffer->get_num_bytes());
+ lt->get_mem_tracker()->note_mem_released(ranges->buffer->get_num_bytes());
ranges->buffer->destroy();
toku_free(ranges->buffer);
@@ -324,6 +324,6 @@ void toku_db_release_lt_key_ranges(DB_TXN *txn, txn_lt_key_ranges *ranges) {
toku::lock_request::retry_all_lock_requests(lt);
// Release our reference on this locktree
- toku::locktree_manager *ltm = &txn->mgrp->i->ltm;
+ toku::locktree::manager *ltm = &txn->mgrp->i->ltm;
ltm->release_lt(lt);
}
diff --git a/storage/tokudb/ft-index/src/ydb_txn.cc b/storage/tokudb/ft-index/src/ydb_txn.cc
index 6f1105412d7..4ab6669b3b7 100644
--- a/storage/tokudb/ft-index/src/ydb_txn.cc
+++ b/storage/tokudb/ft-index/src/ydb_txn.cc
@@ -205,12 +205,6 @@ cleanup:
return r;
}
-static uint32_t toku_txn_id(DB_TXN * txn) {
- HANDLE_PANICKED_ENV(txn->mgrp);
- abort();
- return (uint32_t) -1;
-}
-
static int toku_txn_abort(DB_TXN * txn,
TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra) {
HANDLE_PANICKED_ENV(txn->mgrp);
@@ -387,6 +381,44 @@ static uint64_t locked_txn_get_client_id(DB_TXN *txn) {
return toku_txn_get_client_id(db_txn_struct_i(txn)->tokutxn);
}
+static int toku_txn_discard(DB_TXN *txn, uint32_t flags) {
+ // check parameters
+ if (flags != 0)
+ return EINVAL;
+ TOKUTXN ttxn = db_txn_struct_i(txn)->tokutxn;
+ if (toku_txn_get_state(ttxn) != TOKUTXN_PREPARING)
+ return EINVAL;
+
+ bool low_priority;
+ if (toku_is_big_tokutxn(ttxn)) {
+ low_priority = true;
+ toku_low_priority_multi_operation_client_lock();
+ } else {
+ low_priority = false;
+ toku_multi_operation_client_lock();
+ }
+
+ // discard
+ toku_txn_discard_txn(ttxn);
+
+ // complete
+ toku_txn_complete_txn(ttxn);
+
+ // release locks
+ toku_txn_release_locks(txn);
+
+ if (low_priority) {
+ toku_low_priority_multi_operation_client_unlock();
+ } else {
+ toku_multi_operation_client_unlock();
+ }
+
+ // destroy
+ toku_txn_destroy(txn);
+
+ return 0;
+}
+
static inline void txn_func_init(DB_TXN *txn) {
#define STXN(name) txn->name = locked_txn_ ## name
STXN(abort);
@@ -400,8 +432,8 @@ static inline void txn_func_init(DB_TXN *txn) {
#define SUTXN(name) txn->name = toku_txn_ ## name
SUTXN(prepare);
SUTXN(xa_prepare);
+ SUTXN(discard);
#undef SUTXN
- txn->id = toku_txn_id;
txn->id64 = toku_txn_id64;
}
diff --git a/storage/tokudb/ft-index/src/ydb_write.cc b/storage/tokudb/ft-index/src/ydb_write.cc
index 82fbf439885..7968f3f9668 100644
--- a/storage/tokudb/ft-index/src/ydb_write.cc
+++ b/storage/tokudb/ft-index/src/ydb_write.cc
@@ -253,30 +253,6 @@ toku_db_del(DB *db, DB_TXN *txn, DBT *key, uint32_t flags, bool holds_mo_lock) {
return r;
}
-static int
-db_put(DB *db, DB_TXN *txn, DBT *key, DBT *val, int flags, bool do_log) {
- int r = 0;
- bool unique = false;
- enum ft_msg_type type = FT_INSERT;
- if (flags == DB_NOOVERWRITE) {
- unique = true;
- } else if (flags == DB_NOOVERWRITE_NO_ERROR) {
- type = FT_INSERT_NO_OVERWRITE;
- } else if (flags != 0) {
- // All other non-zero flags are unsupported
- r = EINVAL;
- }
- if (r == 0) {
- TOKUTXN ttxn = txn ? db_txn_struct_i(txn)->tokutxn : nullptr;
- if (unique) {
- r = toku_ft_insert_unique(db->i->ft_handle, key, val, ttxn, do_log);
- } else {
- toku_ft_maybe_insert(db->i->ft_handle, key, val, ttxn, false, ZERO_LSN, do_log, type);
- }
- invariant(r == DB_KEYEXIST || r == 0);
- }
- return r;
-}
int
toku_db_put(DB *db, DB_TXN *txn, DBT *key, DBT *val, uint32_t flags, bool holds_mo_lock) {
@@ -289,16 +265,25 @@ toku_db_put(DB *db, DB_TXN *txn, DBT *key, DBT *val, uint32_t flags, bool holds_
flags &= ~lock_flags;
r = db_put_check_size_constraints(db, key, val);
-
- //Do locking if necessary.
+ if (r == 0) {
+ //Do any checking required by the flags.
+ r = db_put_check_overwrite_constraint(db, txn, key, lock_flags, flags);
+ }
+ //Do locking if necessary. Do not grab the lock again if this DB had a unique
+ //check performed because the lock was already grabbed by its cursor callback.
bool do_locking = (bool)(db->i->lt && !(lock_flags&DB_PRELOCKED_WRITE));
- if (r == 0 && do_locking) {
+ if (r == 0 && do_locking && !(flags & DB_NOOVERWRITE)) {
r = toku_db_get_point_write_lock(db, txn, key);
}
if (r == 0) {
- //Insert into the ft.
+ //Insert into the brt.
+ TOKUTXN ttxn = txn ? db_txn_struct_i(txn)->tokutxn : NULL;
+ enum ft_msg_type type = FT_INSERT;
+ if (flags==DB_NOOVERWRITE_NO_ERROR) {
+ type = FT_INSERT_NO_OVERWRITE;
+ }
if (!holds_mo_lock) toku_multi_operation_client_lock();
- r = db_put(db, txn, key, val, flags, true);
+ toku_ft_maybe_insert(db->i->ft_handle, key, val, ttxn, false, ZERO_LSN, true, type);
if (!holds_mo_lock) toku_multi_operation_client_unlock();
}
@@ -411,9 +396,9 @@ cleanup:
}
static void
-log_del_single(DB_TXN *txn, FT_HANDLE ft_handle, const DBT *key) {
+log_del_single(DB_TXN *txn, FT_HANDLE brt, const DBT *key) {
TOKUTXN ttxn = db_txn_struct_i(txn)->tokutxn;
- toku_ft_log_del(ttxn, ft_handle, key);
+ toku_ft_log_del(ttxn, brt, key);
}
static uint32_t
@@ -428,7 +413,7 @@ sum_size(uint32_t num_arrays, DBT_ARRAY keys[], uint32_t overhead) {
}
static void
-log_del_multiple(DB_TXN *txn, DB *src_db, const DBT *key, const DBT *val, uint32_t num_dbs, FT_HANDLE fts[], DBT_ARRAY keys[]) {
+log_del_multiple(DB_TXN *txn, DB *src_db, const DBT *key, const DBT *val, uint32_t num_dbs, FT_HANDLE brts[], DBT_ARRAY keys[]) {
if (num_dbs > 0) {
TOKUTXN ttxn = db_txn_struct_i(txn)->tokutxn;
FT_HANDLE src_ft = src_db ? src_db->i->ft_handle : NULL;
@@ -437,11 +422,11 @@ log_del_multiple(DB_TXN *txn, DB *src_db, const DBT *key, const DBT *val, uint32
if (del_single_sizes < del_multiple_size) {
for (uint32_t i = 0; i < num_dbs; i++) {
for (uint32_t j = 0; j < keys[i].size; j++) {
- log_del_single(txn, fts[i], &keys[i].dbts[j]);
+ log_del_single(txn, brts[i], &keys[i].dbts[j]);
}
}
} else {
- toku_ft_log_del_multiple(ttxn, src_ft, fts, num_dbs, key, val);
+ toku_ft_log_del_multiple(ttxn, src_ft, brts, num_dbs, key, val);
}
}
}
@@ -554,7 +539,7 @@ env_del_multiple(
uint32_t lock_flags[num_dbs];
uint32_t remaining_flags[num_dbs];
- FT_HANDLE fts[num_dbs];
+ FT_HANDLE brts[num_dbs];
bool indexer_lock_taken = false;
bool src_same = false;
bool indexer_shortcut = false;
@@ -609,7 +594,7 @@ env_del_multiple(
if (r != 0) goto cleanup;
}
}
- fts[which_db] = db->i->ft_handle;
+ brts[which_db] = db->i->ft_handle;
}
if (indexer) {
@@ -626,7 +611,7 @@ env_del_multiple(
}
}
toku_multi_operation_client_lock();
- log_del_multiple(txn, src_db, src_key, src_val, num_dbs, fts, del_keys);
+ log_del_multiple(txn, src_db, src_key, src_val, num_dbs, brts, del_keys);
r = do_del_multiple(txn, num_dbs, db_array, del_keys, src_db, src_key, indexer_shortcut);
toku_multi_operation_client_unlock();
if (indexer_lock_taken) {
@@ -642,19 +627,17 @@ cleanup:
}
static void
-log_put_multiple(DB_TXN *txn, DB *src_db, const DBT *src_key, const DBT *src_val, uint32_t num_dbs, FT_HANDLE fts[]) {
+log_put_multiple(DB_TXN *txn, DB *src_db, const DBT *src_key, const DBT *src_val, uint32_t num_dbs, FT_HANDLE brts[]) {
if (num_dbs > 0) {
TOKUTXN ttxn = db_txn_struct_i(txn)->tokutxn;
FT_HANDLE src_ft = src_db ? src_db->i->ft_handle : NULL;
- toku_ft_log_put_multiple(ttxn, src_ft, fts, num_dbs, src_key, src_val);
+ toku_ft_log_put_multiple(ttxn, src_ft, brts, num_dbs, src_key, src_val);
}
}
-// Requires: If remaining_flags is non-null, this function performs any required uniqueness checks
-// Otherwise, the caller is responsible.
static int
-do_put_multiple(DB_TXN *txn, uint32_t num_dbs, DB *db_array[], DBT_ARRAY keys[], DBT_ARRAY vals[], uint32_t *remaining_flags, DB *src_db, const DBT *src_key, bool indexer_shortcut) {
- int r = 0;
+do_put_multiple(DB_TXN *txn, uint32_t num_dbs, DB *db_array[], DBT_ARRAY keys[], DBT_ARRAY vals[], DB *src_db, const DBT *src_key, bool indexer_shortcut) {
+ TOKUTXN ttxn = db_txn_struct_i(txn)->tokutxn;
for (uint32_t which_db = 0; which_db < num_dbs; which_db++) {
DB *db = db_array[which_db];
@@ -683,21 +666,16 @@ do_put_multiple(DB_TXN *txn, uint32_t num_dbs, DB *db_array[], DBT_ARRAY keys[],
}
if (do_put) {
for (uint32_t i = 0; i < keys[which_db].size; i++) {
- int flags = 0;
- if (remaining_flags != nullptr) {
- flags = remaining_flags[which_db];
- invariant(!(flags & DB_NOOVERWRITE_NO_ERROR));
- }
- r = db_put(db, txn, &keys[which_db].dbts[i], &vals[which_db].dbts[i], flags, false);
- if (r != 0) {
- goto done;
- }
+ // if db is being indexed by an indexer, then put into that db if the src key is to the left or equal to the
+ // indexers cursor. we have to get the src_db from the indexer and find it in the db_array.
+ toku_ft_maybe_insert(db->i->ft_handle,
+ &keys[which_db].dbts[i], &vals[which_db].dbts[i],
+ ttxn, false, ZERO_LSN, false, FT_INSERT);
}
}
}
}
-done:
- return r;
+ return 0;
}
static int
@@ -723,7 +701,7 @@ env_put_multiple_internal(
uint32_t lock_flags[num_dbs];
uint32_t remaining_flags[num_dbs];
- FT_HANDLE fts[num_dbs];
+ FT_HANDLE brts[num_dbs];
bool indexer_shortcut = false;
bool indexer_lock_taken = false;
bool src_same = false;
@@ -776,20 +754,26 @@ env_put_multiple_internal(
r = db_put_check_size_constraints(db, &put_key, &put_val);
if (r != 0) goto cleanup;
+ //Check overwrite constraints
+ r = db_put_check_overwrite_constraint(db, txn,
+ &put_key,
+ lock_flags[which_db], remaining_flags[which_db]);
+ if (r != 0) goto cleanup;
if (remaining_flags[which_db] == DB_NOOVERWRITE_NO_ERROR) {
//put_multiple does not support delaying the no error, since we would
//have to log the flag in the put_multiple.
r = EINVAL; goto cleanup;
}
- //Do locking if necessary.
- if (db->i->lt && !(lock_flags[which_db] & DB_PRELOCKED_WRITE)) {
+ //Do locking if necessary. Do not grab the lock again if this DB had a unique
+ //check performed because the lock was already grabbed by its cursor callback.
+ if (db->i->lt && !(lock_flags[which_db] & DB_PRELOCKED_WRITE) && !(remaining_flags[which_db] & DB_NOOVERWRITE)) {
//Needs locking
r = toku_db_get_point_write_lock(db, txn, &put_key);
if (r != 0) goto cleanup;
}
}
- fts[which_db] = db->i->ft_handle;
+ brts[which_db] = db->i->ft_handle;
}
if (indexer) {
@@ -806,10 +790,8 @@ env_put_multiple_internal(
}
}
toku_multi_operation_client_lock();
- r = do_put_multiple(txn, num_dbs, db_array, put_keys, put_vals, remaining_flags, src_db, src_key, indexer_shortcut);
- if (r == 0) {
- log_put_multiple(txn, src_db, src_key, src_val, num_dbs, fts);
- }
+ log_put_multiple(txn, src_db, src_key, src_val, num_dbs, brts);
+ r = do_put_multiple(txn, num_dbs, db_array, put_keys, put_vals, src_db, src_key, indexer_shortcut);
toku_multi_operation_client_unlock();
if (indexer_lock_taken) {
toku_indexer_unlock(indexer);
@@ -1093,7 +1075,7 @@ env_update_multiple(DB_ENV *env, DB *src_db, DB_TXN *txn,
// recovery so we don't end up losing data.
// So unlike env->put_multiple, we ONLY log a 'put_multiple' log entry.
log_put_multiple(txn, src_db, new_src_key, new_src_data, n_put_dbs, put_fts);
- r = do_put_multiple(txn, n_put_dbs, put_dbs, put_key_arrays, put_val_arrays, nullptr, src_db, new_src_key, indexer_shortcut);
+ r = do_put_multiple(txn, n_put_dbs, put_dbs, put_key_arrays, put_val_arrays, src_db, new_src_key, indexer_shortcut);
}
toku_multi_operation_client_unlock();
if (indexer_lock_taken) {
diff --git a/storage/tokudb/ft-index/toku_include/CMakeLists.txt b/storage/tokudb/ft-index/toku_include/CMakeLists.txt
new file mode 100644
index 00000000000..44291012538
--- /dev/null
+++ b/storage/tokudb/ft-index/toku_include/CMakeLists.txt
@@ -0,0 +1,17 @@
+configure_file(toku_config.h.in toku_config.h)
+add_custom_target(generate_config_h DEPENDS
+ "${CMAKE_CURRENT_BINARY_DIR}/toku_config.h")
+
+# detect when we are being built as a subproject
+if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
+ install(
+ FILES toku_list.h toku_os.h
+ DESTINATION include
+ COMPONENT tokukv_headers
+ )
+ install(
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/toku_config.h"
+ DESTINATION include
+ COMPONENT tokukv_headers
+ )
+endif () \ No newline at end of file
diff --git a/storage/tokudb/ft-index/portability/memory.h b/storage/tokudb/ft-index/toku_include/memory.h
index e4608d6108f..215ea2e209d 100644
--- a/storage/tokudb/ft-index/portability/memory.h
+++ b/storage/tokudb/ft-index/toku_include/memory.h
@@ -207,16 +207,14 @@ void toku_set_func_realloc_only(realloc_fun_t f);
void toku_set_func_free(free_fun_t f);
typedef struct memory_status {
- uint64_t malloc_count; // number of malloc operations
- uint64_t free_count; // number of free operations
- uint64_t realloc_count; // number of realloc operations
- uint64_t malloc_fail; // number of malloc operations that failed
- uint64_t realloc_fail; // number of realloc operations that failed
- uint64_t requested; // number of bytes requested
- uint64_t used; // number of bytes used (requested + overhead), obtained from malloc_usable_size()
- uint64_t freed; // number of bytes freed;
- uint64_t max_requested_size; // largest attempted allocation size
- uint64_t last_failed_size; // size of the last failed allocation attempt
+ uint64_t malloc_count; // number of malloc operations
+ uint64_t free_count; // number of free operations
+ uint64_t realloc_count; // number of realloc operations
+ uint64_t malloc_fail; // number of malloc operations that failed
+ uint64_t realloc_fail; // number of realloc operations that failed
+ uint64_t requested; // number of bytes requested
+ uint64_t used; // number of bytes used (requested + overhead), obtained from malloc_usable_size()
+ uint64_t freed; // number of bytes freed;
volatile uint64_t max_in_use; // maximum memory footprint (used - freed), approximate (not worth threadsafety overhead for exact)
const char *mallocator_version;
uint64_t mmap_threshold;
diff --git a/storage/tokudb/ft-index/toku_include/old-db.h b/storage/tokudb/ft-index/toku_include/old-db.h
new file mode 100644
index 00000000000..94db13d6141
--- /dev/null
+++ b/storage/tokudb/ft-index/toku_include/old-db.h
@@ -0,0 +1,276 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*
+COPYING CONDITIONS NOTICE:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation, and provided that the
+ following conditions are met:
+
+ * Redistributions of source code must retain this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below).
+
+ * Redistributions in binary form must reproduce this COPYING
+ CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
+ DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
+ PATENT MARKING NOTICE (below), and the PATENT RIGHTS
+ GRANT (below) in the documentation and/or other materials
+ provided with the distribution.
+
+ 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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+COPYRIGHT NOTICE:
+
+ TokuDB, Tokutek Fractal Tree Indexing Library.
+ Copyright (C) 2007-2013 Tokutek, Inc.
+
+DISCLAIMER:
+
+ 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.
+
+UNIVERSITY PATENT NOTICE:
+
+ The technology is licensed by the Massachusetts Institute of
+ Technology, Rutgers State University of New Jersey, and the Research
+ Foundation of State University of New York at Stony Brook under
+ United States of America Serial No. 11/760379 and to the patents
+ and/or patent applications resulting from it.
+
+PATENT MARKING NOTICE:
+
+ This software is covered by US Patent No. 8,185,551.
+ This software is covered by US Patent No. 8,489,638.
+
+PATENT RIGHTS GRANT:
+
+ "THIS IMPLEMENTATION" means the copyrightable works distributed by
+ Tokutek as part of the Fractal Tree project.
+
+ "PATENT CLAIMS" means the claims of patents that are owned or
+ licensable by Tokutek, both currently or in the future; and that in
+ the absence of this license would be infringed by THIS
+ IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
+
+ "PATENT CHALLENGE" shall mean a challenge to the validity,
+ patentability, enforceability and/or non-infringement of any of the
+ PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
+
+ Tokutek hereby grants to you, for the term and geographical scope of
+ the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
+ irrevocable (except as stated in this section) patent license to
+ make, have made, use, offer to sell, sell, import, transfer, and
+ otherwise run, modify, and propagate the contents of THIS
+ IMPLEMENTATION, where such license applies only to the PATENT
+ CLAIMS. This grant does not include claims that would be infringed
+ only as a consequence of further modifications of THIS
+ IMPLEMENTATION. If you or your agent or licensee institute or order
+ or agree to the institution of patent litigation against any entity
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
+ THIS IMPLEMENTATION constitutes direct or contributory patent
+ infringement, or inducement of patent infringement, then any rights
+ granted to you under this License shall terminate as of the date
+ such litigation is filed. If you or your agent or exclusive
+ licensee institute or order or agree to the institution of a PATENT
+ CHALLENGE, then Tokutek may terminate any rights granted to you
+ under this License.
+*/
+
+#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
+#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#ifndef _YOBI_DB_H
+#define _YOBI_DB_H
+
+#include "ydb-constants.h"
+
+
+#include <sys/types.h>
+#include <stdio.h>
+
+typedef enum {
+ DB_BTREE=1,
+ // DB_HASH=2,
+ // DB_RECNO=3,
+ // DB_QUEUE=4,
+ // DB_UNKNOWN=5 /* Figure it out on open. */
+} DBTYPE;
+
+typedef enum {
+ DB_NOTICE_LOGFILE_CHANGED
+} db_notices;
+
+enum {
+ DB_VERB_CHKPOINT = 0x0001,
+ DB_VERB_DEADLOCK = 0x0002,
+ DB_VERB_RECOVERY = 0x0004
+
+};
+
+typedef struct yobi_db DB;
+typedef struct yobi_db_btree_stat DB_BTREE_STAT;
+typedef struct yobi_db_env DB_ENV;
+typedef struct yobi_db_key_range DB_KEY_RANGE;
+typedef struct yobi_db_lsn DB_LSN;
+typedef struct yobi_db_txn DB_TXN;
+typedef struct yobi_db_txn_active DB_TXN_ACTIVE;
+typedef struct yobi_db_txn_stat DB_TXN_STAT;
+typedef struct yobi_dbc DBC;
+typedef struct yobi_dbt DBT;
+
+struct yobi_db {
+ void *app_private;
+ int (*close) (DB *, uint32_t);
+ int (*cursor) (DB *, DB_TXN *, DBC **, uint32_t);
+ int (*del) (DB *, DB_TXN *, DBT *, uint32_t);
+ int (*get) (DB *, DB_TXN *, DBT *, DBT *, uint32_t);
+ int (*key_range) (DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, uint32_t);
+ int (*open) (DB *, DB_TXN *,
+ const char *, const char *, DBTYPE, uint32_t, int);
+ int (*put) (DB *, DB_TXN *, DBT *, DBT *, uint32_t);
+ int (*remove) (DB *, const char *, const char *, uint32_t);
+ int (*rename) (DB *, const char *, const char *, const char *, uint32_t);
+ int (*set_bt_compare) (DB *,
+ int (*)(DB *, const DBT *, const DBT *));
+ int (*set_flags) (DB *, uint32_t);
+ int (*stat) (DB *, void *, uint32_t);
+
+ struct ydb_db_internal *i;
+};
+enum {
+ DB_DBT_MALLOC = 0x002,
+ DB_DBT_REALLOC = 0x010,
+ DB_DBT_USERMEM = 0x020,
+ DB_DBT_DUPOK = 0x040
+};
+struct yobi_dbt {
+ void *app_private;
+ void *data;
+ uint32_t flags;
+ uint32_t size;
+ uint32_t ulen;
+};
+struct yobi_db_txn {
+ int (*commit) (DB_TXN*, uint32_t);
+ uint32_t (*id) (DB_TXN *);
+ // internal stuff
+ struct yobi_db_txn_internal *i;
+};
+struct yobi_dbc {
+ int (*c_get) (DBC *, DBT *, DBT *, uint32_t);
+ int (*c_close) (DBC *);
+ int (*c_del) (DBC *, uint32_t);
+ struct yobi_dbc_internal *i;
+};
+struct yobi_db_env {
+ // Methods used by MYSQL
+ void (*err) (const DB_ENV *, int, const char *, ...);
+ int (*open) (DB_ENV *, const char *, uint32_t, int);
+ int (*close) (DB_ENV *, uint32_t);
+ int (*txn_checkpoint) (DB_ENV *, uint32_t, uint32_t, uint32_t);
+ int (*log_flush) (DB_ENV *, const DB_LSN *);
+ void (*set_errcall) (DB_ENV *, void (*)(const char *, char *));
+ void (*set_errpfx) (DB_ENV *, const char *);
+ void (*set_noticecall) (DB_ENV *, void (*)(DB_ENV *, db_notices));
+ int (*set_flags) (DB_ENV *, uint32_t, int);
+ int (*set_data_dir) (DB_ENV *, const char *);
+ int (*set_tmp_dir) (DB_ENV *, const char *);
+ int (*set_verbose) (DB_ENV *, uint32_t, int);
+ int (*set_lg_bsize) (DB_ENV *, uint32_t);
+ int (*set_lg_dir) (DB_ENV *, const char *);
+ int (*set_lg_max) (DB_ENV *, uint32_t);
+ int (*set_cachesize) (DB_ENV *, uint32_t, uint32_t, int);
+ int (*set_lk_detect) (DB_ENV *, uint32_t);
+ int (*set_lk_max) (DB_ENV *, uint32_t);
+ int (*log_archive) (DB_ENV *, char **[], uint32_t);
+ int (*txn_stat) (DB_ENV *, DB_TXN_STAT **, uint32_t);
+#ifdef _YDB_WRAP_H
+#undef txn_begin
+#endif
+ int (*txn_begin) (DB_ENV *, DB_TXN *, DB_TXN **, uint32_t);
+#ifdef _YDB_WRAP_H
+#define txn_begin txn_begin_ydb
+#endif
+ // Internal state
+ struct db_env_ydb_internal *i;
+};
+struct yobi_db_key_range {
+ double less,equal,greater;
+};
+struct yobi_db_btree_stat {
+ uint32_t bt_ndata;
+ uint32_t bt_nkeys;
+};
+struct yobi_db_txn_stat {
+ uint32_t st_nactive;
+ DB_TXN_ACTIVE *st_txnarray;
+};
+struct yobi_db_lsn {
+ int hello;
+};
+struct yobi_db_txn_active {
+ DB_LSN lsn;
+ uint32_t txnid;
+};
+
+#ifndef _YDB_WRAP_H
+#define DB_VERSION_STRING "Yobiduck: Fractal DB (November 19, 2006)"
+#else
+#define DB_VERSION_STRING_ydb "Yobiduck: Fractal DB (November 19, 2006) (wrapped bdb)"
+#endif
+
+enum {
+ DB_ARCH_ABS = 0x001,
+ DB_ARCH_LOG = 0x004
+};
+
+enum {
+ DB_CREATE = 0x0000001,
+ DB_RDONLY = 0x0000010,
+ DB_RECOVER = 0x0000020,
+ DB_THREAD = 0x0000040,
+ DB_TXN_NOSYNC = 0x0000100,
+
+ DB_PRIVATE = 0x0100000
+};
+
+enum {
+ DB_LOCK_DEFAULT = 1,
+ DB_LOCK_OLDEST = 7,
+ DB_LOCK_RANDOM = 8
+};
+
+enum {
+ DB_DUP = 0x000002
+};
+
+enum {
+ DB_NOOVERWRITE = 23
+};
+
+enum {
+ DB_INIT_LOCK = 0x001000,
+ DB_INIT_LOG = 0x002000,
+ DB_INIT_MPOOL = 0x004000,
+ DB_INIT_TXN = 0x008000
+};
+
+int db_create (DB **, DB_ENV *, uint32_t);
+int db_env_create (DB_ENV **, uint32_t);
+
+int txn_begin (DB_ENV *, DB_TXN *, DB_TXN **, uint32_t);
+int txn_commit (DB_TXN *, uint32_t);
+int txn_abort (DB_TXN *);
+
+int log_compare (const DB_LSN *, const DB_LSN *);
+
+#endif
diff --git a/storage/tokudb/ft-index/portability/rdtsc.h b/storage/tokudb/ft-index/toku_include/rdtsc.h
index e70f636e169..e70f636e169 100644
--- a/storage/tokudb/ft-index/portability/rdtsc.h
+++ b/storage/tokudb/ft-index/toku_include/rdtsc.h
diff --git a/storage/tokudb/ft-index/portability/toku_assert.h b/storage/tokudb/ft-index/toku_include/toku_assert.h
index 0214018c11f..ab9978fdf0b 100644
--- a/storage/tokudb/ft-index/portability/toku_assert.h
+++ b/storage/tokudb/ft-index/toku_include/toku_assert.h
@@ -94,16 +94,16 @@ PATENT RIGHTS GRANT:
/* This version will complain if NDEBUG is set. */
/* It evaluates the argument and then calls a function toku_do_assert() which takes all the hits for the branches not taken. */
-#include <portability/toku_config.h>
+#include "toku_config.h"
#include <stdint.h>
#include <errno.h>
-#include <stdio.h>
#ifdef NDEBUG
#error NDEBUG should not be set
#endif
+
static inline int get_error_errno(void);
static inline int
@@ -120,8 +120,7 @@ set_errno(int new_errno)
void toku_assert_init(void) __attribute__((constructor));
-void toku_assert_set_fpointers(int (*toku_maybe_get_engine_status_text_pointer)(char*, int),
- int (*toku_maybe_err_engine_status_pointer)(void),
+void toku_assert_set_fpointers(int (*toku_maybe_get_engine_status_text_pointer)(char*, int),
void (*toku_maybe_set_env_panic_pointer)(int, const char*),
uint64_t num_rows);
@@ -135,15 +134,8 @@ void toku_do_assert_expected_fail(uintptr_t/*expr*/, uintptr_t /*expected*/, con
// #define GCOV
extern void (*do_assert_hook)(void); // Set this to a function you want called after printing the assertion failure message but before calling abort(). By default this is NULL.
-// copied here from ydb-internal.h to avoid inclusion hell, the void * is really a DB_ENV but we don't have that type here
-typedef void (*toku_env_err_func)(const void * env, int error, const char *fmt, ...);
-void db_env_do_backtrace_errfunc(toku_env_err_func errfunc, const void *env);
-void db_env_do_backtrace(FILE *outf);
-#ifdef assert
-# undef assert
-#endif
-#if defined(GCOV)
+#if defined(GCOV) || TOKU_WINDOWS
#define assert(expr) toku_do_assert((expr) != 0, #expr, __FUNCTION__, __FILE__, __LINE__, get_maybe_error_errno())
#define assert_zero(expr) toku_do_assert((expr) == 0, #expr, __FUNCTION__, __FILE__, __LINE__, get_maybe_error_errno())
#define assert_equals(expr, expected) toku_do_assert((expr) == (expected), (expected), #expr, __FUNCTION__, __FILE__, __LINE__, get_maybe_error_errno())
diff --git a/storage/tokudb/ft-index/portability/toku_config.h.in b/storage/tokudb/ft-index/toku_include/toku_config.h.in
index c56674ece9e..c56674ece9e 100644
--- a/storage/tokudb/ft-index/portability/toku_config.h.in
+++ b/storage/tokudb/ft-index/toku_include/toku_config.h.in
diff --git a/storage/tokudb/ft-index/portability/toku_htod.h b/storage/tokudb/ft-index/toku_include/toku_htod.h
index c6a7a143563..71a3ee6e415 100644
--- a/storage/tokudb/ft-index/portability/toku_htod.h
+++ b/storage/tokudb/ft-index/toku_include/toku_htod.h
@@ -109,7 +109,7 @@ PATENT RIGHTS GRANT:
#ifndef _TOKU_HTOD_H
#define _TOKU_HTOD_H
-#include <portability/toku_config.h>
+#include "toku_config.h"
#if defined(HAVE_ENDIAN_H)
# include <endian.h>
diff --git a/storage/tokudb/ft-index/portability/toku_list.h b/storage/tokudb/ft-index/toku_include/toku_list.h
index b39d56ebd32..b39d56ebd32 100644
--- a/storage/tokudb/ft-index/portability/toku_list.h
+++ b/storage/tokudb/ft-index/toku_include/toku_list.h
diff --git a/storage/tokudb/ft-index/portability/toku_os.h b/storage/tokudb/ft-index/toku_include/toku_os.h
index c232919f450..e53885c9791 100644
--- a/storage/tokudb/ft-index/portability/toku_os.h
+++ b/storage/tokudb/ft-index/toku_include/toku_os.h
@@ -95,8 +95,7 @@ PATENT RIGHTS GRANT:
#include <dirent.h>
#include <sys/time.h>
-#include "toku_stdint.h"
-#include "toku_os_types.h"
+#include <toku_os_types.h>
// Returns: the current process id
int toku_os_getpid(void) __attribute__((__visibility__("default")));
@@ -149,9 +148,6 @@ int toku_os_initialize_settings(int verbosity) __attribute__((__visibility__("d
bool toku_os_is_absolute_name(const char* path) __attribute__((__visibility__("default")));
-// Return true if huge pages are enabled. See portability/huge_page_detection.cc for methodology.
-bool toku_os_huge_pages_enabled(void) __attribute__((__visibility__("default")));
-
// Set whether or not writes assert when ENOSPC is returned or they wait for space
void toku_set_assert_on_write_enospc(int do_assert) __attribute__((__visibility__("default")));
@@ -172,6 +168,13 @@ int toku_fsync_dir_by_name_without_accounting(const char *dir_name);
// Return 0 on success, otherwise an error number
int toku_get_filesystem_sizes(const char *path, uint64_t *avail_size, uint64_t *free_size, uint64_t *total_size);
+#if TOKU_WINDOWS
+#include <sys/types.h>
+#include <sys/stat.h>
+//Test if st_mode (from stat) is a directory
+#define S_ISDIR(bitvector) (((bitvector)&_S_IFDIR)!=0)
+#endif
+
// Portable linux 'stat'
int toku_stat(const char *name, toku_struct_stat *statbuf) __attribute__((__visibility__("default")));
// Portable linux 'fstat'
diff --git a/storage/tokudb/ft-index/portability/toku_portability.h b/storage/tokudb/ft-index/toku_include/toku_portability.h
index dc2ac683113..df76e4bab78 100644
--- a/storage/tokudb/ft-index/portability/toku_portability.h
+++ b/storage/tokudb/ft-index/toku_include/toku_portability.h
@@ -101,21 +101,82 @@ PATENT RIGHTS GRANT:
# define constexpr_static_assert(a, b) static_assert(a, b)
#endif
-#if defined(_MSC_VER)
-# error "Windows is not supported."
+#if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(__ICL))
+
+#define TOKU_WINDOWS 1
+#define DEV_NULL_FILE "NUL"
+
+# if defined(_WIN64)
+# define TOKU_WINDOWS_32 0
+# define TOKU_WINDOWS_64 1
+# else
+# define TOKU_WINDOWS_32 1
+# define TOKU_WINDOWS_64 2
#endif
+#else
+
+#define TOKU_WINDOWS 0
+#define TOKU_WINDOWS_32 0
+#define TOKU_WINDOWS_64 0
#define DEV_NULL_FILE "/dev/null"
-// HACK Poison these mcaros so no one uses them
-#define TOKU_WINDOWS ,
-#define TOKU_WINDOWS_32 ,
-#define TOKU_WINDOWS_64 ,
+#endif
// include here, before they get deprecated
#include <toku_atomic.h>
-#if defined(__GNUC__)
+#if TOKU_WINDOWS
+// Windows
+
+#define DO_GCC_PRAGMA(x) /* Nothing */
+
+#if defined(__ICL)
+#define __attribute__(x) /* Nothing */
+#endif
+
+#include <malloc.h>
+#include "toku_stdint.h"
+
+#ifndef TOKU_OFF_T_DEFINED
+#define TOKU_OFF_T_DEFINED
+typedef int64_t toku_off_t;
+#endif
+
+#include <direct.h>
+#include <sys/types.h>
+#include "unistd.h"
+#include "misc.h"
+#include "toku_pthread.h"
+
+#define UNUSED_WARNING(a) a=a /* To make up for missing attributes */
+
+#define cast_to_typeof(v)
+
+#elif defined(__INTEL_COMPILER)
+
+#define DO_GCC_PRAGMA(x) /* Nothing */
+
+#if defined(__ICC)
+// Intel linux
+
+#include <alloca.h>
+#include <toku_stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+#define static_assert(foo, bar)
+#endif
+
+#if defined(__cplusplus)
+# define cast_to_typeof(v) (decltype(v))
+#else
+# define cast_to_typeof(v) (__typeof__(v))
+#endif
+
+#elif defined(__GNUC__)
// GCC linux
#define DO_GCC_PRAGMA(x) _Pragma (#x)
@@ -126,15 +187,12 @@ PATENT RIGHTS GRANT:
#include <sys/time.h>
#include <sys/stat.h>
#include <stdio.h>
-
#if __FreeBSD__
#include <stdarg.h>
#endif
-
#if defined(HAVE_ALLOCA_H)
# include <alloca.h>
#endif
-
#if defined(__cplusplus)
# include <type_traits>
#endif
@@ -145,8 +203,10 @@ PATENT RIGHTS GRANT:
# define cast_to_typeof(v) (__typeof__(v))
#endif
-#else // __GNUC__ was not defined, so...
-# error "Must use a GNUC-compatible compiler."
+#else
+
+#error Not ICC and not GNUC. What compiler?
+
#endif
// Define some constants for Yama in case the build-machine's software is too old.
@@ -205,8 +265,10 @@ extern "C" {
# ifndef DONT_DEPRECATE_ERRNO
# pragma deprecated (errno)
# endif
-# pragma poison dup2
-# pragma poison _dup2
+# ifndef TOKU_WINDOWS_ALLOW_DEPRECATED
+# pragma poison dup2
+# pragma poison _dup2
+# endif
# else
int creat(const char *pathname, mode_t mode) __attribute__((__deprecated__));
int fstat(int fd, struct stat *buf) __attribute__((__deprecated__));
@@ -217,7 +279,8 @@ int syscall(int __sysno, ...) __attribute__((__deprecated__));
# else
long int syscall(long int __sysno, ...) __attribute__((__deprecated__));
# endif
- long int sysconf(int) __attribute__((__deprecated__));
+// Sadly, dlmalloc needs sysconf, and on linux this causes trouble with -combine. So let the warnings show up under windows only.
+// long int sysconf(int) __attribute__((__deprecated__));
int mkdir(const char *pathname, mode_t mode) __attribute__((__deprecated__));
int dup2(int fd, int fd2) __attribute__((__deprecated__));
int _dup2(int fd, int fd2) __attribute__((__deprecated__));
diff --git a/storage/tokudb/ft-index/portability/toku_race_tools.h b/storage/tokudb/ft-index/toku_include/toku_race_tools.h
index 9d3795eae95..77417cb0433 100644
--- a/storage/tokudb/ft-index/portability/toku_race_tools.h
+++ b/storage/tokudb/ft-index/toku_include/toku_race_tools.h
@@ -91,7 +91,7 @@ PATENT RIGHTS GRANT:
#ifndef TOKU_RACE_TOOLS_H
#define TOKU_RACE_TOOLS_H
-#include <portability/toku_config.h>
+#include "toku_config.h"
#if defined(__linux__) && USE_VALGRIND
diff --git a/storage/tokudb/ft-index/tools/CMakeLists.txt b/storage/tokudb/ft-index/tools/CMakeLists.txt
deleted file mode 100644
index 67763535920..00000000000
--- a/storage/tokudb/ft-index/tools/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE DONT_DEPRECATE_ERRNO)
-
-set(utils tokudb_gen tokudb_load tokudb_dump)
-foreach(util ${utils})
- add_executable(${util} ${util}.cc)
- set_target_properties(${util} PROPERTIES
- COMPILE_DEFINITIONS "IS_TDB=1;USE_TDB=1;TDB_IS_STATIC=1")
- target_link_libraries(${util} ${LIBTOKUDB}_static ft_static z lzma ${LIBTOKUPORTABILITY}_static ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_SYSTEM_LIBS})
-
- add_space_separated_property(TARGET ${util} COMPILE_FLAGS -fvisibility=hidden)
-endforeach(util)
diff --git a/storage/tokudb/ft-index/util/CMakeLists.txt b/storage/tokudb/ft-index/util/CMakeLists.txt
index 6a0bb6208a5..08822c4a73c 100644
--- a/storage/tokudb/ft-index/util/CMakeLists.txt
+++ b/storage/tokudb/ft-index/util/CMakeLists.txt
@@ -2,12 +2,10 @@ set(util_srcs
context
frwlock
kibbutz
- memarena
mempool
partitioned_counter
threadpool
scoped_malloc
- x1764
)
add_library(util SHARED ${util_srcs})
diff --git a/storage/tokudb/ft-index/util/context.h b/storage/tokudb/ft-index/util/context.h
index 15f7d732635..3d424ff597d 100644
--- a/storage/tokudb/ft-index/util/context.h
+++ b/storage/tokudb/ft-index/util/context.h
@@ -91,7 +91,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2014 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-#include <portability/toku_portability.h>
+#include <toku_include/toku_portability.h>
#include <db.h>
diff --git a/storage/tokudb/ft-index/util/dmt.cc b/storage/tokudb/ft-index/util/dmt.cc
deleted file mode 100644
index 8d10c5b921c..00000000000
--- a/storage/tokudb/ft-index/util/dmt.cc
+++ /dev/null
@@ -1,1265 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
-#ident "$Id$"
-/*
-COPYING CONDITIONS NOTICE:
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation, and provided that the
- following conditions are met:
-
- * Redistributions of source code must retain this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below).
-
- * Redistributions in binary form must reproduce this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below) in the documentation and/or other materials
- provided with the distribution.
-
- 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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-COPYRIGHT NOTICE:
-
- TokuDB, Tokutek Fractal Tree Indexing Library.
- Copyright (C) 2007-2013 Tokutek, Inc.
-
-DISCLAIMER:
-
- 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.
-
-UNIVERSITY PATENT NOTICE:
-
- The technology is licensed by the Massachusetts Institute of
- Technology, Rutgers State University of New Jersey, and the Research
- Foundation of State University of New York at Stony Brook under
- United States of America Serial No. 11/760379 and to the patents
- and/or patent applications resulting from it.
-
-PATENT MARKING NOTICE:
-
- This software is covered by US Patent No. 8,185,551.
-
-PATENT RIGHTS GRANT:
-
- "THIS IMPLEMENTATION" means the copyrightable works distributed by
- Tokutek as part of the Fractal Tree project.
-
- "PATENT CLAIMS" means the claims of patents that are owned or
- licensable by Tokutek, both currently or in the future; and that in
- the absence of this license would be infringed by THIS
- IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
-
- "PATENT CHALLENGE" shall mean a challenge to the validity,
- patentability, enforceability and/or non-infringement of any of the
- PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
-
- Tokutek hereby grants to you, for the term and geographical scope of
- the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
- irrevocable (except as stated in this section) patent license to
- make, have made, use, offer to sell, sell, import, transfer, and
- otherwise run, modify, and propagate the contents of THIS
- IMPLEMENTATION, where such license applies only to the PATENT
- CLAIMS. This grant does not include claims that would be infringed
- only as a consequence of further modifications of THIS
- IMPLEMENTATION. If you or your agent or licensee institute or order
- or agree to the institution of patent litigation against any entity
- (including a cross-claim or counterclaim in a lawsuit) alleging that
- THIS IMPLEMENTATION constitutes direct or contributory patent
- infringement, or inducement of patent infringement, then any rights
- granted to you under this License shall terminate as of the date
- such litigation is filed. If you or your agent or exclusive
- licensee institute or order or agree to the institution of a PATENT
- CHALLENGE, then Tokutek may terminate any rights granted to you
- under this License.
-*/
-
-#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
-#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-
-#include <string.h>
-#include <db.h>
-
-#include <portability/memory.h>
-#include <limits.h>
-
-namespace toku {
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::create(void) {
- toku_mempool_zero(&this->mp);
- this->values_same_size = true;
- this->value_length = 0;
- this->is_array = true;
- this->d.a.num_values = 0;
- //TODO: maybe allocate enough space for something by default?
- // We may be relying on not needing to allocate space the first time (due to limited time spent while a lock is held)
-}
-
-/**
- * Note: create_from_sorted_memory_of_fixed_size_elements does not take ownership of 'mem'.
- * Owner is still responsible for freeing it.
- * While in the OMT a similar function would steal ownership, this doesn't make sense for the DMT because
- * we (usually) have to add padding for alignment (mem has all of the elements PACKED).
- * Also all current uses (as of Jan 12, 2014) of this function would require mallocing a new array
- * in order to allow stealing.
- */
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::create_from_sorted_memory_of_fixed_size_elements(
- const void *mem,
- const uint32_t numvalues,
- const uint32_t mem_length,
- const uint32_t fixed_value_length) {
- this->values_same_size = true;
- this->value_length = fixed_value_length;
- this->is_array = true;
- this->d.a.num_values = numvalues;
- const uint8_t pad_bytes = get_fixed_length_alignment_overhead();
- uint32_t aligned_memsize = mem_length + numvalues * pad_bytes;
- toku_mempool_construct(&this->mp, aligned_memsize);
- if (aligned_memsize > 0) {
- paranoid_invariant(numvalues > 0);
- void *ptr = toku_mempool_malloc(&this->mp, aligned_memsize, 1);
- paranoid_invariant_notnull(ptr);
- uint8_t * const CAST_FROM_VOIDP(dest, ptr);
- const uint8_t * const CAST_FROM_VOIDP(src, mem);
- if (pad_bytes == 0) {
- paranoid_invariant(aligned_memsize == mem_length);
- memcpy(dest, src, aligned_memsize);
- } else {
- // TODO(leif): check what vectorizes best: multiplying like this or adding to offsets
- const uint32_t fixed_len = this->value_length;
- const uint32_t fixed_aligned_len = align(this->value_length);
- paranoid_invariant(this->d.a.num_values*fixed_len == mem_length);
- for (uint32_t i = 0; i < this->d.a.num_values; i++) {
- memcpy(&dest[i*fixed_aligned_len], &src[i*fixed_len], fixed_len);
- }
- }
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::clone(const dmt &src) {
- *this = src;
- toku_mempool_clone(&src.mp, &this->mp);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::clear(void) {
- this->is_array = true;
- this->d.a.num_values = 0;
- this->values_same_size = true; // Reset state
- this->value_length = 0;
- //TODO(leif): Note that this can mess with our memory_footprint calculation (we may touch past what is marked as 'used' in the mempool)
- // One 'fix' is for mempool to also track what was touched, and reset() shouldn't reset that, though realloc() might.
- toku_mempool_reset(&this->mp);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::destroy(void) {
- this->clear();
- toku_mempool_destroy(&this->mp);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-uint32_t dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::size(void) const {
- if (this->is_array) {
- return this->d.a.num_values;
- } else {
- return this->nweight(this->d.t.root);
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-uint32_t dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::nweight(const subtree &subtree) const {
- if (subtree.is_null()) {
- return 0;
- } else {
- const dmt_node & node = get_node(subtree);
- return node.weight;
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t, int (*h)(const uint32_t size, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::insert(const dmtwriter_t &value, const dmtcmp_t &v, uint32_t *const idx) {
- int r;
- uint32_t insert_idx;
-
- r = this->find_zero<dmtcmp_t, h>(v, nullptr, nullptr, &insert_idx);
- if (r==0) {
- if (idx) *idx = insert_idx;
- return DB_KEYEXIST;
- }
- if (r != DB_NOTFOUND) return r;
-
- if ((r = this->insert_at(value, insert_idx))) return r;
- if (idx) *idx = insert_idx;
-
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::insert_at(const dmtwriter_t &value, const uint32_t idx) {
- if (idx > this->size()) { return EINVAL; }
-
- bool same_size = this->values_same_size && (this->size() == 0 || value.get_size() == this->value_length);
- if (this->is_array) {
- if (same_size && idx == this->d.a.num_values) {
- return this->insert_at_array_end<true>(value);
- }
- this->convert_from_array_to_tree();
- }
- // Is a tree.
- paranoid_invariant(!is_array);
- if (!same_size) {
- this->values_same_size = false;
- this->value_length = 0;
- }
-
- this->maybe_resize_tree(&value);
- subtree *rebalance_subtree = nullptr;
- this->insert_internal(&this->d.t.root, value, idx, &rebalance_subtree);
- if (rebalance_subtree != nullptr) {
- this->rebalance(rebalance_subtree);
- }
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<bool with_resize>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::insert_at_array_end(const dmtwriter_t& value_in) {
- paranoid_invariant(this->is_array);
- paranoid_invariant(this->values_same_size);
- if (this->d.a.num_values == 0) {
- this->value_length = value_in.get_size();
- }
- paranoid_invariant(this->value_length == value_in.get_size());
-
- if (with_resize) {
- this->maybe_resize_array_for_insert();
- }
- dmtdata_t *dest = this->alloc_array_value_end();
- value_in.write_to(dest);
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-dmtdata_t * dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::alloc_array_value_end(void) {
- paranoid_invariant(this->is_array);
- paranoid_invariant(this->values_same_size);
- this->d.a.num_values++;
-
- void *ptr = toku_mempool_malloc(&this->mp, align(this->value_length), 1);
- paranoid_invariant_notnull(ptr);
- paranoid_invariant(reinterpret_cast<size_t>(ptr) % ALIGNMENT == 0);
- dmtdata_t *CAST_FROM_VOIDP(n, ptr);
- paranoid_invariant(n == get_array_value(this->d.a.num_values - 1));
- return n;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-dmtdata_t * dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::get_array_value(const uint32_t idx) const {
- paranoid_invariant(this->is_array);
- paranoid_invariant(this->values_same_size);
-
- paranoid_invariant(idx < this->d.a.num_values);
- return get_array_value_internal(&this->mp, idx);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-dmtdata_t * dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::get_array_value_internal(const struct mempool *mempool, const uint32_t idx) const {
- void* ptr = toku_mempool_get_pointer_from_base_and_offset(mempool, idx * align(this->value_length));
- dmtdata_t *CAST_FROM_VOIDP(value, ptr);
- return value;
-}
-
-//TODO(leif) write microbenchmarks to compare growth factor. Note: growth factor here is actually 2.5 because of mempool_construct
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::maybe_resize_array_for_insert(void) {
- bool space_available = toku_mempool_get_free_size(&this->mp) >= align(this->value_length);
-
- if (!space_available) {
- const uint32_t n = this->d.a.num_values + 1;
- const uint32_t new_n = n <=2 ? 4 : 2*n;
- const uint32_t new_space = align(this->value_length) * new_n;
-
- struct mempool new_kvspace;
- toku_mempool_construct(&new_kvspace, new_space);
- size_t copy_bytes = this->d.a.num_values * align(this->value_length);
- invariant(copy_bytes + align(this->value_length) <= new_space);
- paranoid_invariant(copy_bytes <= toku_mempool_get_used_size(&this->mp));
- // Copy over to new mempool
- if (this->d.a.num_values > 0) {
- void* dest = toku_mempool_malloc(&new_kvspace, copy_bytes, 1);
- invariant(dest!=nullptr);
- memcpy(dest, get_array_value(0), copy_bytes);
- }
- toku_mempool_destroy(&this->mp);
- this->mp = new_kvspace;
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-uint32_t dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::align(const uint32_t x) const {
- return roundup_to_multiple(ALIGNMENT, x);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::prepare_for_serialize(void) {
- if (!this->is_array) {
- this->convert_from_tree_to_array();
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::convert_from_tree_to_array(void) {
- paranoid_invariant(!this->is_array);
- paranoid_invariant(this->values_same_size);
-
- const uint32_t num_values = this->size();
-
- node_offset *tmp_array;
- bool malloced = false;
- tmp_array = alloc_temp_node_offsets(num_values);
- if (!tmp_array) {
- malloced = true;
- XMALLOC_N(num_values, tmp_array);
- }
- this->fill_array_with_subtree_offsets(tmp_array, this->d.t.root);
-
- struct mempool new_mp;
- const uint32_t fixed_len = this->value_length;
- const uint32_t fixed_aligned_len = align(this->value_length);
- size_t mem_needed = num_values * fixed_aligned_len;
- toku_mempool_construct(&new_mp, mem_needed);
- uint8_t* CAST_FROM_VOIDP(dest, toku_mempool_malloc(&new_mp, mem_needed, 1));
- paranoid_invariant_notnull(dest);
- for (uint32_t i = 0; i < num_values; i++) {
- const dmt_node &n = get_node(tmp_array[i]);
- memcpy(&dest[i*fixed_aligned_len], &n.value, fixed_len);
- }
- toku_mempool_destroy(&this->mp);
- this->mp = new_mp;
- this->is_array = true;
- this->d.a.num_values = num_values;
-
- if (malloced) toku_free(tmp_array);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::convert_from_array_to_tree(void) {
- paranoid_invariant(this->is_array);
- paranoid_invariant(this->values_same_size);
-
- //save array-format information to locals
- const uint32_t num_values = this->d.a.num_values;
-
- node_offset *tmp_array;
- bool malloced = false;
- tmp_array = alloc_temp_node_offsets(num_values);
- if (!tmp_array) {
- malloced = true;
- XMALLOC_N(num_values, tmp_array);
- }
-
- struct mempool old_mp = this->mp;
- size_t mem_needed = num_values * align(this->value_length + __builtin_offsetof(dmt_node, value));
- toku_mempool_construct(&this->mp, mem_needed);
-
- for (uint32_t i = 0; i < num_values; i++) {
- dmtwriter_t writer(this->value_length, get_array_value_internal(&old_mp, i));
- tmp_array[i] = node_malloc_and_set_value(writer);
- }
- this->is_array = false;
- this->rebuild_subtree_from_offsets(&this->d.t.root, tmp_array, num_values);
-
- if (malloced) toku_free(tmp_array);
- toku_mempool_destroy(&old_mp);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::delete_at(const uint32_t idx) {
- uint32_t n = this->size();
- if (idx >= n) { return EINVAL; }
-
- if (n == 1) {
- this->clear(); //Emptying out the entire dmt.
- return 0;
- }
- if (this->is_array) {
- this->convert_from_array_to_tree();
- }
- paranoid_invariant(!is_array);
-
- subtree *rebalance_subtree = nullptr;
- this->delete_internal(&this->d.t.root, idx, nullptr, &rebalance_subtree);
- if (rebalance_subtree != nullptr) {
- this->rebalance(rebalance_subtree);
- }
- this->maybe_resize_tree(nullptr);
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename iterate_extra_t,
- int (*f)(const uint32_t, const dmtdata_t &, const uint32_t, iterate_extra_t *const)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::iterate(iterate_extra_t *const iterate_extra) const {
- return this->iterate_on_range<iterate_extra_t, f>(0, this->size(), iterate_extra);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename iterate_extra_t,
- int (*f)(const uint32_t, const dmtdata_t &, const uint32_t, iterate_extra_t *const)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::iterate_on_range(const uint32_t left, const uint32_t right, iterate_extra_t *const iterate_extra) const {
- if (right > this->size()) { return EINVAL; }
- if (left == right) { return 0; }
- if (this->is_array) {
- return this->iterate_internal_array<iterate_extra_t, f>(left, right, iterate_extra);
- }
- return this->iterate_internal<iterate_extra_t, f>(left, right, this->d.t.root, 0, iterate_extra);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::verify(void) const {
- uint32_t num_values = this->size();
- invariant(num_values < UINT32_MAX);
- size_t pool_used = toku_mempool_get_used_size(&this->mp);
- size_t pool_size = toku_mempool_get_size(&this->mp);
- size_t pool_frag = toku_mempool_get_frag_size(&this->mp);
- invariant(pool_used <= pool_size);
- if (this->is_array) {
- invariant(this->values_same_size);
- invariant(num_values == this->d.a.num_values);
-
- // We know exactly how much memory should be used.
- invariant(pool_used == num_values * align(this->value_length));
-
- // Array form must have 0 fragmentation in mempool.
- invariant(pool_frag == 0);
- } else {
- if (this->values_same_size) {
- // We know exactly how much memory should be used.
- invariant(pool_used == num_values * align(this->value_length + __builtin_offsetof(dmt_node, value)));
- } else {
- // We can only do a lower bound on memory usage.
- invariant(pool_used >= num_values * __builtin_offsetof(dmt_node, value));
- }
- std::vector<bool> touched(pool_size, false);
- verify_internal(this->d.t.root, &touched);
- size_t bytes_used = 0;
- for (size_t i = 0; i < pool_size; i++) {
- if (touched.at(i)) {
- ++bytes_used;
- }
- }
- invariant(bytes_used == pool_used);
- }
-}
-
-// Verifies all weights are internally consistent.
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::verify_internal(const subtree &subtree, std::vector<bool> *touched) const {
- if (subtree.is_null()) {
- return;
- }
- const dmt_node &node = get_node(subtree);
-
- if (this->values_same_size) {
- invariant(node.value_length == this->value_length);
- }
-
- size_t offset = toku_mempool_get_offset_from_pointer_and_base(&this->mp, &node);
- size_t node_size = align(__builtin_offsetof(dmt_node, value) + node.value_length);
- invariant(offset <= touched->size());
- invariant(offset+node_size <= touched->size());
- invariant(offset % ALIGNMENT == 0);
- // Mark memory as touched and never allocated to multiple nodes.
- for (size_t i = offset; i < offset+node_size; ++i) {
- invariant(!touched->at(i));
- touched->at(i) = true;
- }
-
- const uint32_t leftweight = this->nweight(node.left);
- const uint32_t rightweight = this->nweight(node.right);
-
- invariant(leftweight + rightweight + 1 == this->nweight(subtree));
- verify_internal(node.left, touched);
- verify_internal(node.right, touched);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename iterate_extra_t,
- int (*f)(const uint32_t, dmtdata_t *, const uint32_t, iterate_extra_t *const)>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::iterate_ptr(iterate_extra_t *const iterate_extra) {
- if (this->is_array) {
- this->iterate_ptr_internal_array<iterate_extra_t, f>(0, this->size(), iterate_extra);
- } else {
- this->iterate_ptr_internal<iterate_extra_t, f>(0, this->size(), this->d.t.root, 0, iterate_extra);
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::fetch(const uint32_t idx, uint32_t *const value_len, dmtdataout_t *const value) const {
- if (idx >= this->size()) { return EINVAL; }
- if (this->is_array) {
- this->fetch_internal_array(idx, value_len, value);
- } else {
- this->fetch_internal(this->d.t.root, idx, value_len, value);
- }
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::find_zero(const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const {
- uint32_t tmp_index;
- uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index;
- int r;
- if (this->is_array) {
- r = this->find_internal_zero_array<dmtcmp_t, h>(extra, value_len, value, child_idxp);
- }
- else {
- r = this->find_internal_zero<dmtcmp_t, h>(this->d.t.root, extra, value_len, value, child_idxp);
- }
- return r;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::find(const dmtcmp_t &extra, int direction, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const {
- uint32_t tmp_index;
- uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index;
- paranoid_invariant(direction != 0);
- if (direction < 0) {
- if (this->is_array) {
- return this->find_internal_minus_array<dmtcmp_t, h>(extra, value_len, value, child_idxp);
- } else {
- return this->find_internal_minus<dmtcmp_t, h>(this->d.t.root, extra, value_len, value, child_idxp);
- }
- } else {
- if (this->is_array) {
- return this->find_internal_plus_array<dmtcmp_t, h>(extra, value_len, value, child_idxp);
- } else {
- return this->find_internal_plus<dmtcmp_t, h>(this->d.t.root, extra, value_len, value, child_idxp);
- }
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-size_t dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::memory_size(void) {
- return (sizeof *this) + toku_mempool_get_size(&this->mp);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-dmt_node_templated<dmtdata_t> & dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::get_node(const subtree &subtree) const {
- paranoid_invariant(!subtree.is_null());
- return get_node(subtree.get_offset());
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-dmt_node_templated<dmtdata_t> & dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::get_node(const node_offset offset) const {
- void* ptr = toku_mempool_get_pointer_from_base_and_offset(&this->mp, offset);
- dmt_node *CAST_FROM_VOIDP(node, ptr);
- return *node;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::node_set_value(dmt_node * n, const dmtwriter_t &value) {
- n->value_length = value.get_size();
- value.write_to(&n->value);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-node_offset dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::node_malloc_and_set_value(const dmtwriter_t &value) {
- size_t val_size = value.get_size();
- size_t size_to_alloc = __builtin_offsetof(dmt_node, value) + val_size;
- size_to_alloc = align(size_to_alloc);
- void* np = toku_mempool_malloc(&this->mp, size_to_alloc, 1);
- paranoid_invariant_notnull(np);
- dmt_node *CAST_FROM_VOIDP(n, np);
- node_set_value(n, value);
-
- return toku_mempool_get_offset_from_pointer_and_base(&this->mp, np);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::node_free(const subtree &st) {
- dmt_node &n = get_node(st);
- size_t size_to_free = __builtin_offsetof(dmt_node, value) + n.value_length;
- size_to_free = align(size_to_free);
- toku_mempool_mfree(&this->mp, &n, size_to_free);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::maybe_resize_tree(const dmtwriter_t * value) {
- const ssize_t curr_capacity = toku_mempool_get_size(&this->mp);
- const ssize_t curr_free = toku_mempool_get_free_size(&this->mp);
- const ssize_t curr_used = toku_mempool_get_used_size(&this->mp);
- ssize_t add_size = 0;
- if (value) {
- add_size = __builtin_offsetof(dmt_node, value) + value->get_size();
- add_size = align(add_size);
- }
-
- const ssize_t need_size = curr_used + add_size;
- paranoid_invariant(need_size <= UINT32_MAX);
- //TODO(leif) consider different growth rates
- const ssize_t new_size = 2*need_size;
- paranoid_invariant(new_size <= UINT32_MAX);
-
- if ((curr_capacity / 2 >= new_size) || // Way too much allocated
- (curr_free < add_size)) { // No room in mempool
- // Copy all memory and reconstruct dmt in new mempool.
- if (curr_free < add_size && toku_mempool_get_frag_size(&this->mp) == 0) {
- // TODO(yoni) or TODO(leif) consider doing this not just when frag size is zero, but also when it is a small percentage of the total mempool size
- // Offsets remain the same in the new mempool so we can just realloc.
- toku_mempool_realloc_larger(&this->mp, new_size);
- } else if (!this->d.t.root.is_null()) {
- struct mempool new_kvspace;
- toku_mempool_construct(&new_kvspace, new_size);
-
- const dmt_node &n = get_node(this->d.t.root);
- node_offset *tmp_array;
- bool malloced = false;
- tmp_array = alloc_temp_node_offsets(n.weight);
- if (!tmp_array) {
- malloced = true;
- XMALLOC_N(n.weight, tmp_array);
- }
- this->fill_array_with_subtree_offsets(tmp_array, this->d.t.root);
- for (node_offset i = 0; i < n.weight; i++) {
- dmt_node &node = get_node(tmp_array[i]);
- const size_t bytes_to_copy = __builtin_offsetof(dmt_node, value) + node.value_length;
- const size_t bytes_to_alloc = align(bytes_to_copy);
- void* newdata = toku_mempool_malloc(&new_kvspace, bytes_to_alloc, 1);
- memcpy(newdata, &node, bytes_to_copy);
- tmp_array[i] = toku_mempool_get_offset_from_pointer_and_base(&new_kvspace, newdata);
- }
-
- struct mempool old_kvspace = this->mp;
- this->mp = new_kvspace;
- this->rebuild_subtree_from_offsets(&this->d.t.root, tmp_array, n.weight);
- if (malloced) toku_free(tmp_array);
- toku_mempool_destroy(&old_kvspace);
- } else {
- toku_mempool_destroy(&this->mp);
- toku_mempool_construct(&this->mp, new_size);
- }
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-bool dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::will_need_rebalance(const subtree &subtree, const int leftmod, const int rightmod) const {
- if (subtree.is_null()) { return false; }
- const dmt_node &n = get_node(subtree);
- // one of the 1's is for the root.
- // the other is to take ceil(n/2)
- const uint32_t weight_left = this->nweight(n.left) + leftmod;
- const uint32_t weight_right = this->nweight(n.right) + rightmod;
- return ((1+weight_left < (1+1+weight_right)/2)
- ||
- (1+weight_right < (1+1+weight_left)/2));
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::insert_internal(subtree *const subtreep, const dmtwriter_t &value, const uint32_t idx, subtree **const rebalance_subtree) {
- if (subtreep->is_null()) {
- paranoid_invariant_zero(idx);
- const node_offset newoffset = this->node_malloc_and_set_value(value);
- dmt_node &newnode = get_node(newoffset);
- newnode.weight = 1;
- newnode.left.set_to_null();
- newnode.right.set_to_null();
- subtreep->set_offset(newoffset);
- } else {
- dmt_node &n = get_node(*subtreep);
- n.weight++;
- if (idx <= this->nweight(n.left)) {
- if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, 1, 0)) {
- *rebalance_subtree = subtreep;
- }
- this->insert_internal(&n.left, value, idx, rebalance_subtree);
- } else {
- if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, 0, 1)) {
- *rebalance_subtree = subtreep;
- }
- const uint32_t sub_index = idx - this->nweight(n.left) - 1;
- this->insert_internal(&n.right, value, sub_index, rebalance_subtree);
- }
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::delete_internal(subtree *const subtreep, const uint32_t idx, subtree *const subtree_replace, subtree **const rebalance_subtree) {
- paranoid_invariant_notnull(subtreep);
- paranoid_invariant_notnull(rebalance_subtree);
- paranoid_invariant(!subtreep->is_null());
- dmt_node &n = get_node(*subtreep);
- const uint32_t leftweight = this->nweight(n.left);
- if (idx < leftweight) {
- n.weight--;
- if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, -1, 0)) {
- *rebalance_subtree = subtreep;
- }
- this->delete_internal(&n.left, idx, subtree_replace, rebalance_subtree);
- } else if (idx == leftweight) {
- // Found the correct index.
- if (n.left.is_null()) {
- paranoid_invariant_zero(idx);
- // Delete n and let parent point to n.right
- subtree ptr_this = *subtreep;
- *subtreep = n.right;
- subtree to_free;
- if (subtree_replace != nullptr) {
- // Swap self with the other node. Taking over all responsibility.
- to_free = *subtree_replace;
- dmt_node &ancestor = get_node(*subtree_replace);
- if (*rebalance_subtree == &ancestor.right) {
- // Take over rebalance responsibility.
- *rebalance_subtree = &n.right;
- }
- n.weight = ancestor.weight;
- n.left = ancestor.left;
- n.right = ancestor.right;
- *subtree_replace = ptr_this;
- } else {
- to_free = ptr_this;
- }
- this->node_free(to_free);
- } else if (n.right.is_null()) {
- // Delete n and let parent point to n.left
- subtree to_free = *subtreep;
- *subtreep = n.left;
- paranoid_invariant(idx>0);
- paranoid_invariant_null(subtree_replace); // To be recursive, we're looking for index 0. n is index > 0 here.
- this->node_free(to_free);
- } else {
- if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, 0, -1)) {
- *rebalance_subtree = subtreep;
- }
- // don't need to copy up value, it's only used by this
- // next call, and when that gets to the bottom there
- // won't be any more recursion
- n.weight--;
- this->delete_internal(&n.right, 0, subtreep, rebalance_subtree);
- }
- } else {
- n.weight--;
- if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, 0, -1)) {
- *rebalance_subtree = subtreep;
- }
- this->delete_internal(&n.right, idx - leftweight - 1, subtree_replace, rebalance_subtree);
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename iterate_extra_t,
- int (*f)(const uint32_t, const dmtdata_t &, const uint32_t, iterate_extra_t *const)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::iterate_internal_array(const uint32_t left, const uint32_t right,
- iterate_extra_t *const iterate_extra) const {
- int r;
- for (uint32_t i = left; i < right; ++i) {
- r = f(this->value_length, *get_array_value(i), i, iterate_extra);
- if (r != 0) {
- return r;
- }
- }
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename iterate_extra_t,
- int (*f)(const uint32_t, dmtdata_t *, const uint32_t, iterate_extra_t *const)>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::iterate_ptr_internal(const uint32_t left, const uint32_t right,
- const subtree &subtree, const uint32_t idx,
- iterate_extra_t *const iterate_extra) {
- if (!subtree.is_null()) {
- dmt_node &n = get_node(subtree);
- const uint32_t idx_root = idx + this->nweight(n.left);
- if (left < idx_root) {
- this->iterate_ptr_internal<iterate_extra_t, f>(left, right, n.left, idx, iterate_extra);
- }
- if (left <= idx_root && idx_root < right) {
- int r = f(n.value_length, &n.value, idx_root, iterate_extra);
- lazy_assert_zero(r);
- }
- if (idx_root + 1 < right) {
- this->iterate_ptr_internal<iterate_extra_t, f>(left, right, n.right, idx_root + 1, iterate_extra);
- }
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename iterate_extra_t,
- int (*f)(const uint32_t, dmtdata_t *, const uint32_t, iterate_extra_t *const)>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::iterate_ptr_internal_array(const uint32_t left, const uint32_t right,
- iterate_extra_t *const iterate_extra) {
- for (uint32_t i = left; i < right; ++i) {
- int r = f(this->value_length, get_array_value(i), i, iterate_extra);
- lazy_assert_zero(r);
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename iterate_extra_t,
- int (*f)(const uint32_t, const dmtdata_t &, const uint32_t, iterate_extra_t *const)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::iterate_internal(const uint32_t left, const uint32_t right,
- const subtree &subtree, const uint32_t idx,
- iterate_extra_t *const iterate_extra) const {
- if (subtree.is_null()) { return 0; }
- int r;
- const dmt_node &n = get_node(subtree);
- const uint32_t idx_root = idx + this->nweight(n.left);
- if (left < idx_root) {
- r = this->iterate_internal<iterate_extra_t, f>(left, right, n.left, idx, iterate_extra);
- if (r != 0) { return r; }
- }
- if (left <= idx_root && idx_root < right) {
- r = f(n.value_length, n.value, idx_root, iterate_extra);
- if (r != 0) { return r; }
- }
- if (idx_root + 1 < right) {
- return this->iterate_internal<iterate_extra_t, f>(left, right, n.right, idx_root + 1, iterate_extra);
- }
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::fetch_internal_array(const uint32_t i, uint32_t *const value_len, dmtdataout_t *const value) const {
- copyout(value_len, value, this->value_length, get_array_value(i));
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::fetch_internal(const subtree &subtree, const uint32_t i, uint32_t *const value_len, dmtdataout_t *const value) const {
- dmt_node &n = get_node(subtree);
- const uint32_t leftweight = this->nweight(n.left);
- if (i < leftweight) {
- this->fetch_internal(n.left, i, value_len, value);
- } else if (i == leftweight) {
- copyout(value_len, value, &n);
- } else {
- this->fetch_internal(n.right, i - leftweight - 1, value_len, value);
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::fill_array_with_subtree_offsets(node_offset *const array, const subtree &subtree) const {
- if (!subtree.is_null()) {
- const dmt_node &tree = get_node(subtree);
- this->fill_array_with_subtree_offsets(&array[0], tree.left);
- array[this->nweight(tree.left)] = subtree.get_offset();
- this->fill_array_with_subtree_offsets(&array[this->nweight(tree.left) + 1], tree.right);
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::rebuild_subtree_from_offsets(subtree *const subtree, const node_offset *const offsets, const uint32_t numvalues) {
- if (numvalues==0) {
- subtree->set_to_null();
- } else {
- uint32_t halfway = numvalues/2;
- subtree->set_offset(offsets[halfway]);
- dmt_node &newnode = get_node(offsets[halfway]);
- newnode.weight = numvalues;
- // value is already in there.
- this->rebuild_subtree_from_offsets(&newnode.left, &offsets[0], halfway);
- this->rebuild_subtree_from_offsets(&newnode.right, &offsets[halfway+1], numvalues-(halfway+1));
- }
-}
-
-//TODO(leif): Note that this can mess with our memory_footprint calculation (we may touch past what is marked as 'used' in the mempool)
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-node_offset* dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::alloc_temp_node_offsets(uint32_t num_offsets) {
- size_t mem_needed = num_offsets * sizeof(node_offset);
- size_t mem_free;
- mem_free = toku_mempool_get_free_size(&this->mp);
- node_offset* CAST_FROM_VOIDP(tmp, toku_mempool_get_next_free_ptr(&this->mp));
- if (mem_free >= mem_needed) {
- return tmp;
- }
- return nullptr;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::rebalance(subtree *const subtree) {
- paranoid_invariant(!subtree->is_null());
-
- // There is a possible "optimization" here:
- // if (this->values_same_size && subtree == &this->d.t.root) {
- // this->convert_from_tree_to_array();
- // return;
- // }
- // but we don't want to do it because it involves actually copying values around
- // as opposed to stopping in the middle of rebalancing (like in the OMT)
-
- node_offset offset = subtree->get_offset();
- const dmt_node &n = get_node(offset);
- node_offset *tmp_array;
- bool malloced = false;
- tmp_array = alloc_temp_node_offsets(n.weight);
- if (!tmp_array) {
- malloced = true;
- XMALLOC_N(n.weight, tmp_array);
- }
- this->fill_array_with_subtree_offsets(tmp_array, *subtree);
- this->rebuild_subtree_from_offsets(subtree, tmp_array, n.weight);
- if (malloced) toku_free(tmp_array);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::copyout(uint32_t *const outlen, dmtdata_t *const out, const dmt_node *const n) {
- if (outlen) {
- *outlen = n->value_length;
- }
- if (out) {
- *out = n->value;
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::copyout(uint32_t *const outlen, dmtdata_t **const out, dmt_node *const n) {
- if (outlen) {
- *outlen = n->value_length;
- }
- if (out) {
- *out = &n->value;
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::copyout(uint32_t *const outlen, dmtdata_t *const out, const uint32_t len, const dmtdata_t *const stored_value_ptr) {
- if (outlen) {
- *outlen = len;
- }
- if (out) {
- *out = *stored_value_ptr;
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::copyout(uint32_t *const outlen, dmtdata_t **const out, const uint32_t len, dmtdata_t *const stored_value_ptr) {
- if (outlen) {
- *outlen = len;
- }
- if (out) {
- *out = stored_value_ptr;
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::find_internal_zero_array(const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const {
- paranoid_invariant_notnull(idxp);
- uint32_t min = 0;
- uint32_t limit = this->d.a.num_values;
- uint32_t best_pos = subtree::NODE_NULL;
- uint32_t best_zero = subtree::NODE_NULL;
-
- while (min!=limit) {
- uint32_t mid = (min + limit) / 2;
- int hv = h(this->value_length, *get_array_value(mid), extra);
- if (hv<0) {
- min = mid+1;
- }
- else if (hv>0) {
- best_pos = mid;
- limit = mid;
- }
- else {
- best_zero = mid;
- limit = mid;
- }
- }
- if (best_zero!=subtree::NODE_NULL) {
- //Found a zero
- copyout(value_len, value, this->value_length, get_array_value(best_zero));
- *idxp = best_zero;
- return 0;
- }
- if (best_pos!=subtree::NODE_NULL) *idxp = best_pos;
- else *idxp = this->d.a.num_values;
- return DB_NOTFOUND;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::find_internal_zero(const subtree &subtree, const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const {
- paranoid_invariant_notnull(idxp);
- if (subtree.is_null()) {
- *idxp = 0;
- return DB_NOTFOUND;
- }
- dmt_node &n = get_node(subtree);
- int hv = h(n.value_length, n.value, extra);
- if (hv<0) {
- int r = this->find_internal_zero<dmtcmp_t, h>(n.right, extra, value_len, value, idxp);
- *idxp += this->nweight(n.left)+1;
- return r;
- } else if (hv>0) {
- return this->find_internal_zero<dmtcmp_t, h>(n.left, extra, value_len, value, idxp);
- } else {
- int r = this->find_internal_zero<dmtcmp_t, h>(n.left, extra, value_len, value, idxp);
- if (r==DB_NOTFOUND) {
- *idxp = this->nweight(n.left);
- copyout(value_len, value, &n);
- r = 0;
- }
- return r;
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::find_internal_plus_array(const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const {
- paranoid_invariant_notnull(idxp);
- uint32_t min = 0;
- uint32_t limit = this->d.a.num_values;
- uint32_t best = subtree::NODE_NULL;
-
- while (min != limit) {
- const uint32_t mid = (min + limit) / 2;
- const int hv = h(this->value_length, *get_array_value(mid), extra);
- if (hv > 0) {
- best = mid;
- limit = mid;
- } else {
- min = mid + 1;
- }
- }
- if (best == subtree::NODE_NULL) { return DB_NOTFOUND; }
- copyout(value_len, value, this->value_length, get_array_value(best));
- *idxp = best;
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::find_internal_plus(const subtree &subtree, const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const {
- paranoid_invariant_notnull(idxp);
- if (subtree.is_null()) {
- return DB_NOTFOUND;
- }
- dmt_node & n = get_node(subtree);
- int hv = h(n.value_length, n.value, extra);
- int r;
- if (hv > 0) {
- r = this->find_internal_plus<dmtcmp_t, h>(n.left, extra, value_len, value, idxp);
- if (r == DB_NOTFOUND) {
- *idxp = this->nweight(n.left);
- copyout(value_len, value, &n);
- r = 0;
- }
- } else {
- r = this->find_internal_plus<dmtcmp_t, h>(n.right, extra, value_len, value, idxp);
- if (r == 0) {
- *idxp += this->nweight(n.left) + 1;
- }
- }
- return r;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::find_internal_minus_array(const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const {
- paranoid_invariant_notnull(idxp);
- uint32_t min = 0;
- uint32_t limit = this->d.a.num_values;
- uint32_t best = subtree::NODE_NULL;
-
- while (min != limit) {
- const uint32_t mid = (min + limit) / 2;
- const int hv = h(this->value_length, *get_array_value(mid), extra);
- if (hv < 0) {
- best = mid;
- min = mid + 1;
- } else {
- limit = mid;
- }
- }
- if (best == subtree::NODE_NULL) { return DB_NOTFOUND; }
- copyout(value_len, value, this->value_length, get_array_value(best));
- *idxp = best;
- return 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
-int dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::find_internal_minus(const subtree &subtree, const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const {
- paranoid_invariant_notnull(idxp);
- if (subtree.is_null()) {
- return DB_NOTFOUND;
- }
- dmt_node & n = get_node(subtree);
- int hv = h(n.value_length, n.value, extra);
- if (hv < 0) {
- int r = this->find_internal_minus<dmtcmp_t, h>(n.right, extra, value_len, value, idxp);
- if (r == 0) {
- *idxp += this->nweight(n.left) + 1;
- } else if (r == DB_NOTFOUND) {
- *idxp = this->nweight(n.left);
- copyout(value_len, value, &n);
- r = 0;
- }
- return r;
- } else {
- return this->find_internal_minus<dmtcmp_t, h>(n.left, extra, value_len, value, idxp);
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-uint32_t dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::get_fixed_length(void) const {
- return this->values_same_size ? this->value_length : 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-uint32_t dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::get_fixed_length_alignment_overhead(void) const {
- return this->values_same_size ? align(this->value_length) - this->value_length : 0;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-bool dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::value_length_is_fixed(void) const {
- return this->values_same_size;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::serialize_values(uint32_t expected_unpadded_memory, struct wbuf *wb) const {
- invariant(this->is_array);
- invariant(this->values_same_size);
- const uint8_t pad_bytes = get_fixed_length_alignment_overhead();
- const uint32_t fixed_len = this->value_length;
- const uint32_t fixed_aligned_len = align(this->value_length);
- paranoid_invariant(expected_unpadded_memory == this->d.a.num_values * this->value_length);
- paranoid_invariant(toku_mempool_get_used_size(&this->mp) >=
- expected_unpadded_memory + pad_bytes * this->d.a.num_values);
- if (this->d.a.num_values == 0) {
- // Nothing to serialize
- } else if (pad_bytes == 0) {
- // Basically a memcpy
- wbuf_nocrc_literal_bytes(wb, get_array_value(0), expected_unpadded_memory);
- } else {
- uint8_t* const dest = wbuf_nocrc_reserve_literal_bytes(wb, expected_unpadded_memory);
- const uint8_t* const src = reinterpret_cast<uint8_t*>(get_array_value(0));
- //TODO(leif) maybe look at vectorization here
- for (uint32_t i = 0; i < this->d.a.num_values; i++) {
- memcpy(&dest[i*fixed_len], &src[i*fixed_aligned_len], fixed_len);
- }
- }
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::builder::create(uint32_t _max_values, uint32_t _max_value_bytes) {
- this->max_values = _max_values;
- this->max_value_bytes = _max_value_bytes;
- this->temp.create();
- paranoid_invariant_null(toku_mempool_get_base(&this->temp.mp));
- this->temp_valid = true;
- this->sorted_node_offsets = nullptr;
- // Include enough space for alignment padding
- size_t initial_space = (ALIGNMENT - 1) * _max_values + _max_value_bytes;
-
- toku_mempool_construct(&this->temp.mp, initial_space); // Adds 25%
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::builder::append(const dmtwriter_t &value) {
- paranoid_invariant(this->temp_valid);
- //NOTE: Always use d.a.num_values for size because we have not yet created root.
- if (this->temp.values_same_size && (this->temp.d.a.num_values == 0 || value.get_size() == this->temp.value_length)) {
- temp.insert_at_array_end<false>(value);
- return;
- }
- if (this->temp.is_array) {
- // Convert to tree format (without weights and linkage)
- XMALLOC_N(this->max_values, this->sorted_node_offsets);
-
- // Include enough space for alignment padding
- size_t mem_needed = (ALIGNMENT - 1 + __builtin_offsetof(dmt_node, value)) * max_values + max_value_bytes;
- struct mempool old_mp = this->temp.mp;
-
- const uint32_t num_values = this->temp.d.a.num_values;
- toku_mempool_construct(&this->temp.mp, mem_needed);
-
- // Copy over and get node_offsets
- for (uint32_t i = 0; i < num_values; i++) {
- dmtwriter_t writer(this->temp.value_length, this->temp.get_array_value_internal(&old_mp, i));
- this->sorted_node_offsets[i] = this->temp.node_malloc_and_set_value(writer);
- }
- this->temp.is_array = false;
- this->temp.values_same_size = false;
- this->temp.value_length = 0;
- toku_mempool_destroy(&old_mp);
- }
- paranoid_invariant(!this->temp.is_array);
- this->sorted_node_offsets[this->temp.d.a.num_values++] = this->temp.node_malloc_and_set_value(value);
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-bool dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::builder::value_length_is_fixed(void) {
- paranoid_invariant(this->temp_valid);
- return this->temp.values_same_size;
-}
-
-template<typename dmtdata_t, typename dmtdataout_t, typename dmtwriter_t>
-void dmt<dmtdata_t, dmtdataout_t, dmtwriter_t>::builder::build(dmt<dmtdata_t, dmtdataout_t, dmtwriter_t> *dest) {
- invariant(this->temp_valid);
- //NOTE: Always use d.a.num_values for size because we have not yet created root.
- invariant(this->temp.d.a.num_values <= this->max_values);
- // Memory invariant is taken care of incrementally (during append())
-
- if (!this->temp.is_array) {
- invariant_notnull(this->sorted_node_offsets);
- this->temp.rebuild_subtree_from_offsets(&this->temp.d.t.root, this->sorted_node_offsets, this->temp.d.a.num_values);
- toku_free(this->sorted_node_offsets);
- this->sorted_node_offsets = nullptr;
- }
- paranoid_invariant_null(this->sorted_node_offsets);
-
- const size_t used = toku_mempool_get_used_size(&this->temp.mp);
- const size_t allocated = toku_mempool_get_size(&this->temp.mp);
- // We want to use no more than (about) the actual used space + 25% overhead for mempool growth.
- // When we know the elements are fixed-length, we use the better dmt constructor.
- // In practice, as of Jan 2014, we use the builder in two cases:
- // - When we know the elements are not fixed-length.
- // - During upgrade of a pre version 26 basement node.
- // During upgrade, we will probably wildly overallocate because we don't account for the values that aren't stored in the dmt, so here we want to shrink the mempool.
- // When we know the elements are not fixed-length, we still know how much memory they occupy in total, modulo alignment, so we want to allow for mempool overhead and worst-case alignment overhead, and not shrink the mempool.
- const size_t max_allowed = used + (ALIGNMENT-1) * this->temp.size();
- const size_t max_allowed_with_mempool_overhead = max_allowed + max_allowed / 4;
- //TODO(leif): get footprint calculation correct (under jemalloc) and add some form of footprint constraint
- if (allocated > max_allowed_with_mempool_overhead) {
- // Reallocate smaller mempool to save memory
- invariant_zero(toku_mempool_get_frag_size(&this->temp.mp));
- struct mempool new_mp;
- toku_mempool_construct(&new_mp, used);
- void * newbase = toku_mempool_malloc(&new_mp, used, 1);
- invariant_notnull(newbase);
- memcpy(newbase, toku_mempool_get_base(&this->temp.mp), used);
- toku_mempool_destroy(&this->temp.mp);
- this->temp.mp = new_mp;
- }
-
- *dest = this->temp;
- this->temp_valid = false;
-
-}
-} // namespace toku
diff --git a/storage/tokudb/ft-index/util/dmt.h b/storage/tokudb/ft-index/util/dmt.h
deleted file mode 100644
index 374fa785e42..00000000000
--- a/storage/tokudb/ft-index/util/dmt.h
+++ /dev/null
@@ -1,728 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
-#pragma once
-
-/*
-COPYING CONDITIONS NOTICE:
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation, and provided that the
- following conditions are met:
-
- * Redistributions of source code must retain this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below).
-
- * Redistributions in binary form must reproduce this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below) in the documentation and/or other materials
- provided with the distribution.
-
- 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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-COPYRIGHT NOTICE:
-
- TokuDB, Tokutek Fractal Tree Indexing Library.
- Copyright (C) 2007-2013 Tokutek, Inc.
-
-DISCLAIMER:
-
- 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.
-
-UNIVERSITY PATENT NOTICE:
-
- The technology is licensed by the Massachusetts Institute of
- Technology, Rutgers State University of New Jersey, and the Research
- Foundation of State University of New York at Stony Brook under
- United States of America Serial No. 11/760379 and to the patents
- and/or patent applications resulting from it.
-
-PATENT MARKING NOTICE:
-
- This software is covered by US Patent No. 8,185,551.
-
-PATENT RIGHTS GRANT:
-
- "THIS IMPLEMENTATION" means the copyrightable works distributed by
- Tokutek as part of the Fractal Tree project.
-
- "PATENT CLAIMS" means the claims of patents that are owned or
- licensable by Tokutek, both currently or in the future; and that in
- the absence of this license would be infringed by THIS
- IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
-
- "PATENT CHALLENGE" shall mean a challenge to the validity,
- patentability, enforceability and/or non-infringement of any of the
- PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
-
- Tokutek hereby grants to you, for the term and geographical scope of
- the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
- irrevocable (except as stated in this section) patent license to
- make, have made, use, offer to sell, sell, import, transfer, and
- otherwise run, modify, and propagate the contents of THIS
- IMPLEMENTATION, where such license applies only to the PATENT
- CLAIMS. This grant does not include claims that would be infringed
- only as a consequence of further modifications of THIS
- IMPLEMENTATION. If you or your agent or licensee institute or order
- or agree to the institution of patent litigation against any entity
- (including a cross-claim or counterclaim in a lawsuit) alleging that
- THIS IMPLEMENTATION constitutes direct or contributory patent
- infringement, or inducement of patent infringement, then any rights
- granted to you under this License shall terminate as of the date
- such litigation is filed. If you or your agent or exclusive
- licensee institute or order or agree to the institution of a PATENT
- CHALLENGE, then Tokutek may terminate any rights granted to you
- under this License.
-*/
-
-#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
-#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-
-#include <stdint.h>
-#include <memory.h>
-#include <toku_portability.h>
-#include <toku_race_tools.h>
-#include "growable_array.h"
-#include "../ft/wbuf.h"
-#include <vector>
-
-namespace toku {
-typedef uint32_t node_offset;
-
-
-/**
- * Dynamic Order Maintenance Tree (DMT)
- *
- * Maintains a collection of totally ordered values, where each value has weight 1.
- * A DMT supports variable sized values.
- * The DMT is a mutable datatype.
- *
- * The Abstraction:
- *
- * An DMT is a vector of values, $V$, where $|V|$ is the length of the vector.
- * The vector is numbered from $0$ to $|V|-1$.
- *
- * We can create a new DMT, which is the empty vector.
- *
- * We can insert a new element $x$ into slot $i$, changing $V$ into $V'$ where
- * $|V'|=1+|V|$ and
- *
- * V'_j = V_j if $j<i$
- * x if $j=i$
- * V_{j-1} if $j>i$.
- *
- * We can specify $i$ using a kind of function instead of as an integer.
- * Let $b$ be a function mapping from values to nonzero integers, such that
- * the signum of $b$ is monotically increasing.
- * We can specify $i$ as the minimum integer such that $b(V_i)>0$.
- *
- * We look up a value using its index, or using a Heaviside function.
- * For lookups, we allow $b$ to be zero for some values, and again the signum of $b$ must be monotonically increasing.
- * When lookup up values, we can look up
- * $V_i$ where $i$ is the minimum integer such that $b(V_i)=0$. (With a special return code if no such value exists.)
- * (Rationale: Ordinarily we want $i$ to be unique. But for various reasons we want to allow multiple zeros, and we want the smallest $i$ in that case.)
- * $V_i$ where $i$ is the minimum integer such that $b(V_i)>0$. (Or an indication that no such value exists.)
- * $V_i$ where $i$ is the maximum integer such that $b(V_i)<0$. (Or an indication that no such value exists.)
- *
- * When looking up a value using a Heaviside function, we get the value and its index.
- *
- * Performance:
- * Insertion and deletion should run with $O(\log |V|)$ time and $O(\log |V|)$ calls to the Heaviside function.
- * The memory required is O(|V|).
- *
- * Usage:
- * The dmt is templated by three parameters:
- * - dmtdata_t is what will be stored within the dmt. These could be pointers or real data types (ints, structs).
- * - dmtdataout_t is what will be returned by find and related functions. By default, it is the same as dmtdata_t, but you can set it to (dmtdata_t *).
- * - dmtwriter_t is a class that effectively handles (de)serialization between the value stored in the dmt and outside the dmt.
- * To create an dmt which will store "TXNID"s, for example, it is a good idea to typedef the template:
- * typedef dmt<TXNID, TXNID, txnid_writer_t> txnid_dmt_t;
- * If you are storing structs (or you want to edit what is stored), you may want to be able to get a pointer to the data actually stored in the dmt (see find_zero). To do this, use the second template parameter:
- * typedef dmt<struct foo, struct foo *, foo_writer_t> foo_dmt_t;
- */
-
-namespace dmt_internal {
-
-class subtree {
-private:
- uint32_t m_index;
-public:
- // The maximum mempool size for a dmt is 2**32-2
- static const uint32_t NODE_NULL = UINT32_MAX;
- inline void set_to_null(void) {
- m_index = NODE_NULL;
- }
-
- inline bool is_null(void) const {
- return NODE_NULL == this->get_offset();
- }
-
- inline node_offset get_offset(void) const {
- return m_index;
- }
-
- inline void set_offset(node_offset index) {
- paranoid_invariant(index != NODE_NULL);
- m_index = index;
- }
-} __attribute__((__packed__,__aligned__(4)));
-
-template<typename dmtdata_t>
-class dmt_node_templated {
-public:
- uint32_t weight;
- subtree left;
- subtree right;
- uint32_t value_length;
- dmtdata_t value;
-} __attribute__((__aligned__(4))); //NOTE: we cannot use attribute packed or dmtdata_t will call copy constructors (dmtdata_t might not be packed by default)
-
-}
-
-using namespace toku::dmt_internal;
-
-// Each data type used in a dmt requires a dmt_writer class (allows you to insert/etc with dynamic sized types).
-// A dmt_writer can be thought of a (de)serializer
-// There is no default implementation.
-// A dmtwriter instance handles reading/writing 'dmtdata_t's to/from the dmt.
-// The class must implement the following functions:
-// The size required in a dmt for the dmtdata_t represented:
-// size_t get_size(void) const;
-// Write the dmtdata_t to memory owned by a dmt:
-// void write_to(dmtdata_t *const dest) const;
-// Constructor (others are allowed, but this one is required)
-// dmtwriter(const uint32_t dmtdata_t_len, dmtdata_t *const src)
-
-template<typename dmtdata_t,
- typename dmtdataout_t,
- typename dmtwriter_t
- >
-class dmt {
-private:
- typedef dmt_node_templated<dmtdata_t> dmt_node;
-
-public:
- static const uint8_t ALIGNMENT = 4;
-
- class builder {
- public:
- void append(const dmtwriter_t &value);
-
- // Create a dmt builder to build a dmt that will have at most n_values values and use
- // at most n_value_bytes bytes in the mempool to store values (not counting node or alignment overhead).
- void create(uint32_t n_values, uint32_t n_value_bytes);
-
- bool value_length_is_fixed(void);
-
- // Constructs a dmt that contains everything that was append()ed to this builder.
- // Destroys this builder and frees associated memory.
- void build(dmt<dmtdata_t, dmtdataout_t, dmtwriter_t> *dest);
- private:
- uint32_t max_values;
- uint32_t max_value_bytes;
- node_offset *sorted_node_offsets;
- bool temp_valid;
- dmt<dmtdata_t, dmtdataout_t, dmtwriter_t> temp;
- };
-
- /**
- * Effect: Create an empty DMT.
- * Performance: constant time.
- */
- void create(void);
-
- /**
- * Effect: Create a DMT containing values. The number of values is in numvalues.
- * Each value is of a fixed (at runtime) length.
- * mem contains the values in packed form (no alignment padding)
- * Caller retains ownership of mem.
- * Requires: this has not been created yet
- * Rationale: Normally to insert N values takes O(N lg N) amortized time.
- * If the N values are known in advance, are sorted, and
- * the structure is empty, we can batch insert them much faster.
- */
- __attribute__((nonnull))
- void create_from_sorted_memory_of_fixed_size_elements(
- const void *mem,
- const uint32_t numvalues,
- const uint32_t mem_length,
- const uint32_t fixed_value_length);
-
- /**
- * Effect: Creates a copy of an dmt.
- * Creates this as the clone.
- * Each element is copied directly. If they are pointers, the underlying data is not duplicated.
- * Performance: O(memory) (essentially a memdup)
- * The underlying structures are memcpy'd. Only the values themselves are copied (shallow copy)
- */
- void clone(const dmt &src);
-
- /**
- * Effect: Set the tree to be empty.
- * Note: Will not reallocate or resize any memory.
- * Note: If this dmt had variable sized elements, it will start tracking again (until it gets values of two different sizes)
- * Performance: time=O(1)
- */
- void clear(void);
-
- /**
- * Effect: Destroy an DMT, freeing all its memory.
- * If the values being stored are pointers, their underlying data is not freed.
- * Those values may be freed before or after calling ::destroy()
- * Rationale: Returns no values since free() cannot fail.
- * Rationale: Does not free the underlying pointers to reduce complexity/maintain abstraction layer
- * Performance: time=O(1)
- */
- void destroy(void);
-
- /**
- * Effect: return |this| (number of values stored in this dmt).
- * Performance: time=O(1)
- */
- uint32_t size(void) const;
-
- /**
- * Effect: Serialize all values contained in this dmt into a packed form (no alignment padding).
- * We serialized to wb. expected_unpadded_memory is the size of memory reserved in the wbuf
- * for serialization. (We assert that serialization requires exactly the expected amount)
- * Requires:
- * ::prepare_for_serialize() has been called and no non-const functions have been called since.
- * This dmt has fixed-length values and is in array form.
- * Performance:
- * O(memory)
- */
- void serialize_values(uint32_t expected_unpadded_memory, struct wbuf *wb) const;
-
- /**
- * Effect: Insert value into the DMT.
- * If there is some i such that $h(V_i, v)=0$ then returns DB_KEYEXIST.
- * Otherwise, let i be the minimum value such that $h(V_i, v)>0$.
- * If no such i exists, then let i be |V|
- * Then this has the same effect as
- * insert_at(tree, value, i);
- * If idx!=NULL then i is stored in *idx
- * Requires: The signum of h must be monotonically increasing.
- * Returns:
- * 0 success
- * DB_KEYEXIST the key is present (h was equal to zero for some value)
- * On nonzero return, dmt is unchanged.
- * Performance: time=O(\log N) amortized.
- * Rationale: Some future implementation may be O(\log N) worst-case time, but O(\log N) amortized is good enough for now.
- */
- template<typename dmtcmp_t, int (*h)(const uint32_t size, const dmtdata_t &, const dmtcmp_t &)>
- int insert(const dmtwriter_t &value, const dmtcmp_t &v, uint32_t *const idx);
-
- /**
- * Effect: Increases indexes of all items at slot >= idx by 1.
- * Insert value into the position at idx.
- * Returns:
- * 0 success
- * EINVAL if idx > this->size()
- * On error, dmt is unchanged.
- * Performance: time=O(\log N) amortized time.
- * Rationale: Some future implementation may be O(\log N) worst-case time, but O(\log N) amortized is good enough for now.
- */
- int insert_at(const dmtwriter_t &value, const uint32_t idx);
-
- /**
- * Effect: Delete the item in slot idx.
- * Decreases indexes of all items at slot > idx by 1.
- * Returns
- * 0 success
- * EINVAL if idx>=this->size()
- * On error, dmt is unchanged.
- * Rationale: To delete an item, first find its index using find or find_zero, then delete it.
- * Performance: time=O(\log N) amortized.
- */
- int delete_at(const uint32_t idx);
-
- /**
- * Effect: Iterate over the values of the dmt, from left to right, calling f on each value.
- * The first argument passed to f is a ref-to-const of the value stored in the dmt.
- * The second argument passed to f is the index of the value.
- * The third argument passed to f is iterate_extra.
- * The indices run from 0 (inclusive) to this->size() (exclusive).
- * Requires: f != NULL
- * Returns:
- * If f ever returns nonzero, then the iteration stops, and the value returned by f is returned by iterate.
- * If f always returns zero, then iterate returns 0.
- * Requires: Don't modify the dmt while running. (E.g., f may not insert or delete values from the dmt.)
- * Performance: time=O(i+\log N) where i is the number of times f is called, and N is the number of elements in the dmt.
- * Rationale: Although the functional iterator requires defining another function (as opposed to C++ style iterator), it is much easier to read.
- * Rationale: We may at some point use functors, but for now this is a smaller change from the old DMT.
- */
- template<typename iterate_extra_t,
- int (*f)(const uint32_t, const dmtdata_t &, const uint32_t, iterate_extra_t *const)>
- int iterate(iterate_extra_t *const iterate_extra) const;
-
- /**
- * Effect: Iterate over the values of the dmt, from left to right, calling f on each value.
- * The first argument passed to f is a ref-to-const of the value stored in the dmt.
- * The second argument passed to f is the index of the value.
- * The third argument passed to f is iterate_extra.
- * The indices run from 0 (inclusive) to this->size() (exclusive).
- * We will iterate only over [left,right)
- *
- * Requires: left <= right
- * Requires: f != NULL
- * Returns:
- * EINVAL if right > this->size()
- * If f ever returns nonzero, then the iteration stops, and the value returned by f is returned by iterate_on_range.
- * If f always returns zero, then iterate_on_range returns 0.
- * Requires: Don't modify the dmt while running. (E.g., f may not insert or delete values from the dmt.)
- * Performance: time=O(i+\log N) where i is the number of times f is called, and N is the number of elements in the dmt.
- * Rational: Although the functional iterator requires defining another function (as opposed to C++ style iterator), it is much easier to read.
- */
- template<typename iterate_extra_t,
- int (*f)(const uint32_t, const dmtdata_t &, const uint32_t, iterate_extra_t *const)>
- int iterate_on_range(const uint32_t left, const uint32_t right, iterate_extra_t *const iterate_extra) const;
-
- // Attempt to verify this dmt is well formed. (Crashes/asserts/aborts if not well formed)
- void verify(void) const;
-
- /**
- * Effect: Iterate over the values of the dmt, from left to right, calling f on each value.
- * The first argument passed to f is a pointer to the value stored in the dmt.
- * The second argument passed to f is the index of the value.
- * The third argument passed to f is iterate_extra.
- * The indices run from 0 (inclusive) to this->size() (exclusive).
- * Requires: same as for iterate()
- * Returns: same as for iterate()
- * Performance: same as for iterate()
- * Rationale: In general, most iterators should use iterate() since they should not modify the data stored in the dmt. This function is for iterators which need to modify values (for example, free_items).
- * Rationale: We assume if you are transforming the data in place, you want to do it to everything at once, so there is not yet an iterate_on_range_ptr (but there could be).
- */
- template<typename iterate_extra_t,
- int (*f)(const uint32_t, dmtdata_t *, const uint32_t, iterate_extra_t *const)>
- void iterate_ptr(iterate_extra_t *const iterate_extra);
-
- /**
- * Effect: Set *value=V_idx
- * Returns
- * 0 success
- * EINVAL if index>=toku_dmt_size(dmt)
- * On nonzero return, *value is unchanged
- * Performance: time=O(\log N)
- */
- int fetch(const uint32_t idx, uint32_t *const value_size, dmtdataout_t *const value) const;
-
- /**
- * Effect: Find the smallest i such that h(V_i, extra)>=0
- * If there is such an i and h(V_i,extra)==0 then set *idxp=i, set *value = V_i, and return 0.
- * If there is such an i and h(V_i,extra)>0 then set *idxp=i and return DB_NOTFOUND.
- * If there is no such i then set *idx=this->size() and return DB_NOTFOUND.
- * Note: value is of type dmtdataout_t, which may be of type (dmtdata_t) or (dmtdata_t *) but is fixed by the instantiation.
- * If it is the value type, then the value is copied out (even if the value type is a pointer to something else)
- * If it is the pointer type, then *value is set to a pointer to the data within the dmt.
- * This is determined by the type of the dmt as initially declared.
- * If the dmt is declared as dmt<foo_t>, then foo_t's will be stored and foo_t's will be returned by find and related functions.
- * If the dmt is declared as dmt<foo_t, foo_t *>, then foo_t's will be stored, and pointers to the stored items will be returned by find and related functions.
- * Rationale:
- * Structs too small for malloc should be stored directly in the dmt.
- * These structs may need to be edited as they exist inside the dmt, so we need a way to get a pointer within the dmt.
- * Using separate functions for returning pointers and values increases code duplication and reduces type-checking.
- * That also reduces the ability of the creator of a data structure to give advice to its future users.
- * Slight overloading in this case seemed to provide a better API and better type checking.
- */
- template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
- int find_zero(const dmtcmp_t &extra, uint32_t *const value_size, dmtdataout_t *const value, uint32_t *const idxp) const;
-
- /**
- * Effect:
- * If direction >0 then find the smallest i such that h(V_i,extra)>0.
- * If direction <0 then find the largest i such that h(V_i,extra)<0.
- * (Direction may not be equal to zero.)
- * If value!=NULL then store V_i in *value
- * If idxp!=NULL then store i in *idxp.
- * Requires: The signum of h is monotically increasing.
- * Returns
- * 0 success
- * DB_NOTFOUND no such value is found.
- * On nonzero return, *value and *idxp are unchanged
- * Performance: time=O(\log N)
- * Rationale:
- * Here's how to use the find function to find various things
- * Cases for find:
- * find first value: ( h(v)=+1, direction=+1 )
- * find last value ( h(v)=-1, direction=-1 )
- * find first X ( h(v)=(v< x) ? -1 : 1 direction=+1 )
- * find last X ( h(v)=(v<=x) ? -1 : 1 direction=-1 )
- * find X or successor to X ( same as find first X. )
- *
- * Rationale: To help understand heaviside functions and behavor of find:
- * There are 7 kinds of heaviside functions.
- * The signus of the h must be monotonically increasing.
- * Given a function of the following form, A is the element
- * returned for direction>0, B is the element returned
- * for direction<0, C is the element returned for
- * direction==0 (see find_zero) (with a return of 0), and D is the element
- * returned for direction==0 (see find_zero) with a return of DB_NOTFOUND.
- * If any of A, B, or C are not found, then asking for the
- * associated direction will return DB_NOTFOUND.
- * See find_zero for more information.
- *
- * Let the following represent the signus of the heaviside function.
- *
- * -...-
- * A
- * D
- *
- * +...+
- * B
- * D
- *
- * 0...0
- * C
- *
- * -...-0...0
- * AC
- *
- * 0...0+...+
- * C B
- *
- * -...-+...+
- * AB
- * D
- *
- * -...-0...0+...+
- * AC B
- */
- template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
- int find(const dmtcmp_t &extra, int direction, uint32_t *const value_size, dmtdataout_t *const value, uint32_t *const idxp) const;
-
- /**
- * Effect: Return the size (in bytes) of the dmt, as it resides in main memory.
- * If the data stored are pointers, don't include the size of what they all point to.
- * //TODO(leif or yoni): (maybe rename and) return memory footprint instead of allocated size
- */
- size_t memory_size(void);
-
- // Returns whether all values in the dmt are known to be the same size.
- // Note:
- // There are no false positives, but false negatives are allowed.
- // A false negative can happen if this dmt had 2 (or more) different size values,
- // and then enough were deleted so that all the remaining ones are the same size.
- // Once that happens, this dmt will never again return true for this function unless/until
- // ::clear() is called
- bool value_length_is_fixed(void) const;
-
-
- // If this dmt is empty, return value is undefined.
- // else if value_length_is_fixed() then it returns the fixed length.
- // else returns 0
- uint32_t get_fixed_length(void) const;
-
- // Preprocesses the dmt so that serialization can happen quickly.
- // After this call, serialize_values() can be called but no other mutator function can be called in between.
- void prepare_for_serialize(void);
-
-private:
- // Do a bit of verification that subtree and nodes act like packed c structs and do not introduce unnecessary padding for alignment.
- ENSURE_POD(subtree);
- static_assert(ALIGNMENT > 0, "ALIGNMENT <= 0");
- static_assert((ALIGNMENT & (ALIGNMENT - 1)) == 0, "ALIGNMENT not a power of 2");
- static_assert(sizeof(dmt_node) - sizeof(dmtdata_t) == __builtin_offsetof(dmt_node, value), "value is not last field in node");
- static_assert(4 * sizeof(uint32_t) == __builtin_offsetof(dmt_node, value), "dmt_node is padded");
- static_assert(__builtin_offsetof(dmt_node, value) % ALIGNMENT == 0, "dmt_node requires padding for alignment");
- ENSURE_POD(dmt_node);
-
- struct dmt_array {
- uint32_t num_values;
- };
-
- struct dmt_tree {
- subtree root;
- };
-
- /*
- Relationship between values_same_size, d.a.num_values, value_length, is_array:
- In an empty dmt:
- is_array is true
- value_same_size is true
- value_length is undefined
- d.a.num_values is 0
- In a non-empty array dmt:
- is_array is true
- values_same_size is true
- value_length is defined
- d.a.num_values > 0
- In a non-empty tree dmt:
- is_array = false
- value_same_size is true iff all values have been the same size since the last time the dmt turned into a tree.
- value_length is defined iff values_same_size is true
- d.a.num_values is undefined (the memory is used for the tree)
- Note that in tree form, the dmt keeps track of if all values are the same size until the first time they are not.
- 'values_same_size' will not become true again (even if we change all values to be the same size)
- until/unless the dmt becomes empty, at which point it becomes an array again.
- */
- bool values_same_size;
- uint32_t value_length; // valid iff values_same_size is true.
- struct mempool mp;
- bool is_array;
- union {
- struct dmt_array a;
- struct dmt_tree t;
- } d;
-
- // Returns pad bytes per element (for alignment) or 0 if not fixed length.
- uint32_t get_fixed_length_alignment_overhead(void) const;
-
- void verify_internal(const subtree &subtree, std::vector<bool> *touched) const;
-
- // Retrieves the node for a given subtree.
- // Requires: !subtree.is_null()
- dmt_node & get_node(const subtree &subtree) const;
-
- // Retrieves the node at a given offset in the mempool.
- dmt_node & get_node(const node_offset offset) const;
-
- // Returns the weight of a subtree rooted at st.
- // if st.is_null(), returns 0
- // Perf: O(1)
- uint32_t nweight(const subtree &st) const;
-
- // Allocates space for a node (in the mempool) and uses the dmtwriter to write the value into the node
- node_offset node_malloc_and_set_value(const dmtwriter_t &value);
-
- // Uses the dmtwriter to write a value into node n
- void node_set_value(dmt_node *n, const dmtwriter_t &value);
-
- // (mempool-)free the memory for a node
- void node_free(const subtree &st);
-
- // Effect: Resizes the mempool (holding the array) if necessary to hold one more item of length: this->value_length
- // Requires:
- // This dmt is in array form (and thus this->values_same_length)
- void maybe_resize_array_for_insert(void);
-
- // Effect: Converts a dmt from array form to tree form.
- // Perf: O(n)
- // Note: This does not clear the 'this->values_same_size' bit
- void convert_to_tree(void);
-
- // Effect: Resizes the mempool holding a tree if necessary. If value==nullptr then it may shrink if overallocated,
- // otherwise resize only happens if there is not enough free space for an insert of value
- void maybe_resize_tree(const dmtwriter_t * value);
-
- // Returns true if the tree rooted at st would need rebalance after adding
- // leftmod to the left subtree and rightmod to the right subtree
- bool will_need_rebalance(const subtree &st, const int leftmod, const int rightmod) const;
-
- __attribute__((nonnull))
- void insert_internal(subtree *const subtreep, const dmtwriter_t &value, const uint32_t idx, subtree **const rebalance_subtree);
-
- template<bool with_resize>
- int insert_at_array_end(const dmtwriter_t& value_in);
-
- dmtdata_t * alloc_array_value_end(void);
-
- dmtdata_t * get_array_value(const uint32_t idx) const;
-
- dmtdata_t * get_array_value_internal(const struct mempool *mempool, const uint32_t idx) const;
-
- void convert_from_array_to_tree(void);
-
- void convert_from_tree_to_array(void);
-
- __attribute__((nonnull(2,5)))
- void delete_internal(subtree *const subtreep, const uint32_t idx, subtree *const subtree_replace, subtree **const rebalance_subtree);
-
- template<typename iterate_extra_t,
- int (*f)(const uint32_t, const dmtdata_t &, const uint32_t, iterate_extra_t *const)>
- int iterate_internal_array(const uint32_t left, const uint32_t right,
- iterate_extra_t *const iterate_extra) const;
-
- template<typename iterate_extra_t,
- int (*f)(const uint32_t, dmtdata_t *, const uint32_t, iterate_extra_t *const)>
- void iterate_ptr_internal(const uint32_t left, const uint32_t right,
- const subtree &subtree, const uint32_t idx,
- iterate_extra_t *const iterate_extra);
-
- template<typename iterate_extra_t,
- int (*f)(const uint32_t, dmtdata_t *, const uint32_t, iterate_extra_t *const)>
- void iterate_ptr_internal_array(const uint32_t left, const uint32_t right,
- iterate_extra_t *const iterate_extra);
-
- template<typename iterate_extra_t,
- int (*f)(const uint32_t, const dmtdata_t &, const uint32_t, iterate_extra_t *const)>
- int iterate_internal(const uint32_t left, const uint32_t right,
- const subtree &subtree, const uint32_t idx,
- iterate_extra_t *const iterate_extra) const;
-
- void fetch_internal_array(const uint32_t i, uint32_t *const value_len, dmtdataout_t *const value) const;
-
- void fetch_internal(const subtree &subtree, const uint32_t i, uint32_t *const value_len, dmtdataout_t *const value) const;
-
- __attribute__((nonnull))
- void fill_array_with_subtree_offsets(node_offset *const array, const subtree &subtree) const;
-
- __attribute__((nonnull))
- void rebuild_subtree_from_offsets(subtree *const subtree, const node_offset *const offsets, const uint32_t numvalues);
-
- __attribute__((nonnull))
- void rebalance(subtree *const subtree);
-
- __attribute__((nonnull))
- static void copyout(uint32_t *const outlen, dmtdata_t *const out, const dmt_node *const n);
-
- __attribute__((nonnull))
- static void copyout(uint32_t *const outlen, dmtdata_t **const out, dmt_node *const n);
-
- __attribute__((nonnull))
- static void copyout(uint32_t *const outlen, dmtdata_t *const out, const uint32_t len, const dmtdata_t *const stored_value_ptr);
-
- __attribute__((nonnull))
- static void copyout(uint32_t *const outlen, dmtdata_t **const out, const uint32_t len, dmtdata_t *const stored_value_ptr);
-
- template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
- int find_internal_zero_array(const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const;
-
- template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
- int find_internal_zero(const subtree &subtree, const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const;
-
- template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
- int find_internal_plus_array(const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const;
-
- template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
- int find_internal_plus(const subtree &subtree, const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const;
-
- template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
- int find_internal_minus_array(const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const;
-
- template<typename dmtcmp_t,
- int (*h)(const uint32_t, const dmtdata_t &, const dmtcmp_t &)>
- int find_internal_minus(const subtree &subtree, const dmtcmp_t &extra, uint32_t *const value_len, dmtdataout_t *const value, uint32_t *const idxp) const;
-
- // Allocate memory for an array: node_offset[num_idx] from pre-allocated contiguous free space in the mempool.
- // If there is not enough space, returns nullptr.
- node_offset* alloc_temp_node_offsets(uint32_t num_idxs);
-
- // Returns the aligned size of x.
- // If x % ALIGNMENT == 0, returns x
- // o.w. returns x + (ALIGNMENT - (x % ALIGNMENT))
- uint32_t align(const uint32_t x) const;
-};
-
-} // namespace toku
-
-// include the implementation here
-#include "dmt.cc"
-
diff --git a/storage/tokudb/ft-index/util/doubly_linked_list.h b/storage/tokudb/ft-index/util/doubly_linked_list.h
index fb125d243be..57c290e1e27 100644
--- a/storage/tokudb/ft-index/util/doubly_linked_list.h
+++ b/storage/tokudb/ft-index/util/doubly_linked_list.h
@@ -117,7 +117,7 @@ PATENT RIGHTS GRANT:
//******************************************************************************
#include <stdbool.h>
-#include <portability/toku_assert.h>
+#include <toku_include/toku_assert.h>
namespace toku {
diff --git a/storage/tokudb/ft-index/util/fmutex.h b/storage/tokudb/ft-index/util/fmutex.h
deleted file mode 100644
index 075925dd03f..00000000000
--- a/storage/tokudb/ft-index/util/fmutex.h
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef FMUTEX_H
-#define FMUTEX_H
-
-// fair mutex
-struct fmutex {
- pthread_mutex_t mutex;
- int mutex_held;
- int num_want_mutex;
- struct queue_item *wait_head;
- struct queue_item *wait_tail;
-};
-
-// item on the queue
-struct queue_item {
- pthread_cond_t *cond;
- struct queue_item *next;
-};
-
-static void enq_item(struct fmutex *fm, struct queue_item *const item) {
- assert(item->next == NULL);
- if (fm->wait_tail != NULL) {
- fm->wait_tail->next = item;
- } else {
- assert(fm->wait_head == NULL);
- fm->wait_head = item;
- }
- fm->wait_tail = item;
-}
-
-static pthread_cond_t *deq_item(struct fmutex *fm) {
- assert(fm->wait_head != NULL);
- assert(fm->wait_tail != NULL);
- struct queue_item *item = fm->wait_head;
- fm->wait_head = fm->wait_head->next;
- if (fm->wait_tail == item) {
- fm->wait_tail = NULL;
- }
- return item->cond;
-}
-
-void fmutex_create(struct fmutex *fm) {
- pthread_mutex_init(&fm->mutex, NULL);
- fm->mutex_held = 0;
- fm->num_want_mutex = 0;
- fm->wait_head = NULL;
- fm->wait_tail = NULL;
-}
-
-void fmutex_destroy(struct fmutex *fm) {
- pthread_mutex_destroy(&fm->mutex);
-}
-
-// Prerequisite: Holds m_mutex.
-void fmutex_lock(struct fmutex *fm) {
- pthread_mutex_lock(&fm->mutex);
-
- if (fm->mutex_held == 0 || fm->num_want_mutex == 0) {
- // No one holds the lock. Grant the write lock.
- fm->mutex_held = 1;
- return;
- }
-
- pthread_cond_t cond;
- pthread_cond_init(&cond, NULL);
- struct queue_item item = { .cond = &cond, .next = NULL };
- enq_item(fm, &item);
-
- // Wait for our turn.
- ++fm->num_want_mutex;
- pthread_cond_wait(&cond, &fm->mutex);
- pthread_cond_destroy(&cond);
-
- // Now it's our turn.
- assert(fm->num_want_mutex > 0);
- assert(fm->mutex_held == 0);
-
- // Not waiting anymore; grab the lock.
- --fm->num_want_mutex;
- fm->mutex_held = 1;
-
- pthread_mutex_unlock();
-}
-
-void fmutex_mutex_unlock(struct fmutex *fm) {
- pthread_mutex_lock();
-
- fm->mutex_held = 0;
- if (fm->wait_head == NULL) {
- assert(fm->num_want_mutex == 0);
- return;
- }
- assert(fm->num_want_mutex > 0);
-
- // Grant lock to the next waiter
- pthread_cond_t *cond = deq_item(fm);
- pthread_cond_signal(cond);
-
- pthread_mutex_unlock();
-}
-
-int fmutex_users(struct fmutex *fm) const {
- return fm->mutex_held + fm->num_want_mutex;
-}
-
-int fmutex_blocked_users(struct fmutex *fm) const {
- return fm->num_want_mutex;
-}
-
-#endif // FMUTEX_H
diff --git a/storage/tokudb/ft-index/util/kibbutz.cc b/storage/tokudb/ft-index/util/kibbutz.cc
index 8e69471e9ab..a84a6f4827f 100644
--- a/storage/tokudb/ft-index/util/kibbutz.cc
+++ b/storage/tokudb/ft-index/util/kibbutz.cc
@@ -89,13 +89,11 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2011-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
+#include "kibbutz.h"
+#include "toku_config.h"
#include <memory.h>
-
-#include <portability/toku_config.h>
#include <toku_pthread.h>
-#include "kibbutz.h"
-
// A Kibbutz is a collection of workers and some work to do.
struct todo {
void (*f)(void *extra);
diff --git a/storage/tokudb/ft-index/util/mempool.cc b/storage/tokudb/ft-index/util/mempool.cc
index 6f3e2c013db..8a37fd41b44 100644
--- a/storage/tokudb/ft-index/util/mempool.cc
+++ b/storage/tokudb/ft-index/util/mempool.cc
@@ -130,34 +130,18 @@ void toku_mempool_init(struct mempool *mp, void *base, size_t free_offset, size_
*/
void toku_mempool_construct(struct mempool *mp, size_t data_size) {
if (data_size) {
- // add 25% slack
- size_t mp_size = data_size + (data_size / 4);
- mp->base = toku_xmalloc_aligned(64, mp_size);
- mp->size = mp_size;
- mp->free_offset = 0;
- mp->frag_size = 0;
+ size_t mpsize = data_size + (data_size/4); // allow 1/4 room for expansion (would be wasted if read-only)
+ mp->base = toku_xmalloc(mpsize); // allocate buffer for mempool
+ mp->size = mpsize;
+ mp->free_offset = 0; // address of first available memory for new data
+ mp->frag_size = 0; // all allocated space is now in use
}
else {
toku_mempool_zero(mp);
+ // fprintf(stderr, "Empty mempool created (base constructor)\n");
}
}
-void toku_mempool_reset(struct mempool *mp) {
- mp->free_offset = 0;
- mp->frag_size = 0;
-}
-
-void toku_mempool_realloc_larger(struct mempool *mp, size_t data_size) {
- invariant(data_size >= mp->free_offset);
-
- size_t mpsize = data_size + (data_size/4); // allow 1/4 room for expansion (would be wasted if read-only)
- void* newmem = toku_xmalloc_aligned(64, mpsize); // allocate new buffer for mempool
- memcpy(newmem, mp->base, mp->free_offset); // Copy old info
- toku_free(mp->base);
- mp->base = newmem;
- mp->size = mpsize;
-}
-
void toku_mempool_destroy(struct mempool *mp) {
// printf("mempool_destroy %p %p %lu %lu\n", mp, mp->base, mp->size, mp->frag_size);
@@ -166,44 +150,27 @@ void toku_mempool_destroy(struct mempool *mp) {
toku_mempool_zero(mp);
}
-void *toku_mempool_get_base(const struct mempool *mp) {
+void *toku_mempool_get_base(struct mempool *mp) {
return mp->base;
}
-void *toku_mempool_get_pointer_from_base_and_offset(const struct mempool *mp, size_t offset) {
- return reinterpret_cast<void*>(reinterpret_cast<char*>(mp->base) + offset);
-}
-
-size_t toku_mempool_get_offset_from_pointer_and_base(const struct mempool *mp, const void* p) {
- paranoid_invariant(p >= mp->base);
- return reinterpret_cast<const char*>(p) - reinterpret_cast<const char*>(mp->base);
-}
-
-size_t toku_mempool_get_size(const struct mempool *mp) {
+size_t toku_mempool_get_size(struct mempool *mp) {
return mp->size;
}
-size_t toku_mempool_get_frag_size(const struct mempool *mp) {
+size_t toku_mempool_get_frag_size(struct mempool *mp) {
return mp->frag_size;
}
-size_t toku_mempool_get_used_size(const struct mempool *mp) {
+size_t toku_mempool_get_used_space(struct mempool *mp) {
return mp->free_offset - mp->frag_size;
}
-void* toku_mempool_get_next_free_ptr(const struct mempool *mp) {
- return toku_mempool_get_pointer_from_base_and_offset(mp, mp->free_offset);
-}
-
-size_t toku_mempool_get_offset_limit(const struct mempool *mp) {
- return mp->free_offset;
-}
-
-size_t toku_mempool_get_free_size(const struct mempool *mp) {
+size_t toku_mempool_get_free_space(struct mempool *mp) {
return mp->size - mp->free_offset;
}
-size_t toku_mempool_get_allocated_size(const struct mempool *mp) {
+size_t toku_mempool_get_allocated_space(struct mempool *mp) {
return mp->free_offset;
}
@@ -244,10 +211,10 @@ size_t toku_mempool_footprint(struct mempool *mp) {
return rval;
}
-void toku_mempool_clone(const struct mempool* orig_mp, struct mempool* new_mp) {
+void toku_mempool_clone(struct mempool* orig_mp, struct mempool* new_mp) {
new_mp->frag_size = orig_mp->frag_size;
new_mp->free_offset = orig_mp->free_offset;
new_mp->size = orig_mp->free_offset; // only make the cloned mempool store what is needed
- new_mp->base = toku_xmalloc_aligned(64, new_mp->size);
+ new_mp->base = toku_xmalloc(new_mp->size);
memcpy(new_mp->base, orig_mp->base, new_mp->size);
}
diff --git a/storage/tokudb/ft-index/util/mempool.h b/storage/tokudb/ft-index/util/mempool.h
index c8be5e13297..fa59d7a63ac 100644
--- a/storage/tokudb/ft-index/util/mempool.h
+++ b/storage/tokudb/ft-index/util/mempool.h
@@ -123,46 +123,26 @@ void toku_mempool_init(struct mempool *mp, void *base, size_t free_offset, size_
*/
void toku_mempool_construct(struct mempool *mp, size_t data_size);
-/* treat mempool as if it has just been created; ignore any frag and start allocating from beginning again.
- */
-void toku_mempool_reset(struct mempool *mp);
-
-/* reallocate memory for construct mempool
- */
-void toku_mempool_realloc_larger(struct mempool *mp, size_t data_size);
-
/* destroy the memory pool */
void toku_mempool_destroy(struct mempool *mp);
/* get the base address of the memory pool */
-void *toku_mempool_get_base(const struct mempool *mp);
-
-/* get the a pointer that is offset bytes in front of base of the memory pool */
-void *toku_mempool_get_pointer_from_base_and_offset(const struct mempool *mp, size_t offset);
-
-/* get the offset from base of a pointer */
-size_t toku_mempool_get_offset_from_pointer_and_base(const struct mempool *mp, const void* p);
-
-/* get the a pointer of the first free byte (if any) */
-void* toku_mempool_get_next_free_ptr(const struct mempool *mp);
-
-/* get the limit of valid offsets. (anything later was not allocated) */
-size_t toku_mempool_get_offset_limit(const struct mempool *mp);
+void *toku_mempool_get_base(struct mempool *mp);
/* get the size of the memory pool */
-size_t toku_mempool_get_size(const struct mempool *mp);
+size_t toku_mempool_get_size(struct mempool *mp);
/* get the amount of fragmented (wasted) space in the memory pool */
-size_t toku_mempool_get_frag_size(const struct mempool *mp);
+size_t toku_mempool_get_frag_size(struct mempool *mp);
/* get the amount of space that is holding useful data */
-size_t toku_mempool_get_used_size(const struct mempool *mp);
+size_t toku_mempool_get_used_space(struct mempool *mp);
/* get the amount of space that is available for new data */
-size_t toku_mempool_get_free_size(const struct mempool *mp);
+size_t toku_mempool_get_free_space(struct mempool *mp);
/* get the amount of space that has been allocated for use (wasted or not) */
-size_t toku_mempool_get_allocated_size(const struct mempool *mp);
+size_t toku_mempool_get_allocated_space(struct mempool *mp);
/* allocate a chunk of memory from the memory pool suitably aligned */
void *toku_mempool_malloc(struct mempool *mp, size_t size, int alignment);
@@ -180,8 +160,6 @@ static inline int toku_mempool_inrange(struct mempool *mp, void *vp, size_t size
/* get memory footprint */
size_t toku_mempool_footprint(struct mempool *mp);
-void toku_mempool_clone(const struct mempool* orig_mp, struct mempool* new_mp);
-
-
+void toku_mempool_clone(struct mempool* orig_mp, struct mempool* new_mp);
#endif // UTIL_MEMPOOL_H
diff --git a/storage/tokudb/ft-index/util/omt.cc b/storage/tokudb/ft-index/util/omt.cc
index 709c7eab4c3..8bff7ef7099 100644
--- a/storage/tokudb/ft-index/util/omt.cc
+++ b/storage/tokudb/ft-index/util/omt.cc
@@ -92,7 +92,7 @@ PATENT RIGHTS GRANT:
#include <string.h>
#include <db.h>
-#include <portability/memory.h>
+#include <toku_include/memory.h>
namespace toku {
@@ -207,9 +207,6 @@ void omt<omtdata_t, omtdataout_t, supports_marks>::clone(const omt &src) {
src.fill_array_with_subtree_values(&this->d.a.values[0], src.d.t.root);
}
this->d.a.num_values = src.size();
- if (supports_marks) {
- this->convert_to_tree();
- }
}
template<typename omtdata_t, typename omtdataout_t, bool supports_marks>
diff --git a/storage/tokudb/ft-index/util/scoped_malloc.cc b/storage/tokudb/ft-index/util/scoped_malloc.cc
index ed8a493233e..7fc847c3af6 100644
--- a/storage/tokudb/ft-index/util/scoped_malloc.cc
+++ b/storage/tokudb/ft-index/util/scoped_malloc.cc
@@ -89,7 +89,7 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
-#include <portability/memory.h>
+#include <toku_include/memory.h>
#include <util/scoped_malloc.h>
diff --git a/storage/tokudb/ft-index/util/tests/omt-test.cc b/storage/tokudb/ft-index/util/tests/omt-test.cc
deleted file mode 100644
index 9eeb7970a47..00000000000
--- a/storage/tokudb/ft-index/util/tests/omt-test.cc
+++ /dev/null
@@ -1,950 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
-#ident "$Id$"
-/*
-COPYING CONDITIONS NOTICE:
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as
- published by the Free Software Foundation, and provided that the
- following conditions are met:
-
- * Redistributions of source code must retain this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below).
-
- * Redistributions in binary form must reproduce this COPYING
- CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
- DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
- PATENT MARKING NOTICE (below), and the PATENT RIGHTS
- GRANT (below) in the documentation and/or other materials
- provided with the distribution.
-
- 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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-COPYRIGHT NOTICE:
-
- TokuDB, Tokutek Fractal Tree Indexing Library.
- Copyright (C) 2007-2013 Tokutek, Inc.
-
-DISCLAIMER:
-
- 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.
-
-UNIVERSITY PATENT NOTICE:
-
- The technology is licensed by the Massachusetts Institute of
- Technology, Rutgers State University of New Jersey, and the Research
- Foundation of State University of New York at Stony Brook under
- United States of America Serial No. 11/760379 and to the patents
- and/or patent applications resulting from it.
-
-PATENT MARKING NOTICE:
-
- This software is covered by US Patent No. 8,185,551.
- This software is covered by US Patent No. 8,489,638.
-
-PATENT RIGHTS GRANT:
-
- "THIS IMPLEMENTATION" means the copyrightable works distributed by
- Tokutek as part of the Fractal Tree project.
-
- "PATENT CLAIMS" means the claims of patents that are owned or
- licensable by Tokutek, both currently or in the future; and that in
- the absence of this license would be infringed by THIS
- IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
-
- "PATENT CHALLENGE" shall mean a challenge to the validity,
- patentability, enforceability and/or non-infringement of any of the
- PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
-
- Tokutek hereby grants to you, for the term and geographical scope of
- the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
- irrevocable (except as stated in this section) patent license to
- make, have made, use, offer to sell, sell, import, transfer, and
- otherwise run, modify, and propagate the contents of THIS
- IMPLEMENTATION, where such license applies only to the PATENT
- CLAIMS. This grant does not include claims that would be infringed
- only as a consequence of further modifications of THIS
- IMPLEMENTATION. If you or your agent or licensee institute or order
- or agree to the institution of patent litigation against any entity
- (including a cross-claim or counterclaim in a lawsuit) alleging that
- THIS IMPLEMENTATION constitutes direct or contributory patent
- infringement, or inducement of patent infringement, then any rights
- granted to you under this License shall terminate as of the date
- such litigation is filed. If you or your agent or exclusive
- licensee institute or order or agree to the institution of a PATENT
- CHALLENGE, then Tokutek may terminate any rights granted to you
- under this License.
-*/
-
-#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
-
-#include "test.h"
-
-#include <util/omt.h>
-
-static void
-parse_args (int argc, const char *argv[]) {
- const char *argv0=argv[0];
- while (argc>1) {
- int resultcode=0;
- if (strcmp(argv[1], "-v")==0) {
- verbose++;
- } else if (strcmp(argv[1], "-q")==0) {
- verbose = 0;
- } else if (strcmp(argv[1], "-h")==0) {
- do_usage:
- fprintf(stderr, "Usage:\n%s [-v|-h]\n", argv0);
- exit(resultcode);
- } else {
- resultcode=1;
- goto do_usage;
- }
- argc--;
- argv++;
- }
-}
-/* End ".h like" stuff. */
-
-struct value {
- uint32_t number;
-};
-#define V(x) ((struct value *)(x))
-
-enum rand_type {
- TEST_RANDOM,
- TEST_SORTED,
- TEST_IDENTITY
-};
-enum close_when_done {
- CLOSE_WHEN_DONE,
- KEEP_WHEN_DONE
-};
-enum create_type {
- STEAL_ARRAY,
- BATCH_INSERT,
- INSERT_AT,
- INSERT_AT_ALMOST_RANDOM,
-};
-
-/* Globals */
-typedef void *OMTVALUE;
-toku::omt<OMTVALUE> *global_omt;
-OMTVALUE* global_values = NULL;
-struct value* global_nums = NULL;
-uint32_t global_length;
-
-static void
-cleanup_globals (void) {
- assert(global_values);
- toku_free(global_values);
- global_values = NULL;
- assert(global_nums);
- toku_free(global_nums);
- global_nums = NULL;
-}
-
-/* Some test wrappers */
-struct functor {
- int (*f)(OMTVALUE, uint32_t, void *);
- void *v;
-};
-int call_functor(const OMTVALUE &v, uint32_t idx, functor *const ftor);
-int call_functor(const OMTVALUE &v, uint32_t idx, functor *const ftor) {
- return ftor->f(const_cast<OMTVALUE>(v), idx, ftor->v);
-}
-static int omt_iterate(toku::omt<void *> *omt, int (*f)(OMTVALUE, uint32_t, void*), void*v) {
- struct functor ftor = { .f = f, .v = v };
- return omt->iterate<functor, call_functor>(&ftor);
-}
-
-struct heftor {
- int (*h)(OMTVALUE, void *v);
- void *v;
-};
-int call_heftor(const OMTVALUE &v, const heftor &htor);
-int call_heftor(const OMTVALUE &v, const heftor &htor) {
- return htor.h(const_cast<OMTVALUE>(v), htor.v);
-}
-static int omt_insert(toku::omt<void *> *omt, OMTVALUE value, int(*h)(OMTVALUE, void*v), void *v, uint32_t *index) {
- struct heftor htor = { .h = h, .v = v };
- return omt->insert<heftor, call_heftor>(value, htor, index);
-}
-static int omt_find_zero(toku::omt<void *> *V, int (*h)(OMTVALUE, void*extra), void*extra, OMTVALUE *value, uint32_t *index) {
- struct heftor htor = { .h = h, .v = extra };
- return V->find_zero<heftor, call_heftor>(htor, value, index);
-}
-static int omt_find(toku::omt<void *> *V, int (*h)(OMTVALUE, void*extra), void*extra, int direction, OMTVALUE *value, uint32_t *index) {
- struct heftor htor = { .h = h, .v = extra };
- return V->find<heftor, call_heftor>(htor, direction, value, index);
-}
-static int omt_split_at(toku::omt<void *> *omt, toku::omt<void *> **newomtp, uint32_t index) {
- toku::omt<void *> *XMALLOC(newomt);
- int r = omt->split_at(newomt, index);
- if (r != 0) {
- toku_free(newomt);
- } else {
- *newomtp = newomt;
- }
- return r;
-}
-static int omt_merge(toku::omt<void *> *leftomt, toku::omt<void *> *rightomt, toku::omt<void *> **newomtp) {
- toku::omt<void *> *XMALLOC(newomt);
- newomt->merge(leftomt, rightomt);
- toku_free(leftomt);
- toku_free(rightomt);
- *newomtp = newomt;
- return 0;
-}
-
-const unsigned int random_seed = 0xFEADACBA;
-
-static void
-init_init_values (unsigned int seed, uint32_t num_elements) {
- srandom(seed);
-
- cleanup_globals();
-
- XMALLOC_N(num_elements, global_values);
- XMALLOC_N(num_elements, global_nums);
- global_length = num_elements;
-}
-
-static void
-init_identity_values (unsigned int seed, uint32_t num_elements) {
- uint32_t i;
-
- init_init_values(seed, num_elements);
-
- for (i = 0; i < global_length; i++) {
- global_nums[i].number = i;
- global_values[i] = (OMTVALUE)&global_nums[i];
- }
-}
-
-static void
-init_distinct_sorted_values (unsigned int seed, uint32_t num_elements) {
- uint32_t i;
-
- init_init_values(seed, num_elements);
-
- uint32_t number = 0;
-
- for (i = 0; i < global_length; i++) {
- number += (uint32_t)(random() % 32) + 1;
- global_nums[i].number = number;
- global_values[i] = (OMTVALUE)&global_nums[i];
- }
-}
-
-static void
-init_distinct_random_values (unsigned int seed, uint32_t num_elements) {
- init_distinct_sorted_values(seed, num_elements);
-
- uint32_t i;
- uint32_t choice;
- uint32_t choices;
- struct value temp;
- for (i = 0; i < global_length - 1; i++) {
- choices = global_length - i;
- choice = random() % choices;
- if (choice != i) {
- temp = global_nums[i];
- global_nums[i] = global_nums[choice];
- global_nums[choice] = temp;
- }
- }
-}
-
-static void
-init_globals (void) {
- XMALLOC_N(1, global_values);
- XMALLOC_N(1, global_nums);
- global_length = 1;
-}
-
-static void
-test_close (enum close_when_done do_close) {
- if (do_close == KEEP_WHEN_DONE) {
- return;
- }
- assert(do_close == CLOSE_WHEN_DONE);
- global_omt->destroy();
- toku_free(global_omt);
-}
-
-static void
-test_create (enum close_when_done do_close) {
- XMALLOC(global_omt);
- global_omt->create();
- test_close(do_close);
-}
-
-static void
-test_create_size (enum close_when_done do_close) {
- test_create(KEEP_WHEN_DONE);
- assert(global_omt->size() == 0);
- test_close(do_close);
-}
-
-static void
-test_create_insert_at_almost_random (enum close_when_done do_close) {
- uint32_t i;
- int r;
- uint32_t size = 0;
-
- test_create(KEEP_WHEN_DONE);
- r = global_omt->insert_at(global_values[0], global_omt->size()+1);
- CKERR2(r, EINVAL);
- r = global_omt->insert_at(global_values[0], global_omt->size()+2);
- CKERR2(r, EINVAL);
- for (i = 0; i < global_length/2; i++) {
- assert(size==global_omt->size());
- r = global_omt->insert_at(global_values[i], i);
- CKERR(r);
- assert(++size==global_omt->size());
- r = global_omt->insert_at(global_values[global_length-1-i], i+1);
- CKERR(r);
- assert(++size==global_omt->size());
- }
- r = global_omt->insert_at(global_values[0], global_omt->size()+1);
- CKERR2(r, EINVAL);
- r = global_omt->insert_at(global_values[0], global_omt->size()+2);
- CKERR2(r, EINVAL);
- assert(size==global_omt->size());
- test_close(do_close);
-}
-
-static void
-test_create_insert_at_sequential (enum close_when_done do_close) {
- uint32_t i;
- int r;
- uint32_t size = 0;
-
- test_create(KEEP_WHEN_DONE);
- r = global_omt->insert_at(global_values[0], global_omt->size()+1);
- CKERR2(r, EINVAL);
- r = global_omt->insert_at(global_values[0], global_omt->size()+2);
- CKERR2(r, EINVAL);
- for (i = 0; i < global_length; i++) {
- assert(size==global_omt->size());
- r = global_omt->insert_at(global_values[i], i);
- CKERR(r);
- assert(++size==global_omt->size());
- }
- r = global_omt->insert_at(global_values[0], global_omt->size()+1);
- CKERR2(r, EINVAL);
- r = global_omt->insert_at(global_values[0], global_omt->size()+2);
- CKERR2(r, EINVAL);
- assert(size==global_omt->size());
- test_close(do_close);
-}
-
-static void
-test_create_from_sorted_array (enum create_type create_choice, enum close_when_done do_close) {
- global_omt = NULL;
-
- if (create_choice == BATCH_INSERT) {
- XMALLOC(global_omt);
- global_omt->create_from_sorted_array(global_values, global_length);
- }
- else if (create_choice == STEAL_ARRAY) {
- XMALLOC(global_omt);
- OMTVALUE* XMALLOC_N(global_length, values_copy);
- memcpy(values_copy, global_values, global_length*sizeof(*global_values));
- global_omt->create_steal_sorted_array(&values_copy, global_length, global_length);
- assert(values_copy==NULL);
- }
- else if (create_choice == INSERT_AT) {
- test_create_insert_at_sequential(KEEP_WHEN_DONE);
- }
- else if (create_choice == INSERT_AT_ALMOST_RANDOM) {
- test_create_insert_at_almost_random(KEEP_WHEN_DONE);
- }
- else {
- assert(false);
- }
-
- assert(global_omt!=NULL);
- test_close(do_close);
-}
-
-static void
-test_create_from_sorted_array_size (enum create_type create_choice, enum close_when_done do_close) {
- test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
- assert(global_omt->size()==global_length);
- test_close(do_close);
-}
-
-static void
-test_fetch_verify (toku::omt<void *> *omtree, OMTVALUE* val, uint32_t len ) {
- uint32_t i;
- int r;
- OMTVALUE v = (OMTVALUE)&i;
- OMTVALUE oldv = v;
-
- assert(len == omtree->size());
- for (i = 0; i < len; i++) {
- assert(oldv!=val[i]);
- v = NULL;
- r = omtree->fetch(i, &v);
- CKERR(r);
- assert(v != NULL);
- assert(v != oldv);
- assert(v == val[i]);
- assert(V(v)->number == V(val[i])->number);
- v = oldv;
- }
-
- for (i = len; i < len*2; i++) {
- v = oldv;
- r = omtree->fetch(i, &v);
- CKERR2(r, EINVAL);
- assert(v == oldv);
- }
-
-}
-
-static void
-test_create_fetch_verify (enum create_type create_choice, enum close_when_done do_close) {
- test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
- test_fetch_verify(global_omt, global_values, global_length);
- test_close(do_close);
-}
-
-static int iterate_helper_error_return = 1;
-
-static int
-iterate_helper (OMTVALUE v, uint32_t idx, void* extra) {
- if (extra == NULL) return iterate_helper_error_return;
- OMTVALUE* vals = (OMTVALUE *)extra;
- assert(v != NULL);
- assert(v == vals[idx]);
- assert(V(v)->number == V(vals[idx])->number);
- return 0;
-}
-
-static void
-test_iterate_verify (toku::omt<void *> *omtree, OMTVALUE* vals, uint32_t len) {
- int r;
- iterate_helper_error_return = 0;
- r = omt_iterate(omtree, iterate_helper, (void*)vals);
- CKERR(r);
- iterate_helper_error_return = 0xFEEDABBA;
- r = omt_iterate(omtree, iterate_helper, NULL);
- if (!len) {
- CKERR2(r, 0);
- }
- else {
- CKERR2(r, iterate_helper_error_return);
- }
-}
-
-static void
-test_create_iterate_verify (enum create_type create_choice, enum close_when_done do_close) {
- test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
- test_iterate_verify(global_omt, global_values, global_length);
- test_close(do_close);
-}
-
-
-static void
-permute_array (uint32_t* arr, uint32_t len) {
- //
- // create a permutation of 0...size-1
- //
- uint32_t i = 0;
- for (i = 0; i < len; i++) {
- arr[i] = i;
- }
- for (i = 0; i < len - 1; i++) {
- uint32_t choices = len - i;
- uint32_t choice = random() % choices;
- if (choice != i) {
- uint32_t temp = arr[i];
- arr[i] = arr[choice];
- arr[choice] = temp;
- }
- }
-}
-
-static void
-test_create_set_at (enum create_type create_choice, enum close_when_done do_close) {
- uint32_t i = 0;
-
- struct value* old_nums = NULL;
- XMALLOC_N(global_length, old_nums);
-
- uint32_t* perm = NULL;
- XMALLOC_N(global_length, perm);
-
- OMTVALUE* old_values = NULL;
- XMALLOC_N(global_length, old_values);
-
- permute_array(perm, global_length);
-
- //
- // These are going to be the new global_values
- //
- for (i = 0; i < global_length; i++) {
- old_nums[i] = global_nums[i];
- old_values[i] = &old_nums[i];
- global_values[i] = &old_nums[i];
- }
- test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
- int r;
- r = global_omt->set_at(global_values[0], global_length);
- CKERR2(r,EINVAL);
- r = global_omt->set_at(global_values[0], global_length+1);
- CKERR2(r,EINVAL);
- for (i = 0; i < global_length; i++) {
- uint32_t choice = perm[i];
- global_values[choice] = &global_nums[choice];
- global_nums[choice].number = (uint32_t)random();
- r = global_omt->set_at(global_values[choice], choice);
- CKERR(r);
- test_iterate_verify(global_omt, global_values, global_length);
- test_fetch_verify(global_omt, global_values, global_length);
- }
- r = global_omt->set_at(global_values[0], global_length);
- CKERR2(r,EINVAL);
- r = global_omt->set_at(global_values[0], global_length+1);
- CKERR2(r,EINVAL);
-
- toku_free(perm);
- toku_free(old_values);
- toku_free(old_nums);
-
- test_close(do_close);
-}
-
-static int
-insert_helper (OMTVALUE value, void* extra_insert) {
- OMTVALUE to_insert = (OMTVALUE)extra_insert;
- assert(to_insert);
-
- if (V(value)->number < V(to_insert)->number) return -1;
- if (V(value)->number > V(to_insert)->number) return +1;
- return 0;
-}
-
-static void
-test_create_insert (enum close_when_done do_close) {
- uint32_t i = 0;
-
- uint32_t* perm = NULL;
- XMALLOC_N(global_length, perm);
-
- permute_array(perm, global_length);
-
- test_create(KEEP_WHEN_DONE);
- int r;
- uint32_t size = global_length;
- global_length = 0;
- while (global_length < size) {
- uint32_t choice = perm[global_length];
- OMTVALUE to_insert = &global_nums[choice];
- uint32_t idx = UINT32_MAX;
-
- assert(global_length==global_omt->size());
- r = omt_insert(global_omt, to_insert, insert_helper, to_insert, &idx);
- CKERR(r);
- assert(idx <= global_length);
- if (idx > 0) {
- assert(V(to_insert)->number > V(global_values[idx-1])->number);
- }
- if (idx < global_length) {
- assert(V(to_insert)->number < V(global_values[idx])->number);
- }
- global_length++;
- assert(global_length==global_omt->size());
- /* Make room */
- for (i = global_length-1; i > idx; i--) {
- global_values[i] = global_values[i-1];
- }
- global_values[idx] = to_insert;
- test_fetch_verify(global_omt, global_values, global_length);
- test_iterate_verify(global_omt, global_values, global_length);
-
- idx = UINT32_MAX;
- r = omt_insert(global_omt, to_insert, insert_helper, to_insert, &idx);
- CKERR2(r, DB_KEYEXIST);
- assert(idx < global_length);
- assert(V(global_values[idx])->number == V(to_insert)->number);
- assert(global_length==global_omt->size());
-
- test_iterate_verify(global_omt, global_values, global_length);
- test_fetch_verify(global_omt, global_values, global_length);
- }
-
- toku_free(perm);
-
- test_close(do_close);
-}
-
-static void
-test_create_delete_at (enum create_type create_choice, enum close_when_done do_close) {
- uint32_t i = 0;
- int r = ENOSYS;
- test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
-
- assert(global_length == global_omt->size());
- r = global_omt->delete_at(global_length);
- CKERR2(r,EINVAL);
- assert(global_length == global_omt->size());
- r = global_omt->delete_at(global_length+1);
- CKERR2(r,EINVAL);
- while (global_length > 0) {
- assert(global_length == global_omt->size());
- uint32_t index_to_delete = random()%global_length;
- r = global_omt->delete_at(index_to_delete);
- CKERR(r);
- for (i = index_to_delete+1; i < global_length; i++) {
- global_values[i-1] = global_values[i];
- }
- global_length--;
- test_fetch_verify(global_omt, global_values, global_length);
- test_iterate_verify(global_omt, global_values, global_length);
- }
- assert(global_length == 0);
- assert(global_length == global_omt->size());
- r = global_omt->delete_at(global_length);
- CKERR2(r, EINVAL);
- assert(global_length == global_omt->size());
- r = global_omt->delete_at(global_length+1);
- CKERR2(r, EINVAL);
- test_close(do_close);
-}
-
-static void
-test_split_merge (enum create_type create_choice, enum close_when_done do_close) {
- int r = ENOSYS;
- uint32_t i = 0;
- toku::omt<void *> *left_split = NULL;
- toku::omt<void *> *right_split = NULL;
- test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
-
- for (i = 0; i <= global_length; i++) {
- r = omt_split_at(global_omt, &right_split, global_length+1);
- CKERR2(r,EINVAL);
- r = omt_split_at(global_omt, &right_split, global_length+2);
- CKERR2(r,EINVAL);
-
- //
- // test successful split
- //
- r = omt_split_at(global_omt, &right_split, i);
- CKERR(r);
- left_split = global_omt;
- global_omt = NULL;
- assert(left_split->size() == i);
- assert(right_split->size() == global_length - i);
- test_fetch_verify(left_split, global_values, i);
- test_iterate_verify(left_split, global_values, i);
- test_fetch_verify(right_split, &global_values[i], global_length - i);
- test_iterate_verify(right_split, &global_values[i], global_length - i);
- //
- // verify that new global_omt's cannot do bad splits
- //
- r = omt_split_at(left_split, &global_omt, i+1);
- CKERR2(r,EINVAL);
- assert(left_split->size() == i);
- assert(right_split->size() == global_length - i);
- r = omt_split_at(left_split, &global_omt, i+2);
- CKERR2(r,EINVAL);
- assert(left_split->size() == i);
- assert(right_split->size() == global_length - i);
- r = omt_split_at(right_split, &global_omt, global_length - i + 1);
- CKERR2(r,EINVAL);
- assert(left_split->size() == i);
- assert(right_split->size() == global_length - i);
- r = omt_split_at(right_split, &global_omt, global_length - i + 1);
- CKERR2(r,EINVAL);
- assert(left_split->size() == i);
- assert(right_split->size() == global_length - i);
-
- //
- // test merge
- //
- r = omt_merge(left_split,right_split,&global_omt);
- CKERR(r);
- left_split = NULL;
- right_split = NULL;
- assert(global_omt->size() == global_length);
- test_fetch_verify(global_omt, global_values, global_length);
- test_iterate_verify(global_omt, global_values, global_length);
- }
- test_close(do_close);
-}
-
-
-static void
-init_values (enum rand_type rand_choice) {
- const uint32_t test_size = 100;
- if (rand_choice == TEST_RANDOM) {
- init_distinct_random_values(random_seed, test_size);
- }
- else if (rand_choice == TEST_SORTED) {
- init_distinct_sorted_values(random_seed, test_size);
- }
- else if (rand_choice == TEST_IDENTITY) {
- init_identity_values( random_seed, test_size);
- }
- else assert(false);
-}
-
-static void
-test_create_array (enum create_type create_choice, enum rand_type rand_choice) {
- /* ********************************************************************** */
- init_values(rand_choice);
- test_create_from_sorted_array( create_choice, CLOSE_WHEN_DONE);
- test_create_from_sorted_array_size(create_choice, CLOSE_WHEN_DONE);
- /* ********************************************************************** */
- init_values(rand_choice);
- test_create_fetch_verify( create_choice, CLOSE_WHEN_DONE);
- /* ********************************************************************** */
- init_values(rand_choice);
- test_create_iterate_verify( create_choice, CLOSE_WHEN_DONE);
- /* ********************************************************************** */
- init_values(rand_choice);
- test_create_set_at( create_choice, CLOSE_WHEN_DONE);
- /* ********************************************************************** */
- init_values(rand_choice);
- test_create_delete_at( create_choice, CLOSE_WHEN_DONE);
- /* ********************************************************************** */
- init_values(rand_choice);
- test_create_insert( CLOSE_WHEN_DONE);
- /* ********************************************************************** */
- init_values(rand_choice);
- test_split_merge( create_choice, CLOSE_WHEN_DONE);
-}
-
-typedef struct {
- uint32_t first_zero;
- uint32_t first_pos;
-} h_extra;
-
-
-static int
-test_heaviside (OMTVALUE v_omt, void* x) {
- OMTVALUE v = (OMTVALUE) v_omt;
- h_extra* extra = (h_extra*)x;
- assert(v && x);
- assert(extra->first_zero <= extra->first_pos);
-
- uint32_t value = V(v)->number;
- if (value < extra->first_zero) return -1;
- if (value < extra->first_pos) return 0;
- return 1;
-}
-
-static void
-heavy_extra (h_extra* extra, uint32_t first_zero, uint32_t first_pos) {
- extra->first_zero = first_zero;
- extra->first_pos = first_pos;
-}
-
-static void
-test_find_dir (int dir, void* extra, int (*h)(OMTVALUE, void*),
- int r_expect, bool idx_will_change, uint32_t idx_expect,
- uint32_t number_expect, bool UU(cursor_valid)) {
- uint32_t idx = UINT32_MAX;
- uint32_t old_idx = idx;
- OMTVALUE omt_val;
- int r;
-
- omt_val = NULL;
-
- /* Verify we can pass NULL value. */
- omt_val = NULL;
- idx = old_idx;
- if (dir == 0) {
- r = omt_find_zero(global_omt, h, extra, NULL, &idx);
- }
- else {
- r = omt_find( global_omt, h, extra, dir, NULL, &idx);
- }
- CKERR2(r, r_expect);
- if (idx_will_change) {
- assert(idx == idx_expect);
- }
- else {
- assert(idx == old_idx);
- }
- assert(omt_val == NULL);
-
- /* Verify we can pass NULL idx. */
- omt_val = NULL;
- idx = old_idx;
- if (dir == 0) {
- r = omt_find_zero(global_omt, h, extra, &omt_val, 0);
- }
- else {
- r = omt_find( global_omt, h, extra, dir, &omt_val, 0);
- }
- CKERR2(r, r_expect);
- assert(idx == old_idx);
- if (r == DB_NOTFOUND) {
- assert(omt_val == NULL);
- }
- else {
- assert(V(omt_val)->number == number_expect);
- }
-
- /* Verify we can pass NULL both. */
- omt_val = NULL;
- idx = old_idx;
- if (dir == 0) {
- r = omt_find_zero(global_omt, h, extra, NULL, 0);
- }
- else {
- r = omt_find( global_omt, h, extra, dir, NULL, 0);
- }
- CKERR2(r, r_expect);
- assert(idx == old_idx);
- assert(omt_val == NULL);
-}
-
-static void
-test_find (enum create_type create_choice, enum close_when_done do_close) {
- h_extra extra;
- init_identity_values(random_seed, 100);
- test_create_from_sorted_array(create_choice, KEEP_WHEN_DONE);
-
-/*
- -...-
- A
-*/
- heavy_extra(&extra, global_length, global_length);
- test_find_dir(-1, &extra, test_heaviside, 0, true, global_length-1, global_length-1, true);
- test_find_dir(+1, &extra, test_heaviside, DB_NOTFOUND, false, 0, 0, false);
- test_find_dir(0, &extra, test_heaviside, DB_NOTFOUND, true, global_length, global_length, false);
-
-
-/*
- +...+
- B
-*/
- heavy_extra(&extra, 0, 0);
- test_find_dir(-1, &extra, test_heaviside, DB_NOTFOUND, false, 0, 0, false);
- test_find_dir(+1, &extra, test_heaviside, 0, true, 0, 0, true);
- test_find_dir(0, &extra, test_heaviside, DB_NOTFOUND, true, 0, 0, false);
-
-/*
- 0...0
- C
-*/
- heavy_extra(&extra, 0, global_length);
- test_find_dir(-1, &extra, test_heaviside, DB_NOTFOUND, false, 0, 0, false);
- test_find_dir(+1, &extra, test_heaviside, DB_NOTFOUND, false, 0, 0, false);
- test_find_dir(0, &extra, test_heaviside, 0, true, 0, 0, true);
-
-/*
- -...-0...0
- AC
-*/
- heavy_extra(&extra, global_length/2, global_length);
- test_find_dir(-1, &extra, test_heaviside, 0, true, global_length/2-1, global_length/2-1, true);
- test_find_dir(+1, &extra, test_heaviside, DB_NOTFOUND, false, 0, 0, false);
- test_find_dir(0, &extra, test_heaviside, 0, true, global_length/2, global_length/2, true);
-
-/*
- 0...0+...+
- C B
-*/
- heavy_extra(&extra, 0, global_length/2);
- test_find_dir(-1, &extra, test_heaviside, DB_NOTFOUND, false, 0, 0, false);
- test_find_dir(+1, &extra, test_heaviside, 0, true, global_length/2, global_length/2, true);
- test_find_dir(0, &extra, test_heaviside, 0, true, 0, 0, true);
-
-/*
- -...-+...+
- AB
-*/
- heavy_extra(&extra, global_length/2, global_length/2);
- test_find_dir(-1, &extra, test_heaviside, 0, true, global_length/2-1, global_length/2-1, true);
- test_find_dir(+1, &extra, test_heaviside, 0, true, global_length/2, global_length/2, true);
- test_find_dir(0, &extra, test_heaviside, DB_NOTFOUND, true, global_length/2, global_length/2, false);
-
-/*
- -...-0...0+...+
- AC B
-*/
- heavy_extra(&extra, global_length/3, 2*global_length/3);
- test_find_dir(-1, &extra, test_heaviside, 0, true, global_length/3-1, global_length/3-1, true);
- test_find_dir(+1, &extra, test_heaviside, 0, true, 2*global_length/3, 2*global_length/3, true);
- test_find_dir(0, &extra, test_heaviside, 0, true, global_length/3, global_length/3, true);
-
- /* Cleanup */
- test_close(do_close);
-}
-
-static void
-runtests_create_choice (enum create_type create_choice) {
- test_create_array(create_choice, TEST_SORTED);
- test_create_array(create_choice, TEST_RANDOM);
- test_create_array(create_choice, TEST_IDENTITY);
- test_find( create_choice, CLOSE_WHEN_DONE);
-}
-
-static void
-test_clone(uint32_t nelts)
-// Test that each clone operation gives the right data back. If nelts is
-// zero, also tests that you still get a valid omt back and that the way
-// to deallocate it still works.
-{
- toku::omt<void *> *src = NULL, *dest = NULL;
- int r;
-
- XMALLOC(src);
- src->create();
- for (long i = 0; i < nelts; ++i) {
- r = src->insert_at((OMTVALUE) i, i);
- assert_zero(r);
- }
-
- XMALLOC(dest);
- dest->clone(*src);
- assert(dest != NULL);
- assert(dest->size() == nelts);
- for (long i = 0; i < nelts; ++i) {
- OMTVALUE v;
- long l;
- r = dest->fetch(i, &v);
- assert_zero(r);
- l = (long) v;
- assert(l == i);
- }
- dest->destroy();
- toku_free(dest);
- src->destroy();
- toku_free(src);
-}
-
-int
-test_main(int argc, const char *argv[]) {
- parse_args(argc, argv);
- init_globals();
- test_create( CLOSE_WHEN_DONE);
- test_create_size( CLOSE_WHEN_DONE);
- runtests_create_choice(BATCH_INSERT);
- runtests_create_choice(STEAL_ARRAY);
- runtests_create_choice(INSERT_AT);
- runtests_create_choice(INSERT_AT_ALMOST_RANDOM);
- test_clone(0);
- test_clone(1);
- test_clone(1000);
- test_clone(10000);
- cleanup_globals();
- return 0;
-}
-
diff --git a/storage/tokudb/ft-index/utils/CMakeLists.txt b/storage/tokudb/ft-index/utils/CMakeLists.txt
new file mode 100644
index 00000000000..06d964f389f
--- /dev/null
+++ b/storage/tokudb/ft-index/utils/CMakeLists.txt
@@ -0,0 +1,21 @@
+set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE DONT_DEPRECATE_ERRNO)
+
+set(utils tokudb_gen tokudb_load tokudb_dump)
+foreach(util ${utils})
+ add_executable(${util} ${util}.cc)
+ set_target_properties(${util} PROPERTIES
+ COMPILE_DEFINITIONS "IS_TDB=1;USE_TDB=1;TDB_IS_STATIC=1")
+ target_link_libraries(${util} ${LIBTOKUDB}_static ft_static z lzma ${LIBTOKUPORTABILITY}_static ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_SYSTEM_LIBS})
+
+ add_space_separated_property(TARGET ${util} COMPILE_FLAGS -fvisibility=hidden)
+
+ if(BDB_FOUND)
+ add_executable(${util}.bdb ${util}.cc)
+ set_property(TARGET ${util}.bdb APPEND PROPERTY
+ COMPILE_DEFINITIONS "IS_TDB=0;USE_BDB=1;TOKU_ALLOW_DEPRECATED")
+ set_target_properties(${util}.bdb PROPERTIES
+ INCLUDE_DIRECTORIES "${BDB_INCLUDE_DIR};${CMAKE_CURRENT_BINARY_DIR}/../toku_include;${CMAKE_CURRENT_SOURCE_DIR}/../toku_include;${CMAKE_CURRENT_SOURCE_DIR}/../portability;${CMAKE_CURRENT_SOURCE_DIR}/..")
+ target_link_libraries(${util}.bdb ${LIBTOKUPORTABILITY} ${BDB_LIBRARIES})
+ add_space_separated_property(TARGET ${util}.bdb COMPILE_FLAGS -fvisibility=hidden)
+ endif()
+endforeach(util)
diff --git a/storage/tokudb/ft-index/tools/parseTraceFiles.py b/storage/tokudb/ft-index/utils/parseTraceFiles.py
index f53ef620111..f53ef620111 100755
--- a/storage/tokudb/ft-index/tools/parseTraceFiles.py
+++ b/storage/tokudb/ft-index/utils/parseTraceFiles.py
diff --git a/storage/tokudb/ft-index/tools/pmprof b/storage/tokudb/ft-index/utils/pmprof
index de0a7e3ce55..de0a7e3ce55 100755
--- a/storage/tokudb/ft-index/tools/pmprof
+++ b/storage/tokudb/ft-index/utils/pmprof
diff --git a/storage/tokudb/ft-index/tools/tokudb_common.h b/storage/tokudb/ft-index/utils/tokudb_common.h
index aeda0ae5027..aeda0ae5027 100644
--- a/storage/tokudb/ft-index/tools/tokudb_common.h
+++ b/storage/tokudb/ft-index/utils/tokudb_common.h
diff --git a/storage/tokudb/ft-index/tools/tokudb_common_funcs.h b/storage/tokudb/ft-index/utils/tokudb_common_funcs.h
index c2737025acc..51f3733b00e 100644
--- a/storage/tokudb/ft-index/tools/tokudb_common_funcs.h
+++ b/storage/tokudb/ft-index/utils/tokudb_common_funcs.h
@@ -326,11 +326,25 @@ resend_signals(void) {
}
#include <memory.h>
+#if IS_TDB && TOKU_WINDOWS
+#include <src/ydb.h>
+#endif
static int test_main (int argc, char *const argv[]);
int
main(int argc, char *const argv[]) {
int r;
+#if IS_TDB && TOKU_WINDOWS
+ toku_ydb_init();
+#endif
+#if !IS_TDB && DB_VERSION_MINOR==4 && DB_VERSION_MINOR == 7
+ r = db_env_set_func_malloc(toku_malloc); assert(r==0);
+ r = db_env_set_func_free(toku_free); assert(r==0);
+ r = db_env_set_func_realloc(toku_realloc); assert(r==0);
+#endif
r = test_main(argc, argv);
+#if IS_TDB && TOKU_WINDOWS
+ toku_ydb_destroy();
+#endif
return r;
}
diff --git a/storage/tokudb/ft-index/tools/tokudb_dump.cc b/storage/tokudb/ft-index/utils/tokudb_dump.cc
index 1020afb70e0..c560093be31 100644
--- a/storage/tokudb/ft-index/tools/tokudb_dump.cc
+++ b/storage/tokudb/ft-index/utils/tokudb_dump.cc
@@ -368,6 +368,15 @@ int create_init_env()
//However, do we need to use DB_INIT_LOG to join a logging environment?
//REMOVE_BITS(flags, DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
SET_BITS(flags, DB_CREATE | DB_PRIVATE);
+#if defined(USE_BDB) && USE_BDB==1
+ {
+ int r;
+ r = dbenv->set_lk_max_objects(dbenv, 100000);
+ assert(r==0);
+ r = dbenv->set_lk_max_locks(dbenv, 100000);
+ assert(r==0);
+ }
+#endif
retval = dbenv->open(dbenv, g.homedir, flags, 0);
if (retval) {
diff --git a/storage/tokudb/ft-index/tools/tokudb_gen.cc b/storage/tokudb/ft-index/utils/tokudb_gen.cc
index c23567116a8..492c0ac6186 100644
--- a/storage/tokudb/ft-index/tools/tokudb_gen.cc
+++ b/storage/tokudb/ft-index/utils/tokudb_gen.cc
@@ -98,7 +98,9 @@ PATENT RIGHTS GRANT:
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
+#if IS_TDB
#include <src/ydb.h>
+#endif
#include "tokudb_common.h"
@@ -255,6 +257,11 @@ static int test_main (int argc, char *const argv[]) {
}
sort_delimiter[0] = (char)temp;
sort_delimiter[1] = '\0';
+#if TOKU_WINDOWS
+ if (!strcmp(sort_delimiter, "\n")) {
+ strcpy(sort_delimiter, "\r\n");
+ }
+#endif
break;
}
case ('V'): {
diff --git a/storage/tokudb/ft-index/tools/tokudb_load.cc b/storage/tokudb/ft-index/utils/tokudb_load.cc
index 2072b2f7f8d..2072b2f7f8d 100644
--- a/storage/tokudb/ft-index/tools/tokudb_load.cc
+++ b/storage/tokudb/ft-index/utils/tokudb_load.cc
diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc
index 5314f86e8ad..c310e33cfe3 100644
--- a/storage/tokudb/ha_tokudb.cc
+++ b/storage/tokudb/ha_tokudb.cc
@@ -471,7 +471,7 @@ typedef struct index_read_info {
static int ai_poll_fun(void *extra, float progress) {
LOADER_CONTEXT context = (LOADER_CONTEXT)extra;
- if (context->thd->killed) {
+ if (thd_killed(context->thd)) {
sprintf(context->write_status_msg, "The process has been killed, aborting add index.");
return ER_ABORTING_CONNECTION;
}
@@ -486,7 +486,7 @@ static int ai_poll_fun(void *extra, float progress) {
static int loader_poll_fun(void *extra, float progress) {
LOADER_CONTEXT context = (LOADER_CONTEXT)extra;
- if (context->thd->killed) {
+ if (thd_killed(context->thd)) {
sprintf(context->write_status_msg, "The process has been killed, aborting bulk load.");
return ER_ABORTING_CONNECTION;
}
@@ -1638,8 +1638,7 @@ int ha_tokudb::initialize_share(
#if WITH_PARTITION_STORAGE_ENGINE
// verify frm data for non-partitioned tables
- if (TOKU_PARTITION_WRITE_FRM_DATA ||
- IF_PARTITIONING(table->part_info, NULL) == NULL) {
+ if (TOKU_PARTITION_WRITE_FRM_DATA || table->part_info == NULL) {
error = verify_frm_data(table->s->path.str, txn);
if (error)
goto exit;
@@ -3331,7 +3330,7 @@ int ha_tokudb::end_bulk_insert(bool abort) {
ai_metadata_update_required = false;
loader_error = 0;
if (loader) {
- if (!abort_loader && !thd->killed) {
+ if (!abort_loader && !thd_killed(thd)) {
DBUG_EXECUTE_IF("tokudb_end_bulk_insert_sleep", {
const char *orig_proc_info = tokudb_thd_get_proc_info(thd);
thd_proc_info(thd, "DBUG sleep");
@@ -3341,7 +3340,7 @@ int ha_tokudb::end_bulk_insert(bool abort) {
error = loader->close(loader);
loader = NULL;
if (error) {
- if (thd->killed) {
+ if (thd_killed(thd)) {
my_error(ER_QUERY_INTERRUPTED, MYF(0));
}
goto cleanup;
@@ -3476,7 +3475,7 @@ int ha_tokudb::is_index_unique(bool* is_unique, DB_TXN* txn, DB* db, KEY* key_in
share->rows,
key_info->name);
thd_proc_info(thd, status_msg);
- if (thd->killed) {
+ if (thd_killed(thd)) {
my_error(ER_QUERY_INTERRUPTED, MYF(0));
error = ER_QUERY_INTERRUPTED;
goto cleanup;
@@ -4375,6 +4374,20 @@ static bool index_key_is_null(TABLE *table, uint keynr, const uchar *key, uint k
return key_can_be_null && key_len > 0 && key[0] != 0;
}
+// Return true if bulk fetch can be used
+static bool tokudb_do_bulk_fetch(THD *thd) {
+ switch (thd_sql_command(thd)) {
+ case SQLCOM_SELECT:
+ case SQLCOM_CREATE_TABLE:
+ case SQLCOM_INSERT_SELECT:
+ case SQLCOM_REPLACE_SELECT:
+ case SQLCOM_DELETE:
+ return THDVAR(thd, bulk_fetch) != 0;
+ default:
+ return false;
+ }
+}
+
//
// Notification that a range query getting all elements that equal a key
// to take place. Will pre acquire read lock
@@ -4383,7 +4396,7 @@ static bool index_key_is_null(TABLE *table, uint keynr, const uchar *key, uint k
// error otherwise
//
int ha_tokudb::prepare_index_key_scan(const uchar * key, uint key_len) {
- TOKUDB_HANDLER_DBUG_ENTER("");
+ TOKUDB_HANDLER_DBUG_ENTER("%p %u", key, key_len);
int error = 0;
DBT start_key, end_key;
THD* thd = ha_thd();
@@ -4407,7 +4420,7 @@ int ha_tokudb::prepare_index_key_scan(const uchar * key, uint key_len) {
range_lock_grabbed = true;
range_lock_grabbed_null = index_key_is_null(table, tokudb_active_index, key, key_len);
- doing_bulk_fetch = (thd_sql_command(thd) == SQLCOM_SELECT);
+ doing_bulk_fetch = tokudb_do_bulk_fetch(thd);
bulk_fetch_iteration = 0;
rows_fetched_using_bulk_fetch = 0;
error = 0;
@@ -4519,6 +4532,7 @@ int ha_tokudb::index_init(uint keynr, bool sorted) {
}
invalidate_bulk_fetch();
doing_bulk_fetch = false;
+ maybe_index_scan = false;
error = 0;
exit:
TOKUDB_HANDLER_DBUG_RETURN(error);
@@ -5261,86 +5275,91 @@ cleanup:
}
int ha_tokudb::get_next(uchar* buf, int direction, DBT* key_to_compare, bool do_key_read) {
- int error = 0;
- uint32_t flags = SET_PRELOCK_FLAG(0);
- THD* thd = ha_thd();
- tokudb_trx_data* trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);;
- bool need_val;
+ int error = 0;
HANDLE_INVALID_CURSOR();
- // we need to read the val of what we retrieve if
- // we do NOT have a covering index AND we are using a clustering secondary
- // key
- need_val = (do_key_read == 0) &&
- (tokudb_active_index == primary_key ||
- key_is_clustering(&table->key_info[tokudb_active_index])
- );
-
- if ((bytes_used_in_range_query_buff - curr_range_query_buff_offset) > 0) {
- error = read_data_from_range_query_buff(buf, need_val, do_key_read);
- }
- else if (icp_went_out_of_range) {
- icp_went_out_of_range = false;
- error = HA_ERR_END_OF_FILE;
+ if (maybe_index_scan) {
+ maybe_index_scan = false;
+ if (!range_lock_grabbed) {
+ error = prepare_index_scan();
+ }
}
- else {
- invalidate_bulk_fetch();
- if (doing_bulk_fetch) {
- struct smart_dbt_bf_info bf_info;
- bf_info.ha = this;
- // you need the val if you have a clustering index and key_read is not 0;
- bf_info.direction = direction;
- bf_info.thd = ha_thd();
- bf_info.need_val = need_val;
- bf_info.buf = buf;
- bf_info.key_to_compare = key_to_compare;
- //
- // call c_getf_next with purpose of filling in range_query_buff
- //
- rows_fetched_using_bulk_fetch = 0;
- // it is expected that we can do ICP in the smart_dbt_bf_callback
- // as a result, it's possible we don't return any data because
- // none of the rows matched the index condition. Therefore, we need
- // this while loop. icp_out_of_range will be set if we hit a row that
- // the index condition states is out of our range. When that hits,
- // we know all the data in the buffer is the last data we will retrieve
- while (bytes_used_in_range_query_buff == 0 && !icp_went_out_of_range && error == 0) {
- if (direction > 0) {
- error = cursor->c_getf_next(cursor, flags, smart_dbt_bf_callback, &bf_info);
- } else {
- error = cursor->c_getf_prev(cursor, flags, smart_dbt_bf_callback, &bf_info);
- }
- }
- // if there is no data set and we went out of range,
- // then there is nothing to return
- if (bytes_used_in_range_query_buff == 0 && icp_went_out_of_range) {
- icp_went_out_of_range = false;
- error = HA_ERR_END_OF_FILE;
- }
- if (bulk_fetch_iteration < HA_TOKU_BULK_FETCH_ITERATION_MAX) {
- bulk_fetch_iteration++;
- }
+
+ if (!error) {
+ uint32_t flags = SET_PRELOCK_FLAG(0);
- error = handle_cursor_error(error, HA_ERR_END_OF_FILE,tokudb_active_index);
- if (error) { goto cleanup; }
-
- //
- // now that range_query_buff is filled, read an element
- //
+ // we need to read the val of what we retrieve if
+ // we do NOT have a covering index AND we are using a clustering secondary
+ // key
+ bool need_val = (do_key_read == 0) &&
+ (tokudb_active_index == primary_key || key_is_clustering(&table->key_info[tokudb_active_index]));
+
+ if ((bytes_used_in_range_query_buff - curr_range_query_buff_offset) > 0) {
error = read_data_from_range_query_buff(buf, need_val, do_key_read);
}
+ else if (icp_went_out_of_range) {
+ icp_went_out_of_range = false;
+ error = HA_ERR_END_OF_FILE;
+ }
else {
- struct smart_dbt_info info;
- info.ha = this;
- info.buf = buf;
- info.keynr = tokudb_active_index;
+ invalidate_bulk_fetch();
+ if (doing_bulk_fetch) {
+ struct smart_dbt_bf_info bf_info;
+ bf_info.ha = this;
+ // you need the val if you have a clustering index and key_read is not 0;
+ bf_info.direction = direction;
+ bf_info.thd = ha_thd();
+ bf_info.need_val = need_val;
+ bf_info.buf = buf;
+ bf_info.key_to_compare = key_to_compare;
+ //
+ // call c_getf_next with purpose of filling in range_query_buff
+ //
+ rows_fetched_using_bulk_fetch = 0;
+ // it is expected that we can do ICP in the smart_dbt_bf_callback
+ // as a result, it's possible we don't return any data because
+ // none of the rows matched the index condition. Therefore, we need
+ // this while loop. icp_out_of_range will be set if we hit a row that
+ // the index condition states is out of our range. When that hits,
+ // we know all the data in the buffer is the last data we will retrieve
+ while (bytes_used_in_range_query_buff == 0 && !icp_went_out_of_range && error == 0) {
+ if (direction > 0) {
+ error = cursor->c_getf_next(cursor, flags, smart_dbt_bf_callback, &bf_info);
+ } else {
+ error = cursor->c_getf_prev(cursor, flags, smart_dbt_bf_callback, &bf_info);
+ }
+ }
+ // if there is no data set and we went out of range,
+ // then there is nothing to return
+ if (bytes_used_in_range_query_buff == 0 && icp_went_out_of_range) {
+ icp_went_out_of_range = false;
+ error = HA_ERR_END_OF_FILE;
+ }
+ if (bulk_fetch_iteration < HA_TOKU_BULK_FETCH_ITERATION_MAX) {
+ bulk_fetch_iteration++;
+ }
- if (direction > 0) {
- error = cursor->c_getf_next(cursor, flags, SMART_DBT_CALLBACK(do_key_read), &info);
- } else {
- error = cursor->c_getf_prev(cursor, flags, SMART_DBT_CALLBACK(do_key_read), &info);
+ error = handle_cursor_error(error, HA_ERR_END_OF_FILE,tokudb_active_index);
+ if (error) { goto cleanup; }
+
+ //
+ // now that range_query_buff is filled, read an element
+ //
+ error = read_data_from_range_query_buff(buf, need_val, do_key_read);
+ }
+ else {
+ struct smart_dbt_info info;
+ info.ha = this;
+ info.buf = buf;
+ info.keynr = tokudb_active_index;
+
+ if (direction > 0) {
+ error = cursor->c_getf_next(cursor, flags, SMART_DBT_CALLBACK(do_key_read), &info);
+ } else {
+ error = cursor->c_getf_prev(cursor, flags, SMART_DBT_CALLBACK(do_key_read), &info);
+ }
+ error = handle_cursor_error(error, HA_ERR_END_OF_FILE, tokudb_active_index);
}
- error = handle_cursor_error(error, HA_ERR_END_OF_FILE, tokudb_active_index);
}
}
@@ -5352,12 +5371,15 @@ int ha_tokudb::get_next(uchar* buf, int direction, DBT* key_to_compare, bool do_
// read the full row by doing a point query into the
// main table.
//
-
if (!error && !do_key_read && (tokudb_active_index != primary_key) && !key_is_clustering(&table->key_info[tokudb_active_index])) {
error = read_full_row(buf);
}
- trx->stmt_progress.queried++;
- track_progress(thd);
+
+ if (!error) {
+ tokudb_trx_data* trx = (tokudb_trx_data *) thd_get_ha_data(ha_thd(), tokudb_hton);
+ trx->stmt_progress.queried++;
+ track_progress(ha_thd());
+ }
cleanup:
return error;
}
@@ -5426,8 +5448,7 @@ int ha_tokudb::index_first(uchar * buf) {
info.buf = buf;
info.keynr = tokudb_active_index;
- error = cursor->c_getf_first(cursor, flags,
- SMART_DBT_CALLBACK(key_read), &info);
+ error = cursor->c_getf_first(cursor, flags, SMART_DBT_CALLBACK(key_read), &info);
error = handle_cursor_error(error,HA_ERR_END_OF_FILE,tokudb_active_index);
//
@@ -5437,9 +5458,11 @@ int ha_tokudb::index_first(uchar * buf) {
if (!error && !key_read && (tokudb_active_index != primary_key) && !key_is_clustering(&table->key_info[tokudb_active_index])) {
error = read_full_row(buf);
}
- trx->stmt_progress.queried++;
+ if (trx) {
+ trx->stmt_progress.queried++;
+ }
track_progress(thd);
-
+ maybe_index_scan = true;
cleanup:
TOKUDB_HANDLER_DBUG_RETURN(error);
}
@@ -5469,8 +5492,7 @@ int ha_tokudb::index_last(uchar * buf) {
info.buf = buf;
info.keynr = tokudb_active_index;
- error = cursor->c_getf_last(cursor, flags,
- SMART_DBT_CALLBACK(key_read), &info);
+ error = cursor->c_getf_last(cursor, flags, SMART_DBT_CALLBACK(key_read), &info);
error = handle_cursor_error(error,HA_ERR_END_OF_FILE,tokudb_active_index);
//
// still need to get entire contents of the row if operation done on
@@ -5484,6 +5506,7 @@ int ha_tokudb::index_last(uchar * buf) {
trx->stmt_progress.queried++;
}
track_progress(thd);
+ maybe_index_scan = true;
cleanup:
TOKUDB_HANDLER_DBUG_RETURN(error);
}
@@ -5643,8 +5666,8 @@ cleanup:
TOKUDB_HANDLER_DBUG_RETURN(error);
}
-int ha_tokudb::prelock_range( const key_range *start_key, const key_range *end_key) {
- TOKUDB_HANDLER_DBUG_ENTER("");
+int ha_tokudb::prelock_range(const key_range *start_key, const key_range *end_key) {
+ TOKUDB_HANDLER_DBUG_ENTER("%p %p", start_key, end_key);
THD* thd = ha_thd();
int error = 0;
@@ -5709,11 +5732,8 @@ int ha_tokudb::prelock_range( const key_range *start_key, const key_range *end_k
goto cleanup;
}
- //
// at this point, determine if we will be doing bulk fetch
- // as of now, only do it if we are doing a select
- //
- doing_bulk_fetch = (thd_sql_command(thd) == SQLCOM_SELECT);
+ doing_bulk_fetch = tokudb_do_bulk_fetch(thd);
bulk_fetch_iteration = 0;
rows_fetched_using_bulk_fetch = 0;
@@ -5728,7 +5748,7 @@ cleanup:
// Forward scans use read_range_first()/read_range_next().
//
int ha_tokudb::prepare_range_scan( const key_range *start_key, const key_range *end_key) {
- TOKUDB_HANDLER_DBUG_ENTER("");
+ TOKUDB_HANDLER_DBUG_ENTER("%p %p", start_key, end_key);
int error = prelock_range(start_key, end_key);
if (!error) {
range_lock_grabbed = true;
@@ -5742,7 +5762,7 @@ int ha_tokudb::read_range_first(
bool eq_range,
bool sorted)
{
- TOKUDB_HANDLER_DBUG_ENTER("");
+ TOKUDB_HANDLER_DBUG_ENTER("%p %p %u %u", start_key, end_key, eq_range, sorted);
int error = prelock_range(start_key, end_key);
if (error) { goto cleanup; }
range_lock_grabbed = true;
@@ -6852,7 +6872,7 @@ int ha_tokudb::create(const char *name, TABLE * form, HA_CREATE_INFO * create_in
if (error) { goto cleanup; }
#if WITH_PARTITION_STORAGE_ENGINE
- if (TOKU_PARTITION_WRITE_FRM_DATA || IF_PARTITIONING(form->part_info, NULL) == NULL) {
+ if (TOKU_PARTITION_WRITE_FRM_DATA || form->part_info == NULL) {
error = write_frm_data(status_block, txn, form->s->path.str);
if (error) { goto cleanup; }
}
@@ -7718,7 +7738,7 @@ int ha_tokudb::tokudb_add_index(
thd_progress_report(thd, num_processed, (long long unsigned) share->rows);
#endif
- if (thd->killed) {
+ if (thd_killed(thd)) {
error = ER_ABORTING_CONNECTION;
goto cleanup;
}
diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h
index 3d7584a308a..e43ca87843a 100644
--- a/storage/tokudb/ha_tokudb.h
+++ b/storage/tokudb/ha_tokudb.h
@@ -251,6 +251,7 @@ private:
uint64_t bulk_fetch_iteration;
uint64_t rows_fetched_using_bulk_fetch;
bool doing_bulk_fetch;
+ bool maybe_index_scan;
//
// buffer used to temporarily store a "packed key"
diff --git a/storage/tokudb/ha_tokudb_alter_56.cc b/storage/tokudb/ha_tokudb_alter_56.cc
index 5062a2ae67b..e55b7b48ad8 100644
--- a/storage/tokudb/ha_tokudb_alter_56.cc
+++ b/storage/tokudb/ha_tokudb_alter_56.cc
@@ -720,27 +720,6 @@ bool ha_tokudb::commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_i
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
bool result = false; // success
THD *thd = ha_thd();
- MDL_ticket *ticket = table->mdl_ticket;
- if (ticket->get_type() != MDL_EXCLUSIVE) {
- // get exclusive lock no matter what
-#if defined(MARIADB_BASE_VERSION)
- killed_state saved_killed_state = thd->killed;
- thd->killed = NOT_KILLED;
- while (wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) && thd->killed)
- thd->killed = NOT_KILLED;
- assert(ticket->get_type() == MDL_EXCLUSIVE);
- if (thd->killed == NOT_KILLED)
- thd->killed = saved_killed_state;
-#else
- THD::killed_state saved_killed_state = thd->killed;
- thd->killed = THD::NOT_KILLED;
- while (wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) && thd->killed)
- thd->killed = THD::NOT_KILLED;
- assert(ticket->get_type() == MDL_EXCLUSIVE);
- if (thd->killed == THD::NOT_KILLED)
- thd->killed = saved_killed_state;
-#endif
- }
if (commit) {
#if (50613 <= MYSQL_VERSION_ID && MYSQL_VERSION_ID <= 50699) || \
@@ -768,6 +747,35 @@ bool ha_tokudb::commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_i
}
if (!commit) {
+ if (table->mdl_ticket->get_type() != MDL_EXCLUSIVE &&
+ (ctx->add_index_changed || ctx->drop_index_changed || ctx->compression_changed)) {
+
+ // get exclusive lock no matter what
+#if defined(MARIADB_BASE_VERSION)
+ killed_state saved_killed_state = thd->killed;
+ thd->killed = NOT_KILLED;
+ for (volatile uint i = 0; wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED); i++) {
+ if (thd->killed != NOT_KILLED)
+ thd->killed = NOT_KILLED;
+ sleep(1);
+ }
+ assert(table->mdl_ticket->get_type() == MDL_EXCLUSIVE);
+ if (thd->killed == NOT_KILLED)
+ thd->killed = saved_killed_state;
+#else
+ THD::killed_state saved_killed_state = thd->killed;
+ thd->killed = THD::NOT_KILLED;
+ for (volatile uint i = 0; wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED); i++) {
+ if (thd->killed != THD::NOT_KILLED)
+ thd->killed = THD::NOT_KILLED;
+ sleep(1);
+ }
+ assert(table->mdl_ticket->get_type() == MDL_EXCLUSIVE);
+ if (thd->killed == THD::NOT_KILLED)
+ thd->killed = saved_killed_state;
+#endif
+ }
+
// abort the alter transaction NOW so that any alters are rolled back. this allows the following restores to work.
tokudb_trx_data *trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);
assert(ctx->alter_txn == trx->stmt);
diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc
index 9e9d90f8c9c..29b79d50735 100644
--- a/storage/tokudb/hatoku_hton.cc
+++ b/storage/tokudb/hatoku_hton.cc
@@ -336,7 +336,7 @@ static int tokudb_init_func(void *p) {
#if TOKUDB_CHECK_JEMALLOC
if (tokudb_check_jemalloc && dlsym(RTLD_DEFAULT, "mallctl") == NULL) {
- sql_print_error("%s not initialized because jemalloc is not loaded", tokudb_hton_name);
+ sql_print_error("%s is not initialized because jemalloc is not loaded", tokudb_hton_name);
goto error;
}
#endif
@@ -522,6 +522,7 @@ static int tokudb_init_func(void *p) {
if (r) {
DBUG_PRINT("info", ("env->open %d", r));
+ handle_ydb_error(r);
goto error;
}
@@ -600,8 +601,35 @@ int tokudb_end(handlerton * hton, ha_panic_function type) {
if (db_env) {
if (tokudb_init_flags & DB_INIT_LOG)
tokudb_cleanup_log_files();
- error = db_env->close(db_env, 0); // Error is logged
- assert(error==0);
+#if TOKU_INCLUDE_XA
+ long total_prepared = 0; // count the total number of prepared txn's that we discard
+ while (1) {
+ // get xid's
+ const long n_xid = 1;
+ TOKU_XA_XID xids[n_xid];
+ long n_prepared = 0;
+ error = db_env->txn_xa_recover(db_env, xids, n_xid, &n_prepared, total_prepared == 0 ? DB_FIRST : DB_NEXT);
+ assert(error == 0);
+ if (n_prepared == 0)
+ break;
+ // discard xid's
+ for (long i = 0; i < n_xid; i++) {
+ DB_TXN *txn = NULL;
+ error = db_env->get_txn_from_xid(db_env, &xids[i], &txn);
+ assert(error == 0);
+ error = txn->discard(txn, 0);
+ assert(error == 0);
+ }
+ total_prepared += n_prepared;
+ }
+#endif
+ error = db_env->close(db_env, total_prepared > 0 ? TOKUFT_DIRTY_SHUTDOWN : 0);
+#if TOKU_INCLUDE_XA
+ if (error != 0 && total_prepared > 0) {
+ sql_print_error("%s: %ld prepared txns still live, please shutdown, error %d", tokudb_hton_name, total_prepared, error);
+ } else
+#endif
+ assert(error == 0);
db_env = NULL;
}
@@ -693,7 +721,7 @@ static void commit_txn_with_progress(DB_TXN* txn, uint32_t flags, THD* thd) {
info.thd = thd;
int r = txn->commit_with_progress(txn, flags, txn_progress_func, &info);
if (r != 0) {
- sql_print_error("tried committing transaction %p and got error code %d", txn, r);
+ sql_print_error("%s: tried committing transaction %p and got error code %d", tokudb_hton_name, txn, r);
}
assert(r == 0);
thd_proc_info(thd, orig_proc_info);
@@ -705,7 +733,7 @@ static void abort_txn_with_progress(DB_TXN* txn, THD* thd) {
info.thd = thd;
int r = txn->abort_with_progress(txn, txn_progress_func, &info);
if (r != 0) {
- sql_print_error("tried aborting transaction %p and got error code %d", txn, r);
+ sql_print_error("%s: tried aborting transaction %p and got error code %d", tokudb_hton_name, txn, r);
}
assert(r == 0);
thd_proc_info(thd, orig_proc_info);
@@ -804,7 +832,7 @@ static int tokudb_xa_prepare(handlerton* hton, THD* thd, bool all) {
TOKUDB_DBUG_RETURN(r);
}
-static int tokudb_xa_recover(handlerton* hton, XID* xid_list, uint len) {
+static int tokudb_xa_recover(handlerton* hton, XID* xid_list, uint len) {
TOKUDB_DBUG_ENTER("");
int r = 0;
if (len == 0 || xid_list == NULL) {
@@ -1205,7 +1233,7 @@ static void tokudb_handle_fatal_signal(handlerton *hton __attribute__ ((__unused
#endif
static void tokudb_print_error(const DB_ENV * db_env, const char *db_errpfx, const char *buffer) {
- sql_print_error("%s: %s", db_errpfx, buffer);
+ sql_print_error("%s: %s", db_errpfx, buffer);
}
static void tokudb_cleanup_log_files(void) {
@@ -1384,6 +1412,7 @@ static struct st_mysql_sys_var *tokudb_system_variables[] = {
#if TOKUDB_CHECK_JEMALLOC
MYSQL_SYSVAR(check_jemalloc),
#endif
+ MYSQL_SYSVAR(bulk_fetch),
NULL
};
@@ -1958,7 +1987,7 @@ static void tokudb_lock_timeout_callback(DB *db, uint64_t requesting_txnid, cons
}
// dump to stderr
if (lock_timeout_debug & 2) {
- TOKUDB_TRACE("%s", log_str.c_ptr());
+ sql_print_error("%s: %s", tokudb_hton_name, log_str.c_ptr());
}
}
}
diff --git a/storage/tokudb/hatoku_hton.h b/storage/tokudb/hatoku_hton.h
index 054a5119702..80ddc7c7aba 100644
--- a/storage/tokudb/hatoku_hton.h
+++ b/storage/tokudb/hatoku_hton.h
@@ -461,6 +461,8 @@ static uint tokudb_check_jemalloc;
static MYSQL_SYSVAR_UINT(check_jemalloc, tokudb_check_jemalloc, 0, "Check if jemalloc is linked", NULL, NULL, 1, 0, 1, 0);
#endif
+static MYSQL_THDVAR_BOOL(bulk_fetch, PLUGIN_VAR_THDLOCAL, "enable bulk fetch", NULL /*check*/, NULL /*update*/, true /*default*/);
+
extern HASH tokudb_open_tables;
extern pthread_mutex_t tokudb_mutex;
extern uint32_t tokudb_write_status_frequency;
diff --git a/storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash.test b/storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash.test
index 97818a597e2..07b117947a0 100644
--- a/storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash.test
+++ b/storage/tokudb/mysql-test/rpl/t/tokudb_innodb_xa_crash.test
@@ -1,6 +1,6 @@
---source include/master-slave.inc
--source include/have_tokudb.inc
--source include/have_innodb.inc
+--source include/master-slave.inc
eval CREATE TABLE t1(`a` INT) ENGINE=TokuDB;
eval CREATE TABLE t2(`a` INT) ENGINE=InnoDB;
diff --git a/storage/tokudb/mysql-test/tokudb/include/have_tokudb.inc b/storage/tokudb/mysql-test/tokudb/include/have_tokudb.inc
index e69de29bb2d..12b29a22d2c 100644
--- a/storage/tokudb/mysql-test/tokudb/include/have_tokudb.inc
+++ b/storage/tokudb/mysql-test/tokudb/include/have_tokudb.inc
@@ -0,0 +1 @@
+let $datadir=`select @@datadir`;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_create_select_hash_part.result b/storage/tokudb/mysql-test/tokudb/r/bf_create_select_hash_part.result
new file mode 100644
index 00000000000..f8c8e6c596d
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_create_select_hash_part.result
@@ -0,0 +1,328 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2,t3;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) as select * from t;
+CREATE TABLE `t2` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) PARTITION BY HASH (num)
+PARTITIONS 8 as select * from t;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2;
+DROP TABLE t3;
+1
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t3;
+1
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_create_select_nonpart.result b/storage/tokudb/mysql-test/tokudb/r/bf_create_select_nonpart.result
new file mode 100644
index 00000000000..adacf1ed6aa
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_create_select_nonpart.result
@@ -0,0 +1,242 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) as select * from t;
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1;
+DROP TABLE t2;
+1
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TABLE t2;
+1
+drop table t,t1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_create_select_range_part.result b/storage/tokudb/mysql-test/tokudb/r/bf_create_select_range_part.result
new file mode 100644
index 00000000000..0e055e76d3f
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_create_select_range_part.result
@@ -0,0 +1,335 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) as select * from t;
+CREATE TABLE `t2` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) PARTITION BY RANGE (num)
+(PARTITION p0 VALUES LESS THAN (1000000),
+PARTITION p1 VALUES LESS THAN (2000000),
+PARTITION p2 VALUES LESS THAN (3000000),
+PARTITION p3 VALUES LESS THAN (4000000),
+PARTITION p4 VALUES LESS THAN (5000000),
+PARTITION p5 VALUES LESS THAN (6000000),
+PARTITION p6 VALUES LESS THAN (7000000),
+PARTITION p7 VALUES LESS THAN MAXVALUE) as select * from t;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1;
+count(*)
+8388608
+DROP TABLE t3;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2;
+DROP TABLE t4;
+1
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE `t3` (`x` bigint);
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+DROP TABLE t3;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+DROP TABLE t4;
+1
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_create_temp_select_nonpart.result b/storage/tokudb/mysql-test/tokudb/r/bf_create_temp_select_nonpart.result
new file mode 100644
index 00000000000..6eddfaa9e82
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_create_temp_select_nonpart.result
@@ -0,0 +1,242 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) as select * from t;
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+DROP TEMPORARY TABLE t2;
+1
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+DROP TEMPORARY TABLE t2;
+1
+drop table t,t1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_delete_nonpart.result b/storage/tokudb/mysql-test/tokudb/r/bf_delete_nonpart.result
new file mode 100644
index 00000000000..e83b150c543
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_delete_nonpart.result
@@ -0,0 +1,54 @@
+set default_storage_engine='tokudb';
+drop table if exists t;
+CREATE TABLE `t` (id bigint not null auto_increment primary key, val bigint not null default 0);
+INSERT INTO t (id) values (null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+set tokudb_bulk_fetch = ON;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+set tokudb_bulk_fetch = OFF;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+delete from t where val > 0;
+1
+drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_delete_trigger.result b/storage/tokudb/mysql-test/tokudb/r/bf_delete_trigger.result
new file mode 100644
index 00000000000..78bd8d2fe14
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_delete_trigger.result
@@ -0,0 +1,54 @@
+set default_storage_engine='tokudb';
+drop table if exists t;
+create table t (id bigint not null primary key, x bigint not null);
+insert into t values (1,0),(2,0),(3,0),(4,0);
+create trigger t_delete before delete on t for each row insert into t values (1000000,0);
+begin;
+delete from t where x=0;
+ERROR HY000: Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_delete;
+create trigger t_delete after delete on t for each row insert into t values (1000000,0);
+begin;
+delete from t where x=0;
+ERROR HY000: Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_delete;
+create trigger t_delete before delete on t for each row delete from t where id=1000000;
+begin;
+delete from t where x=0;
+ERROR HY000: Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_delete;
+create trigger t_delete after delete on t for each row delete from t where id=1000000;
+begin;
+delete from t where x=0;
+ERROR HY000: Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_delete;
+create trigger t_delete before delete on t for each row update t set x=x+1 where id=1000000;
+begin;
+delete from t where x=0;
+ERROR HY000: Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_delete;
+create trigger t_delete after delete on t for each row update t set x=x+1 where id=10000000;
+begin;
+delete from t where x=0;
+ERROR HY000: Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_delete;
+create table count (count bigint not null);
+create trigger t_delete before delete on t for each row insert into count select count(*) from t;
+begin;
+delete from t where x=0;
+select * from count;
+count
+4
+3
+2
+1
+rollback;
+drop trigger t_delete;
+drop table count;
+drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_dup_key_nonpart.result b/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_dup_key_nonpart.result
new file mode 100644
index 00000000000..22e2846d181
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_dup_key_nonpart.result
@@ -0,0 +1,207 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) as select * from t;
+CREATE TABLE `t2` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`count` bigint(20) NOT NULL,
+UNIQUE (num)
+) ENGINE=TokuDB DEFAULT CHARSET=latin1;
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+1
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+1
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_nonpart.result b/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_nonpart.result
new file mode 100644
index 00000000000..ba7d0f63cd6
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_nonpart.result
@@ -0,0 +1,205 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) as select * from t;
+CREATE TABLE `t2` (
+`count` bigint(20) NOT NULL
+) ENGINE=TokuDB DEFAULT CHARSET=latin1;
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+INSERT into t2 SELECT count(*) from t1;
+1
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+1
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_trigger.result b/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_trigger.result
new file mode 100644
index 00000000000..860d26602dd
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_trigger.result
@@ -0,0 +1,45 @@
+set default_storage_engine='tokudb';
+drop table if exists s,t;
+create table s (id bigint not null primary key, x bigint);
+insert into s values (1,0),(2,0),(3,0),(4,0);
+create table t like s;
+begin;
+insert into t select * from s;
+rollback;
+create trigger t_trigger before insert on t for each row insert into s values (1000000,0);
+begin;
+insert into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row insert into s values (1000000,0);
+begin;
+insert into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+insert into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+insert into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+insert into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+insert into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+drop table s,t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_update_trigger.result b/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_update_trigger.result
new file mode 100644
index 00000000000..d7588441d92
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_insert_select_update_trigger.result
@@ -0,0 +1,121 @@
+set default_storage_engine='tokudb';
+drop table if exists s,t;
+create table s (id bigint not null primary key, x bigint);
+insert into s values (1,0),(2,0),(3,0),(4,0);
+create table t like s;
+begin;
+insert into t select * from s;
+rollback;
+create trigger t_trigger before insert on t for each row insert into s values (1000000,0);
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row insert into s values (1000000,0);
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+truncate table t;
+insert into t values (1,0);
+create trigger t_trigger before insert on t for each row insert into s values (1000000,0);
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row insert into s values (1000000,0);
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+truncate table t;
+insert into t values (1,0);
+create trigger t_trigger before update on t for each row insert into s values (1000000,0);
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after update on t for each row insert into s values (1000000,0);
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before update on t for each row delete from s where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after update on t for each row delete from s where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before update on t for each row update s set x=x+1 where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after update on t for each row update s set x=x+1 where id=1000000;
+begin;
+insert into t select * from s on duplicate key update x=t.x+1;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+drop table s,t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_replace_select_nonpart.result b/storage/tokudb/mysql-test/tokudb/r/bf_replace_select_nonpart.result
new file mode 100644
index 00000000000..eab0f103ed6
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_replace_select_nonpart.result
@@ -0,0 +1,367 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) as select * from t;
+CREATE TABLE `t2` (
+`count` bigint(20) NOT NULL
+) ENGINE=TokuDB DEFAULT CHARSET=latin1;
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+REPLACE into t2 SELECT count(*) from t1;
+1
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+INSERT IGNORE into t2 SELECT count(*) from t1;
+1
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+1
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+1
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_replace_select_trigger.result b/storage/tokudb/mysql-test/tokudb/r/bf_replace_select_trigger.result
new file mode 100644
index 00000000000..acd17170301
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_replace_select_trigger.result
@@ -0,0 +1,121 @@
+set default_storage_engine='tokudb';
+drop table if exists s,t;
+create table s (id bigint not null primary key, x bigint);
+insert into s values (1,0),(2,0),(3,0),(4,0);
+create table t like s;
+begin;
+replace into t select * from s;
+rollback;
+create trigger t_trigger before insert on t for each row replace into s values (1000000,0);
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row replace into s values (1000000,0);
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+truncate table t;
+insert into t values (1,1);
+create trigger t_trigger before insert on t for each row replace into s values (1000000,0);
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row replace into s values (1000000,0);
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+truncate table t;
+insert into t values (1,1);
+create trigger t_trigger before delete on t for each row replace into s values (1000000,0);
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after delete on t for each row replace into s values (1000000,0);
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before delete on t for each row delete from s where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after delete on t for each row delete from s where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger before delete on t for each row update s set x=x+1 where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+create trigger t_trigger after delete on t for each row update s set x=x+1 where id=1000000;
+begin;
+replace into t select * from s;
+ERROR HY000: Can't update table 's' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+rollback;
+drop trigger t_trigger;
+drop table s,t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bf_select_part.result b/storage/tokudb/mysql-test/tokudb/r/bf_select_part.result
new file mode 100644
index 00000000000..f36fc0e1ce3
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bf_select_part.result
@@ -0,0 +1,543 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2,t3;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) as select * from t;
+CREATE TABLE `t2` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) PARTITION BY HASH (num)
+PARTITIONS 8 as select * from t;
+CREATE TABLE `t3` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+) PARTITION BY RANGE (num)
+(PARTITION p0 VALUES LESS THAN (1000000),
+PARTITION p1 VALUES LESS THAN (2000000),
+PARTITION p2 VALUES LESS THAN (3000000),
+PARTITION p3 VALUES LESS THAN (4000000),
+PARTITION p4 VALUES LESS THAN (5000000),
+PARTITION p5 VALUES LESS THAN (6000000),
+PARTITION p6 VALUES LESS THAN (7000000),
+PARTITION p7 VALUES LESS THAN MAXVALUE) as select * from t;
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+SELECT count(*) from t2;
+count(*)
+8388608
+1
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t1;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+SELECT count(*) from t3;
+count(*)
+8388608
+1
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t2 where num > 7000000;
+count(*)
+1847274
+1
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t1 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+SELECT count(*) from t3 where num > 7000000;
+count(*)
+1847274
+1
+drop table t,t1,t2,t3;
diff --git a/storage/tokudb/mysql-test/tokudb/r/information-schema-global-status.result b/storage/tokudb/mysql-test/tokudb/r/information-schema-global-status.result
index 438d10ac282..a417483cefb 100644
--- a/storage/tokudb/mysql-test/tokudb/r/information-schema-global-status.result
+++ b/storage/tokudb/mysql-test/tokudb/r/information-schema-global-status.result
@@ -16,8 +16,6 @@ TOKUDB_BASEMENTS_FETCHED_PRELOCKED_RANGE_SECONDS
TOKUDB_BASEMENTS_FETCHED_TARGET_QUERY
TOKUDB_BASEMENTS_FETCHED_TARGET_QUERY_BYTES
TOKUDB_BASEMENTS_FETCHED_TARGET_QUERY_SECONDS
-TOKUDB_BASEMENT_DESERIALIZATION_FIXED_KEY
-TOKUDB_BASEMENT_DESERIALIZATION_VARIABLE_KEY
TOKUDB_BROADCASE_MESSAGES_INJECTED_AT_ROOT
TOKUDB_BUFFERS_DECOMPRESSED_FOR_WRITE
TOKUDB_BUFFERS_DECOMPRESSED_PREFETCH
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_create_select_hash_part.test b/storage/tokudb/mysql-test/tokudb/t/bf_create_select_hash_part.test
new file mode 100644
index 00000000000..b9ec8c52aa8
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_create_select_hash_part.test
@@ -0,0 +1,143 @@
+# Verify that index and range scans are not slow
+# on tables during create select statements
+# due to tokudb bulk fetch not being used
+
+source include/have_tokudb.inc;
+source include/have_partition.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2,t3;
+enable_warnings;
+
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# Create base table (control table) from source table t
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) as select * from t;
+
+# Create source hash partitioned table from source table t
+CREATE TABLE `t2` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) PARTITION BY HASH (num)
+PARTITIONS 8 as select * from t;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ CREATE TABLE `t3` (`x` bigint);
+ SELECT count(*) from t1;
+ DROP TABLE t3;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ CREATE TABLE t3 AS SELECT count(*) from t2;
+ DROP TABLE t3;
+ inc $i;
+}
+
+let $time_elapsed_create_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_create_select seconds.;
+
+# This check evaluates whether the time elapsed during the create select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+# Additionally, it is important to note that 1.5 is the multiplier applied to the time_elapsed_select
+# value because it appears that MySQL 5.5.39 uses a sorted index scan during the create select statement
+# while Percona Server 5.6 uses an unsorted index scan.
+# The issue has been resolved in MySQL 5.6 but still persists in Maria 10.0.12
+# in the defect found at https://mariadb.atlassian.net/browse/MDEV-6547.
+let $verdict = `select abs($time_elapsed_create_select - $time_elapsed_select) <= 1.5 * $time_elapsed_select`;
+echo $verdict;
+if (!$verdict) { echo index scan t2 $time_elapsed_create_select $time_elapsed_select; }
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ CREATE TABLE `t3` (`x` bigint);
+ SELECT count(*) from t1 where num > 7000000;
+ DROP TABLE t3;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ CREATE TABLE t3 AS SELECT count(*) from t2 where num > 7000000;
+ DROP TABLE t3;
+ inc $i;
+}
+
+let $time_elapsed_create_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_create_select seconds.;
+
+# This check evaluates whether the time elapsed during the create select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+# Additionally, it is important to note that 1.5 is the multiplier applied to the time_elapsed_select
+# value because it appears that MySQL 5.5.39 uses a sorted index scan during the create select statement
+# while Percona Server 5.6 uses an unsorted index scan.
+# The issue has been resolved in MySQL 5.6 but still persists in Maria 10.0.12
+# in the defect found at https://mariadb.atlassian.net/browse/MDEV-6547.
+let $verdict = `select abs($time_elapsed_create_select - $time_elapsed_select) <= 1.5 * $time_elapsed_select`;
+echo $verdict;
+if (!$verdict) { echo range scan t2 $time_elapsed_create_select $time_elapsed_select; }
+
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_create_select_nonpart.test b/storage/tokudb/mysql-test/tokudb/t/bf_create_select_nonpart.test
new file mode 100644
index 00000000000..a8b7f9c9f6a
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_create_select_nonpart.test
@@ -0,0 +1,118 @@
+# Verify that index and range scans are not slow
+# on tables during create select statements
+# due to tokudb bulk fetch not being used
+
+source include/have_tokudb.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2;
+enable_warnings;
+
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# Create first table from source table t
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) as select * from t;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ CREATE TABLE t2 AS SELECT count(*) from t1;
+ DROP TABLE t2;
+ inc $i;
+}
+
+let $time_elapsed_create_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_create_select seconds.;
+
+# This check evaluates whether the time elapsed during the create select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_create_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ CREATE TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+ DROP TABLE t2;
+ inc $i;
+}
+
+let $time_elapsed_create_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_create_select seconds.;
+
+# This check evaluates whether the time elapsed during the create select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_create_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+drop table t,t1;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_create_select_range_part.test b/storage/tokudb/mysql-test/tokudb/t/bf_create_select_range_part.test
new file mode 100644
index 00000000000..a48f272b84f
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_create_select_range_part.test
@@ -0,0 +1,138 @@
+# Verify that index and range scans are not slow
+# on tables during create select statements
+# due to tokudb bulk fetch not being used
+
+source include/have_tokudb.inc;
+source include/have_partition.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2;
+enable_warnings;
+
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# Create base table (control table) from source table t
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) as select * from t;
+
+# Create source range partitioned table from source table t
+CREATE TABLE `t2` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) PARTITION BY RANGE (num)
+(PARTITION p0 VALUES LESS THAN (1000000),
+ PARTITION p1 VALUES LESS THAN (2000000),
+ PARTITION p2 VALUES LESS THAN (3000000),
+ PARTITION p3 VALUES LESS THAN (4000000),
+ PARTITION p4 VALUES LESS THAN (5000000),
+ PARTITION p5 VALUES LESS THAN (6000000),
+ PARTITION p6 VALUES LESS THAN (7000000),
+ PARTITION p7 VALUES LESS THAN MAXVALUE) as select * from t;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ CREATE TABLE `t3` (`x` bigint);
+ SELECT count(*) from t1;
+ DROP TABLE t3;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ CREATE TABLE t4 AS SELECT count(*) from t2;
+ DROP TABLE t4;
+ inc $i;
+}
+
+let $time_elapsed_create_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_create_select seconds.;
+
+# This check evaluates whether the time elapsed during the create select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_create_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ CREATE TABLE `t3` (`x` bigint);
+ SELECT count(*) from t1 where num > 7000000;
+ DROP TABLE t3;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ CREATE TABLE t4 AS SELECT count(*) from t2 where num > 7000000;
+ DROP TABLE t4;
+ inc $i;
+}
+
+let $time_elapsed_create_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_create_select seconds.;
+
+# This check evaluates whether the time elapsed during the create select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_create_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_create_temp_select_nonpart.test b/storage/tokudb/mysql-test/tokudb/t/bf_create_temp_select_nonpart.test
new file mode 100644
index 00000000000..fdd665076c9
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_create_temp_select_nonpart.test
@@ -0,0 +1,118 @@
+# Verify that index and range scans are not slow
+# on temporary tables during create select statements
+# due to tokudb bulk fetch not being used
+
+source include/have_tokudb.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2;
+enable_warnings;
+
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# Create first table from source table t
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) as select * from t;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1;
+ DROP TEMPORARY TABLE t2;
+ inc $i;
+}
+
+let $time_elapsed_create_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_create_select seconds.;
+
+# This check evaluates whether the time elapsed during the create select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_create_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Range scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ CREATE TEMPORARY TABLE t2 AS SELECT count(*) from t1 where num > 7000000;
+ DROP TEMPORARY TABLE t2;
+ inc $i;
+}
+
+let $time_elapsed_create_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Range scans took $time_elapsed_create_select seconds.;
+
+# This check evaluates whether the time elapsed during the create select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_create_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+drop table t,t1;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_delete_nonpart.test b/storage/tokudb/mysql-test/tokudb/t/bf_delete_nonpart.test
new file mode 100644
index 00000000000..65b26df230e
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_delete_nonpart.test
@@ -0,0 +1,68 @@
+# Verify that index scans for delete statements use bulk fetch and are
+# at least twice as fast
+
+source include/have_tokudb.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t;
+enable_warnings;
+
+CREATE TABLE `t` (id bigint not null auto_increment primary key, val bigint not null default 0);
+
+# put 8M rows into t
+INSERT INTO t (id) values (null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# run $maxq measurements
+let $maxq = 10;
+
+# measure the time to do $maxq deletes from t that affect no rows with bulk fetch ON
+set tokudb_bulk_fetch = ON;
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ delete from t where val > 0;
+ inc $i;
+}
+let $time_elapsed_bf_on = `select to_seconds(now()) - $s`;
+
+# measure the time to do $maxq deletes from t that affect no rows with bulk fetch OFF
+set tokudb_bulk_fetch = OFF;
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ delete from t where val > 0;
+ inc $i;
+}
+let $time_elapsed_bf_off = `select to_seconds(now()) - $s`;
+
+# verify that a delete scan with bulk fetch ON is at least 2 times faster than with bulk fetch OFF
+let $verdict = `select $time_elapsed_bf_off > $time_elapsed_bf_on && ($time_elapsed_bf_off - $time_elapsed_bf_on) / $time_elapsed_bf_on >= 2`;
+echo $verdict;
+if (!$verdict) { echo $time_elapsed_bf_on $time_elapsed_bf_off; }
+
+drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_delete_trigger.test b/storage/tokudb/mysql-test/tokudb/t/bf_delete_trigger.test
new file mode 100644
index 00000000000..031a48feab1
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_delete_trigger.test
@@ -0,0 +1,70 @@
+# verify that delete triggers can not insert, delete, or update rows in the target table
+
+source include/have_tokudb.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t;
+enable_warnings;
+
+create table t (id bigint not null primary key, x bigint not null);
+insert into t values (1,0),(2,0),(3,0),(4,0);
+
+# verify that a before delete trigger can not insert into the target table
+create trigger t_delete before delete on t for each row insert into t values (1000000,0);
+begin;
+error 1442;
+delete from t where x=0;
+rollback;
+drop trigger t_delete;
+
+# verify that an after delete trigger can not insert into the target table
+create trigger t_delete after delete on t for each row insert into t values (1000000,0);
+begin;
+error 1442;
+delete from t where x=0;
+rollback;
+drop trigger t_delete;
+
+# verify that a before delete trigger can not delete from the target table
+create trigger t_delete before delete on t for each row delete from t where id=1000000;
+begin;
+error 1442;
+delete from t where x=0;
+rollback;
+drop trigger t_delete;
+
+# verify that an after delete trigger can not delete from the target table
+create trigger t_delete after delete on t for each row delete from t where id=1000000;
+begin;
+error 1442;
+delete from t where x=0;
+rollback;
+drop trigger t_delete;
+
+# verify that a before delete trigger can not update the target table
+create trigger t_delete before delete on t for each row update t set x=x+1 where id=1000000;
+begin;
+error 1442;
+delete from t where x=0;
+rollback;
+drop trigger t_delete;
+
+# verify that an after delete trigger can not update the target table
+create trigger t_delete after delete on t for each row update t set x=x+1 where id=10000000;
+begin;
+error 1442;
+delete from t where x=0;
+rollback;
+drop trigger t_delete;
+
+# can execute select on the target table in a delete trigger. it better use a different handler.
+create table count (count bigint not null);
+create trigger t_delete before delete on t for each row insert into count select count(*) from t;
+begin;
+delete from t where x=0;
+select * from count;
+rollback;
+drop trigger t_delete;
+drop table count;
+
+drop table t; \ No newline at end of file
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_dup_key_nonpart.test b/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_dup_key_nonpart.test
new file mode 100644
index 00000000000..3200beeaba9
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_dup_key_nonpart.test
@@ -0,0 +1,127 @@
+# Verify that index and range scans are not slow
+# on tables during insert select on duplicate key statements
+# due to tokudb bulk fetch not being used.
+# In this test case, the on duplicate key condition does not need to fire
+# since the performance of the embedded select statement is all we are measuring.
+
+source include/have_tokudb.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2;
+enable_warnings;
+
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# Create first table from source table t
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) as select * from t;
+
+# Create second table t2 that will serve as the target for the insert select statment
+CREATE TABLE `t2` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `count` bigint(20) NOT NULL,
+ UNIQUE (num)
+ ) ENGINE=TokuDB DEFAULT CHARSET=latin1;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ INSERT into t2 (num,count) SELECT NULL,count(*) from t1 on DUPLICATE KEY UPDATE count=count+1;
+ inc $i;
+}
+let $time_elapsed_insert_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_insert_select seconds.;
+
+# This check evaluates whether the time elapsed during the insert select on duplicate key statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_insert_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Range scans took $time_elapsed_select seconds.;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ INSERT into t2 (num,count) SELECT NULL,count(*) from t1 where num > 7000000 on DUPLICATE KEY UPDATE count=count+1;
+ inc $i;
+}
+let $time_elapsed_insert_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Range scans took $time_elapsed_insert_select seconds.;
+
+# This check evaluates whether the time elapsed during the insert select on duplicate key statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_insert_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+enable_warnings;
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_nonpart.test b/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_nonpart.test
new file mode 100644
index 00000000000..11f14013a30
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_nonpart.test
@@ -0,0 +1,122 @@
+# Verify that index and range scans are not slow
+# on tables during insert select statements
+# due to tokudb bulk fetch not being used
+
+source include/have_tokudb.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2;
+enable_warnings;
+
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# Create first table from source table t
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) as select * from t;
+
+# Create second table t2 that will serve as the target for the insert select statment
+CREATE TABLE `t2` (
+ `count` bigint(20) NOT NULL
+ ) ENGINE=TokuDB DEFAULT CHARSET=latin1;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ INSERT into t2 SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_insert_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_insert_select seconds.;
+
+# This check evaluates whether the time elapsed during the insert select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_insert_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# This check evaluates whether the time elapsed during the insert select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+#echo Range scans took $time_elapsed_select seconds.;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ INSERT into t2 SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_insert_select = `select to_seconds(now()) - $s`;
+
+# This check evaluates whether the time elapsed during the insert select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+#echo Range scans took $time_elapsed_insert_select seconds.;
+
+# This check evaluates whether the time elapsed during the insert select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_insert_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_trigger.test b/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_trigger.test
new file mode 100644
index 00000000000..337013c9dad
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_trigger.test
@@ -0,0 +1,65 @@
+# verify that various insert triggers can not execute on the source table for an insert select statement
+
+source include/have_tokudb.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists s,t;
+enable_warnings;
+
+create table s (id bigint not null primary key, x bigint);
+insert into s values (1,0),(2,0),(3,0),(4,0);
+
+create table t like s;
+begin;
+insert into t select * from s;
+rollback;
+
+# verify that before insert triggers can not insert into the source table
+create trigger t_trigger before insert on t for each row insert into s values (1000000,0);
+begin;
+error 1442;
+insert into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not insert into the source table
+create trigger t_trigger after insert on t for each row insert into s values (1000000,0);
+begin;
+error 1442;
+insert into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not delete from the source table
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+insert into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not delete from the source table
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+insert into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not update the source table
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+insert into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not update the source table
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+insert into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+drop table s,t;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_update_trigger.test b/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_update_trigger.test
new file mode 100644
index 00000000000..d5addc69076
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_insert_select_update_trigger.test
@@ -0,0 +1,170 @@
+# verify that various insert triggers can not execute on the source table for an insert select statement
+
+source include/have_tokudb.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists s,t;
+enable_warnings;
+
+create table s (id bigint not null primary key, x bigint);
+insert into s values (1,0),(2,0),(3,0),(4,0);
+
+create table t like s;
+begin;
+insert into t select * from s;
+rollback;
+# insert into t values (1,0);
+
+# verify that before insert triggers can not insert into the source table
+create trigger t_trigger before insert on t for each row insert into s values (1000000,0);
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not insert into the source table
+create trigger t_trigger after insert on t for each row insert into s values (1000000,0);
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not delete from the source table
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not delete from the source table
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not update the source table
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not update the source table
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# force duplicate keys
+truncate table t;
+insert into t values (1,0);
+
+# verify that before insert triggers can not insert into the source table
+create trigger t_trigger before insert on t for each row insert into s values (1000000,0);
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not insert into the source table
+create trigger t_trigger after insert on t for each row insert into s values (1000000,0);
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not delete from the source table
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not delete from the source table
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not update the source table
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not update the source table
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# force duplicate keys
+truncate table t;
+insert into t values (1,0);
+
+# verify that before insert triggers can not insert into the source table
+create trigger t_trigger before update on t for each row insert into s values (1000000,0);
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not insert into the source table
+create trigger t_trigger after update on t for each row insert into s values (1000000,0);
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that before update triggers can not delete from the source table
+create trigger t_trigger before update on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not delete from the source table
+create trigger t_trigger after update on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that before update triggers can not update the source table
+create trigger t_trigger before update on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not update the source table
+create trigger t_trigger after update on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+insert into t select * from s on duplicate key update x=t.x+1;
+rollback;
+drop trigger t_trigger;
+
+drop table s,t;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_replace_select_nonpart.test b/storage/tokudb/mysql-test/tokudb/t/bf_replace_select_nonpart.test
new file mode 100644
index 00000000000..380eb5adda8
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_replace_select_nonpart.test
@@ -0,0 +1,190 @@
+# Verify that index and range scans are not slow
+# on tables during replace select and insert ignore statements
+# due to tokudb bulk fetch not being used
+
+source include/have_tokudb.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2;
+enable_warnings;
+
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# Create first table from source table t
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) as select * from t;
+
+# Create second table t2 that will serve as the target for the replace select statment
+CREATE TABLE `t2` (
+ `count` bigint(20) NOT NULL
+ ) ENGINE=TokuDB DEFAULT CHARSET=latin1;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ REPLACE into t2 SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_replace_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_replace_select seconds.;
+
+# This check evaluates whether the time elapsed during the replace select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_replace_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+##############################################################
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ INSERT IGNORE into t2 SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_insert_ignore_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_insert_ignore_select seconds.;
+
+# This check evaluates whether the time elapsed during the insert ignore select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_insert_ignore_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+##################################################################
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Range scans took $time_elapsed_select seconds.;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ REPLACE into t2 SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_replace_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Range scans took $time_elapsed_replace_select seconds.;
+
+# This check evaluates whether the time elapsed during the replace select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_replace_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+####################################################################
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Range scans took $time_elapsed_select seconds.;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ INSERT IGNORE into t2 SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_insert_ignore_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Range scans took $time_elapsed_insert_ignore_select seconds.;
+
+# This check evaluates whether the time elapsed during the insert ignore select statement is on par
+# with the select statement, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_insert_ignore_select - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+
+#########################################################################
+
+drop table t,t1,t2;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_replace_select_trigger.test b/storage/tokudb/mysql-test/tokudb/t/bf_replace_select_trigger.test
new file mode 100644
index 00000000000..6b098ce04af
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_replace_select_trigger.test
@@ -0,0 +1,169 @@
+# verify that various insert and update triggers can not execute on the source table
+# for a replace select statement
+
+source include/have_tokudb.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists s,t;
+enable_warnings;
+
+create table s (id bigint not null primary key, x bigint);
+insert into s values (1,0),(2,0),(3,0),(4,0);
+
+create table t like s;
+begin;
+replace into t select * from s;
+rollback;
+
+# verify that before insert triggers can not replace into the source table
+create trigger t_trigger before insert on t for each row replace into s values (1000000,0);
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not replace into the source table
+create trigger t_trigger after insert on t for each row replace into s values (1000000,0);
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not delete from the source table
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not delete from the source table
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not update the source table
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not update the source table
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+truncate table t;
+insert into t values (1,1);
+
+# verify that before insert triggers can not replace into the source table
+create trigger t_trigger before insert on t for each row replace into s values (1000000,0);
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not replace into the source table
+create trigger t_trigger after insert on t for each row replace into s values (1000000,0);
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not delete from the source table
+create trigger t_trigger before insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not delete from the source table
+create trigger t_trigger after insert on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that before insert triggers can not update the source table
+create trigger t_trigger before insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after insert triggers can not update the source table
+create trigger t_trigger after insert on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+truncate table t;
+insert into t values (1,1);
+
+# verify that before delete triggers can not replace into the source table
+create trigger t_trigger before delete on t for each row replace into s values (1000000,0);
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after delete triggers can not replace into the source table
+create trigger t_trigger after delete on t for each row replace into s values (1000000,0);
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that before delete triggers can not delete from the source table
+create trigger t_trigger before delete on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after delete triggers can not delete from the source table
+create trigger t_trigger after delete on t for each row delete from s where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that before delete triggers can not update the source table
+create trigger t_trigger before delete on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+# verify that after delete triggers can not update the source table
+create trigger t_trigger after delete on t for each row update s set x=x+1 where id=1000000;
+begin;
+error 1442;
+replace into t select * from s;
+rollback;
+drop trigger t_trigger;
+
+
+drop table s,t;
diff --git a/storage/tokudb/mysql-test/tokudb/t/bf_select_part.test b/storage/tokudb/mysql-test/tokudb/t/bf_select_part.test
new file mode 100644
index 00000000000..d9faa4b0bb2
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bf_select_part.test
@@ -0,0 +1,220 @@
+# Verify that index and range scans are not slow
+# on tables during create select statements
+# against hash and range partitioned tables
+# due to tokudb bulk fetch not being used
+
+source include/have_tokudb.inc;
+source include/have_partition.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2,t3;
+enable_warnings;
+
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+INSERT INTO t SELECT null,val FROM t;
+SELECT count(*) FROM t;
+
+# Create first table from source table t
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) as select * from t;
+
+# Create second table from source table t
+CREATE TABLE `t2` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) PARTITION BY HASH (num)
+PARTITIONS 8 as select * from t;
+
+# Create third table from source table t;
+CREATE TABLE `t3` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+) PARTITION BY RANGE (num)
+(PARTITION p0 VALUES LESS THAN (1000000),
+ PARTITION p1 VALUES LESS THAN (2000000),
+ PARTITION p2 VALUES LESS THAN (3000000),
+ PARTITION p3 VALUES LESS THAN (4000000),
+ PARTITION p4 VALUES LESS THAN (5000000),
+ PARTITION p5 VALUES LESS THAN (6000000),
+ PARTITION p6 VALUES LESS THAN (7000000),
+ PARTITION p7 VALUES LESS THAN MAXVALUE) as select * from t;
+
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+# echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t2;
+ inc $i;
+}
+
+let $time_elapsed_select_hash = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+# echo Index scans took $time_elapsed_select_hash seconds.;
+
+# This check evaluates whether the time elapsed during the select statement
+# against a hashed partition table is on par with the select statment
+# against a non-partitioned table, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_select_hash - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+if (!$verdict) { echo index scan t2 $time_elapsed_select_hash $time_elapsed_select; }
+
+######################################################################
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t1;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ SELECT count(*) from t3;
+ inc $i;
+}
+
+let $time_elapsed_select_range = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select_range seconds.;
+
+# This check evaluates whether the time elapsed during the select statement
+# against a range partition table is on par with the select statment
+# against a non-partitioned table, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_select_range - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+if (!$verdict) { echo index scan t3 $time_elapsed_select_range $time_elapsed_select; }
+
+#########################################################################
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t2 where num > 7000000;
+ inc $i;
+}
+
+let $time_elapsed_select_hash = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select_hash seconds.;
+
+
+# This check evaluates whether the time elapsed during the select statement
+# against a hash partition table is on par with the select statment
+# against a non-partitioned table, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_select_hash - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+if (!$verdict) { echo range scan t2 $time_elapsed_select_hash $time_elapsed_select; }
+
+#########################################################################
+
+let $maxrq = 30;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t1 where num > 7000000;
+ inc $i;
+}
+let $time_elapsed_select = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select seconds.;
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxrq) {
+ SELECT count(*) from t3 where num > 7000000;
+ inc $i;
+}
+
+let $time_elapsed_select_range = `select to_seconds(now()) - $s`;
+
+# The following line can be used to display the time elapsed data
+# which could be useful for debugging.
+#echo Index scans took $time_elapsed_select_range seconds.;
+
+
+# This check evaluates whether the time elapsed during the select statement
+# against a range partition table is on par with the select statment
+# against a non-partitioned table, which will confirm that bulk fetch is in fact being used.
+let $verdict = `select abs($time_elapsed_select_range - $time_elapsed_select) <= $time_elapsed_select`;
+echo $verdict;
+if (!$verdict) { echo range scan t3 $time_elapsed_select_range $time_elapsed_select; }
+
+drop table t,t1,t2,t3;
diff --git a/storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_mixed.test b/storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_mixed.test
index 28a11cf302c..9e48d056417 100644
--- a/storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_mixed.test
+++ b/storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_mixed.test
@@ -1,6 +1,6 @@
-source include/master-slave.inc;
source include/have_binlog_format_mixed.inc;
source include/have_tokudb.inc;
+source include/master-slave.inc;
set default_storage_engine='tokudb';
create table tt (id int primary key, x int);
diff --git a/storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_statement.test b/storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_statement.test
index bab2aadb340..90575c615af 100644
--- a/storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_statement.test
+++ b/storage/tokudb/mysql-test/tokudb/t/fast_update_binlog_statement.test
@@ -1,6 +1,6 @@
-source include/master-slave.inc;
source include/have_binlog_format_statement.inc;
source include/have_tokudb.inc;
+source include/master-slave.inc;
set default_storage_engine='tokudb';
create table tt (id int primary key, x int);
diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_released.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_released.test
index 003e98a4c3e..584a657f01e 100644
--- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_released.test
+++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_released.test
@@ -37,10 +37,12 @@ source include/wait_condition.inc;
real_sleep 1; # delay a little to shorten the update -> write row -> lock wait race
replace_column 1 TRX_ID 2 MYSQL_ID;
+replace_result $datadir ./;
select * from information_schema.tokudb_locks;
# should find the presence of a lock_wait on the 2nd transaction
replace_column 1 REQUEST_TRX_ID 2 BLOCK_TRX_ID 6 LOCK_WAITS_START_TIME;
+replace_result $datadir ./;
select * from information_schema.tokudb_lock_waits;
# should find the presence of two transactions
@@ -51,6 +53,7 @@ connection conn_a;
commit;
# verify that the lock on the 1st transaction is released and replaced by the lock for the 2nd transaction
replace_column 1 TRX_ID 2 MYSQL_ID;
+replace_result $datadir ./;
select * from information_schema.tokudb_locks;
select * from information_schema.tokudb_lock_waits;
@@ -87,10 +90,12 @@ source include/wait_condition.inc;
real_sleep 1; # delay a little to shorten the update -> write row -> lock wait race
replace_column 1 TRX_ID 2 MYSQL_ID;
+replace_result $datadir ./;
select * from information_schema.tokudb_locks;
# should find the presence of a lock_wait on the 2nd transaction
replace_column 1 REQUEST_TRX_ID 2 BLOCK_TRX_ID 6 LOCK_WAITS_START_TIME;
+replace_result $datadir ./;
select * from information_schema.tokudb_lock_waits;
# should find the presence of two transactions
@@ -101,6 +106,7 @@ connection conn_a;
commit;
# verify that the lock on the 1st transaction is released and replaced by the lock for the 2nd transaction
replace_column 1 TRX_ID 2 MYSQL_ID;
+replace_result $datadir ./;
select * from information_schema.tokudb_locks;
select * from information_schema.tokudb_lock_waits;
diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test
index d7925733a0f..75929fa3b3d 100644
--- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test
+++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test
@@ -30,10 +30,12 @@ source include/wait_condition.inc;
real_sleep 1; # delay a little to shorten the update -> write row -> lock wait race
replace_column 1 TRX_ID 2 MYSQL_ID;
+replace_result $datadir ./;
select * from information_schema.tokudb_locks;
# should find the presence of a lock_wait on the 2nd transaction
replace_column 1 REQUEST_TRX_ID 2 BLOCK_TRX_ID 6 LOCK_WAITS_START_TIME;
+replace_result $datadir ./;
select * from information_schema.tokudb_lock_waits;
# should find the presence of two transactions
diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test
index e5a67559b1a..617b487f043 100644
--- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test
+++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test
@@ -29,6 +29,7 @@ insert into t values (6);
# should find 3 locks for 2 transactions
connection default;
replace_column 1 TRX_ID 2 MYSQL_ID;
+replace_result $datadir ./;
eval select * from information_schema.tokudb_locks order by locks_trx_id,locks_key_left;
connection conn_a;
@@ -42,4 +43,4 @@ commit;
disconnect conn_a;
-drop table t; \ No newline at end of file
+drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks_released.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks_released.test
index 1bd2c6614ac..eac0f6da418 100644
--- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks_released.test
+++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks_released.test
@@ -36,12 +36,14 @@ source include/wait_condition.inc;
real_sleep 1; # delay a little to shorten the update -> write row -> lock wait race
replace_column 1 TRX_ID 2 MYSQL_ID;
+replace_result $datadir ./;
eval select * from information_schema.tokudb_locks;
connection conn_a;
commit;
# verify that the lock on the 1st transaction is released and replaced by the lock for the 2nd transaction
replace_column 1 TRX_ID 2 MYSQL_ID;
+replace_result $datadir ./;
select * from information_schema.tokudb_locks;
connection conn_b;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/mdev5932.result b/storage/tokudb/mysql-test/tokudb_bugs/r/mdev5932.result
index 2aaa321fed6..f179ee36f95 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/mdev5932.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/mdev5932.result
@@ -1,5 +1,6 @@
drop table if exists t1,t2;
drop table if exists t1i,t2i;
+drop table if exists tsub,t3;
CREATE TABLE t1 (a CHAR(3), INDEX(a)) ENGINE=TokuDB;
INSERT INTO t1 VALUES ('foo'),( NULL);
SELECT * FROM t1 WHERE 'bar' NOT IN ( SELECT t1_1.a FROM t1 AS t1_1, t1 AS t1_2 );
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/part_index_scan.result b/storage/tokudb/mysql-test/tokudb_bugs/r/part_index_scan.result
new file mode 100644
index 00000000000..0d416c734b7
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/part_index_scan.result
@@ -0,0 +1,248 @@
+set default_storage_engine='tokudb';
+drop table if exists t,t1,t2,t3;
+CREATE TABLE `t` (
+`num` int(10) unsigned auto_increment NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+SELECT count(*) FROM t;
+count(*)
+8388608
+CREATE TABLE `t1` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+);
+CREATE TABLE `t2` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+)
+PARTITION BY HASH (num) PARTITIONS 10;
+CREATE TABLE `t3` (
+`num` int(10) unsigned NOT NULL,
+`val` varchar(32) DEFAULT NULL,
+PRIMARY KEY (`num`)
+)
+PARTITION BY RANGE (num)
+(PARTITION p0 VALUES LESS THAN (1000000),
+PARTITION p1 VALUES LESS THAN (2000000),
+PARTITION p2 VALUES LESS THAN (3000000),
+PARTITION p3 VALUES LESS THAN (4000000),
+PARTITION p4 VALUES LESS THAN (5000000),
+PARTITION p5 VALUES LESS THAN (6000000),
+PARTITION p6 VALUES LESS THAN (7000000),
+PARTITION p7 VALUES LESS THAN (8000000),
+PARTITION px VALUES LESS THAN MAXVALUE);
+insert into t1 select * from t;
+insert into t2 select * from t;
+insert into t3 select * from t;
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t1;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+select count(*) from t2;
+count(*)
+8388608
+1
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+select count(*) from t3;
+count(*)
+8388608
+1
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t1 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+select count(*) from t2 where num>7000000;
+count(*)
+1847274
+1
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+select count(*) from t3 where num>7000000;
+count(*)
+1847274
+1
+drop table if exists t,t1,t2,t3;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result b/storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result
index 7b4e16df207..841642132a3 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/simple_icp.result
@@ -149,7 +149,7 @@ Variable_name Value
Handler_read_next 0
explain select * from foo where a > 19 and c=10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE foo range a a 5 NULL 1402 Using where
+1 SIMPLE foo range a a 5 NULL 1408 Using where
select * from foo where a > 19 and c=10;
a b c d e
20 1 10 NULL NULL
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/mdev5932.test b/storage/tokudb/mysql-test/tokudb_bugs/t/mdev5932.test
index 34a1f7eab82..879b57ade63 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/mdev5932.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/mdev5932.test
@@ -4,6 +4,7 @@ source include/have_innodb.inc;
disable_warnings;
drop table if exists t1,t2;
drop table if exists t1i,t2i;
+drop table if exists tsub,t3;
enable_warnings;
CREATE TABLE t1 (a CHAR(3), INDEX(a)) ENGINE=TokuDB;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/part_index_scan.test b/storage/tokudb/mysql-test/tokudb_bugs/t/part_index_scan.test
new file mode 100644
index 00000000000..b38a979752b
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/part_index_scan.test
@@ -0,0 +1,157 @@
+# verify that index scans on parititions are not slow
+# due to tokudb bulk fetch not being used
+
+source include/have_tokudb.inc;
+source include/have_partition.inc;
+source include/big_test.inc;
+set default_storage_engine='tokudb';
+disable_warnings;
+drop table if exists t,t1,t2,t3;
+enable_warnings;
+
+let $debug = 0;
+let $maxq = 10;
+
+CREATE TABLE `t` (
+ `num` int(10) unsigned auto_increment NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+# put 8M rows into t
+if ($debug) { let $ts = `select now()`; echo "start $ts"; }
+INSERT INTO t values (null,null);
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+INSERT INTO t SELECT null,null FROM t;
+if ($debug) { let $ts = `select now()`; echo "select $ts"; }
+SELECT count(*) FROM t;
+if ($debug) { let $ts = `select now()`; echo "select done $ts"; }
+
+CREATE TABLE `t1` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+);
+
+CREATE TABLE `t2` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+)
+PARTITION BY HASH (num) PARTITIONS 10;
+
+CREATE TABLE `t3` (
+ `num` int(10) unsigned NOT NULL,
+ `val` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`num`)
+)
+PARTITION BY RANGE (num)
+(PARTITION p0 VALUES LESS THAN (1000000),
+ PARTITION p1 VALUES LESS THAN (2000000),
+ PARTITION p2 VALUES LESS THAN (3000000),
+ PARTITION p3 VALUES LESS THAN (4000000),
+ PARTITION p4 VALUES LESS THAN (5000000),
+ PARTITION p5 VALUES LESS THAN (6000000),
+ PARTITION p6 VALUES LESS THAN (7000000),
+ PARTITION p7 VALUES LESS THAN (8000000),
+ PARTITION px VALUES LESS THAN MAXVALUE);
+
+if ($debug) { let $ts = `select now()`; echo "insert t1 $ts"; }
+insert into t1 select * from t;
+if ($debug) { let $ts = `select now()`; echo "insert t2 $ts"; }
+insert into t2 select * from t;
+if ($debug) { let $ts = `select now()`; echo "insert t3 $ts"; }
+insert into t3 select * from t;
+if ($debug) { let $ts = `select now()`; echo "select t1 $ts"; }
+
+# verify that full index scans on partitioned tables t2 and t3 are comparable to a non-partitioned table t1
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ select count(*) from t1;
+ inc $i;
+}
+let $t1 = `select to_seconds(now()) - $s`;
+
+if ($debug) { let $ts = `select now()`; echo "select t2 $ts"; }
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ select count(*) from t2;
+ inc $i;
+}
+let $t2 = `select to_seconds(now()) - $s`;
+let $d = `select abs($t2 - $t1) <= $t1`;
+echo $d;
+
+if ($debug) { let $ts = `select now()`; echo "select t3 $ts"; }
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ select count(*) from t3;
+ inc $i;
+}
+let $t3 = `select to_seconds(now()) - $s`;
+let $d = `select abs($t3 - $t1) <= $t1`;
+echo $d;
+
+if ($debug) { let $ts = `select now()`; echo "select t1 $ts"; }
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ select count(*) from t1 where num>7000000;
+ inc $i;
+}
+let $t1 = `select to_seconds(now()) - $s`;
+
+if ($debug) { let $ts = `select now()`; echo "select t2 $ts"; }
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ select count(*) from t2 where num>7000000;
+ inc $i;
+}
+let $t2 = `select to_seconds(now()) - $s`;
+let $d = `select abs($t2 - $t1) <= $t1`;
+echo $d;
+
+if ($debug) { let $ts = `select now()`; echo "select t3 $ts"; }
+
+let $s = `select to_seconds(now())`;
+let $i = 0;
+while ($i < $maxq) {
+ select count(*) from t3 where num>7000000;
+ inc $i;
+}
+let $t3 = `select to_seconds(now()) - $s`;
+let $d = `select abs($t3 - $t1) <= $t1`;
+echo $d;
+
+if ($debug) { let $ts = `select now()`; echo "done $ts"; }
+
+drop table if exists t,t1,t2,t3;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_mixed_replace_into.test b/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_mixed_replace_into.test
index 05e6e2fb228..2f53ee5f118 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_mixed_replace_into.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_mixed_replace_into.test
@@ -1,6 +1,6 @@
source include/have_tokudb.inc;
-source include/master-slave.inc;
source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
set default_storage_engine='tokudb';
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_row_replace_into.test b/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_row_replace_into.test
index 062f11e0ed9..b44877e9fa5 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_row_replace_into.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_row_replace_into.test
@@ -1,6 +1,6 @@
source include/have_tokudb.inc;
-source include/master-slave.inc;
source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
set default_storage_engine='tokudb';
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_stmt_replace_into.test b/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_stmt_replace_into.test
index f7e4c7a09e0..d1d0ef11f1b 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_stmt_replace_into.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/rpl_stmt_replace_into.test
@@ -1,6 +1,6 @@
source include/have_tokudb.inc;
-source include/master-slave.inc;
source include/have_binlog_format_statement.inc;
+source include/master-slave.inc;
set default_storage_engine='tokudb';
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/xa-3.test b/storage/tokudb/mysql-test/tokudb_bugs/t/xa-3.test
index 4bca18ad109..116d5b5d99b 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/xa-3.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/xa-3.test
@@ -1,6 +1,7 @@
-- source include/have_innodb.inc
-- source include/have_tokudb.inc
-- source include/have_debug.inc
+-- source include/not_embedded.inc
--disable_warnings
drop table if exists t1, t2;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/xa-4.test b/storage/tokudb/mysql-test/tokudb_bugs/t/xa-4.test
index 5e4071c7b93..014b371630f 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/xa-4.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/xa-4.test
@@ -1,6 +1,7 @@
-- source include/have_innodb.inc
-- source include/have_tokudb.inc
-- source include/have_debug.inc
+-- source include/not_embedded.inc
--disable_warnings
drop table if exists t1, t2;
diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/r/autoinc.result b/storage/tokudb/mysql-test/tokudb_mariadb/r/autoinc.result
new file mode 100644
index 00000000000..3d424357736
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_mariadb/r/autoinc.result
@@ -0,0 +1,36 @@
+create table t1 (a int auto_increment, b bigint(20), primary key (b,a)) engine=tokudb;
+start transaction;
+insert t1 (b) values (1);
+set tokudb_lock_timeout=1;
+insert t1 (b) values (1);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+set tokudb_lock_timeout=default;
+insert t1 (b) values (1);
+insert t1 (b) values (1);
+commit;
+commit;
+select * from t1;
+a b
+1 1
+2 1
+3 1
+alter table t1 partition by range (b) (partition p0 values less than (9));
+start transaction;
+insert t1 (b) values (2);
+set tokudb_lock_timeout=1;
+insert t1 (b) values (2);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+set tokudb_lock_timeout=default;
+insert t1 (b) values (2);
+insert t1 (b) values (2);
+commit;
+commit;
+select * from t1;
+a b
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+drop table t1;
diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/t/autoinc.test b/storage/tokudb/mysql-test/tokudb_mariadb/t/autoinc.test
new file mode 100644
index 00000000000..99fd5333920
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_mariadb/t/autoinc.test
@@ -0,0 +1,51 @@
+#
+# MDEV-6605 Multiple Clients Inserting Causing Error: Failed to read auto-increment value from storage engine
+#
+
+--source include/have_partition.inc
+create table t1 (a int auto_increment, b bigint(20), primary key (b,a)) engine=tokudb;
+
+# first, without partitions
+start transaction;
+insert t1 (b) values (1);
+
+--connect(con2,localhost,root)
+set tokudb_lock_timeout=1;
+# auto-inc value is locked
+--error ER_LOCK_WAIT_TIMEOUT
+insert t1 (b) values (1);
+# but no deadlock
+set tokudb_lock_timeout=default;
+--send insert t1 (b) values (1)
+--connection default
+insert t1 (b) values (1);
+commit;
+--connection con2
+--reap
+commit;
+select * from t1;
+
+# now with partitions
+--connection default
+alter table t1 partition by range (b) (partition p0 values less than (9));
+start transaction;
+insert t1 (b) values (2);
+
+--connection con2
+set tokudb_lock_timeout=1;
+# auto-inc value is locked
+--error ER_LOCK_WAIT_TIMEOUT
+insert t1 (b) values (2);
+# but no deadlock
+set tokudb_lock_timeout=default;
+--send insert t1 (b) values (2)
+--connection default
+insert t1 (b) values (2);
+commit;
+--connection con2
+--reap
+commit;
+select * from t1;
+
+drop table t1;
+
diff --git a/storage/tokudb/scripts/atc.ontime/atc_ontime_create.sql b/storage/tokudb/scripts/atc.ontime/atc_ontime_create.sql
deleted file mode 100644
index 72148f81d6f..00000000000
--- a/storage/tokudb/scripts/atc.ontime/atc_ontime_create.sql
+++ /dev/null
@@ -1,95 +0,0 @@
-CREATE TABLE `ontime` (
- `Year` year(4) DEFAULT NULL,
- `Quarter` tinyint(4) DEFAULT NULL,
- `Month` tinyint(4) DEFAULT NULL,
- `DayofMonth` tinyint(4) DEFAULT NULL,
- `DayOfWeek` tinyint(4) DEFAULT NULL,
- `FlightDate` date DEFAULT NULL,
- `UniqueCarrier` char(7) DEFAULT NULL,
- `AirlineID` int(11) DEFAULT NULL,
- `Carrier` char(2) DEFAULT NULL,
- `TailNum` varchar(50) DEFAULT NULL,
- `FlightNum` varchar(10) DEFAULT NULL,
- `Origin` char(5) DEFAULT NULL,
- `OriginCityName` varchar(100) DEFAULT NULL,
- `OriginState` char(2) DEFAULT NULL,
- `OriginStateFips` varchar(10) DEFAULT NULL,
- `OriginStateName` varchar(100) DEFAULT NULL,
- `OriginWac` int(11) DEFAULT NULL,
- `Dest` char(5) DEFAULT NULL,
- `DestCityName` varchar(100) DEFAULT NULL,
- `DestState` char(2) DEFAULT NULL,
- `DestStateFips` varchar(10) DEFAULT NULL,
- `DestStateName` varchar(100) DEFAULT NULL,
- `DestWac` int(11) DEFAULT NULL,
- `CRSDepTime` int(11) DEFAULT NULL,
- `DepTime` int(11) DEFAULT NULL,
- `DepDelay` int(11) DEFAULT NULL,
- `DepDelayMinutes` int(11) DEFAULT NULL,
- `DepDel15` int(11) DEFAULT NULL,
- `DepartureDelayGroups` int(11) DEFAULT NULL,
- `DepTimeBlk` varchar(20) DEFAULT NULL,
- `TaxiOut` int(11) DEFAULT NULL,
- `WheelsOff` int(11) DEFAULT NULL,
- `WheelsOn` int(11) DEFAULT NULL,
- `TaxiIn` int(11) DEFAULT NULL,
- `CRSArrTime` int(11) DEFAULT NULL,
- `ArrTime` int(11) DEFAULT NULL,
- `ArrDelay` int(11) DEFAULT NULL,
- `ArrDelayMinutes` int(11) DEFAULT NULL,
- `ArrDel15` int(11) DEFAULT NULL,
- `ArrivalDelayGroups` int(11) DEFAULT NULL,
- `ArrTimeBlk` varchar(20) DEFAULT NULL,
- `Cancelled` tinyint(4) DEFAULT NULL,
- `CancellationCode` char(1) DEFAULT NULL,
- `Diverted` tinyint(4) DEFAULT NULL,
- `CRSElapsedTime` INT(11) DEFAULT NULL,
- `ActualElapsedTime` INT(11) DEFAULT NULL,
- `AirTime` INT(11) DEFAULT NULL,
- `Flights` INT(11) DEFAULT NULL,
- `Distance` INT(11) DEFAULT NULL,
- `DistanceGroup` TINYINT(4) DEFAULT NULL,
- `CarrierDelay` INT(11) DEFAULT NULL,
- `WeatherDelay` INT(11) DEFAULT NULL,
- `NASDelay` INT(11) DEFAULT NULL,
- `SecurityDelay` INT(11) DEFAULT NULL,
- `LateAircraftDelay` INT(11) DEFAULT NULL,
- `FirstDepTime` varchar(10) DEFAULT NULL,
- `TotalAddGTime` varchar(10) DEFAULT NULL,
- `LongestAddGTime` varchar(10) DEFAULT NULL,
- `DivAirportLandings` varchar(10) DEFAULT NULL,
- `DivReachedDest` varchar(10) DEFAULT NULL,
- `DivActualElapsedTime` varchar(10) DEFAULT NULL,
- `DivArrDelay` varchar(10) DEFAULT NULL,
- `DivDistance` varchar(10) DEFAULT NULL,
- `Div1Airport` varchar(10) DEFAULT NULL,
- `Div1WheelsOn` varchar(10) DEFAULT NULL,
- `Div1TotalGTime` varchar(10) DEFAULT NULL,
- `Div1LongestGTime` varchar(10) DEFAULT NULL,
- `Div1WheelsOff` varchar(10) DEFAULT NULL,
- `Div1TailNum` varchar(10) DEFAULT NULL,
- `Div2Airport` varchar(10) DEFAULT NULL,
- `Div2WheelsOn` varchar(10) DEFAULT NULL,
- `Div2TotalGTime` varchar(10) DEFAULT NULL,
- `Div2LongestGTime` varchar(10) DEFAULT NULL,
- `Div2WheelsOff` varchar(10) DEFAULT NULL,
- `Div2TailNum` varchar(10) DEFAULT NULL,
- `Div3Airport` varchar(10) DEFAULT NULL,
- `Div3WheelsOn` varchar(10) DEFAULT NULL,
- `Div3TotalGTime` varchar(10) DEFAULT NULL,
- `Div3LongestGTime` varchar(10) DEFAULT NULL,
- `Div3WheelsOff` varchar(10) DEFAULT NULL,
- `Div3TailNum` varchar(10) DEFAULT NULL,
- `Div4Airport` varchar(10) DEFAULT NULL,
- `Div4WheelsOn` varchar(10) DEFAULT NULL,
- `Div4TotalGTime` varchar(10) DEFAULT NULL,
- `Div4LongestGTime` varchar(10) DEFAULT NULL,
- `Div4WheelsOff` varchar(10) DEFAULT NULL,
- `Div4TailNum` varchar(10) DEFAULT NULL,
- `Div5Airport` varchar(10) DEFAULT NULL,
- `Div5WheelsOn` varchar(10) DEFAULT NULL,
- `Div5TotalGTime` varchar(10) DEFAULT NULL,
- `Div5LongestGTime` varchar(10) DEFAULT NULL,
- `Div5WheelsOff` varchar(10) DEFAULT NULL,
- `Div5TailNum` varchar(10) DEFAULT NULL
-) ENGINE=TOKUDB; \ No newline at end of file
diff --git a/storage/tokudb/scripts/atc.ontime/atc_ontime_create_covered.sql b/storage/tokudb/scripts/atc.ontime/atc_ontime_create_covered.sql
deleted file mode 100644
index 4ea091409c5..00000000000
--- a/storage/tokudb/scripts/atc.ontime/atc_ontime_create_covered.sql
+++ /dev/null
@@ -1,103 +0,0 @@
-CREATE TABLE `ontime` (
- `Year` year(4) DEFAULT NULL,
- `Quarter` tinyint(4) DEFAULT NULL,
- `Month` tinyint(4) DEFAULT NULL,
- `DayofMonth` tinyint(4) DEFAULT NULL,
- `DayOfWeek` tinyint(4) DEFAULT NULL,
- `FlightDate` date DEFAULT NULL,
- `UniqueCarrier` char(7) DEFAULT NULL,
- `AirlineID` int(11) DEFAULT NULL,
- `Carrier` char(2) DEFAULT NULL,
- `TailNum` varchar(50) DEFAULT NULL,
- `FlightNum` varchar(10) DEFAULT NULL,
- `Origin` char(5) DEFAULT NULL,
- `OriginCityName` varchar(100) DEFAULT NULL,
- `OriginState` char(2) DEFAULT NULL,
- `OriginStateFips` varchar(10) DEFAULT NULL,
- `OriginStateName` varchar(100) DEFAULT NULL,
- `OriginWac` int(11) DEFAULT NULL,
- `Dest` char(5) DEFAULT NULL,
- `DestCityName` varchar(100) DEFAULT NULL,
- `DestState` char(2) DEFAULT NULL,
- `DestStateFips` varchar(10) DEFAULT NULL,
- `DestStateName` varchar(100) DEFAULT NULL,
- `DestWac` int(11) DEFAULT NULL,
- `CRSDepTime` int(11) DEFAULT NULL,
- `DepTime` int(11) DEFAULT NULL,
- `DepDelay` int(11) DEFAULT NULL,
- `DepDelayMinutes` int(11) DEFAULT NULL,
- `DepDel15` int(11) DEFAULT NULL,
- `DepartureDelayGroups` int(11) DEFAULT NULL,
- `DepTimeBlk` varchar(20) DEFAULT NULL,
- `TaxiOut` int(11) DEFAULT NULL,
- `WheelsOff` int(11) DEFAULT NULL,
- `WheelsOn` int(11) DEFAULT NULL,
- `TaxiIn` int(11) DEFAULT NULL,
- `CRSArrTime` int(11) DEFAULT NULL,
- `ArrTime` int(11) DEFAULT NULL,
- `ArrDelay` int(11) DEFAULT NULL,
- `ArrDelayMinutes` int(11) DEFAULT NULL,
- `ArrDel15` int(11) DEFAULT NULL,
- `ArrivalDelayGroups` int(11) DEFAULT NULL,
- `ArrTimeBlk` varchar(20) DEFAULT NULL,
- `Cancelled` tinyint(4) DEFAULT NULL,
- `CancellationCode` char(1) DEFAULT NULL,
- `Diverted` tinyint(4) DEFAULT NULL,
- `CRSElapsedTime` INT(11) DEFAULT NULL,
- `ActualElapsedTime` INT(11) DEFAULT NULL,
- `AirTime` INT(11) DEFAULT NULL,
- `Flights` INT(11) DEFAULT NULL,
- `Distance` INT(11) DEFAULT NULL,
- `DistanceGroup` TINYINT(4) DEFAULT NULL,
- `CarrierDelay` INT(11) DEFAULT NULL,
- `WeatherDelay` INT(11) DEFAULT NULL,
- `NASDelay` INT(11) DEFAULT NULL,
- `SecurityDelay` INT(11) DEFAULT NULL,
- `LateAircraftDelay` INT(11) DEFAULT NULL,
- `FirstDepTime` varchar(10) DEFAULT NULL,
- `TotalAddGTime` varchar(10) DEFAULT NULL,
- `LongestAddGTime` varchar(10) DEFAULT NULL,
- `DivAirportLandings` varchar(10) DEFAULT NULL,
- `DivReachedDest` varchar(10) DEFAULT NULL,
- `DivActualElapsedTime` varchar(10) DEFAULT NULL,
- `DivArrDelay` varchar(10) DEFAULT NULL,
- `DivDistance` varchar(10) DEFAULT NULL,
- `Div1Airport` varchar(10) DEFAULT NULL,
- `Div1WheelsOn` varchar(10) DEFAULT NULL,
- `Div1TotalGTime` varchar(10) DEFAULT NULL,
- `Div1LongestGTime` varchar(10) DEFAULT NULL,
- `Div1WheelsOff` varchar(10) DEFAULT NULL,
- `Div1TailNum` varchar(10) DEFAULT NULL,
- `Div2Airport` varchar(10) DEFAULT NULL,
- `Div2WheelsOn` varchar(10) DEFAULT NULL,
- `Div2TotalGTime` varchar(10) DEFAULT NULL,
- `Div2LongestGTime` varchar(10) DEFAULT NULL,
- `Div2WheelsOff` varchar(10) DEFAULT NULL,
- `Div2TailNum` varchar(10) DEFAULT NULL,
- `Div3Airport` varchar(10) DEFAULT NULL,
- `Div3WheelsOn` varchar(10) DEFAULT NULL,
- `Div3TotalGTime` varchar(10) DEFAULT NULL,
- `Div3LongestGTime` varchar(10) DEFAULT NULL,
- `Div3WheelsOff` varchar(10) DEFAULT NULL,
- `Div3TailNum` varchar(10) DEFAULT NULL,
- `Div4Airport` varchar(10) DEFAULT NULL,
- `Div4WheelsOn` varchar(10) DEFAULT NULL,
- `Div4TotalGTime` varchar(10) DEFAULT NULL,
- `Div4LongestGTime` varchar(10) DEFAULT NULL,
- `Div4WheelsOff` varchar(10) DEFAULT NULL,
- `Div4TailNum` varchar(10) DEFAULT NULL,
- `Div5Airport` varchar(10) DEFAULT NULL,
- `Div5WheelsOn` varchar(10) DEFAULT NULL,
- `Div5TotalGTime` varchar(10) DEFAULT NULL,
- `Div5LongestGTime` varchar(10) DEFAULT NULL,
- `Div5WheelsOff` varchar(10) DEFAULT NULL,
- `Div5TailNum` varchar(10) DEFAULT NULL,
- KEY `Year` (`Year`,`Month`),
- KEY `Year_2` (`Year`,`DayOfWeek`),
- KEY `Year_3` (`Year`,`DepDelay`,`DayOfWeek`),
- KEY `DayOfWeek` (`DayOfWeek`,`Year`,`DepDelay`),
- KEY `Year_4` (`Year`,`DepDelay`,`Origin`,`Carrier`),
- KEY `DepDelay` (`DepDelay`,`Year`),
- KEY `Year_5` (`Year`,`DestCityName`,`OriginCityName`),
- KEY `DestCityName` (`DestCityName`,`OriginCityName`,`Year`)
-) ENGINE=TOKUDB; \ No newline at end of file
diff --git a/storage/tokudb/scripts/atc.ontime/nodistinct.q8.sql b/storage/tokudb/scripts/atc.ontime/nodistinct.q8.sql
deleted file mode 100644
index 547d6fa08e0..00000000000
--- a/storage/tokudb/scripts/atc.ontime/nodistinct.q8.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-# Q8: As final I tested most popular destination in sense count of direct connected cities for different diapason of years.
-SELECT DestCityName, COUNT( OriginCityName) FROM ontime WHERE Year BETWEEN 2006 and 2007 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q0.result b/storage/tokudb/scripts/atc.ontime/q0.result
deleted file mode 100644
index 457e3b525de..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q0.result
+++ /dev/null
@@ -1,2 +0,0 @@
-avg(c1)
-485021.3730
diff --git a/storage/tokudb/scripts/atc.ontime/q0.sql b/storage/tokudb/scripts/atc.ontime/q0.sql
deleted file mode 100644
index 258c88927b2..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q0.sql
+++ /dev/null
@@ -1 +0,0 @@
-select avg(c1) from (select year,month,count(*) as c1 from ontime group by YEAR,month) t;
diff --git a/storage/tokudb/scripts/atc.ontime/q1.result b/storage/tokudb/scripts/atc.ontime/q1.result
deleted file mode 100644
index e1f9df4d004..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q1.result
+++ /dev/null
@@ -1,8 +0,0 @@
-DayOfWeek c
-5 8732424
-1 8730614
-4 8710843
-3 8685626
-2 8639632
-7 8274367
-6 7514194
diff --git a/storage/tokudb/scripts/atc.ontime/q1.sql b/storage/tokudb/scripts/atc.ontime/q1.sql
deleted file mode 100644
index e155da8fc3d..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q1.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DayOfWeek, count(*) AS c FROM ontime WHERE Year BETWEEN 2000 AND 2008 GROUP BY DayOfWeek ORDER BY c DESC;
diff --git a/storage/tokudb/scripts/atc.ontime/q2.result b/storage/tokudb/scripts/atc.ontime/q2.result
deleted file mode 100644
index 0f88b842f45..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q2.result
+++ /dev/null
@@ -1,8 +0,0 @@
-DayOfWeek c
-5 2088300
-4 1918325
-1 1795120
-7 1782292
-3 1640798
-2 1538291
-6 1391984
diff --git a/storage/tokudb/scripts/atc.ontime/q2.sql b/storage/tokudb/scripts/atc.ontime/q2.sql
deleted file mode 100644
index 9d31ecd0ec5..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q2.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DayOfWeek, count(*) AS c FROM ontime WHERE DepDelay>10 AND Year BETWEEN 2000 AND 2008 GROUP BY DayOfWeek ORDER BY c DESC;
diff --git a/storage/tokudb/scripts/atc.ontime/q3.result b/storage/tokudb/scripts/atc.ontime/q3.result
deleted file mode 100644
index ecacefe261e..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q3.result
+++ /dev/null
@@ -1,11 +0,0 @@
-Origin c
-ORD 846692
-ATL 822955
-DFW 601318
-LAX 391247
-PHX 391191
-LAS 351713
-DEN 345108
-EWR 292916
-DTW 289233
-IAH 283861
diff --git a/storage/tokudb/scripts/atc.ontime/q3.sql b/storage/tokudb/scripts/atc.ontime/q3.sql
deleted file mode 100644
index 9daa49cda68..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q3.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT Origin, count(*) AS c FROM ontime WHERE DepDelay>10 AND Year BETWEEN 2000 AND 2008 GROUP BY Origin ORDER BY c DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q4.result b/storage/tokudb/scripts/atc.ontime/q4.result
deleted file mode 100644
index 1de2cf2c5d2..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q4.result
+++ /dev/null
@@ -1,21 +0,0 @@
-carrier count(*)
-WN 296293
-AA 176203
-MQ 145630
-US 135987
-UA 128174
-OO 127426
-EV 101796
-XE 99915
-DL 93675
-NW 90429
-CO 76662
-YV 67905
-FL 59460
-OH 59034
-B6 50740
-9E 46948
-AS 42830
-F9 23035
-AQ 4299
-HA 2746
diff --git a/storage/tokudb/scripts/atc.ontime/q4.sql b/storage/tokudb/scripts/atc.ontime/q4.sql
deleted file mode 100644
index 20447cd17ce..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q4.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT carrier, count(*) FROM ontime WHERE DepDelay>10 AND Year=2007 GROUP BY carrier ORDER BY 2 DESC;
diff --git a/storage/tokudb/scripts/atc.ontime/q5.result b/storage/tokudb/scripts/atc.ontime/q5.result
deleted file mode 100644
index a790800d53f..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q5.result
+++ /dev/null
@@ -1,21 +0,0 @@
-carrier c c2 c3
-EV 101796 286234 355.6391
-US 135987 485447 280.1274
-AA 176203 633857 277.9854
-MQ 145630 540494 269.4387
-AS 42830 160185 267.3783
-B6 50740 191450 265.0300
-UA 128174 490002 261.5785
-WN 296293 1168871 253.4865
-OH 59034 236032 250.1102
-CO 76662 323151 237.2327
-F9 23035 97760 235.6281
-YV 67905 294362 230.6853
-XE 99915 434773 229.8096
-FL 59460 263159 225.9471
-NW 90429 414526 218.1504
-OO 127426 597880 213.1297
-DL 93675 475889 196.8421
-9E 46948 258851 181.3707
-AQ 4299 46360 92.7308
-HA 2746 56175 48.8830
diff --git a/storage/tokudb/scripts/atc.ontime/q5.sql b/storage/tokudb/scripts/atc.ontime/q5.sql
deleted file mode 100644
index 59e5c8b95db..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q5.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT t.carrier, c, c2, c*1000/c2 as c3 FROM (SELECT carrier, count(*) AS c FROM ontime WHERE DepDelay>10 AND Year=2007 GROUP BY carrier) t JOIN (SELECT carrier, count(*) AS c2 FROM ontime WHERE Year=2007 GROUP BY carrier) t2 ON (t.Carrier=t2.Carrier) ORDER BY c3 DESC;
diff --git a/storage/tokudb/scripts/atc.ontime/q6.result b/storage/tokudb/scripts/atc.ontime/q6.result
deleted file mode 100644
index 85a1db42079..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q6.result
+++ /dev/null
@@ -1,21 +0,0 @@
-carrier c c2 c3
-UA 1096646 490002 2238.0439
-AS 354145 160185 2210.8500
-DL 1050448 475889 2207.3383
-AA 1276555 633857 2013.9479
-US 909154 485447 1872.8182
-WN 2165483 1168871 1852.6279
-NW 725076 414526 1749.1689
-MQ 876799 540494 1622.2178
-CO 522219 323151 1616.0216
-EV 461050 286234 1610.7451
-OH 301681 236032 1278.1360
-FL 298916 263159 1135.8760
-B6 197249 191450 1030.2899
-OO 556247 597880 930.3656
-F9 72150 97760 738.0319
-YV 198787 294362 675.3147
-XE 233488 434773 537.0343
-AQ 17239 46360 371.8507
-9E 89391 258851 345.3377
-HA 15968 56175 284.2546
diff --git a/storage/tokudb/scripts/atc.ontime/q6.sql b/storage/tokudb/scripts/atc.ontime/q6.sql
deleted file mode 100644
index 9ac157c9ac0..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q6.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT t.carrier, c, c2, c*1000/c2 as c3 FROM (SELECT carrier, count(*) AS c FROM ontime WHERE DepDelay>10 AND Year BETWEEN 2000 and 2008 GROUP BY carrier) t JOIN (SELECT carrier, count(*) AS c2 FROM ontime WHERE Year=2007 GROUP BY carrier) t2 ON (t.Carrier=t2.Carrier) ORDER BY c3 DESC;
diff --git a/storage/tokudb/scripts/atc.ontime/q7.result b/storage/tokudb/scripts/atc.ontime/q7.result
deleted file mode 100644
index ffc0236300d..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q7.result
+++ /dev/null
@@ -1,22 +0,0 @@
-Year c1/c2
-1988 166.1709
-1989 199.5009
-1990 166.4513
-1991 147.2163
-1992 146.7543
-1993 154.2498
-1994 165.6803
-1995 193.9344
-1996 221.8281
-1997 191.6513
-1998 193.5638
-1999 200.8742
-2000 231.7167
-2001 189.0581
-2002 162.3769
-2003 150.2455
-2004 192.4838
-2005 207.5929
-2006 231.5599
-2007 245.3487
-2008 219.9228
diff --git a/storage/tokudb/scripts/atc.ontime/q7.sql b/storage/tokudb/scripts/atc.ontime/q7.sql
deleted file mode 100644
index d0313c06dee..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q7.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT t.Year, c1/c2 FROM (select Year,count(*)*1000 as c1 from ontime WHERE DepDelay>10 GROUP BY Year) t JOIN (select Year,count(*) as c2 from ontime GROUP BY Year) t2 ON (t.Year=t2.Year);
diff --git a/storage/tokudb/scripts/atc.ontime/q8.10y.destcityname.result b/storage/tokudb/scripts/atc.ontime/q8.10y.destcityname.result
deleted file mode 100644
index e98b44c790b..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.10y.destcityname.result
+++ /dev/null
@@ -1,11 +0,0 @@
-DestCityName COUNT( DISTINCT OriginCityName)
-Atlanta, GA 190
-Chicago, IL 159
-Dallas/Ft.Worth, TX 151
-Cincinnati, OH 139
-Minneapolis, MN 131
-Houston, TX 127
-Detroit, MI 121
-Denver, CO 120
-Salt Lake City, UT 116
-New York, NY 111
diff --git a/storage/tokudb/scripts/atc.ontime/q8.10y.destcityname.sql b/storage/tokudb/scripts/atc.ontime/q8.10y.destcityname.sql
deleted file mode 100644
index 6ae5b91a54c..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.10y.destcityname.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime FORCE INDEX(DestCityName) WHERE Year BETWEEN 1999 and 2009 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q8.10y.result b/storage/tokudb/scripts/atc.ontime/q8.10y.result
deleted file mode 100644
index e98b44c790b..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.10y.result
+++ /dev/null
@@ -1,11 +0,0 @@
-DestCityName COUNT( DISTINCT OriginCityName)
-Atlanta, GA 190
-Chicago, IL 159
-Dallas/Ft.Worth, TX 151
-Cincinnati, OH 139
-Minneapolis, MN 131
-Houston, TX 127
-Detroit, MI 121
-Denver, CO 120
-Salt Lake City, UT 116
-New York, NY 111
diff --git a/storage/tokudb/scripts/atc.ontime/q8.10y.sql b/storage/tokudb/scripts/atc.ontime/q8.10y.sql
deleted file mode 100644
index f70b4f6f220..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.10y.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime WHERE Year BETWEEN 1999 and 2009 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q8.1y.sql b/storage/tokudb/scripts/atc.ontime/q8.1y.sql
deleted file mode 100644
index 40b87b644b1..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.1y.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime WHERE Year BETWEEN 1999 and 1999 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q8.1y.year5.sql b/storage/tokudb/scripts/atc.ontime/q8.1y.year5.sql
deleted file mode 100644
index ef56cc3786f..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.1y.year5.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime USE INDEX(year_5) WHERE Year BETWEEN 1999 and 1999 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q8.2y.sql b/storage/tokudb/scripts/atc.ontime/q8.2y.sql
deleted file mode 100644
index 7ab2d10080f..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.2y.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime WHERE Year BETWEEN 1999 and 2000 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q8.3y.sql b/storage/tokudb/scripts/atc.ontime/q8.3y.sql
deleted file mode 100644
index 340dc1aea4e..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.3y.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime WHERE Year BETWEEN 1999 and 2001 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q8.4y.sql b/storage/tokudb/scripts/atc.ontime/q8.4y.sql
deleted file mode 100644
index c271654ad8e..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.4y.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime WHERE Year BETWEEN 1999 and 2002 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q8.result b/storage/tokudb/scripts/atc.ontime/q8.result
deleted file mode 100644
index 35ed3e3f2c2..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.result
+++ /dev/null
@@ -1,11 +0,0 @@
-DestCityName COUNT( DISTINCT OriginCityName)
-Atlanta, GA 183
-Chicago, IL 147
-Dallas/Ft.Worth, TX 133
-Cincinnati, OH 129
-Minneapolis, MN 128
-Houston, TX 114
-Detroit, MI 112
-Denver, CO 111
-Salt Lake City, UT 108
-New York, NY 101
diff --git a/storage/tokudb/scripts/atc.ontime/q8.sql b/storage/tokudb/scripts/atc.ontime/q8.sql
deleted file mode 100644
index bd5312a4b76..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime WHERE Year BETWEEN 2006 and 2007 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q8.year5.sql b/storage/tokudb/scripts/atc.ontime/q8.year5.sql
deleted file mode 100644
index f6944cfccb9..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q8.year5.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT DestCityName, COUNT( DISTINCT OriginCityName) FROM ontime use index(year_5) WHERE Year BETWEEN 2006 and 2007 GROUP BY DestCityName ORDER BY 2 DESC LIMIT 10;
diff --git a/storage/tokudb/scripts/atc.ontime/q9.result b/storage/tokudb/scripts/atc.ontime/q9.result
deleted file mode 100644
index 4790afb414b..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q9.result
+++ /dev/null
@@ -1,22 +0,0 @@
-year c1
-1988 5202096
-1989 5041200
-1990 5270893
-1991 5076925
-1992 5092157
-1993 5070501
-1994 5180048
-1995 5327435
-1996 5351983
-1997 5411843
-1998 5384721
-1999 5527884
-2000 5683047
-2001 5967780
-2002 5271359
-2003 6488540
-2004 7129270
-2005 7140596
-2006 7141922
-2007 7455458
-2008 7009728
diff --git a/storage/tokudb/scripts/atc.ontime/q9.sql b/storage/tokudb/scripts/atc.ontime/q9.sql
deleted file mode 100644
index 13ac1150449..00000000000
--- a/storage/tokudb/scripts/atc.ontime/q9.sql
+++ /dev/null
@@ -1 +0,0 @@
-select year,count(*) as c1 from ontime group by YEAR;
diff --git a/storage/tokudb/scripts/atc.ontime/qcount.main.sql b/storage/tokudb/scripts/atc.ontime/qcount.main.sql
deleted file mode 100644
index 0d27b611f44..00000000000
--- a/storage/tokudb/scripts/atc.ontime/qcount.main.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-select count(*) from ontime use index();
-
diff --git a/storage/tokudb/scripts/atc.ontime/qcount.result b/storage/tokudb/scripts/atc.ontime/qcount.result
deleted file mode 100644
index 59130c40662..00000000000
--- a/storage/tokudb/scripts/atc.ontime/qcount.result
+++ /dev/null
@@ -1,2 +0,0 @@
-count(*)
-122225386
diff --git a/storage/tokudb/scripts/atc.ontime/qcount.sql b/storage/tokudb/scripts/atc.ontime/qcount.sql
deleted file mode 100644
index b3428c5781b..00000000000
--- a/storage/tokudb/scripts/atc.ontime/qcount.sql
+++ /dev/null
@@ -1 +0,0 @@
-select count(*) from ontime;
diff --git a/storage/tokudb/scripts/atc.readme b/storage/tokudb/scripts/atc.readme
deleted file mode 100644
index 856dc532b13..00000000000
--- a/storage/tokudb/scripts/atc.readme
+++ /dev/null
@@ -1,19 +0,0 @@
-The script to run the load the air traffic ontime database and run queries against it
-is called run.atc.ontime.bas.
-
-The queries are in the tokudb-engine/scripts/atc.ontime directory.
-
-The data for the ontime database is in the amazon s3 bucket called tokutek-mysql-data.
-
-$ s3ls -l tokutek-mysql-data --prefix=atc_On_Time_Performance
-2010-06-15T13:07:09.000Z 1073741824 atc_On_Time_Performance.mysql.csv.gz.aa
-2010-06-15T13:08:19.000Z 1073741824 atc_On_Time_Performance.mysql.csv.gz.ab
-2010-06-15T13:09:38.000Z 1073741824 atc_On_Time_Performance.mysql.csv.gz.ac
-2010-06-15T13:10:54.000Z 446709742 atc_On_Time_Performance.mysql.csv.gz.ad
-2010-06-15T13:11:26.000Z 503 atc_On_Time_Performance.mysql.csv.gz.xml
-
-The raw data is also stored in the amazon s3 bucket called tokutek-mysql-data.
-
-$ s3ls -l tokutek-mysql-data --prefix=atc
-
-
diff --git a/storage/tokudb/scripts/nightly.mysql.build.and.test.bash b/storage/tokudb/scripts/nightly.mysql.build.and.test.bash
deleted file mode 100755
index b9d1b6aca7f..00000000000
--- a/storage/tokudb/scripts/nightly.mysql.build.and.test.bash
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env bash
-
-function usage() {
- echo "run nightly mysql and fractal tree regressions"
- echo "uses gearman to schedule jobs onto test machines"
-}
-
-# generate a script that makes a mysql release and run tests on it
-function make_and_test_mysql() {
- echo $(date) $* >>$nightlytrace 2>&1
- echo "bash -x \$HOME/github/tokudb-engine/scripts/tokutek.make.mysql.bash $* >>$mysqltrace 2>&1; \
- buildexitcode=\$?; \
- echo \$(date) \$HOME/github/tokudb-engine/scripts/tokutek.make.mysql.bash -$* \$buildexitcode >>$mysqltrace; \
- if [ \$buildexitcode -eq 0 ] ; then \$HOME/bin/test.mysql.bash $* >>/tmp/mysql.test.trace 2>&1; fi" \
- | $gearmandir/bin/gearman -b -f mysql-build-$system-$arch -h $gearmandhost -p 4730 >>$nightlytrace 2>&1
-}
-
-# make a mysql release
-function make_mysql() {
- echo $(date) $* >>$nightlytrace 2>&1
- echo "\$HOME/github/tokudb-engine/scripts/tokutek.make.mysql.bash $* >>$mysqltrace 2>&1" | $gearmandir/bin/gearman -b -f mysql-build-$system-$arch -h $gearmandhost -p 4730 >>$nightlytrace 2>&1
-}
-
-# setup the PATH since cron gives us a minimal PATH
-PATH=$HOME/bin:$HOME/usr/local/bin:/usr/local/bin:$PATH
-source /etc/profile
-
-github_token=
-gearmandhost=localhost
-gearmandir=/usr/local/gearmand-1.1.6
-system=$(uname -s | tr '[:upper:]' '[:lower:]')
-arch=$(uname -m | tr '[:upper:]' '[:lower:]')
-now_ts=$(date +%s)
-cc=gcc
-cxx=g++
-
-while [ $# -gt 0 ] ; do
- arg=$1; shift
- if [[ $arg =~ --(.*)=(.*) ]] ; then
- eval ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
- else
- usage; exit 1;
- fi
-done
-
-nightlytrace=/tmp/$(whoami).nightly.trace
-mysqltrace=/tmp/$(whoami).mysql.build.trace.$now_ts
-
-make_and_test_mysql --mysqlbuild=mysql-5.6.16-tokudb-${now_ts}-debug-e-${system}-${arch} --cc=$cc --cxx=$cxx --github_token=$github_token
-make_and_test_mysql --mysqlbuild=mysql-5.6.16-tokudb-${now_ts}-e-${system}-${arch} --cc=$cc --cxx=$cxx --github_token=$github_token --tests=run.mysql.tests.bash:run.sql.bench.bash
-
-make_and_test_mysql --mysqlbuild=mysql-5.5.36-tokudb-${now_ts}-debug-e-${system}-${arch} --cc=$cc --cxx=$cxx --github_token=$github_token
-make_and_test_mysql --mysqlbuild=mysql-5.5.36-tokudb-${now_ts}-e-${system}-${arch} --cc=$cc --cxx=$cxx --github_token=$github_token --tests=run.mysql.tests.bash:run.sql.bench.bash
-
-make_and_test_mysql --mysqlbuild=mariadb-5.5.35-tokudb-${now_ts}-debug-e-${system}-${arch} --cc=$cc --cxx=$cxx --github_token=$github_token
-make_and_test_mysql --mysqlbuild=mariadb-5.5.35-tokudb-${now_ts}-e-${system}-${arch} --cc=$cc --cxx=$cxx --github_token=$github_token --tests=run.mysql.tests.bash:run.sql.bench.bash
-
-exit 0
diff --git a/storage/tokudb/scripts/nightly.mysql.build.and.test.my.cnf b/storage/tokudb/scripts/nightly.mysql.build.and.test.my.cnf
deleted file mode 100644
index a837340924e..00000000000
--- a/storage/tokudb/scripts/nightly.mysql.build.and.test.my.cnf
+++ /dev/null
@@ -1,7 +0,0 @@
-[mysqld]
-tmpdir=/data/mysql/tmp
-max_connections=1024
-table_open_cache=1024
-loose_tokudb_cache_size=8G
-loose_tokudb_directio=1
-
diff --git a/storage/tokudb/scripts/run.atc.ontime.bash b/storage/tokudb/scripts/run.atc.ontime.bash
deleted file mode 100755
index dddab8bb1fe..00000000000
--- a/storage/tokudb/scripts/run.atc.ontime.bash
+++ /dev/null
@@ -1,267 +0,0 @@
-#!/usr/bin/env bash
-
-function usage() {
- echo "run the atc ontime load and run"
- echo "--mysqlbuild=$mysqlbuild"
- echo "[--commit=$commit]"
- echo "[--dbname=$dbname]"
- echo "[--load=$load] [--check=$check] [--run=$run]"
- echo "[--engine=$engine]"
- echo "[--tokudb_load_save_space=$tokudb_load_save_space] [--tokudb_row_format=$tokudb_row_format] [--tokudb_loader_memory_size=$tokudb_loader_memory_size]"
-}
-
-function retry() {
- local cmd
- local retries
- local exitcode
- cmd=$*
- let retries=0
- while [ $retries -le 10 ] ; do
- echo `date` $cmd
- bash -c "$cmd"
- exitcode=$?
- echo `date` $cmd $exitcode $retries
- let retries=retries+1
- if [ $exitcode -eq 0 ] ; then break; fi
- sleep 10
- done
- test $exitcode = 0
-}
-
-mysqlbuild=
-commit=0
-mysqlserver=`hostname`
-mysqluser=`whoami`
-mysqlsocket=/tmp/mysql.sock
-svnserver=https://svn.tokutek.com/tokudb
-basedir=$HOME/svn.build
-builddir=$basedir/mysql.build
-dbname=atc
-tblname=ontime
-load=1
-check=1
-run=1
-engine=tokudb
-tokudb_load_save_space=0
-tokudb_row_format=
-tokudb_loader_memory_size=
-verbose=0
-svn_server=https://svn.tokutek.com/tokudb
-svn_branch=.
-svn_revision=HEAD
-
-# parse the command line
-while [ $# -gt 0 ] ; do
- arg=$1; shift
- if [[ $arg =~ --(.*)=(.*) ]] ; then
- eval ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
- else
- usage; exit 1
- fi
-done
-
-if [[ $mysqlbuild =~ (.*)-(tokudb\-.*)-(linux)-(x86_64) ]] ; then
- mysql=${BASH_REMATCH[1]}
- tokudb=${BASH_REMATCH[2]}
- system=${BASH_REMATCH[3]}
- arch=${BASH_REMATCH[4]}
-else
- exit 1
-fi
-
-if [ -d /usr/local/mysql/bin ] ; then
- export PATH=/usr/local/mysql/bin:$PATH
-fi
-
-if [ -d /usr/local/mysql/lib/mysql ] ; then
- export LD_LIBRARY_PATH=/usr/local/mysql/lib/mysql:$PATH
-fi
-
-# goto the base directory
-if [ ! -d $basedir ] ; then mkdir $basedir; fi
-
-pushd $basedir
-
-# update the build directory
-if [ ! -d $builddir ] ; then mkdir $builddir; fi
-
-date=`date +%Y%m%d`
-testresultsdir=$builddir/$date
-pushd $builddir
- while [ ! -d $date ] ; do
- svn mkdir $svn_server/mysql.build/$date -m ""
- svn checkout $svn_server/mysql.build/$date
- if [ $? -ne 0 ] ; then rm -rf $date; fi
- done
-popd
-
-if [ $dbname = "atc" -a $engine != "tokudb" ] ; then dbname="atc_$engine"; fi
-
-runfile=$testresultsdir/$dbname-$tblname-$mysqlbuild-$mysqlserver
-if [ $tokudb_load_save_space != 0 ] ; then runfile=$runfile-compress; fi
-if [ "$tokudb_row_format" != "" ] ; then runfile=$runfile-$tokudb_row_format; fi
-if [ "$tokudb_loader_memory_size" != "" ] ; then runfile=$runfile-$tokudb_loader_memory_size; fi
-rm -rf $runfile
-
-testresult="PASS"
-
-# maybe get the atc data from s3
-if [ $testresult = "PASS" ] ; then
- f=atc_On_Time_Performance.mysql.csv
- if [ ! -f $f ] ; then
- f=$f.gz
- if [ ! -f $f ] ; then
- echo `date` s3get --bundle tokutek-mysql-data $f >>$runfile 2>&1
- s3get --verbose --bundle tokutek-mysql-data $f >>$runfile 2>&1
- exitcode=$?
- echo `date` s3get --bundle tokutek-mysql-data $f $exitcode >>$runfile 2>&1
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- if [ $testresult = "PASS" ] ; then
- echo `date` gunzip $f >>$runfile 2>&1
- gunzip $f
- exitcode=$?
- echo `date` gunzip $f $exitcode >>$runfile 2>&1
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- fi
- fi
- fi
-fi
-
-# checkout the atc test from svn
-atc=atc-$mysqlbuild
-if [ $testresult = "PASS" ] ; then
- if [ -d atc-$mysqlbuild ] ; then rm -rf atc-$mysqlbuild; fi
-
- retry svn export -r $svn_revision $svn_server/$svn_branch/mysql/tests/atc atc-$mysqlbuild
- exitcode=$?
- echo `date` svn export -r $svn_revision $svn_server/$svn_branch/mysql/tests/atc $exitcode >>$runfile 2>&1
- if [ $exitcode != 0 ] ; then
- retry svn export -r $svn_revision $svn_server/mysql/tests/atc atc-$mysqlbuild
- exitcode=$?
- echo `date` svn export -r $svn_revision $svn_server/mysql/tests/atc $exitcode >>$runfile 2>&1
- fi
- if [ $exitcode != 0 ] ; then testresult="FAIL"; fi
-fi
-
-# create the database
-if [ $load -ne 0 -a $testresult = "PASS" ] ; then
- echo `date` drop database if exists $dbname >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -e "drop database if exists $dbname" >>$runfile 2>&1
- exitcode=$?
- echo `date` drop database if exists $dbname $exitcode>>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- echo `date` create database $dbname >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -e "create database $dbname" >>$runfile 2>&1
- exitcode=$?
- echo `date` create database $dbname $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
-fi
-
-# create the table
-if [ $load -ne 0 -a $testresult = "PASS" ] ; then
- echo `date` create table $dbname.$tblname >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "source $atc/atc_ontime_create_covered.sql" >>$runfile 2>&1
- exitcode=$?
- echo `date` create table $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
-fi
-
-if [ $load -ne 0 -a $testresult = "PASS" -a "$tokudb_row_format" != "" ] ; then
- echo `date` create table $dbname.$tblname >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "alter table $tblname row_format=$tokudb_row_format" >>$runfile 2>&1
- exitcode=$?
- echo `date` create table $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
-fi
-
-if [ $load -ne 0 -a $testresult = "PASS" -a $engine != "tokudb" ] ; then
- echo `date` alter table $engine >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "alter table $tblname engine=$engine" >>$runfile 2>&1
- exitcode=$?
- echo `date` alter table $engine $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
-fi
-
-if [ $testresult = "PASS" ] ; then
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "show create table $tblname" >>$runfile 2>&1
-fi
-
-if [ $testresult = "PASS" ] ; then
- let default_loader_memory_size="$(mysql -S $mysqlsocket -u $mysqluser -e'select @@tokudb_loader_memory_size' --silent --skip-column-names)"
- exitcode=$?
- echo `date` get tokudb_loader_memory_size $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- if [ "$tokudb_loader_memory_size" = "" ] ; then tokudb_loader_memory_size=$default_loader_memory_size; fi
-fi
-
-# load the data
-if [ $load -ne 0 -a $testresult = "PASS" ] ; then
- echo `date` load data >>$runfile
- start=$(date +%s)
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "set tokudb_loader_memory_size=$tokudb_loader_memory_size;\
- set tokudb_load_save_space=$tokudb_load_save_space; load data infile '$basedir/atc_On_Time_Performance.mysql.csv' into table $tblname" >>$runfile 2>&1
- exitcode=$?
- let loadtime=$(date +%s)-$start
- echo `date` load data loadtime=$loadtime $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
-fi
-
-# check the tables
-if [ $check -ne 0 -a $testresult = "PASS" ] ; then
- echo `date` check table $tblname >> $runfile
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "check table $tblname" >>$runfile 2>&1
- exitcode=$?
- echo `date` check table $tblname $exitcode >> $runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
-fi
-
-# run the queries
-if [ $run -ne 0 -a $testresult = "PASS" ] ; then
- pushd $atc
- for qfile in q*.sql ; do
- if [[ $qfile =~ q(.*)\.sql ]] ; then
- qname=${BASH_REMATCH[1]}
- q=`cat $qfile`
- qrun=q${qname}.run
-
- echo `date` explain $qfile >>$runfile
- if [ $verbose -ne 0 ] ; then echo explain $q >>$runfile; fi
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "explain $q" >$qrun
- exitcode=$?
- echo `date` explain $qfile $exitcode >>$runfile
- if [ $verbose -ne 0 ] ; then cat $qrun >>$runfile; fi
-
- echo `date` $qfile >>$runfile
- start=$(date +%s)
- if [ $verbose -ne 0 ] ; then echo $q >>$runfile; fi
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "$q" >$qrun
- exitcode=$?
- let qtime=$(date +%s)-$start
- echo `date` $qfile qtime=$qtime $exitcode >>$runfile
- if [ $verbose -ne 0 ] ; then cat $qrun >>$runfile; fi
- if [ $exitcode -ne 0 ] ; then
- testresult="FAIL"
- else
- if [ -f q${qname}.result ] ; then
- diff $qrun q${qname}.result >>$runfile
- exitcode=$?
- if [ $exitcode -ne 0 ] ; then
- testresult="FAIL"
- fi
- fi
- fi
- fi
- done
- popd
-fi
-
-# commit results
-if [ $commit != 0 ] ; then
- svn add $runfile
- retry svn commit -m \"$testresult $dbname $tblname $mysqlbuild $mysqlserver\" $runfile
-fi
-
-popd
-
-if [ $testresult = "PASS" ] ; then exitcode=0; else exitcode=1; fi
-exit $exitcode
diff --git a/storage/tokudb/scripts/run.iibench.bash b/storage/tokudb/scripts/run.iibench.bash
deleted file mode 100755
index e6e57e7f512..00000000000
--- a/storage/tokudb/scripts/run.iibench.bash
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/env bash
-
-function usage() {
- echo "run iibench"
- echo "--mysqlbuild=$mysqlbuild"
- echo "[--max_row=$max_rows] [--rows_per_report=$rows_per_report] [--insert_only=$insert_only] [ --check=$check]"
- echo "[--commit=$commit]"
-}
-
-function retry() {
- local cmd=$*
- local retries
- local exitcode
- let retries=0
- while [ $retries -le 10 ] ; do
- echo `date` $cmd
- bash -c "$cmd"
- exitcode=$?
- echo `date` $cmd $exitcode $retries
- let retries=retries+1
- if [ $exitcode -eq 0 ] ; then break; fi
- sleep 10
- done
- test $exitcode = 0
-}
-
-mysqlbuild=
-commit=0
-check=1
-mysqlserver=`hostname`
-mysqluser=`whoami`
-mysqlsocket=/tmp/mysql.sock
-svn_server=https://svn.tokutek.com/tokudb
-svn_branch=.
-svn_revision=HEAD
-basedir=$HOME/svn.build
-builddir=$basedir/mysql.build
-system=`uname -s | tr [:upper:] [:lower:]`
-instancetype=
-testinstance=
-arch=`uname -m | tr [:upper:] [:lower:]`
-tracefile=/tmp/run.iibench.trace
-cmd=iibench
-dbname=$cmd
-engine=tokudb
-tblname=testit
-max_rows=50000000
-rows_per_report=1000000
-insert_only=1
-
-# parse the command line
-while [ $# -gt 0 ] ; do
- arg=$1; shift
- if [ $arg = "--replace_into" ] ; then
- cmd=replace_into
- elif [ $arg = "--insert_ignore" ] ; then
- cmd=insert_ignore
- elif [[ $arg =~ --(.*)=(.*) ]] ; then
- eval ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
- else
- usage; exit 1
- fi
-done
-
-if [[ $mysqlbuild =~ (.*)-(tokudb-.*)-(linux)-(x86_64) ]] ; then
- mysql=${BASH_REMATCH[1]}
- tokudb=${BASH_REMATCH[2]}
- system=${BASH_REMATCH[3]}
- arch=${BASH_REMATCH[4]}
-else
- exit 1
-fi
-
-# setup the dbname
-if [ $dbname = "iibench" ] ; then dbname=${cmd}_${engine}; fi
-if [ "$testinstance" != "" ] ; then dbname=${dbname}_${testinstance}; fi
-
-if [ -d /usr/local/mysql ] ; then
- export PATH=/usr/local/mysql/bin:$PATH
-fi
-
-if [ -d /usr/local/mysql/lib/mysql ] ; then
- export LD_LIBRARY_PATH=/usr/local/mysql/lib/mysql:$PATH
-fi
-
-# goto the base directory
-if [ ! -d $basedir ] ; then mkdir $basedir; fi
-pushd $basedir
-
-# update the build directory
-if [ $commit != 0 ] ; then
- if [ ! -d $builddir ] ; then mkdir $builddir; fi
-
- date=`date +%Y%m%d`
- testresultsdir=$builddir/$date
- pushd $builddir
- while [ ! -d $date ] ; do
- svn mkdir $svn_server/mysql.build/$date -m ""
- svn checkout -q $svn_server/mysql.build/$date
- if [ $? -ne 0 ] ; then rm -rf $date; fi
- done
- popd
-else
- testresultsdir=$PWD
-fi
-
-# checkout the code
-testdir=iibench-$mysqlbuild-$mysqlserver
-if [ "$testinstance" != "" ] ; then testdir=$testdir-$testinstance; fi
-rm -rf $testdir
-retry svn export -q -r $svn_revision $svn_server/$svn_branch/iibench $testdir
-exitcode=$?
-if [ $exitcode != 0 ] ; then
- retry svn export -q -r $svn_revision $svn_server/iibench $testdir
- exitcode=$?
-fi
-if [ $exitcode != 0 ] ; then exit 1; fi
-
-# create the iibench database
-mysql -S $mysqlsocket -u root -e "grant all on *.* to '$mysqluser'@'$mysqlserver'"
-exitcode=$?
-if [ $exitcode != 0 ] ; then exit 1; fi
-
-mysql -S $mysqlsocket -u $mysqluser -e "drop database if exists $dbname"
-exitcode=$?
-if [ $exitcode != 0 ] ; then exit 1; fi
-
-mysql -S $mysqlsocket -u $mysqluser -e "create database $dbname"
-exitcode=$?
-if [ $exitcode != 0 ] ; then exit 1; fi
-
-# run
-if [ $cmd = "iibench" -a $insert_only != 0 ] ; then
- runfile=$testresultsdir/$dbname-insert_only-$max_rows-$mysqlbuild-$mysqlserver
-else
- runfile=$testresultsdir/$dbname-$max_rows-$mysqlbuild-$mysqlserver
-fi
-if [ "$instancetype" != "" ] ; then runfile=$runfile-$instancetype; fi
-testresult="PASS"
-
-pushd $testdir/py
- echo `date` $cmd start $mysql $svn_branch $svn_revision $max_rows $rows_per_report >>$runfile
- runcmd=$cmd.py
- args="--db_user=$mysqluser --db_name=$dbname --db_socket=$mysqlsocket --engine=$engine --setup --max_rows=$max_rows --rows_per_report=$rows_per_report --table_name=$tblname"
- if [ $cmd = "iibench" -a $insert_only != 0 ] ; then runcmd="$runcmd --insert_only"; fi
- if [ $cmd = "replace_into" ] ; then runcmd="replace_into.py --use_replace_into"; fi
- if [ $cmd = "insert_ignore" ] ; then runcmd="replace_into.py"; fi
- ./$runcmd $args >>$runfile 2>&1
- exitcode=$?
- echo `date` $cmd complete $exitcode >>$runfile
- if [ $exitcode != 0 ] ; then testresult="FAIL"; fi
-popd
-
-if [ $check != 0 -a $testresult = "PASS" ] ; then
- echo `date` check table $tblname >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "check table $tblname" >>$runfile 2>&1
- exitcode=$?
- echo `date` check table $tblname $exitcode >>$runfile
- if [ $exitcode != 0 ] ; then testresult="FAIL"; fi
-fi
-
-# commit results
-if [ $commit != 0 ] ; then
- if [ $cmd = "iibench" -a $insert_only != 0 ] ; then cmd="$cmd insert_only"; fi
- svn add $runfile
- retry svn commit -m \"$testresult $cmd $max_rows $dbname $mysqlbuild $mysqlserver `hostname`\" $runfile
-fi
-
-popd
-
-if [ $testresult = "PASS" ] ; then exitcode=0; else exitcode=1; fi
-exit $exitcode
diff --git a/storage/tokudb/scripts/run.mysql.tests.bash b/storage/tokudb/scripts/run.mysql.tests.bash
deleted file mode 100755
index ce0fe88d99d..00000000000
--- a/storage/tokudb/scripts/run.mysql.tests.bash
+++ /dev/null
@@ -1,196 +0,0 @@
-#!/usr/bin/env bash
-# ident 4, no tabs
-
-function usage() {
- echo "run the tokudb mysql tests"
- echo "--mysqlbuild=$mysqlbuild"
- echo "--commit=$commit"
- echo "--tests=$tests --engine=$engine"
-}
-
-function retry() {
- local cmd
- local retries
- local exitcode
- cmd=$*
- let retries=0
- while [ $retries -le 10 ] ; do
- echo `date` $cmd
- bash -c "$cmd"
- exitcode=$?
- echo `date` $cmd $exitcode $retries
- let retries=retries+1
- if [ $exitcode -eq 0 ] ; then break; fi
- sleep 10
- done
- test $exitcode = 0
-}
-
-svnserver=https://svn.tokutek.com/tokudb
-basedir=$HOME/svn.build
-builddir=$basedir/mysql.build
-mysqlbuild=
-mysql_basedir=/usr/local/mysql
-mysqlserver=`hostname`
-commit=0
-tests="*"
-engine=""
-parallel=auto
-
-while [ $# -gt 0 ] ; do
- arg=$1; shift
- if [[ $arg =~ --(.*)=(.*) ]] ; then
- eval ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
- else
- usage; exit 1
- fi
-done
-
-if [[ $mysqlbuild =~ (.*)-(tokudb\-.*)-(linux)-(x86_64) ]] ; then
- mysql=${BASH_REMATCH[1]}
- tokudb=${BASH_REMATCH[2]}
- system=${BASH_REMATCH[3]}
- arch=${BASH_REMATCH[4]}
-else
- echo $mysqlbuild is not a tokudb build
-fi
-
-if [ -d $mysql_basedir/lib/mysql ] ; then
- export LD_LIBRARY_PATH=$mysql_basedir/lib/mysql
-fi
-
-# update the build directory
-if [ ! -d $basedir ] ; then mkdir $basedir ; fi
-
-pushd $basedir
-if [ $? != 0 ] ; then exit 1; fi
-
-if [ ! -d $builddir ] ; then mkdir $builddir; fi
-
-# make the subversion directory that will hold the test results
-date=`date +%Y%m%d`
-testresultsdir=$builddir/$date
-pushd $builddir
-if [ $? = 0 ] ; then
- while [ ! -d $date ] ; do
- svn mkdir $svnserver/mysql.build/$date -m ""
- svn checkout -q $svnserver/mysql.build/$date
- if [ $? -ne 0 ] ; then rm -rf $date; fi
- done
- popd
-fi
-
-# generate a trace file name
-if [ -z $engine ] ; then
- tracefile=mysql-test-$mysqlbuild-$mysqlserver
-else
- tracefile=mysql-engine-$engine-$mysqlbuild-$mysqlserver
-fi
-echo >$testresultsdir/$tracefile
-
-if [ -z $engine ] ; then
-
- # run all test suites including main
- teststorun_original="main"
- teststorun_tokudb=""
- pushd $mysql_basedir/mysql-test/suite
- if [ $? = 0 ] ; then
- for t in $tests ; do
- if [[ $t =~ .*\.xfail$ ]] ; then continue; fi
- if [ $t = "perfschema_stress" ] ; then continue; fi
- if [ $t = "large_tests" ] ; then continue; fi
- if [ $t = "pbxt" ] ; then continue; fi
- if [ -d $t/t ] ; then
- if [[ $t =~ tokudb* ]] ; then
- if [ -z $teststorun_tokudb ] ; then teststorun_tokudb="$t" ; else teststorun_tokudb="$teststorun_tokudb,$t"; fi
- else
- teststorun_original="$teststorun_original,$t";
- fi
- fi
- done
- popd
- fi
-
- # run the tests
- pushd $mysql_basedir/mysql-test
- if [ $? = 0 ] ; then
- if [[ $mysqlbuild =~ tokudb ]] ; then
- # run standard tests
- if [[ $mysqlbuild =~ 5\\.5 ]] ; then
- ./mysql-test-run.pl --suite=$teststorun_original --big-test --max-test-fail=0 --force --retry=1 --testcase-timeout=60 \
- --mysqld=--default-storage-engine=myisam --mysqld=--sql-mode="" \
- --mysqld=--loose-tokudb_debug=3072 \
- --parallel=$parallel >>$testresultsdir/$tracefile 2>&1
- else
- ./mysql-test-run.pl --suite=$teststorun_original --big-test --max-test-fail=0 --force --retry=1 --testcase-timeout=60 \
- --mysqld=--loose-tokudb_debug=3072 \
- --parallel=$parallel >>$testresultsdir/$tracefile 2>&1
- fi
-
- # run tokudb tests
- ./mysql-test-run.pl --suite=$teststorun_tokudb --big-test --max-test-fail=0 --force --retry=1 --testcase-timeout=60 \
- --mysqld=--loose-tokudb_debug=3072 \
- --parallel=$parallel >>$testresultsdir/$tracefile 2>&1
- # setup for engines tests
- engine="tokudb"
- else
- ./mysql-test-run.pl --suite=$teststorun_original --big-test --max-test-fail=0 --force --retry=1 --testcase-timeout=60 \
- --parallel=$parallel >>$testresultsdir/$tracefile 2>&1
- fi
- popd
- fi
-fi
-
-if [ ! -z $engine ] ; then
- teststorun="engines/funcs,engines/iuds"
- pushd $mysql_basedir/mysql-test
- if [ $? = 0 ] ; then
- if [[ $mysqlbuild =~ 5\\.6 ]] ; then
- ./mysql-test-run.pl --suite=$teststorun --force --retry-failure=0 --max-test-fail=0 --nowarnings --testcase-timeout=60 \
- --mysqld=--default-storage-engine=$engine --mysqld=--default-tmp-storage-engine=$engine \
- --parallel=$parallel >>$testresultsdir/$tracefile 2>&1
- else
- ./mysql-test-run.pl --suite=$teststorun --force --retry-failure=0 --max-test-fail=0 --nowarnings --testcase-timeout=60 \
- --mysqld=--default-storage-engine=$engine \
- --parallel=$parallel >>$testresultsdir/$tracefile 2>&1
- fi
- popd
- fi
-fi
-
-# summarize the results
-let tests_failed=0
-let tests_passed=0
-while read line ; do
- if [[ "$line" =~ (Completed|Timeout):\ Failed\ ([0-9]+)\/([0-9]+) ]] ; then
- # failed[2]/total[3]
- let tests_failed=tests_failed+${BASH_REMATCH[2]}
- let tests_passed=tests_passed+${BASH_REMATCH[3]}-${BASH_REMATCH[2]}
- elif [[ "$line" =~ Completed:\ All\ ([0-9]+)\ tests ]] ; then
- # passed[1]
- let tests_passed=tests_passed+${BASH_REMATCH[1]}
- fi
-done <$testresultsdir/$tracefile
-
-# commit the results
-if [ $tests_failed = 0 ] ; then
- testresult="PASS=$tests_passed"
-else
- testresult="FAIL=$tests_failed PASS=$tests_passed"
-fi
-pushd $testresultsdir
-if [ $? = 0 ] ; then
- if [ $commit != 0 ] ; then
- svn add $tracefile
- if [[ $tracefile =~ "mysql-test" ]] ; then test=mysql-test; else test=mysql-engine-$engine; fi
- retry svn commit -m \"$testresult $test $mysqlbuild $mysqlserver\" $tracefile
- fi
- popd
-fi
-
-popd # $basedir
-
-if [[ $testresult =~ "PASS" ]] ; then exitcode=0; else exitcode=1; fi
-exit $exitcode
-
-
diff --git a/storage/tokudb/scripts/run.sql.bench.bash b/storage/tokudb/scripts/run.sql.bench.bash
deleted file mode 100755
index 2e24c9c5c89..00000000000
--- a/storage/tokudb/scripts/run.sql.bench.bash
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/usr/bin/env bash
-
-function usage() {
- echo "run the sql bench tests"
- echo "--mysqlbuild=$mysqlbuild"
- echo "--commit=$commit"
-}
-
-function retry() {
- local cmd
- local retries
- local exitcode
- cmd=$*
- let retries=0
- while [ $retries -le 10 ] ; do
- echo `date` $cmd
- bash -c "$cmd"
- exitcode=$?
- echo `date` $cmd $exitcode $retries
- let retries=retries+1
- if [ $exitcode -eq 0 ] ; then break; fi
- sleep 10
- done
- test $exitcode = 0
-}
-
-svnserver=https://svn.tokutek.com/tokudb
-basedir=$HOME/svn.build
-builddir=$basedir/mysql.build
-mysqlbuild=
-mysqlserver=`hostname`
-commit=0
-engine=tokudb
-socket=/tmp/mysql.sock
-system=`uname -s | tr [:upper:] [:lower:]`
-arch=`uname -m | tr [:upper:] [:lower:]`
-
-# parse the command line
-while [ $# -gt 0 ] ; do
- arg=$1; shift
- if [[ $arg =~ --(.*)=(.*) ]] ; then
- eval ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
- else
- usage; exit 1
- fi
-done
-
-if [[ $mysqlbuild =~ (.*)-(tokudb-.*)-(linux)-(x86_64) ]] ; then
- mysql=${BASH_REMATCH[1]}
- tokudb=${BASH_REMATCH[2]}
- system=${BASH_REMATCH[3]}
- arch=${BASH_REMATCH[4]}
-else
- echo $mysqlbuild is not a tokudb build
-fi
-
-# goto the base directory
-if [ ! -d $basedir ] ; then mkdir $basedir; fi
-pushd $basedir
-
-# update the build directory
-if [ ! -d $builddir ] ; then mkdir $builddir; fi
-
-date=`date +%Y%m%d`
-testresultsdir=$builddir/$date
-pushd $builddir
-while [ ! -d $date ] ; do
- svn mkdir $svnserver/mysql.build/$date -m ""
- svn checkout -q $svnserver/mysql.build/$date
- if [ $? -ne 0 ] ; then rm -rf $date; fi
-done
-popd
-
-# run the tests
-pushd /usr/local/mysql/sql-bench
-
-tracefile=sql-bench-$engine-$mysqlbuild-$mysqlserver.trace
-summaryfile=sql-bench-$engine-$mysqlbuild-$mysqlserver.summary
-
-function mydate() {
- date +"%Y%m%d %H:%M:%S"
-}
-
-function runtests() {
- testargs=$*
- for testname in test-* ; do
- chmod +x ./$testname
- echo `mydate` $testname $testargs
- ./$testname $testargs
- exitcode=$?
- echo `mydate`
- if [ $exitcode != 0 ] ; then
- # assume that the test failure due to a crash. allow mysqld to restart.
- sleep 60
- fi
- done
-}
-
->$testresultsdir/$tracefile
-
-runtests --create-options=engine=$engine --socket=$socket --verbose --small-test >>$testresultsdir/$tracefile 2>&1
-runtests --create-options=engine=$engine --socket=$socket --verbose --small-test --fast >>$testresultsdir/$tracefile 2>&1
-runtests --create-options=engine=$engine --socket=$socket --verbose >>$testresultsdir/$tracefile 2>&1
-runtests --create-options=engine=$engine --socket=$socket --verbose --fast >>$testresultsdir/$tracefile 2>&1
-runtests --create-options=engine=$engine --socket=$socket --verbose --fast --fast-insert >>$testresultsdir/$tracefile 2>&1
-runtests --create-options=engine=$engine --socket=$socket --verbose --fast --lock-tables >>$testresultsdir/$tracefile 2>&1
-
-popd
-
-# summarize the results
-while read l ; do
- if [[ $l =~ ^([0-9]{8}\ [0-9]{2}:[0-9]{2}:[0-9]{2})(.*)$ ]] ; then
- t=${BASH_REMATCH[1]}
- cmd=${BASH_REMATCH[2]}
- if [ -z "$cmd" ] ; then
- let duration=$(date -d "$t" +%s)-$(date -d "$tlast" +%s)
- printf "%4s %s %8d %s\n" "$status" "$tlast" "$duration" "$cmdlast"
- else
- cmdlast=$cmd
- tlast=$t
- status=PASS
- fi
- else
- if [[ $l =~ Got\ error|Died ]] ; then
- status=FAIL
- fi
- fi
-done <$testresultsdir/$tracefile >$testresultsdir/$summaryfile
-
-testresult=""
-pf=`mktemp`
-egrep "^PASS" $testresultsdir/$summaryfile >$pf 2>&1
-if [ $? -eq 0 ] ; then testresult="PASS=`cat $pf | wc -l` $testresult"; fi
-egrep "^FAIL" $testresultsdir/$summaryfile >$pf 2>&1
-if [ $? -eq 0 ] ; then testresult="FAIL=`cat $pf | wc -l` $testresult"; fi
-rm $pf
-if [ "$testresult" = "" ] ; then testresult="?"; fi
-
-# commit the results
-pushd $testresultsdir
-if [ $commit != 0 ] ; then
- svn add $tracefile $summaryfile
- retry svn commit -m \"$testresult sql-bench $mysqlbuild $mysqlserver\" $tracefile $summaryfile
-fi
-popd
-
-popd
-
-if [[ $testresult =~ "PASS" ]] ; then exitcode=0; else exitcode=1; fi
-exit $exitcode
-
-
-
diff --git a/storage/tokudb/scripts/run.tpch.bash b/storage/tokudb/scripts/run.tpch.bash
deleted file mode 100755
index efc37d25d2e..00000000000
--- a/storage/tokudb/scripts/run.tpch.bash
+++ /dev/null
@@ -1,342 +0,0 @@
-#!/usr/bin/env bash
-
-function usage() {
- echo "run the TPCH load and compare test"
- echo "[--SCALE=$SCALE] [--ENGINE=$ENGINE]"
- echo "[--dbgen=$dbgen] [--load=$load] [--check=$check] [--compare=$compare] [--query=$query]"
- echo "[--mysqlbuild=$mysqlbuild] [--commit=$commit]"
- echo "[--testinstance=$testinstance]"
- echo "[--tokudb_load_save_space=$tokudb_load_save_space] [--tokudb_row_format=$tokudb_row_format] [--tokudb_loader_memory_size=$tokudb_loader_memory_size]"
-}
-
-function retry() {
- local cmd
- local retries
- local exitcode
- cmd=$*
- let retries=0
- while [ $retries -le 10 ] ; do
- echo `date` $cmd
- bash -c "$cmd"
- exitcode=$?
- echo `date` $cmd $exitcode $retries
- let retries=retries+1
- if [ $exitcode -eq 0 ] ; then break; fi
- sleep 1
- done
- test $exitcode = 0
-}
-
-SCALE=1
-ENGINE=tokudb
-TABLES="part partsupp customer lineitem nation orders region supplier"
-dbgen=1
-load=1
-compare=1
-query=0
-check=1
-datadir=/usr/local/mysql/data
-mysqlbuild=
-commit=0
-mysqlserver=`hostname`
-mysqluser=`whoami`
-mysqlsocket=/tmp/mysql.sock
-basedir=$HOME/svn.build
-builddir=$basedir/mysql.build
-system=`uname -s | tr [:upper:] [:lower:]`
-arch=`uname -m | tr [:upper:] [:lower:]`
-testinstance=
-tokudb_load_save_space=0
-tokudb_row_format=
-tokudb_loader_memory_size=
-svn_server=https://svn.tokutek.com/tokudb
-svn_branch=.
-svn_revision=HEAD
-
-# parse the command line
-while [ $# -gt 0 ] ; do
- arg=$1; shift
- if [[ $arg =~ --(.*)=(.*) ]] ; then
- eval ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
- else
- usage; exit 1
- fi
-done
-
-if [[ $mysqlbuild =~ (.*)-(tokudb\-.*)-(linux)-(x86_64) ]] ; then
- mysql=${BASH_REMATCH[1]}
- tokudb=${BASH_REMATCH[2]}
- system=${BASH_REMATCH[3]}
- arch=${BASH_REMATCH[4]}
-else
- exit 1
-fi
-
-dbname=tpch${SCALE}G_${ENGINE}
-if [ "$testinstance" != "" ] ; then dbname=${dbname}_${testinstance}; fi
-tpchdir=$basedir/tpch${SCALE}G
-
-if [ -d /usr/local/mysql ] ; then
- export PATH=/usr/local/mysql/bin:$PATH
-fi
-
-if [ -d /usr/local/mysql/lib/mysql ] ; then
- export LD_LIBRARY_PATH=/usr/local/mysql/lib/mysql:$PATH
-fi
-
-# goto the base directory
-if [ ! -d $basedir ] ; then mkdir $basedir; fi
-
-pushd $basedir
-
-# update the build directory
-if [ $commit != 0 ] ; then
- if [ ! -d $builddir ] ; then mkdir $builddir; fi
-
- date=`date +%Y%m%d`
- testresultsdir=$builddir/$date
- pushd $builddir
- while [ ! -d $date ] ; do
- svn mkdir $svn_server/mysql.build/$date -m ""
- svn checkout -q $svn_server/mysql.build/$date
- if [ $? -ne 0 ] ; then rm -rf $date; fi
- done
- popd
-else
- testresultsdir=$PWD
-fi
-
-runfile=$testresultsdir/$dbname
-if [ $tokudb_load_save_space != 0 ] ; then runfile=$runfile-compress; fi
-if [ "$tokudb_row_format" != "" ] ; then runfile=$runfile-$tokudb_row_format; fi
-if [ "$tokudb_loader_memory_size" != "" ] ; then runfile=$runfile-$tokudb_loader_memory_size; fi
-runfile=$runfile-$mysqlbuild-$mysqlserver
-rm -rf $runfile
-
-testresult="PASS"
-
-# maybe get the tpch data from AWS S3
-if [ $compare != 0 ] && [ ! -d $tpchdir ] ; then
- tpchtarball=tpch${SCALE}G_data_dump.tar
- if [ ! -f $tpchtarball ] ; then
- echo `date` s3get --bundle tokutek-mysql-data $tpchtarball >>$runfile 2>&1
- s3get --verbose --bundle tokutek-mysql-data $tpchtarball >>$runfile 2>&1
- exitcode=$?
- echo `date` s3get --bundle tokutek-mysql-data $tpchtarball $exitcode >>$runfile 2>&1
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- fi
- if [ $testresult = "PASS" ] ; then
- tar xf $tpchtarball
- exitcode=$?
- echo `date` tar xf $tpchtarball $exitcode >>$runfile 2>&1
- if [ $exitcode -ne 0 ] ; then
- testresult="FAIL"
- else
- # gunzip the data files
- pushd tpch${SCALE}G/data/tpch${SCALE}G
- for f in *.gz ; do
- echo `date` gunzip $f >>$runfile 2>&1
- gunzip $f
- done
- ls -l >>$runfile 2>&1
- popd
- fi
- fi
-fi
-
-# checkout the tpch scripts
-tpchtestdir=tpch-$mysqlbuild
-if [ "$testinstance" != "" ] ; then tpchtestdir=${tpchtestdir}_${testinstance}; fi
-if [ $testresult = "PASS" ] ; then
- rm -rf $tpchtestdir
- retry svn export -q -r $svn_revision $svn_server/$svn_branch/tpch $tpchtestdir
- exitcode=$?
- echo `date` export $svn_server/$svn_branch/tpch $exitcode >>$runfile 2>&1
- if [ $exitcode != 0 ] ; then
- retry svn export -q -r $svn_revision $svn_server/tpch $tpchtestdir
- exitcode=$?
- echo `date` export $svn_server/tpch $exitcode >>$runfile 2>&1
- fi
- if [ $exitcode != 0 ] ; then testresult="FAIL"; fi
-fi
-
-# generate the tpch data
-if [ $dbgen != 0 -a $testresult = "PASS" ] ; then
- pushd $tpchtestdir/dbgen
- make
- exitcode=$?
- echo `date` make dbgen $exitcode >>$runfile 2>&1
- if [ $exitcode != 0 ] ; then testresult="FAIL"; fi
- popd
- if [ $testresult = "PASS" ] ; then
- dbgen=0
- mkdir -p tpch${SCALE}G/data/tpch${SCALE}G
- pushd tpch${SCALE}G/data/tpch${SCALE}G
- if [ ! -f lineitem.tbl ] ; then dbgen=1; fi
- popd
- if [ $dbgen != 0 ] ; then
- pushd $tpchtestdir/dbgen
- ./dbgen -fF -s $SCALE
- exitcode=$?
- echo `date` dbgen -fF -s $SCALE $exitcode >>$runfile 2>&1
- if [ $exitcode != 0 ] ; then
- testresult="FAIL"
- else
- ls -l *.tbl >>$runfile
- chmod 0644 *.tbl
- ls -l *.tbl >>$runfile
- mv *.tbl $basedir/tpch${SCALE}G/data/tpch${SCALE}G
- fi
- popd
- fi
- fi
-fi
-
-# create the tpch database
-if [ $load != 0 -a $testresult = "PASS" ] ; then
- echo `date` drop database if exists $dbname >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -e "drop database if exists $dbname" >>$runfile 2>&1
- exitcode=$?
- echo `date` drop database if exists $dbname $exitcode>>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- echo `date` create database $dbname >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -e "create database $dbname" >>$runfile 2>&1
- exitcode=$?
- echo `date` create database $dbname $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
-fi
-
-# create the tpch tables
-if [ $load != 0 -a $testresult = "PASS" ] ; then
- echo `date` create table >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "source $basedir/tpch-$mysqlbuild/scripts/${ENGINE}_tpch_create_table.sql" >>$runfile 2>&1
- exitcode=$?
- echo `date` create table $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
-fi
-
-# get the current loader memory size
-if [ $load != 0 -a $testresult = "PASS" ] ; then
- let default_loader_memory_size="$(mysql -S $mysqlsocket -u $mysqluser -e'select @@tokudb_loader_memory_size' --silent --skip-column-names)"
- exitcode=$?
- echo `date` get tokudb_loader_memory_size $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- if [ "$tokudb_loader_memory_size" = "" ] ; then tokudb_loader_memory_size=$default_loader_memory_size; fi
-fi
-
-# load the data
-if [ $load != 0 -a $testresult = "PASS" ] ; then
- for tblname in $TABLES ; do
- echo `date` load table $tblname >>$runfile
- ls -l $tpchdir/data/tpch${SCALE}G/$tblname.tbl >>$runfile
- start=$(date +%s)
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "set tokudb_loader_memory_size=$tokudb_loader_memory_size;\
- set tokudb_load_save_space=$tokudb_load_save_space;\
- load data infile '$tpchdir/data/tpch${SCALE}G/$tblname.tbl' into table $tblname fields terminated by '|';" >>$runfile 2>&1
- exitcode=$?
- let loadtime=$(date +%s)-$start
- echo `date` load table $tblname $exitcode loadtime=$loadtime>>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- done
-fi
-
-if [ $check != 0 -a $testresult = "PASS" ] ; then
- for tblname in lineitem ; do
- echo `date` add clustering index $tblname >>$runfile
- start=$(date +%s)
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "set tokudb_loader_memory_size=$tokudb_loader_memory_size;\
- set tokudb_load_save_space=$tokudb_load_save_space;\
- set tokudb_create_index_online=0;\
- create clustering index i_shipdate on lineitem (l_shipdate);" >>$runfile 2>&1
- exitcode=$?
- let loadtime=$(date +%s)-$start
- echo `date` add clustering index $tblname $exitcode loadtime=$loadtime >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- done
-fi
-
-# check the tables
-if [ $check != 0 -a $testresult = "PASS" ] ; then
- for tblname in $TABLES ; do
- echo `date` check table $tblname >>$runfile
- start=$(date +%s)
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "check table $tblname" >>$runfile 2>&1
- exitcode=$?
- let checktime=$(date +%s)-$start
- echo `date` check table $tblname $exitcode checktime=$checktime >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- done
-fi
-
-if [ $check != 0 -a $testresult = "PASS" ] ; then
- for tblname in lineitem ; do
- echo `date` drop index $tblname >>$runfile
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "drop index i_shipdate on lineitem" >>$runfile 2>&1
- exitcode=$?
- echo `date` drop index $tblname $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then testresult="FAIL"; fi
- done
-fi
-
-# compare the data
-if [ $compare != 0 -a $testresult = "PASS" ] ; then
- if [ -d $tpchdir/dump/tpch${SCALE}G ] ; then
- mysql -S $mysqlsocket -u $mysqluser -D $dbname -e "source $basedir/tpch-$mysqlbuild/scripts/dumptpch.sql" >>$runfile 2>&1
- exitcode=$?
- echo `date` dump data $exitcode >>$runfile
- if [ $exitcode -ne 0 ] ; then
- testresult="FAIL"
- else
- # force the permissions on the dumpdir open
- pushd $datadir/$dbname
- exitcode=$?
- if [ $exitcode != 0 ] ; then
- sudo chmod g+rwx $datadir
- sudo chmod g+rwx $datadir/$dbname
- pushd $datadir/$dbname
- exitcode=$?
- fi
- if [ $exitcode = 0 ] ; then
- popd
- fi
-
- # compare the dump files
- dumpdir=$datadir/$dbname
- comparedir=$tpchdir/dump/tpch${SCALE}G
- for f in $dumpdir/dump* ; do
- d=`basename $f`
- if [ ! -f $comparedir/$d ] && [ -f $comparedir/$d.gz ] ; then
- pushd $comparedir; gunzip $d.gz; popd
- fi
- if [ -f $comparedir/$d ] ; then
- diff -q $dumpdir/$d $comparedir/$d
- if [ $? = 0 ] ; then
- result="PASS"
- else
- result="FAIL"
- testresult="FAIL"
- fi
- else
- result="MISSING"
- testresult="FAIL"
- fi
- echo `date` $d $result >>$runfile
- done
- if [ $testresult = "PASS" ] ; then
- # remove the dump files
- rm -f $datadir/$dbname/dump*
- fi
- fi
- fi
-fi
-
-# commit results
-if [ $commit != 0 ] ; then
- svn add $runfile
- retry svn commit -m \"$testresult $dbname $mysqlbuild $mysqlserver\" $runfile
-fi
-
-popd
-
-if [ $testresult = "PASS" ] ; then exitcode=0; else exitcode=1; fi
-exit $exitcode
diff --git a/storage/tokudb/scripts/setup.mysql.bash b/storage/tokudb/scripts/setup.mysql.bash
deleted file mode 100755
index 85132350289..00000000000
--- a/storage/tokudb/scripts/setup.mysql.bash
+++ /dev/null
@@ -1,231 +0,0 @@
-#!/usr/bin/env bash
-
-function usage() {
- echo "setup.mysql.bash"
- echo "--mysqlbuild=$mysqlbuild --shutdown=$shutdown --install=$install --startup=$startup"
-}
-
-function download_file() {
- local file=$1
- s3get $s3bucket $file $file
-}
-
-function download_tarball() {
- local tarball=$1
- if [ ! -f $tarball ] ; then
- download_file $tarball
- if [ $? -ne 0 ] ; then test 0 = 1; return; fi
- fi
- if [ ! -f $tarball.md5 ] ; then
- download_file $tarball.md5
- if [ $? -ne 0 ] ; then test 0 = 1; return; fi
- fi
-}
-
-function install_tarball() {
- local basedir=$1; local tarball=$2
- tar -x -z -f $basedir/$tarball
- if [ $? -ne 0 ] ; then test 0 = 1; return; fi
-}
-
-function check_md5() {
- local tarball=$1
- md5sum --check $tarball.md5
- if [ $? -ne 0 ] ; then
- # support jacksum md5 output which is almost the same as md5sum
- diff -b <(cat $tarball.md5) <(md5sum $tarball)
- if [ $? -ne 0 ] ; then test 0 = 1; return; fi
- fi
-}
-
-mysqlbuild=
-shutdown=1
-install=1
-startup=1
-s3bucket=tokutek-mysql-build
-sleeptime=60
-builtins="mysqlbuild shutdown install startup s3bucket sleeptime"
-mysqld_args="--user=mysql --core-file --core-file-size=unlimited"
-sudo=/usr/bin/sudo
-defaultsfile=""
-if [ -f /etc/$(whoami).my.cnf ] ; then
- defaultsfile=/etc/$(whoami).my.cnf
-fi
-
-function is_builtin() {
- local v=$1; shift
- local x
- for x in $* ; do
- if [ $v = $x ] ; then echo 1; return; fi
- done
- echo 0
-}
-
-while [ $# -gt 0 ] ; do
- arg=$1; shift
- if [ $arg = "--help" -o $arg = "-h" -o $arg = "-?" ] ; then
- usage; exit 1
- elif [[ $arg =~ --(.*)=(.*) ]] ; then
- r=$(is_builtin ${BASH_REMATCH[1]} $builtins)
- if [ $r = 1 ] ; then
- eval ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
- else
- mysqld_args="$mysqld_args $arg"
- fi
- else
- mysqld_args="$mysqld_args $arg"
- fi
-done
-
-if [ -d /data/mysql/tmp ] ; then mysqld_args="$mysqld_args --tmpdir=/data/mysql/tmp"; fi
-
-if [[ $mysqlbuild =~ (.*)-(tokudb\-.*)-(linux)-(x86_64) ]] ; then
- mysql=${BASH_REMATCH[1]}
- tokudb=${BASH_REMATCH[2]}
- system=${BASH_REMATCH[3]}
- arch=${BASH_REMATCH[4]}
-else
- echo $mysqlbuild is not a tokudb build
-fi
-
-if [ ! -d downloads ] ; then mkdir downloads; fi
-
-pushd downloads
-if [ $? != 0 ] ; then exit 1; fi
-
-basedir=$PWD
-
-mysqltarball=$mysqlbuild.tar.gz
-
-# get the tarball
-download_tarball $mysqltarball
-if [ $? -ne 0 ] ; then exit 1; fi
-
-# check the md5 sum
-check_md5 $mysqltarball
-if [ $? -ne 0 ] ; then exit 1; fi
-
-tokudbtarball=""
-if [[ $mysqltarball =~ ^(Percona-Server.*)\.(Linux\.x86_64.*)$ ]] ; then
- tar tzf $mysqltarball | egrep ha_tokudb.so >/dev/null 2>&1
- if [ $? -ne 0 ] ; then
- tokudbtarball=${BASH_REMATCH[1]}.TokuDB.${BASH_REMATCH[2]}
- download_tarball $tokudbtarball
- if [ $? -ne 0 ] ; then exit 1; fi
- check_md5 $tokudbtarball
- if [ $? -ne 0 ] ; then exit 1; fi
- fi
-fi
-
-# set ldpath
-ldpath=""
-if [ -d /usr/local/gcc-4.7/lib64 ] ; then
- echo skip ldpath="export LD_LIBRARY_PATH=/usr/local/gcc-4.7/lib64:\$LD_LIBRARY_PATH;"
-fi
-
-# shutdown mysql
-if [ $shutdown -ne 0 ] ; then
- if [ -x /etc/init.d/mysql ] ; then
- $sudo setsid /etc/init.d/mysql stop
- else
- /usr/local/mysql/bin/mysqladmin shutdown
- fi
- sleep $sleeptime
-fi
-
-pushd /usr/local
-if [ $? = 0 ] ; then
- rm mysql
- popd
-fi
-
-# install the release
-pushd /usr/local/mysqls 2>/dev/null
-if [ $? = 0 ] ; then
- mysqldir=mysqls/$mysqlbuild
-else
- pushd /usr/local
- if [ $? -ne 0 ] ; then exit 1; fi
- mysqldir=$mysqlbuild
-fi
-
-if [ ! -d $mysqlbuild ] || [ $install -ne 0 ] ; then
- rm mysql
- if [ -d $mysqlbuild ] ; then $sudo rm -rf $mysqlbuild; fi
-
- install_tarball $basedir $mysqltarball
- if [ $? -ne 0 ] ; then exit 1; fi
-
- if [ $tokudbtarball ] ; then
- install_tarball $basedir $tokudbtarball
- if [ $? -ne 0 ] ; then exit 1; fi
- fi
-
- ln -s $mysqldir /usr/local/mysql
- if [ $? -ne 0 ] ; then exit 1; fi
- ln -s $mysqldir /usr/local/$mysqlbuild
- if [ $? -ne 0 ] ; then exit 1; fi
-
- installdb=$mysqlbuild/bin/mysql_install_db
- if [ ! -f $installdb ] ; then
- installdb=$mysqlbuild/scripts/mysql_install_db
- fi
-
- $sudo chown -R mysql $mysqlbuild/data
- $sudo chgrp -R mysql $mysqlbuild/data
-
- # 5.6 debug build needs this
- if [ ! -f $mysqlbuild/bin/mysqld ] && [ -f $mysqlbuild/bin/mysqld-debug ] ; then
- ln $mysqlbuild/bin/mysqld-debug $mysqlbuild/bin/mysqld
- fi
-
- if [ -z "$defaultsfile" ] ; then
- default_arg=""
- else
- default_arg="--defaults-file=$defaultsfile"
- fi
- $sudo bash -c "$ldpath $installdb $default_arg --user=mysql --basedir=$PWD/$mysqlbuild --datadir=$PWD/$mysqlbuild/data"
- if [ $? -ne 0 ] ; then exit 1; fi
-else
- # create link
- rm /usr/local/mysql
- ln -s $mysqldir /usr/local/mysql
- if [ $? -ne 0 ] ; then exit 1; fi
- rm /usr/local/$mysqlbuild
- ln -s $mysqldir /usr/local/$mysqlbuild
- if [ $? -ne 0 ] ; then exit 1; fi
-fi
-popd
-
-# start mysql
-if [ $startup -ne 0 ] ; then
- ulimit -a
- # increase the open file limit
- ulimit -n 10240
- exitcode=$?
- echo ulimit -n 10240 exitcode $exitcode
-
- if [ -x /etc/init.d/mysql ] ; then
- $sudo setsid /etc/init.d/mysql start
- else
- if [ -z "$defaultsfile" ] ; then
- default_arg=""
- else
- default_arg="--defaults-file=$defaultsfile"
- fi
- j=/usr/local/mysql/lib/mysql/libjemalloc.so
- if [ -f $j ] ; then
- default_arg="$default_arg --malloc-lib=$j"
- fi
- $sudo -b bash -c "$ldpath /usr/local/mysql/bin/mysqld_safe $default_arg $mysqld_args" >/dev/null 2>&1 &
- fi
- sleep $sleeptime
-
- # add mysql grants
- /usr/local/mysql/bin/mysql -u root -e "grant all on *.* to tokubuild@localhost"
- /usr/local/mysql/bin/mysql -u root -e "grant all on *.* to 'ec2-user'@localhost"
-fi
-
-popd
-
-exit 0
diff --git a/storage/tokudb/scripts/test.mysql.bash b/storage/tokudb/scripts/test.mysql.bash
deleted file mode 100755
index 5c389e05f3f..00000000000
--- a/storage/tokudb/scripts/test.mysql.bash
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env bash
-
-function usage() {
- echo "run the mysql tests"
- echo "--mysqlbuild=$mysqlbuild --tests=$tests"
-}
-
-function expand() {
- echo $* | tr ,: " "
-}
-
-mysqlbuild=
-mysqlsocket=/tmp/mysql.sock
-gearmandir=/usr/local/gearmand-1.1.6
-gearmandhost=localhost
-system=$(uname -s | tr [:upper:] [:lower:])
-arch=$(uname -m | tr [:upper:] [:lower:])
-tests=run.mysql.tests.bash
-
-while [ $# -gt 0 ] ; do
- arg=$1; shift
- if [[ $arg =~ --(.*)=(.*) ]] ; then
- eval ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
- else
- usage; exit 1;
- fi
-done
-
-if [ -z $mysqlbuild ] ; then exit 1; fi
-
-for testname in $(expand $tests) ; do
- if [ $testname = "run.mysql.tests.bash" ] ; then
- run_mysqld=0
- else
- run_mysqld=1
- fi
- if [ $run_mysqld = 0 ] ; then
- setupextra="--shutdown=1 --install=1 --startup=0"
- else
- setupextra="--shutdown=1 --install=1 --startup=1"
- fi
- echo "echo \$(date) $mysqlbuild >>/tmp/$(whoami).$testname.trace 2>&1; \
- \$HOME/bin/setup.mysql.bash --mysqlbuild=$mysqlbuild $setupextra >>/tmp/$(whoami).$testname.trace 2>&1; \
- testexitcode=\$?; \
- echo \$(date) $mysqlbuild \$testexitcode >>/tmp/$(whoami).$testname.trace 2>&1; \
- if [ \$testexitcode -ne 0 ] ; then exit 1; fi; \
- \$HOME/bin/$testname --mysqlbuild=$mysqlbuild --commit=1 >>/tmp/$(whoami).$testname.trace 2>&1; \
- if [ $run_mysqld != 0 ] ; then mysqladmin -S$mysqlsocket shutdown; fi" | $gearmandir/bin/gearman -b -f mysql-test-$system-$arch -h $gearmandhost -p 4730
-done
-
-exit 0
diff --git a/storage/tokudb/scripts/testbuildfromsrc.bash b/storage/tokudb/scripts/testbuildfromsrc.bash
deleted file mode 100644
index 136841ea284..00000000000
--- a/storage/tokudb/scripts/testbuildfromsrc.bash
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env bash
-
-# for all source tarballs and their coresponding md5 files, build a binary release tarball
-
-system=$(uname -s|tr [:upper:] [:lower:])
-arch=$(uname -m)
-
-function expand() {
- echo $* | tr ,: " "
-}
-
-for f in *.md5; do
- if [[ $f =~ (.*).tar.gz.md5 ]] ; then
- mysqlsrc=${BASH_REMATCH[1]}
- else
- exit 1
- fi
- if [ -d $mysqlsrc ] ; then continue; fi
- md5sum --check $mysqlsrc.tar.gz.md5
- if [ $? != 0 ] ; then exit 1; fi
- tar xzf $mysqlsrc.tar.gz
- if [ $? != 0 ] ; then exit 1; fi
- mkdir $mysqlsrc/build.RelWithDebInfo
- pushd $mysqlsrc/build.RelWithDebInfo
- if [ $? != 0 ] ; then exit 1; fi
- cmake -D BUILD_CONFIG=mysql_release -D CMAKE_BUILD_TYPE=RelWithDebInfo -D BUILD_TESTING=OFF ..
- if [ $? != 0 ] ; then exit 1; fi
- make -j4 package
- if [ $? != 0 ] ; then exit 1; fi
- if [ ! -f $mysqlsrc-$system-$arch.tar.gz ] ; then exit 1; fi
- popd
-done
diff --git a/storage/tokudb/scripts/testsandbox.bash b/storage/tokudb/scripts/testsandbox.bash
deleted file mode 100644
index c348db6fd4a..00000000000
--- a/storage/tokudb/scripts/testsandbox.bash
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env bash
-
-# for all tokudb binary tarballs, verify that we can create and run the tarball using the MySQL sandbox.
-
-function expand() {
- echo $* | tr ,: " "
-}
-
-let n=0
-for f in *.md5; do
- if [[ $f =~ (.*).tar.gz.md5 ]] ; then
- mysqlbuild=${BASH_REMATCH[1]}
- else
- exit 1
- fi
-
- md5sum --check $f
- if [ $? != 0 ] ; then exit 1; fi
- make_sandbox --add_prefix=test$n- $mysqlbuild.tar.gz -- --sandbox_directory=test$n
- if [ $? != 0 ] ; then exit 1; fi
- pushd $HOME/sandboxes
- if [ $? = 0 ] ; then
- ./use_all 'show engines'
- ./use_all 'create table test.t (a int primary key, b bigint, c varchar(256), d blob(500000), clustering key(b))'
- ./use_all 'show create table test.t'
- ./stop_all
- popd
- fi
- let n=n+1
-done
-
-
diff --git a/storage/tokudb/scripts/tpch.readme b/storage/tokudb/scripts/tpch.readme
deleted file mode 100644
index b5128045ade..00000000000
--- a/storage/tokudb/scripts/tpch.readme
+++ /dev/null
@@ -1,34 +0,0 @@
-TPCH is an industry standard data warehouse benchmark. We use TPCH databases to test the TokuDB loader.
-
-The run.tpch.bash script loads a TPCH database at a given scale factor into TokuDB. It then uses the SQL
-CHECK TABLE statement to verify the fractal tree invariants. Finally, it dumps the database and compares
-with a precomputed dump of the database from InnoDB.
-
-Here are some TPCH databases dumped from InnoDB. These dumps are used to compare with TPCH data loaded
-into TokuDB.
-
-$ s3ls tokutek-mysql-data -l --prefix=tpch
-2010-08-16T21:21:10.000Z 1073741824 tpch10G_data_dump.tar.0
-2010-08-16T21:38:45.000Z 1073741824 tpch10G_data_dump.tar.1
-2010-08-16T21:56:43.000Z 1073741824 tpch10G_data_dump.tar.2
-2010-08-16T22:14:49.000Z 1073741824 tpch10G_data_dump.tar.3
-2010-08-16T22:32:38.000Z 1073741824 tpch10G_data_dump.tar.4
-2010-08-16T22:51:04.000Z 1073741824 tpch10G_data_dump.tar.5
-2010-08-16T23:08:51.000Z 91262976 tpch10G_data_dump.tar.6
-2010-08-16T23:10:21.000Z 654 tpch10G_data_dump.tar.xml
-2010-08-12T17:45:09.000Z 633579520 tpch1G_data_dump.tar
-2010-08-12T17:56:30.000Z 160 tpch1G_data_dump.tar.xml
-2010-08-06T13:57:51.000Z 633610240 tpch1G_data_dump_innodb.tar
-2010-08-06T14:07:09.000Z 174 tpch1G_data_dump_innodb.tar.xml
-2010-11-28T12:20:58.000Z 886 tpch30G_data_dump.tar.xml
-2010-09-14T19:16:30.000Z 1073741824 tpch30G_dump_data.tar.0
-2010-09-14T19:40:02.000Z 1073741824 tpch30G_dump_data.tar.1
-2010-09-14T20:12:22.000Z 1073741824 tpch30G_dump_data.tar.2
-2010-09-14T20:45:23.000Z 1073741824 tpch30G_dump_data.tar.3
-2010-09-14T21:14:07.000Z 1073741824 tpch30G_dump_data.tar.4
-2010-09-14T21:37:54.000Z 1073741824 tpch30G_dump_data.tar.5
-2010-09-14T21:57:02.000Z 1073741824 tpch30G_dump_data.tar.6
-2010-09-14T22:16:59.000Z 1073741824 tpch30G_dump_data.tar.7
-2010-09-14T22:36:22.000Z 1073741824 tpch30G_dump_data.tar.8
-2010-09-14T22:55:25.000Z 382511104 tpch30G_dump_data.tar.9
-2010-09-14T23:02:04.000Z 886 tpch30G_dump_data.tar.xml
diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h
index c11beae39b4..066fd34d668 100644
--- a/storage/xtradb/include/os0sync.h
+++ b/storage/xtradb/include/os0sync.h
@@ -741,13 +741,16 @@ architecture. Disable memory barrier for Intel architecture for now. */
#elif defined(HAVE_WINDOWS_MM_FENCE)
# define HAVE_MEMORY_BARRIER
-# include <mmintrin.h>
+# include <intrin.h>
# define os_rmb _mm_lfence()
# define os_wmb _mm_sfence()
# define os_isync os_rmb; os_wmb
# define IB_MEMORY_BARRIER_STARTUP_MSG \
"_mm_lfence() and _mm_sfence() are used for memory barrier"
+# define os_atomic_lock_release_byte(ptr) \
+ (void) InterlockedExchange(ptr, 0)
+
#else
# define os_rmb do { } while(0)
# define os_wmb do { } while(0)
diff --git a/storage/xtradb/os/os0stacktrace.cc b/storage/xtradb/os/os0stacktrace.cc
index f7fb1212e5f..c4c428e0db3 100644
--- a/storage/xtradb/os/os0stacktrace.cc
+++ b/storage/xtradb/os/os0stacktrace.cc
@@ -85,7 +85,7 @@ os_stacktrace_print(
caller_address = (void*) uc->uc_mcontext.gregs[REG_RIP] ;
#elif defined(__hppa__)
ucontext_t* uc = (ucontext_t*) ucontext;
- caller_address = (void*) uc->uc_mcontext.sc_iaoq[0] & ~0x3UL ;
+ caller_address = (void*) (uc->uc_mcontext.sc_iaoq[0] & ~0x3UL) ;
#elif (defined (__ppc__)) || (defined (__powerpc__))
ucontext_t* uc = (ucontext_t*) ucontext;
caller_address = (void*) uc->uc_mcontext.regs->nip ;