summaryrefslogtreecommitdiff
path: root/storage/tokudb/ft-index
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2014-04-23 12:34:24 +0200
committerOlivier Bertrand <bertrandop@gmail.com>2014-04-23 12:34:24 +0200
commit9d29647487e8170d018413aacc6ec580decd59b1 (patch)
tree4707bad014790789c076f014c1edc50105e3b21e /storage/tokudb/ft-index
parent95b7d92da34a4d16bccdd5e853ede55131e63a49 (diff)
parent39750cd4dbe9b79a100d45aae010f39f71ec7ddf (diff)
downloadmariadb-git-9d29647487e8170d018413aacc6ec580decd59b1.tar.gz
- Commit merged files
removed: libmysql/libmysql.ver.in libmysql/rpm_support.cc mysql-test/r/backup.result mysql-test/r/binlog_tx_isolation.result mysql-test/r/isam.result mysql-test/r/rpl_colSize.result mysql-test/r/rpl_extraColmaster_innodb.result mysql-test/r/rpl_extraColmaster_myisam.result mysql-test/r/slave-running.result mysql-test/r/slave-stopped.result storage/test_sql_discovery/mysql-test/archive/discover.rdiff storage/test_sql_discovery/mysql-test/main/r/plugin.rdiff storage/tokudb/ft-index/portability/tests/test-fair-rwlock.cc storage/tokudb/ft-index/portability/toku_fair_rwlock.cc storage/tokudb/ft-index/portability/toku_fair_rwlock.h storage/tokudb/scripts/run.tests.7.0.3.bash added: cmake/CPackRPM.cmake cmake/pcre.cmake mysql-test/include/have_metadata_lock_info.inc mysql-test/include/have_metadata_lock_info.opt mysql-test/include/have_rbr_triggers.inc mysql-test/include/have_unix_socket.inc mysql-test/include/save_master_gtid.inc mysql-test/include/sync_with_master_gtid.inc mysql-test/r/create_or_replace.result mysql-test/r/create_or_replace2.result mysql-test/r/failed_auth_unixsocket.result mysql-test/r/locked_temporary-5955.result mysql-test/r/lowercase_table5.result mysql-test/r/selectivity_no_engine.result mysql-test/r/stack-crash.result mysql-test/r/udf_debug_sync.result mysql-test/r/union_crash-714.result mysql-test/std_data/mariadb-5.5-binlog.000001 mysql-test/suite/archive/archive_no_symlink-master.opt mysql-test/suite/archive/archive_no_symlink.result mysql-test/suite/archive/archive_no_symlink.test mysql-test/suite/archive/archive_symlink.result mysql-test/suite/archive/archive_symlink.test mysql-test/suite/federated/federated_maybe_16324629.result mysql-test/suite/federated/federated_maybe_16324629.test mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result mysql-test/suite/innodb/r/row_lock.result mysql-test/suite/innodb/t/innodb-change-buffer-recovery-master.opt mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test mysql-test/suite/innodb/t/row_lock.test mysql-test/suite/innodb_zip/ mysql-test/suite/innodb_zip/r/ mysql-test/suite/innodb_zip/t/ mysql-test/suite/multi_source/gtid_ignore_duplicates.cnf mysql-test/suite/multi_source/gtid_ignore_duplicates.result mysql-test/suite/multi_source/gtid_ignore_duplicates.test mysql-test/suite/plugins/r/server_audit.result mysql-test/suite/plugins/t/server_audit.opt mysql-test/suite/plugins/t/server_audit.test mysql-test/suite/roles/grant-5771.result mysql-test/suite/roles/grant-5771.test mysql-test/suite/rpl/r/create_or_replace_mix.result mysql-test/suite/rpl/r/create_or_replace_row.result mysql-test/suite/rpl/r/create_or_replace_statement.result mysql-test/suite/rpl/r/rpl_old_master.result mysql-test/suite/rpl/r/rpl_parallel2.result mysql-test/suite/rpl/r/rpl_row_triggers.result mysql-test/suite/rpl/r/rpl_row_triggers_sbr.result mysql-test/suite/rpl/t/create_or_replace.inc mysql-test/suite/rpl/t/create_or_replace_mix.cnf mysql-test/suite/rpl/t/create_or_replace_mix.test mysql-test/suite/rpl/t/create_or_replace_row.cnf mysql-test/suite/rpl/t/create_or_replace_row.test mysql-test/suite/rpl/t/create_or_replace_statement.cnf mysql-test/suite/rpl/t/create_or_replace_statement.test mysql-test/suite/rpl/t/rpl_000011-slave.opt mysql-test/suite/rpl/t/rpl_old_master.test mysql-test/suite/rpl/t/rpl_parallel2.test mysql-test/suite/rpl/t/rpl_row_triggers.test mysql-test/suite/rpl/t/rpl_row_triggers_sbr.test mysql-test/suite/sys_vars/r/gtid_ignore_duplicates_basic.result mysql-test/suite/sys_vars/r/last_gtid_basic.result mysql-test/suite/sys_vars/r/slave_ddl_exec_mode_basic.result mysql-test/suite/sys_vars/r/slave_domain_parallel_threads_basic.result mysql-test/suite/sys_vars/r/version_malloc_library_basic.result mysql-test/suite/sys_vars/t/gtid_ignore_duplicates_basic.test mysql-test/suite/sys_vars/t/last_gtid_basic.test mysql-test/suite/sys_vars/t/slave_ddl_exec_mode_basic.test mysql-test/suite/sys_vars/t/slave_domain_parallel_threads_basic.test mysql-test/suite/sys_vars/t/version_malloc_library_basic.test mysql-test/t/create_or_replace-master.opt mysql-test/t/create_or_replace.test mysql-test/t/create_or_replace2.test mysql-test/t/failed_auth_unixsocket.test mysql-test/t/locked_temporary-5955.test mysql-test/t/lowercase_table5.test mysql-test/t/selectivity_no_engine.test mysql-test/t/stack-crash.test mysql-test/t/udf_debug_sync.test mysql-test/t/union_crash-714.test packaging/rpm-oel/ packaging/rpm-oel/CMakeLists.txt packaging/rpm-oel/filter-provides.sh packaging/rpm-oel/filter-requires.sh packaging/rpm-oel/my.cnf packaging/rpm-oel/my_config.h packaging/rpm-oel/mysql-embedded-check.c packaging/rpm-oel/mysql-systemd-start packaging/rpm-oel/mysql.conf packaging/rpm-oel/mysql.init packaging/rpm-oel/mysql.spec.in packaging/rpm-oel/mysql_config.sh packaging/rpm-oel/mysqld.service plugin/server_audit/ plugin/server_audit/CMakeLists.txt plugin/server_audit/COPYING plugin/server_audit/server_audit.c storage/connect/mysql-test/connect/r/xml_mult.result storage/connect/mysql-test/connect/std_data/bookstore.xml storage/connect/mysql-test/connect/t/xml_mult.test storage/oqgraph/mysql-test/oqgraph/connections_mdev5748.result storage/oqgraph/mysql-test/oqgraph/connections_mdev5748.test storage/oqgraph/mysql-test/oqgraph/regression_mdev5744.opt storage/oqgraph/mysql-test/oqgraph/regression_mdev5744.result storage/oqgraph/mysql-test/oqgraph/regression_mdev5744.test storage/sphinx/mysql-test/sphinx/union-5539.result storage/sphinx/mysql-test/sphinx/union-5539.test storage/tokudb/ft-index/ft/tests/mempool-115.cc storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc storage/tokudb/ft-index/locktree/tests/lock_request_not_killed.cc storage/tokudb/ft-index/locktree/tests/lock_request_wait_time_callback.cc storage/tokudb/ft-index/locktree/tests/locktree_escalation_1big7lt_1small.cc storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_1lt.cc storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_2lt.cc storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc storage/tokudb/ft-index/src/tests/env_nproc.cc storage/tokudb/ft-index/src/tests/get_last_key.cc storage/tokudb/ft-index/src/tests/locktree_escalation_stalls.cc storage/tokudb/ft-index/src/tests/recover-child-rollback.cc storage/tokudb/ft-index/src/tests/test_bad_implicit_promotion.cc storage/tokudb/ft-index/src/tests/test_cursor_interrupt.cc storage/tokudb/ft-index/src/tests/test_insert_many_gc.cc storage/tokudb/ft-index/util/context.cc storage/tokudb/ft-index/util/context.h storage/tokudb/ft-index/util/scoped_malloc.cc storage/tokudb/ft-index/util/scoped_malloc.h storage/tokudb/ft-index/util/tests/test-frwlock-fair-writers.cc storage/tokudb/ft-index/util/tests/test-rwlock-unfair-writers.cc storage/tokudb/mysql-test/tokudb_alter_table/r/drop_pk_with_prefix.result storage/tokudb/mysql-test/tokudb_alter_table/r/hcad_drop_char0_t6.result storage/tokudb/mysql-test/tokudb_alter_table/r/mod_enum.result storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_add_key.result storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_col_rename.result storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_default.result storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_key.result storage/tokudb/mysql-test/tokudb_alter_table/t/drop_pk_with_prefix.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_drop_char0_t6.test storage/tokudb/mysql-test/tokudb_alter_table/t/mod_enum.test storage/tokudb/mysql-test/tokudb_alter_table/t/null_bytes_add_key.test storage/tokudb/mysql-test/tokudb_alter_table/t/null_bytes_col_rename.test storage/tokudb/mysql-test/tokudb_alter_table/t/null_bytes_drop_default.test storage/tokudb/mysql-test/tokudb_alter_table/t/null_bytes_drop_key.test storage/tokudb/mysql-test/tokudb_bugs/include/not_5_5.inc storage/tokudb/mysql-test/tokudb_bugs/r/alter_external_lock_assert.result storage/tokudb/mysql-test/tokudb_bugs/r/alter_part_tokudb_bug_155.result storage/tokudb/mysql-test/tokudb_bugs/r/alter_table_copy_table.result storage/tokudb/mysql-test/tokudb_bugs/r/commit_index_end_1.result storage/tokudb/mysql-test/tokudb_bugs/r/commit_index_end_2.result storage/tokudb/mysql-test/tokudb_bugs/r/leak172.result storage/tokudb/mysql-test/tokudb_bugs/r/optimize_temp_table_tokudb.result storage/tokudb/mysql-test/tokudb_bugs/r/subselect_index_next_same_bug_157.result storage/tokudb/mysql-test/tokudb_bugs/std_data/ storage/tokudb/mysql-test/tokudb_bugs/std_data/leak172_t1.data storage/tokudb/mysql-test/tokudb_bugs/std_data/leak172_t2.data storage/tokudb/mysql-test/tokudb_bugs/t/alter_external_lock_assert.test storage/tokudb/mysql-test/tokudb_bugs/t/alter_part_tokudb_bug_155.test storage/tokudb/mysql-test/tokudb_bugs/t/alter_table_copy_table.test storage/tokudb/mysql-test/tokudb_bugs/t/commit_index_end_1.test storage/tokudb/mysql-test/tokudb_bugs/t/commit_index_end_2.test storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test storage/tokudb/mysql-test/tokudb_bugs/t/optimize_temp_table_tokudb.test storage/tokudb/mysql-test/tokudb_bugs/t/subselect_index_next_same_bug_157.test storage/tokudb/mysql-test/tokudb_mariadb/r/create_or_replace.result storage/tokudb/mysql-test/tokudb_mariadb/r/discover_names.result storage/tokudb/mysql-test/tokudb_mariadb/t/create_or_replace.test storage/tokudb/mysql-test/tokudb_mariadb/t/discover_names.test renamed: libmysql/libmysql_rpm_version.in => libmysql/libmysql_versions.ld.in mysql-test/suite/innodb/r/innodb-create-options.result => mysql-test/suite/innodb_zip/r/innodb-create-options.result mysql-test/suite/innodb/r/innodb-zip.result => mysql-test/suite/innodb_zip/r/innodb-zip.result mysql-test/suite/innodb/r/innodb_bug36169.result => mysql-test/suite/innodb_zip/r/innodb_bug36169.result mysql-test/suite/innodb/r/innodb_bug36172.result => mysql-test/suite/innodb_zip/r/innodb_bug36172.result mysql-test/suite/innodb/r/innodb_bug52745.result => mysql-test/suite/innodb_zip/r/innodb_bug52745.result mysql-test/suite/innodb/r/innodb_bug53591.result => mysql-test/suite/innodb_zip/r/innodb_bug53591.result mysql-test/suite/innodb/r/innodb_bug56680.result => mysql-test/suite/innodb_zip/r/innodb_bug56680.result mysql-test/suite/innodb/r/innodb_cmp_drop_table.result => mysql-test/suite/innodb_zip/r/innodb_cmp_drop_table.result mysql-test/suite/innodb/r/innodb_index_large_prefix.result => mysql-test/suite/innodb_zip/r/innodb_index_large_prefix.result mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result => mysql-test/suite/innodb_zip/r/innodb_prefix_index_liftedlimit.result mysql-test/suite/innodb/t/innodb-create-options.test => mysql-test/suite/innodb_zip/t/innodb-create-options.test mysql-test/suite/innodb/t/innodb-zip.test => mysql-test/suite/innodb_zip/t/innodb-zip.test mysql-test/suite/innodb/t/innodb_bug36169.test => mysql-test/suite/innodb_zip/t/innodb_bug36169.test mysql-test/suite/innodb/t/innodb_bug36172.test => mysql-test/suite/innodb_zip/t/innodb_bug36172.test mysql-test/suite/innodb/t/innodb_bug52745.test => mysql-test/suite/innodb_zip/t/innodb_bug52745.test mysql-test/suite/innodb/t/innodb_bug53591.test => mysql-test/suite/innodb_zip/t/innodb_bug53591.test mysql-test/suite/innodb/t/innodb_bug56680.test => mysql-test/suite/innodb_zip/t/innodb_bug56680.test mysql-test/suite/innodb/t/innodb_cmp_drop_table-master.opt => mysql-test/suite/innodb_zip/t/innodb_cmp_drop_table-master.opt mysql-test/suite/innodb/t/innodb_cmp_drop_table.test => mysql-test/suite/innodb_zip/t/innodb_cmp_drop_table.test mysql-test/suite/innodb/t/innodb_index_large_prefix.test => mysql-test/suite/innodb_zip/t/innodb_index_large_prefix.test mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test => mysql-test/suite/innodb_zip/t/innodb_prefix_index_liftedlimit.test mysql-test/suite/roles/show_grants_anon-5238.result => mysql-test/suite/roles/grant_empty.result mysql-test/suite/roles/show_grants_anon-5238.test => mysql-test/suite/roles/grant_empty.test modified: .bzrignore CMakeLists.txt CREDITS VERSION client/CMakeLists.txt client/mysql.cc client/mysql_plugin.c client/mysqlcheck.c client/mysqldump.c client/mysqltest.cc cmake/cpack_rpm.cmake cmake/install_macros.cmake cmake/jemalloc.cmake cmake/mysql_add_executable.cmake cmake/plugin.cmake cmake/versioninfo.rc.in cmake/zlib.cmake config.h.cmake dbug/dbug.c debian/dist/Debian/mariadb-server-10.0.files.in debian/dist/Ubuntu/mariadb-server-10.0.files.in debian/po/it.po debian/po/sv.po extra/jemalloc/ChangeLog extra/jemalloc/include/jemalloc/internal/arena.h extra/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in extra/jemalloc/include/jemalloc/internal/private_namespace.h extra/jemalloc/include/jemalloc/internal/tcache.h extra/jemalloc/src/arena.c extra/replace.c extra/yassl/CMakeLists.txt extra/yassl/include/yassl_error.hpp extra/yassl/include/yassl_types.hpp extra/yassl/src/handshake.cpp extra/yassl/src/yassl_error.cpp extra/yassl/src/yassl_imp.cpp extra/yassl/taocrypt/CMakeLists.txt include/atomic/gcc_builtins.h include/hash.h include/heap.h include/ma_dyncol.h include/maria.h include/my_bitmap.h include/my_getopt.h include/my_global.h include/my_net.h include/my_pthread.h include/my_sys.h include/my_time.h include/my_valgrind.h include/myisam.h include/mysql/plugin.h include/mysql/plugin_audit.h include/mysql/plugin_audit.h.pp include/mysql/plugin_auth.h.pp include/mysql/plugin_ftparser.h.pp include/mysql/psi/mysql_thread.h include/queues.h include/welcome_copyright_notice.h libmysql/CMakeLists.txt libmysql/conf_to_src.c libmysql/libmysql.c libmysqld/CMakeLists.txt libmysqld/examples/CMakeLists.txt libmysqld/lib_sql.cc mysql-test/CMakeLists.txt mysql-test/collections/default.weekly mysql-test/extra/rpl_tests/rpl_ddl.test mysql-test/extra/rpl_tests/rpl_log.test mysql-test/extra/rpl_tests/rpl_stop_slave.test mysql-test/include/commit.inc mysql-test/include/ctype_filesort2.inc mysql-test/include/have_innodb.combinations mysql-test/include/index_merge_ror_cpk.inc mysql-test/include/mtr_check.sql mysql-test/include/type_hrtime.inc mysql-test/lib/My/Config.pm mysql-test/lib/My/SafeProcess/safe_process.cc mysql-test/lib/My/SysInfo.pm mysql-test/lib/mtr_cases.pm mysql-test/mysql-test-run.pl mysql-test/r/alter_table.result mysql-test/r/blackhole.result mysql-test/r/cast.result mysql-test/r/comment_column.result mysql-test/r/comments.result mysql-test/r/commit_1innodb.result mysql-test/r/contributors.result mysql-test/r/create-big.result mysql-test/r/create.result mysql-test/r/ctype_binary.result mysql-test/r/ctype_cp1250_ch.result mysql-test/r/ctype_cp1251.result mysql-test/r/ctype_latin1.result mysql-test/r/ctype_ucs.result mysql-test/r/ctype_utf16.result mysql-test/r/ctype_utf16le.result mysql-test/r/ctype_utf32.result mysql-test/r/ctype_utf8.result mysql-test/r/ctype_utf8mb4.result mysql-test/r/derived_view.result mysql-test/r/distinct.result mysql-test/r/drop.result mysql-test/r/dyncol.result mysql-test/r/error_simulation.result mysql-test/r/events_trans.result mysql-test/r/func_compress.result mysql-test/r/func_group.result mysql-test/r/func_math.result mysql-test/r/func_misc.result mysql-test/r/func_regexp.result mysql-test/r/func_str.result mysql-test/r/func_time.result mysql-test/r/gis-precise.result mysql-test/r/gis.result mysql-test/r/index_intersect_innodb.result mysql-test/r/index_merge_innodb.result mysql-test/r/index_merge_myisam.result mysql-test/r/information_schema-big.result mysql-test/r/information_schema.result mysql-test/r/information_schema_all_engines.result mysql-test/r/innodb_ext_key.result mysql-test/r/join.result mysql-test/r/join_outer.result mysql-test/r/join_outer_jcl6.result mysql-test/r/key.result mysql-test/r/lowercase_fs_off.result mysql-test/r/lowercase_table.result mysql-test/r/lowercase_table2.result mysql-test/r/lowercase_view.result mysql-test/r/merge.result mysql-test/r/multi_update.result mysql-test/r/myisampack.result mysql-test/r/mysqld--help.result mysql-test/r/mysqldump.result mysql-test/r/not_embedded_server.result mysql-test/r/not_partition.result mysql-test/r/old-mode.result mysql-test/r/partition.result mysql-test/r/partition_debug_sync.result mysql-test/r/partition_disabled.result mysql-test/r/partition_error.result mysql-test/r/partition_exchange.result mysql-test/r/partition_innodb.result mysql-test/r/partition_order.result mysql-test/r/partition_windows.result mysql-test/r/plugin.result mysql-test/r/plugin_auth_qa_3.result mysql-test/r/ps.result mysql-test/r/ps_ddl.result mysql-test/r/range.result mysql-test/r/range_mrr_icp.result mysql-test/r/range_vs_index_merge.result mysql-test/r/range_vs_index_merge_innodb.result mysql-test/r/rpl_mysqldump_slave.result mysql-test/r/select.result mysql-test/r/select_found.result mysql-test/r/select_jcl6.result mysql-test/r/select_pkeycache.result mysql-test/r/selectivity.result mysql-test/r/selectivity_innodb.result mysql-test/r/show_check.result mysql-test/r/sp-security.result mysql-test/r/ssl.result mysql-test/r/stat_tables.result mysql-test/r/stat_tables_innodb.result mysql-test/r/stat_tables_par.result mysql-test/r/stat_tables_par_innodb.result mysql-test/r/stat_tables_partition.result mysql-test/r/stat_tables_rbr.result mysql-test/r/stat_tables_repl.result mysql-test/r/statistics.result mysql-test/r/subselect.result mysql-test/r/subselect2.result mysql-test/r/subselect4.result mysql-test/r/subselect_exists2in.result mysql-test/r/subselect_exists_to_in.result mysql-test/r/subselect_extra.result mysql-test/r/subselect_innodb.result mysql-test/r/subselect_mat.result mysql-test/r/subselect_no_mat.result mysql-test/r/subselect_no_opts.result mysql-test/r/subselect_no_scache.result mysql-test/r/subselect_no_semijoin.result mysql-test/r/subselect_sj.result mysql-test/r/subselect_sj2.result mysql-test/r/subselect_sj2_jcl6.result mysql-test/r/subselect_sj2_mat.result mysql-test/r/subselect_sj_jcl6.result mysql-test/r/subselect_sj_mat.result mysql-test/r/temporal_literal.result mysql-test/r/timezone2.result mysql-test/r/trigger.result mysql-test/r/type_datetime.result mysql-test/r/type_datetime_hires.result mysql-test/r/type_float.result mysql-test/r/type_time.result mysql-test/r/type_time_hires.result mysql-test/r/type_timestamp_hires.result mysql-test/r/update.result mysql-test/r/variables.result mysql-test/r/view.result mysql-test/r/view_grant.result mysql-test/r/xml.result mysql-test/std_data/cacert.pem mysql-test/std_data/client-cert.pem mysql-test/std_data/client-key.pem mysql-test/std_data/server-cert.pem mysql-test/std_data/server-key.pem mysql-test/std_data/server8k-cert.pem mysql-test/std_data/server8k-key.pem mysql-test/suite.pm mysql-test/suite/archive/discover.result mysql-test/suite/archive/discover.test mysql-test/suite/binlog/r/binlog_checkpoint.result mysql-test/suite/binlog/t/binlog_checkpoint.test mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test mysql-test/suite/csv/csv.result mysql-test/suite/csv/csv.test mysql-test/suite/federated/federated.test mysql-test/suite/funcs_1/r/innodb_func_view.result mysql-test/suite/funcs_1/r/innodb_views.result mysql-test/suite/funcs_1/r/is_columns_is.result mysql-test/suite/funcs_1/r/memory_func_view.result mysql-test/suite/funcs_1/r/memory_views.result mysql-test/suite/funcs_1/r/myisam_func_view.result mysql-test/suite/funcs_1/r/myisam_views-big.result mysql-test/suite/funcs_1/views/func_view.inc mysql-test/suite/heap/heap.result mysql-test/suite/heap/heap.test mysql-test/suite/innodb/r/innodb_bug54044.result mysql-test/suite/innodb/r/innodb_information_schema.result mysql-test/suite/innodb/r/innodb_mysql.result mysql-test/suite/innodb/t/innodb_bug54044.test mysql-test/suite/innodb/t/innodb_bug60196-master.opt mysql-test/suite/innodb/t/innodb_mysql.test mysql-test/suite/maria/icp.result mysql-test/suite/maria/maria-preload.result mysql-test/suite/maria/maria.result mysql-test/suite/maria/maria.test mysql-test/suite/multi_source/skip_counter.result mysql-test/suite/multi_source/skip_counter.test mysql-test/suite/optimizer_unfixed_bugs/t/bug42991.test mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result mysql-test/suite/parts/r/partition_mgm_lc2_memory.result mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result mysql-test/suite/perfschema/r/dml_setup_instruments.result mysql-test/suite/perfschema/r/func_mutex.result mysql-test/suite/perfschema/r/hostcache_ipv4_blocked.result mysql-test/suite/perfschema/r/hostcache_ipv6_blocked.result mysql-test/suite/perfschema/r/server_init.result mysql-test/suite/perfschema/t/func_mutex.test mysql-test/suite/perfschema/t/hostcache_ipv4_blocked.test mysql-test/suite/perfschema/t/hostcache_ipv6_blocked.test mysql-test/suite/perfschema/t/server_init.test mysql-test/suite/plugins/t/unix_socket.test mysql-test/suite/roles/recursive_dbug.result mysql-test/suite/rpl/disabled.def mysql-test/suite/rpl/r/rpl_000011.result mysql-test/suite/rpl/r/rpl_ddl.result mysql-test/suite/rpl/r/rpl_drop_view.result mysql-test/suite/rpl/r/rpl_gtid_basic.result mysql-test/suite/rpl/r/rpl_gtid_crash.result mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result mysql-test/suite/rpl/r/rpl_gtid_ignored.result mysql-test/suite/rpl/r/rpl_gtid_nobinlog.result mysql-test/suite/rpl/r/rpl_gtid_startpos.result mysql-test/suite/rpl/r/rpl_gtid_stop_start.result mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result mysql-test/suite/rpl/r/rpl_mdev382.result mysql-test/suite/rpl/r/rpl_parallel.result mysql-test/suite/rpl/r/rpl_parallel_no_log_slave_updates.result mysql-test/suite/rpl/r/rpl_row_create_table.result mysql-test/suite/rpl/r/rpl_row_log.result mysql-test/suite/rpl/r/rpl_row_log_innodb.result mysql-test/suite/rpl/r/rpl_row_show_relaylog_events.result mysql-test/suite/rpl/r/rpl_stm_log.result mysql-test/suite/rpl/r/rpl_stm_mix_show_relaylog_events.result mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result mysql-test/suite/rpl/t/rpl_000011.test mysql-test/suite/rpl/t/rpl_bug37426.test mysql-test/suite/rpl/t/rpl_connection.test mysql-test/suite/rpl/t/rpl_create_if_not_exists.test mysql-test/suite/rpl/t/rpl_drop_db.test mysql-test/suite/rpl/t/rpl_gtid_basic.test mysql-test/suite/rpl/t/rpl_gtid_crash.test mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test mysql-test/suite/rpl/t/rpl_gtid_ignored.test mysql-test/suite/rpl/t/rpl_gtid_mdev4485.test mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test mysql-test/suite/rpl/t/rpl_gtid_startpos.test mysql-test/suite/rpl/t/rpl_gtid_stop_start.test mysql-test/suite/rpl/t/rpl_heartbeat_basic.test mysql-test/suite/rpl/t/rpl_known_bugs_detection.test mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test mysql-test/suite/rpl/t/rpl_mix_found_rows.test mysql-test/suite/rpl/t/rpl_parallel.test mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates.test mysql-test/suite/rpl/t/rpl_row_create_table.test mysql-test/suite/rpl/t/rpl_row_find_row_debug.test mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test mysql-test/suite/rpl/t/rpl_row_utf32.test mysql-test/suite/rpl/t/rpl_stm_log.test mysql-test/suite/rpl/t/rpl_stm_sql_mode.test mysql-test/suite/rpl/t/rpl_stm_stop_middle_group.test mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test mysql-test/suite/sys_vars/r/back_log_basic.result mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result mysql-test/suite/sys_vars/r/old_mode_basic.result mysql-test/suite/sys_vars/r/optimizer_switch_basic.result mysql-test/suite/sys_vars/r/progress_report_time_basic.result mysql-test/suite/sys_vars/t/old_mode_basic.test mysql-test/suite/vcol/r/vcol_misc.result mysql-test/suite/vcol/t/vcol_misc.test mysql-test/t/aborted_clients.test mysql-test/t/alter_table.test mysql-test/t/auth_rpl.test mysql-test/t/blackhole.test mysql-test/t/cast.test mysql-test/t/comment_column.test mysql-test/t/comments.test mysql-test/t/create-big.test mysql-test/t/create.test mysql-test/t/derived_view.test mysql-test/t/distinct.test mysql-test/t/drop.test mysql-test/t/dyncol.test mysql-test/t/error_simulation.test mysql-test/t/events_trans.test mysql-test/t/func_compress.test mysql-test/t/func_gconcat.test mysql-test/t/func_group.test mysql-test/t/func_math.test mysql-test/t/func_misc.test mysql-test/t/func_regexp.test mysql-test/t/func_time.test mysql-test/t/gis-precise.test mysql-test/t/gis.test mysql-test/t/information_schema.test mysql-test/t/join.test mysql-test/t/key.test mysql-test/t/lowercase_table.test mysql-test/t/lowercase_table2.test mysql-test/t/lowercase_table4-master.opt mysql-test/t/lowercase_table4.test mysql-test/t/multi_update.test mysql-test/t/myisampack.test mysql-test/t/mysqld--help.test mysql-test/t/mysqldump.test mysql-test/t/not_embedded_server.test mysql-test/t/not_partition.test mysql-test/t/old-mode.test mysql-test/t/partition.test mysql-test/t/partition_debug_sync.test mysql-test/t/partition_disabled.test mysql-test/t/partition_error.test mysql-test/t/partition_exchange.test mysql-test/t/partition_innodb.test mysql-test/t/plugin.test mysql-test/t/ps.test mysql-test/t/ps_ddl.test mysql-test/t/range.test mysql-test/t/range_vs_index_merge.test mysql-test/t/rpl_mysqldump_slave.test mysql-test/t/select.test mysql-test/t/select_found.test mysql-test/t/selectivity.test mysql-test/t/show_check.test mysql-test/t/sp-security.test mysql-test/t/stat_tables_par.test mysql-test/t/statistics.test mysql-test/t/subselect4.test mysql-test/t/subselect_exists2in.test mysql-test/t/subselect_innodb.test mysql-test/t/subselect_sj.test mysql-test/t/subselect_sj2.test mysql-test/t/subselect_sj_mat.test mysql-test/t/temporal_literal.test mysql-test/t/timezone2.test mysql-test/t/type_float.test mysql-test/t/type_time.test mysql-test/t/update.test mysql-test/t/view.test mysql-test/t/view_grant.test mysql-test/t/xml.test mysql-test/valgrind.supp mysys/array.c mysys/file_logger.c mysys/hash.c mysys/ma_dyncol.c mysys/md5.c.THIS mysys/mf_iocache.c mysys/mf_keycache.c mysys/mf_qsort.c mysys/mf_radix.c mysys/mf_same.c mysys/mf_soundex.c mysys/mf_tempdir.c mysys/mf_tempfile.c mysys/mf_wcomp.c mysys/mulalloc.c mysys/my_access.c mysys/my_aes.c.THIS mysys/my_alloc.c mysys/my_bitmap.c mysys/my_conio.c mysys/my_copy.c mysys/my_crc32.c mysys/my_delete.c mysys/my_div.c mysys/my_error.c mysys/my_fopen.c mysys/my_gethwaddr.c mysys/my_getpagesize.c mysys/my_getwd.c mysys/my_libwrap.c mysys/my_lockmem.c mysys/my_malloc.c mysys/my_memmem.c mysys/my_mkdir.c mysys/my_once.c mysys/my_rename.c mysys/my_symlink2.c mysys/my_wincond.c mysys/my_winthread.c mysys/safemalloc.c mysys/test_dir.c mysys/test_xml.c mysys/thr_alarm.c mysys/thr_mutex.c mysys/tree.c packaging/WiX/CPackWixConfig.cmake packaging/WiX/custom_ui.wxs packaging/WiX/mysql_server.wxs.in plugin/auth_pam/auth_pam.c plugin/auth_socket/auth_socket.c plugin/daemon_example/daemon_example.cc plugin/feedback/CMakeLists.txt plugin/feedback/feedback.cc plugin/handler_socket/libhsclient/auto_file.hpp plugin/locale_info/locale_info.cc plugin/metadata_lock_info/metadata_lock_info.cc plugin/metadata_lock_info/mysql-test/metadata_lock_info/r/user_lock.result plugin/qc_info/CMakeLists.txt plugin/qc_info/qc_info.cc plugin/query_response_time/mysql-test/query_response_time/basic.result plugin/query_response_time/plugin.cc plugin/sql_errlog/sql_errlog.c plugin/win_auth_client/CMakeLists.txt scripts/CMakeLists.txt scripts/mysql_config.pl.in scripts/mysql_config.sh scripts/mysql_install_db.pl.in scripts/mysql_install_db.sh scripts/mysql_system_tables.sql scripts/mysql_system_tables_fix.sql scripts/mysqlaccess.sh sql-bench/innotest1.sh sql-bench/innotest1a.sh sql-bench/innotest1b.sh sql-bench/innotest2.sh sql-bench/innotest2a.sh sql-bench/innotest2b.sh sql-bench/limits/access_odbc.cfg sql-common/client.c sql-common/my_time.c sql-common/mysql_async.c sql-common/pack.c sql/CMakeLists.txt sql/authors.h sql/contributors.h sql/create_options.cc sql/custom_conf.h sql/event_db_repository.cc sql/event_scheduler.cc sql/event_scheduler.h sql/events.cc sql/events.h sql/field.cc sql/field.h sql/field_conv.cc sql/filesort.cc sql/filesort_utils.h sql/ha_ndbcluster_binlog.cc sql/ha_ndbcluster_cond.cc sql/ha_ndbcluster_cond.h sql/ha_ndbcluster_tables.h sql/ha_partition.cc sql/ha_partition.h sql/handler.cc sql/handler.h sql/hash_filo.h sql/hostname.cc sql/item.cc sql/item.h sql/item_cmpfunc.cc sql/item_cmpfunc.h sql/item_create.cc sql/item_func.cc sql/item_func.h sql/item_geofunc.cc sql/item_strfunc.cc sql/item_strfunc.h sql/item_subselect.cc sql/item_subselect.h sql/item_sum.cc sql/item_sum.h sql/item_timefunc.cc sql/item_xmlfunc.cc sql/item_xmlfunc.h sql/key.cc sql/key.h sql/lex_symbol.h sql/lock.cc sql/log.cc sql/log.h sql/log_event.cc sql/log_event.h sql/log_event_old.cc sql/log_event_old.h sql/mdl.cc sql/mdl.h sql/mem_root_array.h sql/message.h sql/multi_range_read.cc sql/my_apc.h sql/my_decimal.h sql/mysqld.cc sql/mysqld.h sql/net_serv.cc sql/opt_index_cond_pushdown.cc sql/opt_range.cc sql/opt_range.h sql/opt_subselect.cc sql/opt_subselect.h sql/opt_sum.cc sql/opt_table_elimination.cc sql/partition_element.h sql/partition_info.cc sql/partition_info.h sql/password.c sql/rpl_filter.cc sql/rpl_gtid.cc sql/rpl_gtid.h sql/rpl_injector.h sql/rpl_mi.cc sql/rpl_parallel.cc sql/rpl_parallel.h sql/rpl_record.cc sql/rpl_record.h sql/rpl_rli.cc sql/rpl_rli.h sql/rpl_utility.cc sql/rpl_utility.h sql/scheduler.cc sql/scheduler.h sql/set_var.cc sql/set_var.h sql/share/charsets/Index.xml sql/share/charsets/armscii8.xml sql/share/charsets/ascii.xml sql/share/charsets/cp1250.xml sql/share/charsets/cp852.xml sql/share/charsets/hebrew.xml sql/share/charsets/latin1.xml sql/share/charsets/latin2.xml sql/share/charsets/latin5.xml sql/share/errmsg-utf8.txt sql/signal_handler.cc sql/slave.cc sql/sp_head.cc sql/sp_head.h sql/sp_rcontext.h sql/spatial.cc sql/sql_acl.cc sql/sql_admin.cc sql/sql_admin.h sql/sql_alter.cc sql/sql_analyse.cc sql/sql_analyse.h sql/sql_audit.cc sql/sql_audit.h sql/sql_base.cc sql/sql_base.h sql/sql_binlog.cc sql/sql_bitmap.h sql/sql_cache.cc sql/sql_class.cc sql/sql_class.h sql/sql_connect.cc sql/sql_db.cc sql/sql_delete.cc sql/sql_derived.cc sql/sql_error.cc sql/sql_handler.cc sql/sql_help.cc sql/sql_insert.cc sql/sql_insert.h sql/sql_join_cache.cc sql/sql_lex.cc sql/sql_lex.h sql/sql_lifo_buffer.h sql/sql_list.h sql/sql_load.cc sql/sql_manager.cc sql/sql_parse.cc sql/sql_parse.h sql/sql_partition.cc sql/sql_partition_admin.cc sql/sql_plugin.cc sql/sql_prepare.cc sql/sql_prepare.h sql/sql_priv.h sql/sql_rename.cc sql/sql_repl.cc sql/sql_repl.h sql/sql_select.cc sql/sql_select.h sql/sql_servers.cc sql/sql_show.cc sql/sql_show.h sql/sql_statistics.cc sql/sql_statistics.h sql/sql_string.cc sql/sql_string.h sql/sql_table.cc sql/sql_table.h sql/sql_test.cc sql/sql_time.cc sql/sql_time.h sql/sql_trigger.cc sql/sql_truncate.cc sql/sql_udf.cc sql/sql_union.cc sql/sql_update.cc sql/sql_view.cc sql/sql_yacc.yy sql/strfunc.cc sql/sys_vars.cc sql/sys_vars.h sql/table.cc sql/table.h sql/table_cache.cc sql/table_cache.h sql/threadpool_unix.cc sql/transaction.cc sql/transaction.h sql/tztime.cc sql/uniques.cc sql/unireg.cc storage/archive/ha_archive.cc storage/cassandra/ha_cassandra.cc storage/connect/csort.cpp storage/connect/domdoc.cpp storage/connect/filamfix.cpp storage/connect/filamtxt.cpp storage/connect/filamvct.cpp storage/connect/ha_connect.cc storage/connect/ha_connect.h storage/connect/inihandl.c storage/connect/myconn.cpp storage/connect/odbconn.cpp storage/connect/os.h storage/connect/osutil.h storage/connect/plgdbutl.cpp storage/connect/reldef.cpp storage/connect/tabdos.cpp storage/connect/tabfmt.cpp storage/connect/tabmysql.cpp storage/connect/taboccur.cpp storage/connect/tabodbc.cpp storage/connect/tabxml.cpp storage/connect/tabxml.h storage/connect/valblk.cpp storage/connect/value.cpp storage/connect/xindex.cpp storage/example/ha_example.cc storage/example/ha_example.h storage/federated/ha_federated.cc storage/federated/ha_federated.h storage/federatedx/CMakeLists.txt storage/federatedx/federatedx_io_mysql.cc storage/federatedx/ha_federatedx.cc storage/heap/_check.c storage/heap/_rectest.c storage/heap/ha_heap.cc storage/heap/ha_heap.h storage/heap/hp_create.c storage/heap/hp_delete.c storage/heap/hp_extra.c storage/heap/hp_hash.c storage/heap/hp_open.c storage/heap/hp_rfirst.c storage/heap/hp_rlast.c storage/heap/hp_rnext.c storage/heap/hp_rprev.c storage/heap/hp_rrnd.c storage/heap/hp_rsame.c storage/heap/hp_scan.c storage/heap/hp_update.c storage/heap/hp_write.c storage/innobase/CMakeLists.txt storage/innobase/api/api0api.cc storage/innobase/btr/btr0btr.cc storage/innobase/btr/btr0cur.cc storage/innobase/btr/btr0pcur.cc storage/innobase/compile-innodb* storage/innobase/dict/dict0crea.cc storage/innobase/dict/dict0dict.cc storage/innobase/dict/dict0load.cc storage/innobase/dict/dict0mem.cc storage/innobase/dict/dict0stats.cc storage/innobase/fil/fil0fil.cc storage/innobase/fts/fts0config.cc storage/innobase/fts/fts0fts.cc storage/innobase/fts/fts0opt.cc storage/innobase/fts/fts0que.cc storage/innobase/handler/ha_innodb.cc storage/innobase/handler/handler0alter.cc storage/innobase/handler/i_s.cc storage/innobase/ibuf/ibuf0ibuf.cc storage/innobase/include/api0api.h storage/innobase/include/btr0cur.h storage/innobase/include/btr0pcur.h storage/innobase/include/btr0pcur.ic storage/innobase/include/btr0sea.h storage/innobase/include/db0err.h storage/innobase/include/dict0stats.ic storage/innobase/include/dict0types.h storage/innobase/include/fts0fts.h storage/innobase/include/fts0types.h storage/innobase/include/ibuf0ibuf.h storage/innobase/include/log0log.h storage/innobase/include/mtr0mtr.h storage/innobase/include/mtr0mtr.ic storage/innobase/include/os0file.h storage/innobase/include/row0ftsort.h storage/innobase/include/srv0conc.h storage/innobase/include/srv0mon.h storage/innobase/include/srv0mon.ic storage/innobase/include/sync0arr.h storage/innobase/include/sync0arr.ic storage/innobase/include/sync0sync.h storage/innobase/include/trx0trx.h storage/innobase/include/univ.i storage/innobase/include/ut0bh.h storage/innobase/include/ut0bh.ic storage/innobase/log/log0log.cc storage/innobase/mtr/mtr0mtr.cc storage/innobase/os/os0file.cc storage/innobase/os/os0thread.cc storage/innobase/pars/make_bison.sh* storage/innobase/pars/make_flex.sh* storage/innobase/row/row0ftsort.cc storage/innobase/row/row0log.cc storage/innobase/row/row0merge.cc storage/innobase/row/row0mysql.cc storage/innobase/row/row0quiesce.cc storage/innobase/row/row0sel.cc storage/innobase/srv/srv0mon.cc storage/innobase/srv/srv0start.cc storage/innobase/sync/sync0arr.cc storage/innobase/sync/sync0rw.cc storage/innobase/sync/sync0sync.cc storage/innobase/trx/trx0purge.cc storage/innobase/trx/trx0sys.cc storage/innobase/trx/trx0trx.cc storage/innobase/ut/ut0ut.cc storage/maria/ha_maria.cc storage/maria/ha_maria.h storage/maria/ma_blockrec.c storage/maria/ma_check.c storage/maria/ma_create.c storage/maria/ma_delete_table.c storage/maria/ma_dynrec.c storage/maria/ma_extra.c storage/maria/ma_ft_boolean_search.c storage/maria/ma_locking.c storage/maria/ma_loghandler.c storage/maria/ma_open.c storage/maria/ma_packrec.c storage/maria/ma_pagecache.c storage/maria/ma_pagecrc.c storage/maria/ma_range.c storage/maria/ma_recovery.c storage/maria/ma_static.c storage/maria/ma_test1.c storage/maria/ma_test2.c storage/maria/ma_test_force_start.pl storage/maria/ma_unique.c storage/maria/maria_chk.c storage/maria/maria_def.h storage/maria/maria_pack.c storage/maria/maria_read_log.c storage/maria/unittest/ma_pagecache_single.c storage/maria/unittest/ma_test_loghandler-t.c storage/maria/unittest/ma_test_loghandler_multigroup-t.c storage/myisam/ft_boolean_search.c storage/myisam/ft_stopwords.c storage/myisam/ftbench/Ecompare.pl storage/myisam/ftbench/Ecreate.pl storage/myisam/ftbench/Ereport.pl storage/myisam/ftbench/ft-test-run.sh storage/myisam/ha_myisam.cc storage/myisam/mi_check.c storage/myisam/mi_checksum.c storage/myisam/mi_create.c storage/myisam/mi_delete.c storage/myisam/mi_delete_table.c storage/myisam/mi_dynrec.c storage/myisam/mi_extra.c storage/myisam/mi_locking.c storage/myisam/mi_open.c storage/myisam/mi_rfirst.c storage/myisam/mi_rlast.c storage/myisam/mi_rrnd.c storage/myisam/mi_rsamepos.c storage/myisam/mi_scan.c storage/myisam/mi_search.c storage/myisam/mi_test1.c storage/myisam/mi_write.c storage/myisam/myisamchk.c storage/myisam/myisampack.c storage/myisam/rt_index.h storage/myisam/rt_key.c storage/myisam/rt_key.h storage/myisam/rt_mbr.c storage/myisam/rt_mbr.h storage/myisam/sp_defs.h storage/myisammrg/myrg_delete.c storage/myisammrg/myrg_locking.c storage/myisammrg/myrg_panic.c storage/myisammrg/myrg_range.c storage/myisammrg/myrg_rfirst.c storage/myisammrg/myrg_rlast.c storage/myisammrg/myrg_rnext.c storage/myisammrg/myrg_rnext_same.c storage/myisammrg/myrg_rprev.c storage/myisammrg/myrg_rrnd.c storage/myisammrg/myrg_rsame.c storage/myisammrg/myrg_update.c storage/myisammrg/myrg_write.c storage/ndb/config/win-includes storage/ndb/config/win-libraries storage/ndb/config/win-name storage/ndb/config/win-sources storage/ndb/include/debugger/DebuggerNames.hpp storage/ndb/include/debugger/EventLogger.hpp storage/ndb/include/debugger/GrepError.hpp storage/ndb/include/debugger/SignalLoggerManager.hpp storage/ndb/include/editline/editline.h storage/ndb/include/kernel/AttributeDescriptor.hpp storage/ndb/include/kernel/AttributeHeader.hpp storage/ndb/include/kernel/AttributeList.hpp storage/ndb/include/kernel/BlockNumbers.h storage/ndb/include/kernel/GlobalSignalNumbers.h storage/ndb/include/kernel/GrepEvent.hpp storage/ndb/include/kernel/Interpreter.hpp storage/ndb/include/kernel/LogLevel.hpp storage/ndb/include/kernel/NodeBitmask.hpp storage/ndb/include/kernel/NodeInfo.hpp storage/ndb/include/kernel/NodeState.hpp storage/ndb/include/kernel/RefConvert.hpp storage/ndb/include/kernel/kernel_types.h storage/ndb/include/kernel/ndb_limits.h storage/ndb/include/kernel/signaldata/AbortAll.hpp storage/ndb/include/kernel/signaldata/AccFrag.hpp storage/ndb/include/kernel/signaldata/AccLock.hpp storage/ndb/include/kernel/signaldata/AccScan.hpp storage/ndb/include/kernel/signaldata/AccSizeAltReq.hpp storage/ndb/include/kernel/signaldata/AllocNodeId.hpp storage/ndb/include/kernel/signaldata/AlterIndx.hpp storage/ndb/include/kernel/signaldata/AlterTab.hpp storage/ndb/include/kernel/signaldata/AlterTable.hpp storage/ndb/include/kernel/signaldata/AlterTrig.hpp storage/ndb/include/kernel/signaldata/ApiBroadcast.hpp storage/ndb/include/kernel/signaldata/ApiRegSignalData.hpp storage/ndb/include/kernel/signaldata/ApiVersion.hpp storage/ndb/include/kernel/signaldata/ArbitSignalData.hpp storage/ndb/include/kernel/signaldata/AttrInfo.hpp storage/ndb/include/kernel/signaldata/BackupContinueB.hpp storage/ndb/include/kernel/signaldata/BackupImpl.hpp storage/ndb/include/kernel/signaldata/BackupSignalData.hpp storage/ndb/include/kernel/signaldata/BlockCommitOrd.hpp storage/ndb/include/kernel/signaldata/BuildIndx.hpp storage/ndb/include/kernel/signaldata/CheckNodeGroups.hpp storage/ndb/include/kernel/signaldata/CloseComReqConf.hpp storage/ndb/include/kernel/signaldata/CmInit.hpp storage/ndb/include/kernel/signaldata/CmRegSignalData.hpp storage/ndb/include/kernel/signaldata/CmvmiCfgConf.hpp storage/ndb/include/kernel/signaldata/CntrMasterConf.hpp storage/ndb/include/kernel/signaldata/CntrMasterReq.hpp storage/ndb/include/kernel/signaldata/ConfigParamId.hpp storage/ndb/include/kernel/signaldata/ContinueFragmented.hpp storage/ndb/include/kernel/signaldata/CopyActive.hpp storage/ndb/include/kernel/signaldata/CopyFrag.hpp storage/ndb/include/kernel/signaldata/CopyGCIReq.hpp storage/ndb/include/kernel/signaldata/CreateEvnt.hpp storage/ndb/include/kernel/signaldata/CreateFilegroup.hpp storage/ndb/include/kernel/signaldata/CreateFilegroupImpl.hpp storage/ndb/include/kernel/signaldata/CreateFrag.hpp storage/ndb/include/kernel/signaldata/CreateFragmentation.hpp storage/ndb/include/kernel/signaldata/CreateIndx.hpp storage/ndb/include/kernel/signaldata/CreateObj.hpp storage/ndb/include/kernel/signaldata/CreateTab.hpp storage/ndb/include/kernel/signaldata/CreateTable.hpp storage/ndb/include/kernel/signaldata/CreateTrig.hpp storage/ndb/include/kernel/signaldata/DiAddTab.hpp storage/ndb/include/kernel/signaldata/DiGetNodes.hpp storage/ndb/include/kernel/signaldata/DictLock.hpp storage/ndb/include/kernel/signaldata/DictObjOp.hpp storage/ndb/include/kernel/signaldata/DictSchemaInfo.hpp storage/ndb/include/kernel/signaldata/DictSizeAltReq.hpp storage/ndb/include/kernel/signaldata/DictStart.hpp storage/ndb/include/kernel/signaldata/DictTabInfo.hpp storage/ndb/include/kernel/signaldata/DihAddFrag.hpp storage/ndb/include/kernel/signaldata/DihContinueB.hpp storage/ndb/include/kernel/signaldata/DihSizeAltReq.hpp storage/ndb/include/kernel/signaldata/DihStartTab.hpp storage/ndb/include/kernel/signaldata/DihSwitchReplica.hpp storage/ndb/include/kernel/signaldata/DisconnectRep.hpp storage/ndb/include/kernel/signaldata/DropFilegroup.hpp storage/ndb/include/kernel/signaldata/DropFilegroupImpl.hpp storage/ndb/include/kernel/signaldata/DropIndx.hpp storage/ndb/include/kernel/signaldata/DropObj.hpp storage/ndb/include/kernel/signaldata/DropTab.hpp storage/ndb/include/kernel/signaldata/DropTabFile.hpp storage/ndb/include/kernel/signaldata/DropTable.hpp storage/ndb/include/kernel/signaldata/DropTrig.hpp storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp storage/ndb/include/kernel/signaldata/EmptyLcp.hpp storage/ndb/include/kernel/signaldata/EndTo.hpp storage/ndb/include/kernel/signaldata/EventReport.hpp storage/ndb/include/kernel/signaldata/EventSubscribeReq.hpp storage/ndb/include/kernel/signaldata/ExecFragReq.hpp storage/ndb/include/kernel/signaldata/Extent.hpp storage/ndb/include/kernel/signaldata/FailRep.hpp storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp storage/ndb/include/kernel/signaldata/FsAppendReq.hpp storage/ndb/include/kernel/signaldata/FsCloseReq.hpp storage/ndb/include/kernel/signaldata/FsConf.hpp storage/ndb/include/kernel/signaldata/FsOpenReq.hpp storage/ndb/include/kernel/signaldata/FsReadWriteReq.hpp storage/ndb/include/kernel/signaldata/FsRef.hpp storage/ndb/include/kernel/signaldata/FsRemoveReq.hpp storage/ndb/include/kernel/signaldata/GCPSave.hpp storage/ndb/include/kernel/signaldata/GetTabInfo.hpp storage/ndb/include/kernel/signaldata/GetTableId.hpp storage/ndb/include/kernel/signaldata/GrepImpl.hpp storage/ndb/include/kernel/signaldata/HotSpareRep.hpp storage/ndb/include/kernel/signaldata/IndxAttrInfo.hpp storage/ndb/include/kernel/signaldata/IndxKeyInfo.hpp storage/ndb/include/kernel/signaldata/InvalidateNodeLCPConf.hpp storage/ndb/include/kernel/signaldata/InvalidateNodeLCPReq.hpp storage/ndb/include/kernel/signaldata/KeyInfo.hpp storage/ndb/include/kernel/signaldata/LCP.hpp storage/ndb/include/kernel/signaldata/LgmanContinueB.hpp storage/ndb/include/kernel/signaldata/ListTables.hpp storage/ndb/include/kernel/signaldata/LqhFrag.hpp storage/ndb/include/kernel/signaldata/LqhKey.hpp storage/ndb/include/kernel/signaldata/LqhSizeAltReq.hpp storage/ndb/include/kernel/signaldata/LqhTransConf.hpp storage/ndb/include/kernel/signaldata/ManagementServer.hpp storage/ndb/include/kernel/signaldata/MasterGCP.hpp storage/ndb/include/kernel/signaldata/MasterLCP.hpp storage/ndb/include/kernel/signaldata/NFCompleteRep.hpp storage/ndb/include/kernel/signaldata/NdbSttor.hpp storage/ndb/include/kernel/signaldata/NdbfsContinueB.hpp storage/ndb/include/kernel/signaldata/NextScan.hpp storage/ndb/include/kernel/signaldata/NodeFailRep.hpp storage/ndb/include/kernel/signaldata/NodeStateSignalData.hpp storage/ndb/include/kernel/signaldata/PackedSignal.hpp storage/ndb/include/kernel/signaldata/PgmanContinueB.hpp storage/ndb/include/kernel/signaldata/PrepDropTab.hpp storage/ndb/include/kernel/signaldata/PrepFailReqRef.hpp storage/ndb/include/kernel/signaldata/ReadNodesConf.hpp storage/ndb/include/kernel/signaldata/RelTabMem.hpp storage/ndb/include/kernel/signaldata/RepImpl.hpp storage/ndb/include/kernel/signaldata/RestoreContinueB.hpp storage/ndb/include/kernel/signaldata/RestoreImpl.hpp storage/ndb/include/kernel/signaldata/ResumeReq.hpp storage/ndb/include/kernel/signaldata/RouteOrd.hpp storage/ndb/include/kernel/signaldata/ScanFrag.hpp storage/ndb/include/kernel/signaldata/ScanTab.hpp storage/ndb/include/kernel/signaldata/SetLogLevelOrd.hpp storage/ndb/include/kernel/signaldata/SetVarReq.hpp storage/ndb/include/kernel/signaldata/SignalData.hpp storage/ndb/include/kernel/signaldata/SignalDataPrint.hpp storage/ndb/include/kernel/signaldata/SignalDroppedRep.hpp storage/ndb/include/kernel/signaldata/SrFragidConf.hpp storage/ndb/include/kernel/signaldata/StartFragReq.hpp storage/ndb/include/kernel/signaldata/StartInfo.hpp storage/ndb/include/kernel/signaldata/StartMe.hpp storage/ndb/include/kernel/signaldata/StartOrd.hpp storage/ndb/include/kernel/signaldata/StartPerm.hpp storage/ndb/include/kernel/signaldata/StartRec.hpp storage/ndb/include/kernel/signaldata/StartTo.hpp storage/ndb/include/kernel/signaldata/StopMe.hpp storage/ndb/include/kernel/signaldata/StopPerm.hpp storage/ndb/include/kernel/signaldata/StopReq.hpp storage/ndb/include/kernel/signaldata/SumaImpl.hpp storage/ndb/include/kernel/signaldata/SystemError.hpp storage/ndb/include/kernel/signaldata/TamperOrd.hpp storage/ndb/include/kernel/signaldata/TcCommit.hpp storage/ndb/include/kernel/signaldata/TcContinueB.hpp storage/ndb/include/kernel/signaldata/TcHbRep.hpp storage/ndb/include/kernel/signaldata/TcIndx.hpp storage/ndb/include/kernel/signaldata/TcKeyConf.hpp storage/ndb/include/kernel/signaldata/TcKeyFailConf.hpp storage/ndb/include/kernel/signaldata/TcKeyRef.hpp storage/ndb/include/kernel/signaldata/TcKeyReq.hpp storage/ndb/include/kernel/signaldata/TcRollbackRep.hpp storage/ndb/include/kernel/signaldata/TcSizeAltReq.hpp storage/ndb/include/kernel/signaldata/TestOrd.hpp storage/ndb/include/kernel/signaldata/TransIdAI.hpp storage/ndb/include/kernel/signaldata/TrigAttrInfo.hpp storage/ndb/include/kernel/signaldata/TsmanContinueB.hpp storage/ndb/include/kernel/signaldata/TupCommit.hpp storage/ndb/include/kernel/signaldata/TupFrag.hpp storage/ndb/include/kernel/signaldata/TupKey.hpp storage/ndb/include/kernel/signaldata/TupSizeAltReq.hpp storage/ndb/include/kernel/signaldata/TuxBound.hpp storage/ndb/include/kernel/signaldata/TuxContinueB.hpp storage/ndb/include/kernel/signaldata/TuxMaint.hpp storage/ndb/include/kernel/signaldata/TuxSizeAltReq.hpp storage/ndb/include/kernel/signaldata/UpdateTo.hpp storage/ndb/include/kernel/signaldata/UtilDelete.hpp storage/ndb/include/kernel/signaldata/UtilExecute.hpp storage/ndb/include/kernel/signaldata/UtilLock.hpp storage/ndb/include/kernel/signaldata/UtilPrepare.hpp storage/ndb/include/kernel/signaldata/UtilRelease.hpp storage/ndb/include/kernel/signaldata/UtilSequence.hpp storage/ndb/include/kernel/signaldata/WaitGCP.hpp storage/ndb/include/kernel/trigger_definitions.h storage/ndb/include/logger/ConsoleLogHandler.hpp storage/ndb/include/logger/FileLogHandler.hpp storage/ndb/include/logger/LogHandler.hpp storage/ndb/include/logger/Logger.hpp storage/ndb/include/logger/SysLogHandler.hpp storage/ndb/include/mgmapi/mgmapi.h storage/ndb/include/mgmapi/mgmapi_debug.h storage/ndb/include/mgmapi/mgmapi_error.h storage/ndb/include/mgmapi/ndb_logevent.h storage/ndb/include/mgmapi/ndbd_exit_codes.h storage/ndb/include/mgmcommon/ConfigRetriever.hpp storage/ndb/include/mgmcommon/IPCConfig.hpp storage/ndb/include/mgmcommon/MgmtErrorReporter.hpp storage/ndb/include/ndb_constants.h storage/ndb/include/ndb_global.h.in storage/ndb/include/ndb_init.h storage/ndb/include/ndb_types.h.in storage/ndb/include/ndb_version.h.in storage/ndb/include/ndbapi/Ndb.hpp storage/ndb/include/ndbapi/NdbApi.hpp storage/ndb/include/ndbapi/NdbBlob.hpp storage/ndb/include/ndbapi/NdbDictionary.hpp storage/ndb/include/ndbapi/NdbError.hpp storage/ndb/include/ndbapi/NdbEventOperation.hpp storage/ndb/include/ndbapi/NdbIndexOperation.hpp storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp storage/ndb/include/ndbapi/NdbIndexStat.hpp storage/ndb/include/ndbapi/NdbOperation.hpp storage/ndb/include/ndbapi/NdbPool.hpp storage/ndb/include/ndbapi/NdbRecAttr.hpp storage/ndb/include/ndbapi/NdbReceiver.hpp storage/ndb/include/ndbapi/NdbScanFilter.hpp storage/ndb/include/ndbapi/NdbScanOperation.hpp storage/ndb/include/ndbapi/NdbTransaction.hpp storage/ndb/include/ndbapi/ndb_cluster_connection.hpp storage/ndb/include/ndbapi/ndb_opt_defaults.h storage/ndb/include/ndbapi/ndbapi_limits.h storage/ndb/include/ndbapi/ndberror.h storage/ndb/include/newtonapi/dba.h storage/ndb/include/newtonapi/defs/pcn_types.h storage/ndb/include/portlib/NdbCondition.h storage/ndb/include/portlib/NdbConfig.h storage/ndb/include/portlib/NdbDaemon.h storage/ndb/include/portlib/NdbEnv.h storage/ndb/include/portlib/NdbHost.h storage/ndb/include/portlib/NdbMain.h storage/ndb/include/portlib/NdbMem.h storage/ndb/include/portlib/NdbMutex.h storage/ndb/include/portlib/NdbSleep.h storage/ndb/include/portlib/NdbTCP.h storage/ndb/include/portlib/NdbThread.h storage/ndb/include/portlib/NdbTick.h storage/ndb/include/portlib/PortDefs.h storage/ndb/include/portlib/prefetch.h storage/ndb/include/transporter/TransporterCallback.hpp storage/ndb/include/transporter/TransporterDefinitions.hpp storage/ndb/include/transporter/TransporterRegistry.hpp storage/ndb/include/util/BaseString.hpp storage/ndb/include/util/Bitmask.hpp storage/ndb/include/util/File.hpp storage/ndb/include/util/InputStream.hpp storage/ndb/include/util/NdbAutoPtr.hpp storage/ndb/include/util/NdbOut.hpp storage/ndb/include/util/NdbSqlUtil.hpp storage/ndb/include/util/OutputStream.hpp storage/ndb/include/util/Parser.hpp storage/ndb/include/util/Properties.hpp storage/ndb/include/util/SimpleProperties.hpp storage/ndb/include/util/SocketAuthenticator.hpp storage/ndb/include/util/SocketClient.hpp storage/ndb/include/util/SocketServer.hpp storage/ndb/include/util/UtilBuffer.hpp storage/ndb/include/util/Vector.hpp storage/ndb/include/util/basestring_vsnprintf.h storage/ndb/include/util/md5_hash.hpp storage/ndb/include/util/ndb_opts.h storage/ndb/include/util/ndb_rand.h storage/ndb/include/util/random.h storage/ndb/include/util/socket_io.h storage/ndb/include/util/uucode.h storage/ndb/include/util/version.h storage/ndb/ndbapi-examples/mgmapi_logevent/main.cpp storage/ndb/ndbapi-examples/mgmapi_logevent2/main.cpp storage/ndb/ndbapi-examples/ndbapi_async/ndbapi_async.cpp storage/ndb/ndbapi-examples/ndbapi_async1/ndbapi_async1.cpp storage/ndb/ndbapi-examples/ndbapi_event/ndbapi_event.cpp storage/ndb/ndbapi-examples/ndbapi_retries/ndbapi_retries.cpp storage/ndb/ndbapi-examples/ndbapi_scan/ndbapi_scan.cpp storage/ndb/ndbapi-examples/ndbapi_simple/ndbapi_simple.cpp storage/ndb/ndbapi-examples/ndbapi_simple_dual/main.cpp storage/ndb/ndbapi-examples/ndbapi_simple_index/main.cpp storage/ndb/src/common/debugger/BlockNames.cpp storage/ndb/src/common/debugger/DebuggerNames.cpp storage/ndb/src/common/debugger/EventLogger.cpp storage/ndb/src/common/debugger/GrepError.cpp storage/ndb/src/common/debugger/SignalLoggerManager.cpp storage/ndb/src/common/debugger/signaldata/AccLock.cpp storage/ndb/src/common/debugger/signaldata/AlterIndx.cpp storage/ndb/src/common/debugger/signaldata/AlterTab.cpp storage/ndb/src/common/debugger/signaldata/AlterTable.cpp storage/ndb/src/common/debugger/signaldata/AlterTrig.cpp storage/ndb/src/common/debugger/signaldata/BackupImpl.cpp storage/ndb/src/common/debugger/signaldata/BackupSignalData.cpp storage/ndb/src/common/debugger/signaldata/CloseComReqConf.cpp storage/ndb/src/common/debugger/signaldata/ContinueB.cpp storage/ndb/src/common/debugger/signaldata/CopyGCI.cpp storage/ndb/src/common/debugger/signaldata/CreateEvnt.cpp storage/ndb/src/common/debugger/signaldata/CreateFragmentation.cpp storage/ndb/src/common/debugger/signaldata/CreateIndx.cpp storage/ndb/src/common/debugger/signaldata/CreateTrig.cpp storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp storage/ndb/src/common/debugger/signaldata/DihContinueB.cpp storage/ndb/src/common/debugger/signaldata/DihSwitchReplicaReq.cpp storage/ndb/src/common/debugger/signaldata/DisconnectRep.cpp storage/ndb/src/common/debugger/signaldata/DropIndx.cpp storage/ndb/src/common/debugger/signaldata/DropTab.cpp storage/ndb/src/common/debugger/signaldata/DropTrig.cpp storage/ndb/src/common/debugger/signaldata/FailRep.cpp storage/ndb/src/common/debugger/signaldata/FireTrigOrd.cpp storage/ndb/src/common/debugger/signaldata/FsAppendReq.cpp storage/ndb/src/common/debugger/signaldata/FsCloseReq.cpp storage/ndb/src/common/debugger/signaldata/FsConf.cpp storage/ndb/src/common/debugger/signaldata/FsOpenReq.cpp storage/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp storage/ndb/src/common/debugger/signaldata/FsRef.cpp storage/ndb/src/common/debugger/signaldata/GCPSave.cpp storage/ndb/src/common/debugger/signaldata/IndxAttrInfo.cpp storage/ndb/src/common/debugger/signaldata/IndxKeyInfo.cpp storage/ndb/src/common/debugger/signaldata/LCP.cpp storage/ndb/src/common/debugger/signaldata/LqhFrag.cpp storage/ndb/src/common/debugger/signaldata/LqhKey.cpp storage/ndb/src/common/debugger/signaldata/LqhTrans.cpp storage/ndb/src/common/debugger/signaldata/MasterLCP.cpp storage/ndb/src/common/debugger/signaldata/NFCompleteRep.cpp storage/ndb/src/common/debugger/signaldata/NdbSttor.cpp storage/ndb/src/common/debugger/signaldata/NdbfsContinueB.cpp storage/ndb/src/common/debugger/signaldata/PackedSignal.cpp storage/ndb/src/common/debugger/signaldata/PrepDropTab.cpp storage/ndb/src/common/debugger/signaldata/PrepFailReqRef.cpp storage/ndb/src/common/debugger/signaldata/ScanFrag.cpp storage/ndb/src/common/debugger/signaldata/ScanTab.cpp storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp storage/ndb/src/common/debugger/signaldata/SignalDroppedRep.cpp storage/ndb/src/common/debugger/signaldata/SignalNames.cpp storage/ndb/src/common/debugger/signaldata/StartRec.cpp storage/ndb/src/common/debugger/signaldata/SumaImpl.cpp storage/ndb/src/common/debugger/signaldata/SystemError.cpp storage/ndb/src/common/debugger/signaldata/TcIndx.cpp storage/ndb/src/common/debugger/signaldata/TcKeyConf.cpp storage/ndb/src/common/debugger/signaldata/TcKeyRef.cpp storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp storage/ndb/src/common/debugger/signaldata/TcRollbackRep.cpp storage/ndb/src/common/debugger/signaldata/TrigAttrInfo.cpp storage/ndb/src/common/debugger/signaldata/TupCommit.cpp storage/ndb/src/common/debugger/signaldata/TupKey.cpp storage/ndb/src/common/debugger/signaldata/TuxMaint.cpp storage/ndb/src/common/debugger/signaldata/UtilDelete.cpp storage/ndb/src/common/debugger/signaldata/UtilExecute.cpp storage/ndb/src/common/debugger/signaldata/UtilLock.cpp storage/ndb/src/common/debugger/signaldata/UtilPrepare.cpp storage/ndb/src/common/debugger/signaldata/UtilSequence.cpp storage/ndb/src/common/logger/ConsoleLogHandler.cpp storage/ndb/src/common/logger/FileLogHandler.cpp storage/ndb/src/common/logger/LogHandler.cpp storage/ndb/src/common/logger/LogHandlerList.cpp storage/ndb/src/common/logger/LogHandlerList.hpp storage/ndb/src/common/logger/Logger.cpp storage/ndb/src/common/logger/SysLogHandler.cpp storage/ndb/src/common/logger/listtest/LogHandlerListUnitTest.cpp storage/ndb/src/common/logger/listtest/LogHandlerListUnitTest.hpp storage/ndb/src/common/logger/loggertest/LoggerUnitTest.cpp storage/ndb/src/common/logger/loggertest/LoggerUnitTest.hpp storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp storage/ndb/src/common/mgmcommon/IPCConfig.cpp storage/ndb/src/common/mgmcommon/printConfig/printConfig.cpp storage/ndb/src/common/portlib/NdbCondition.c storage/ndb/src/common/portlib/NdbConfig.c storage/ndb/src/common/portlib/NdbDaemon.c storage/ndb/src/common/portlib/NdbEnv.c storage/ndb/src/common/portlib/NdbHost.c storage/ndb/src/common/portlib/NdbMem.c storage/ndb/src/common/portlib/NdbMutex.c storage/ndb/src/common/portlib/NdbPortLibTest.cpp storage/ndb/src/common/portlib/NdbSleep.c storage/ndb/src/common/portlib/NdbTCP.cpp storage/ndb/src/common/portlib/NdbThread.c storage/ndb/src/common/portlib/NdbTick.c storage/ndb/src/common/portlib/memtest.c storage/ndb/src/common/portlib/mmstest.cpp storage/ndb/src/common/portlib/munmaptest.cpp storage/ndb/src/common/portlib/win32/NdbCondition.c storage/ndb/src/common/portlib/win32/NdbDaemon.c storage/ndb/src/common/portlib/win32/NdbEnv.c storage/ndb/src/common/portlib/win32/NdbHost.c storage/ndb/src/common/portlib/win32/NdbMem.c storage/ndb/src/common/portlib/win32/NdbMutex.c storage/ndb/src/common/portlib/win32/NdbSleep.c storage/ndb/src/common/portlib/win32/NdbTCP.c storage/ndb/src/common/portlib/win32/NdbThread.c storage/ndb/src/common/portlib/win32/NdbTick.c storage/ndb/src/common/transporter/Packer.cpp storage/ndb/src/common/transporter/Packer.hpp storage/ndb/src/common/transporter/SCI_Transporter.cpp storage/ndb/src/common/transporter/SCI_Transporter.hpp storage/ndb/src/common/transporter/SHM_Buffer.hpp storage/ndb/src/common/transporter/SHM_Transporter.cpp storage/ndb/src/common/transporter/SHM_Transporter.hpp storage/ndb/src/common/transporter/SHM_Transporter.unix.cpp storage/ndb/src/common/transporter/SHM_Transporter.win32.cpp storage/ndb/src/common/transporter/SendBuffer.cpp storage/ndb/src/common/transporter/SendBuffer.hpp storage/ndb/src/common/transporter/TCP_Transporter.cpp storage/ndb/src/common/transporter/TCP_Transporter.hpp storage/ndb/src/common/transporter/Transporter.cpp storage/ndb/src/common/transporter/Transporter.hpp storage/ndb/src/common/transporter/TransporterInternalDefinitions.hpp storage/ndb/src/common/transporter/TransporterRegistry.cpp storage/ndb/src/common/transporter/basictest/basicTransporterTest.cpp storage/ndb/src/common/transporter/buddy.cpp storage/ndb/src/common/transporter/buddy.hpp storage/ndb/src/common/transporter/failoverSCI/failoverSCI.cpp storage/ndb/src/common/transporter/perftest/perfTransporterTest.cpp storage/ndb/src/common/transporter/priotest/prioSCI/prioSCI.cpp storage/ndb/src/common/transporter/priotest/prioSHM/prioSHM.cpp storage/ndb/src/common/transporter/priotest/prioTCP/prioTCP.cpp storage/ndb/src/common/transporter/priotest/prioTransporterTest.cpp storage/ndb/src/common/transporter/priotest/prioTransporterTest.hpp storage/ndb/src/common/util/BaseString.cpp storage/ndb/src/common/util/File.cpp storage/ndb/src/common/util/InputStream.cpp storage/ndb/src/common/util/NdbOut.cpp storage/ndb/src/common/util/NdbSqlUtil.cpp storage/ndb/src/common/util/OutputStream.cpp storage/ndb/src/common/util/Parser.cpp storage/ndb/src/common/util/Properties.cpp storage/ndb/src/common/util/SimpleProperties.cpp storage/ndb/src/common/util/SocketAuthenticator.cpp storage/ndb/src/common/util/SocketClient.cpp storage/ndb/src/common/util/SocketServer.cpp storage/ndb/src/common/util/basestring_vsnprintf.c storage/ndb/src/common/util/filetest/FileUnitTest.cpp storage/ndb/src/common/util/filetest/FileUnitTest.hpp storage/ndb/src/common/util/md5_hash.cpp storage/ndb/src/common/util/ndb_init.c storage/ndb/src/common/util/ndb_rand.c storage/ndb/src/common/util/random.c storage/ndb/src/common/util/socket_io.cpp storage/ndb/src/common/util/strdup.c storage/ndb/src/common/util/testProperties/testProperties.cpp storage/ndb/src/common/util/testSimpleProperties/sp_test.cpp storage/ndb/src/common/util/uucode.c storage/ndb/src/common/util/version.c storage/ndb/src/cw/cpcc-win32/C++/CPC_GUI.cpp storage/ndb/src/cw/cpcc-win32/C++/CPC_GUI.h storage/ndb/src/cw/cpcc-win32/C++/NdbControls.cpp storage/ndb/src/cw/cpcc-win32/C++/StdAfx.cpp storage/ndb/src/cw/cpcc-win32/C++/StdAfx.h storage/ndb/src/cw/cpcc-win32/C++/TreeView.cpp storage/ndb/src/cw/cpcc-win32/C++/TreeView.h storage/ndb/src/cw/cpcc-win32/C++/resource.h storage/ndb/src/cw/cpcc-win32/csharp/CPC_Form.cs storage/ndb/src/cw/cpcc-win32/csharp/Computer.cs storage/ndb/src/cw/cpcc-win32/csharp/ComputerAddDialog.cs storage/ndb/src/cw/cpcc-win32/csharp/ComputerRemoveDialog.cs storage/ndb/src/cw/cpcc-win32/csharp/Database.cs storage/ndb/src/cw/cpcc-win32/csharp/PanelWizard.cs storage/ndb/src/cw/cpcc-win32/csharp/Process.cs storage/ndb/src/cw/cpcc-win32/csharp/ProcessDefineDialog.cs storage/ndb/src/cw/cpcc-win32/csharp/fileaccess/FileMgmt.cs storage/ndb/src/cw/cpcc-win32/csharp/simpleparser/SimpleCPCParser.cs storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/SocketComm.cs storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/myTcpClient.cs storage/ndb/src/cw/cpcc-win32/csharp/startDatabaseDlg.cs storage/ndb/src/cw/cpcc-win32/csharp/telnetclient/telnetClient.cs storage/ndb/src/cw/cpcd/APIService.cpp storage/ndb/src/cw/cpcd/APIService.hpp storage/ndb/src/cw/cpcd/CPCD.cpp storage/ndb/src/cw/cpcd/CPCD.hpp storage/ndb/src/cw/cpcd/Monitor.cpp storage/ndb/src/cw/cpcd/Process.cpp storage/ndb/src/cw/cpcd/common.cpp storage/ndb/src/cw/cpcd/common.hpp storage/ndb/src/cw/cpcd/main.cpp storage/ndb/src/cw/test/socketclient/socketClientTest.cpp storage/ndb/src/cw/util/ClientInterface.cpp storage/ndb/src/cw/util/ClientInterface.hpp storage/ndb/src/cw/util/SocketRegistry.cpp storage/ndb/src/cw/util/SocketRegistry.hpp storage/ndb/src/cw/util/SocketService.cpp storage/ndb/src/cw/util/SocketService.hpp storage/ndb/src/kernel/SimBlockList.cpp storage/ndb/src/kernel/blocks/backup/Backup.cpp storage/ndb/src/kernel/blocks/backup/Backup.hpp storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp storage/ndb/src/kernel/blocks/backup/BackupInit.cpp storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp storage/ndb/src/kernel/blocks/backup/read.cpp storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp storage/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp storage/ndb/src/kernel/blocks/dbdih/printSysfile/printSysfile.cpp storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp storage/ndb/src/kernel/blocks/dblqh/redoLogReader/reader.cpp storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp storage/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxStat.cpp storage/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp storage/ndb/src/kernel/blocks/diskpage.hpp storage/ndb/src/kernel/blocks/lgman.hpp storage/ndb/src/kernel/blocks/mutexes.hpp storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrSysTable.cpp storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/AsyncFileTest.cpp storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.cpp storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp storage/ndb/src/kernel/blocks/ndbfs/Filename.hpp storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.cpp storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/MemoryChannelTest.cpp storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp storage/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp storage/ndb/src/kernel/blocks/pgman.cpp storage/ndb/src/kernel/blocks/pgman.hpp storage/ndb/src/kernel/blocks/print_file.cpp storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp storage/ndb/src/kernel/blocks/qmgr/timer.hpp storage/ndb/src/kernel/blocks/record_types.hpp storage/ndb/src/kernel/blocks/restore.cpp storage/ndb/src/kernel/blocks/restore.hpp storage/ndb/src/kernel/blocks/suma/Suma.cpp storage/ndb/src/kernel/blocks/suma/Suma.hpp storage/ndb/src/kernel/blocks/suma/SumaInit.cpp storage/ndb/src/kernel/blocks/trix/Trix.cpp storage/ndb/src/kernel/blocks/trix/Trix.hpp storage/ndb/src/kernel/blocks/tsman.cpp storage/ndb/src/kernel/blocks/tsman.hpp storage/ndb/src/kernel/error/ErrorHandlingMacros.hpp storage/ndb/src/kernel/error/ErrorReporter.cpp storage/ndb/src/kernel/error/ErrorReporter.hpp storage/ndb/src/kernel/error/TimeModule.cpp storage/ndb/src/kernel/error/TimeModule.hpp storage/ndb/src/kernel/error/ndbd_exit_codes.c storage/ndb/src/kernel/main.cpp storage/ndb/src/kernel/vm/Array.hpp storage/ndb/src/kernel/vm/ArrayPool.hpp storage/ndb/src/kernel/vm/CArray.hpp storage/ndb/src/kernel/vm/Callback.hpp storage/ndb/src/kernel/vm/ClusterConfiguration.cpp storage/ndb/src/kernel/vm/ClusterConfiguration.hpp storage/ndb/src/kernel/vm/Configuration.cpp storage/ndb/src/kernel/vm/Configuration.hpp storage/ndb/src/kernel/vm/DLCFifoList.hpp storage/ndb/src/kernel/vm/DLCHashTable.hpp storage/ndb/src/kernel/vm/DLFifoList.hpp storage/ndb/src/kernel/vm/DLHashTable.hpp storage/ndb/src/kernel/vm/DLHashTable2.hpp storage/ndb/src/kernel/vm/DLList.hpp storage/ndb/src/kernel/vm/DataBuffer.hpp storage/ndb/src/kernel/vm/DynArr256.cpp storage/ndb/src/kernel/vm/DynArr256.hpp storage/ndb/src/kernel/vm/Emulator.cpp storage/ndb/src/kernel/vm/Emulator.hpp storage/ndb/src/kernel/vm/FastScheduler.cpp storage/ndb/src/kernel/vm/FastScheduler.hpp storage/ndb/src/kernel/vm/GlobalData.hpp storage/ndb/src/kernel/vm/KeyDescriptor.hpp storage/ndb/src/kernel/vm/KeyTable.hpp storage/ndb/src/kernel/vm/KeyTable2.hpp storage/ndb/src/kernel/vm/KeyTable2Ref.hpp storage/ndb/src/kernel/vm/LinearPool.hpp storage/ndb/src/kernel/vm/LongSignal.hpp storage/ndb/src/kernel/vm/Mutex.cpp storage/ndb/src/kernel/vm/Mutex.hpp storage/ndb/src/kernel/vm/NdbdSuperPool.cpp storage/ndb/src/kernel/vm/NdbdSuperPool.hpp storage/ndb/src/kernel/vm/Pool.cpp storage/ndb/src/kernel/vm/Pool.hpp storage/ndb/src/kernel/vm/Prio.hpp storage/ndb/src/kernel/vm/RWPool.cpp storage/ndb/src/kernel/vm/RWPool.hpp storage/ndb/src/kernel/vm/RequestTracker.hpp storage/ndb/src/kernel/vm/Rope.hpp storage/ndb/src/kernel/vm/SLFifoList.hpp storage/ndb/src/kernel/vm/SLList.hpp storage/ndb/src/kernel/vm/SafeCounter.cpp storage/ndb/src/kernel/vm/SafeCounter.hpp storage/ndb/src/kernel/vm/SectionReader.cpp storage/ndb/src/kernel/vm/SectionReader.hpp storage/ndb/src/kernel/vm/SignalCounter.hpp storage/ndb/src/kernel/vm/SimBlockList.hpp storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp storage/ndb/src/kernel/vm/SimulatedBlock.cpp storage/ndb/src/kernel/vm/SimulatedBlock.hpp storage/ndb/src/kernel/vm/SuperPool.cpp storage/ndb/src/kernel/vm/SuperPool.hpp storage/ndb/src/kernel/vm/ThreadConfig.cpp storage/ndb/src/kernel/vm/ThreadConfig.hpp storage/ndb/src/kernel/vm/TimeQueue.cpp storage/ndb/src/kernel/vm/TimeQueue.hpp storage/ndb/src/kernel/vm/TransporterCallback.cpp storage/ndb/src/kernel/vm/VMSignal.cpp storage/ndb/src/kernel/vm/VMSignal.hpp storage/ndb/src/kernel/vm/WOPool.cpp storage/ndb/src/kernel/vm/WOPool.hpp storage/ndb/src/kernel/vm/WaitQueue.hpp storage/ndb/src/kernel/vm/WatchDog.cpp storage/ndb/src/kernel/vm/WatchDog.hpp storage/ndb/src/kernel/vm/al_test/arrayListTest.cpp storage/ndb/src/kernel/vm/al_test/arrayPoolTest.cpp storage/ndb/src/kernel/vm/al_test/main.cpp storage/ndb/src/kernel/vm/bench_pool.cpp storage/ndb/src/kernel/vm/ndbd_malloc.cpp storage/ndb/src/kernel/vm/ndbd_malloc.hpp storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp storage/ndb/src/kernel/vm/pc.hpp storage/ndb/src/kernel/vm/testCopy/rr.cpp storage/ndb/src/kernel/vm/testCopy/testCopy.cpp storage/ndb/src/kernel/vm/testDataBuffer/testDataBuffer.cpp storage/ndb/src/kernel/vm/testLongSig/testLongSig.cpp storage/ndb/src/kernel/vm/testSimplePropertiesSection/test.cpp storage/ndb/src/kernel/vm/testSuperPool.cpp storage/ndb/src/mgmapi/LocalConfig.cpp storage/ndb/src/mgmapi/LocalConfig.hpp storage/ndb/src/mgmapi/mgmapi.cpp storage/ndb/src/mgmapi/mgmapi_configuration.hpp storage/ndb/src/mgmapi/mgmapi_internal.h storage/ndb/src/mgmapi/ndb_logevent.cpp storage/ndb/src/mgmapi/ndb_logevent.hpp storage/ndb/src/mgmapi/test/keso.c storage/ndb/src/mgmapi/test/mgmSrvApi.cpp storage/ndb/src/mgmclient/CommandInterpreter.cpp storage/ndb/src/mgmclient/main.cpp storage/ndb/src/mgmclient/ndb_mgmclient.h storage/ndb/src/mgmclient/ndb_mgmclient.hpp storage/ndb/src/mgmclient/test_cpcd/test_cpcd.cpp storage/ndb/src/mgmsrv/Config.cpp storage/ndb/src/mgmsrv/Config.hpp storage/ndb/src/mgmsrv/ConfigInfo.cpp storage/ndb/src/mgmsrv/ConfigInfo.hpp storage/ndb/src/mgmsrv/InitConfigFileParser.cpp storage/ndb/src/mgmsrv/InitConfigFileParser.hpp storage/ndb/src/mgmsrv/MgmtSrvr.cpp storage/ndb/src/mgmsrv/MgmtSrvr.hpp storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp storage/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp storage/ndb/src/mgmsrv/Services.cpp storage/ndb/src/mgmsrv/Services.hpp storage/ndb/src/mgmsrv/SignalQueue.cpp storage/ndb/src/mgmsrv/SignalQueue.hpp storage/ndb/src/mgmsrv/convertStrToInt.cpp storage/ndb/src/mgmsrv/convertStrToInt.hpp storage/ndb/src/mgmsrv/main.cpp storage/ndb/src/mgmsrv/mkconfig/mkconfig.cpp storage/ndb/src/ndbapi/API.hpp storage/ndb/src/ndbapi/ClusterMgr.cpp storage/ndb/src/ndbapi/ClusterMgr.hpp storage/ndb/src/ndbapi/DictCache.cpp storage/ndb/src/ndbapi/DictCache.hpp storage/ndb/src/ndbapi/Ndb.cpp storage/ndb/src/ndbapi/NdbApiSignal.cpp storage/ndb/src/ndbapi/NdbApiSignal.hpp storage/ndb/src/ndbapi/NdbBlob.cpp storage/ndb/src/ndbapi/NdbBlobImpl.hpp storage/ndb/src/ndbapi/NdbDictionary.cpp storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp storage/ndb/src/ndbapi/NdbErrorOut.cpp storage/ndb/src/ndbapi/NdbEventOperation.cpp storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp storage/ndb/src/ndbapi/NdbImpl.hpp storage/ndb/src/ndbapi/NdbIndexOperation.cpp storage/ndb/src/ndbapi/NdbIndexStat.cpp storage/ndb/src/ndbapi/NdbLinHash.hpp storage/ndb/src/ndbapi/NdbOperation.cpp storage/ndb/src/ndbapi/NdbOperationDefine.cpp storage/ndb/src/ndbapi/NdbOperationExec.cpp storage/ndb/src/ndbapi/NdbOperationInt.cpp storage/ndb/src/ndbapi/NdbOperationScan.cpp storage/ndb/src/ndbapi/NdbOperationSearch.cpp storage/ndb/src/ndbapi/NdbPool.cpp storage/ndb/src/ndbapi/NdbPoolImpl.cpp storage/ndb/src/ndbapi/NdbPoolImpl.hpp storage/ndb/src/ndbapi/NdbRecAttr.cpp storage/ndb/src/ndbapi/NdbReceiver.cpp storage/ndb/src/ndbapi/NdbScanFilter.cpp storage/ndb/src/ndbapi/NdbScanOperation.cpp storage/ndb/src/ndbapi/NdbTransaction.cpp storage/ndb/src/ndbapi/NdbTransactionScan.cpp storage/ndb/src/ndbapi/NdbUtil.cpp storage/ndb/src/ndbapi/NdbUtil.hpp storage/ndb/src/ndbapi/NdbWaiter.hpp storage/ndb/src/ndbapi/Ndberr.cpp storage/ndb/src/ndbapi/Ndbif.cpp storage/ndb/src/ndbapi/Ndbinit.cpp storage/ndb/src/ndbapi/Ndblist.cpp storage/ndb/src/ndbapi/ObjectMap.cpp storage/ndb/src/ndbapi/ObjectMap.hpp storage/ndb/src/ndbapi/SignalSender.cpp storage/ndb/src/ndbapi/SignalSender.hpp storage/ndb/src/ndbapi/TransporterFacade.cpp storage/ndb/src/ndbapi/TransporterFacade.hpp storage/ndb/src/ndbapi/ndb_cluster_connection.cpp storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp storage/ndb/src/ndbapi/ndberror.c storage/ndb/src/ndbapi/signal-sender/SignalSender.cpp storage/ndb/src/ndbapi/signal-sender/SignalSender.hpp storage/ndb/test/include/AtrtClient.hpp storage/ndb/test/include/CpcClient.hpp storage/ndb/test/include/DbUtil.hpp storage/ndb/test/include/HugoAsynchTransactions.hpp storage/ndb/test/include/HugoCalculator.hpp storage/ndb/test/include/HugoOperations.hpp storage/ndb/test/include/HugoTransactions.hpp storage/ndb/test/include/NDBT.hpp storage/ndb/test/include/NDBT_DataSet.hpp storage/ndb/test/include/NDBT_DataSetTransaction.hpp storage/ndb/test/include/NDBT_Error.hpp storage/ndb/test/include/NDBT_Output.hpp storage/ndb/test/include/NDBT_ResultRow.hpp storage/ndb/test/include/NDBT_ReturnCodes.h storage/ndb/test/include/NDBT_Stats.hpp storage/ndb/test/include/NDBT_Table.hpp storage/ndb/test/include/NDBT_Tables.hpp storage/ndb/test/include/NDBT_Test.hpp storage/ndb/test/include/NDBT_Thread.hpp storage/ndb/test/include/NdbBackup.hpp storage/ndb/test/include/NdbConfig.hpp storage/ndb/test/include/NdbGrep.hpp storage/ndb/test/include/NdbMixRestarter.hpp storage/ndb/test/include/NdbRestarter.hpp storage/ndb/test/include/NdbRestarts.hpp storage/ndb/test/include/NdbSchemaCon.hpp storage/ndb/test/include/NdbSchemaOp.hpp storage/ndb/test/include/NdbTest.hpp storage/ndb/test/include/NdbTimer.hpp storage/ndb/test/include/TestNdbEventOperation.hpp storage/ndb/test/include/UtilTransactions.hpp storage/ndb/test/include/getarg.h storage/ndb/test/ndbapi/InsertRecs.cpp storage/ndb/test/ndbapi/ScanFilter.hpp storage/ndb/test/ndbapi/ScanFunctions.hpp storage/ndb/test/ndbapi/ScanInterpretTest.hpp storage/ndb/test/ndbapi/TraceNdbApi.cpp storage/ndb/test/ndbapi/VerifyNdbApi.cpp storage/ndb/test/ndbapi/acid.cpp storage/ndb/test/ndbapi/acid2.cpp storage/ndb/test/ndbapi/acrt/NdbRepStress.cpp storage/ndb/test/ndbapi/adoInsertRecs.cpp storage/ndb/test/ndbapi/asyncGenerator.cpp storage/ndb/test/ndbapi/bank/Bank.cpp storage/ndb/test/ndbapi/bank/Bank.hpp storage/ndb/test/ndbapi/bank/BankLoad.cpp storage/ndb/test/ndbapi/bank/bankCreator.cpp storage/ndb/test/ndbapi/bank/bankMakeGL.cpp storage/ndb/test/ndbapi/bank/bankSumAccounts.cpp storage/ndb/test/ndbapi/bank/bankTimer.cpp storage/ndb/test/ndbapi/bank/bankTransactionMaker.cpp storage/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp storage/ndb/test/ndbapi/bank/testBank.cpp storage/ndb/test/ndbapi/bench/asyncGenerator.cpp storage/ndb/test/ndbapi/bench/dbGenerator.h storage/ndb/test/ndbapi/bench/dbPopulate.cpp storage/ndb/test/ndbapi/bench/dbPopulate.h storage/ndb/test/ndbapi/bench/macros.h storage/ndb/test/ndbapi/bench/mainAsyncGenerator.cpp storage/ndb/test/ndbapi/bench/mainPopulate.cpp storage/ndb/test/ndbapi/bench/ndb_async1.cpp storage/ndb/test/ndbapi/bench/ndb_async2.cpp storage/ndb/test/ndbapi/bench/ndb_error.hpp storage/ndb/test/ndbapi/bench/ndb_schema.hpp storage/ndb/test/ndbapi/bench/ndb_user_transaction.cpp storage/ndb/test/ndbapi/bench/ndb_user_transaction2.cpp storage/ndb/test/ndbapi/bench/ndb_user_transaction3.cpp storage/ndb/test/ndbapi/bench/ndb_user_transaction4.cpp storage/ndb/test/ndbapi/bench/ndb_user_transaction5.cpp storage/ndb/test/ndbapi/bench/ndb_user_transaction6.cpp storage/ndb/test/ndbapi/bench/testData.h storage/ndb/test/ndbapi/bench/testDefinitions.h storage/ndb/test/ndbapi/bench/userInterface.cpp storage/ndb/test/ndbapi/bench/userInterface.h storage/ndb/test/ndbapi/benchronja.cpp storage/ndb/test/ndbapi/bulk_copy.cpp storage/ndb/test/ndbapi/cdrserver.cpp storage/ndb/test/ndbapi/celloDb.cpp storage/ndb/test/ndbapi/create_all_tabs.cpp storage/ndb/test/ndbapi/create_tab.cpp storage/ndb/test/ndbapi/drop_all_tabs.cpp storage/ndb/test/ndbapi/flexAsynch.cpp storage/ndb/test/ndbapi/flexBench.cpp storage/ndb/test/ndbapi/flexHammer.cpp storage/ndb/test/ndbapi/flexScan.cpp storage/ndb/test/ndbapi/flexTT.cpp storage/ndb/test/ndbapi/flexTimedAsynch.cpp storage/ndb/test/ndbapi/flex_bench_mysql.cpp storage/ndb/test/ndbapi/index.cpp storage/ndb/test/ndbapi/index2.cpp storage/ndb/test/ndbapi/initronja.cpp storage/ndb/test/ndbapi/interpreterInTup.cpp storage/ndb/test/ndbapi/mainAsyncGenerator.cpp storage/ndb/test/ndbapi/msa.cpp storage/ndb/test/ndbapi/ndb_async1.cpp storage/ndb/test/ndbapi/ndb_async2.cpp storage/ndb/test/ndbapi/ndb_user_populate.cpp storage/ndb/test/ndbapi/ndb_user_transaction.cpp storage/ndb/test/ndbapi/ndb_user_transaction2.cpp storage/ndb/test/ndbapi/ndb_user_transaction3.cpp storage/ndb/test/ndbapi/ndb_user_transaction4.cpp storage/ndb/test/ndbapi/ndb_user_transaction5.cpp storage/ndb/test/ndbapi/ndb_user_transaction6.cpp storage/ndb/test/ndbapi/restarter.cpp storage/ndb/test/ndbapi/restarter2.cpp storage/ndb/test/ndbapi/restarts.cpp storage/ndb/test/ndbapi/size.cpp storage/ndb/test/ndbapi/testBackup.cpp storage/ndb/test/ndbapi/testBasic.cpp storage/ndb/test/ndbapi/testBasicAsynch.cpp storage/ndb/test/ndbapi/testBlobs.cpp storage/ndb/test/ndbapi/testDataBuffers.cpp storage/ndb/test/ndbapi/testDeadlock.cpp storage/ndb/test/ndbapi/testDict.cpp storage/ndb/test/ndbapi/testGrepVerify.cpp storage/ndb/test/ndbapi/testIndex.cpp storage/ndb/test/ndbapi/testIndexStat.cpp storage/ndb/test/ndbapi/testInterpreter.cpp storage/ndb/test/ndbapi/testMgm.cpp storage/ndb/test/ndbapi/testNDBT.cpp storage/ndb/test/ndbapi/testNdbApi.cpp storage/ndb/test/ndbapi/testNodeRestart.cpp storage/ndb/test/ndbapi/testOIBasic.cpp storage/ndb/test/ndbapi/testOperations.cpp storage/ndb/test/ndbapi/testOrderedIndex.cpp storage/ndb/test/ndbapi/testPartitioning.cpp storage/ndb/test/ndbapi/testReadPerf.cpp storage/ndb/test/ndbapi/testRestartGci.cpp storage/ndb/test/ndbapi/testSRBank.cpp storage/ndb/test/ndbapi/testScan.cpp storage/ndb/test/ndbapi/testScanInterpreter.cpp storage/ndb/test/ndbapi/testScanPerf.cpp storage/ndb/test/ndbapi/testSystemRestart.cpp storage/ndb/test/ndbapi/testTimeout.cpp storage/ndb/test/ndbapi/testTransactions.cpp storage/ndb/test/ndbapi/test_event.cpp storage/ndb/test/ndbapi/test_event_merge.cpp storage/ndb/test/ndbapi/test_event_multi_table.cpp storage/ndb/test/ndbapi/userInterface.cpp storage/ndb/test/ndbnet/test.run storage/ndb/test/ndbnet/testError.run storage/ndb/test/ndbnet/testMNF.run storage/ndb/test/ndbnet/testNR.run storage/ndb/test/ndbnet/testNR1.run storage/ndb/test/ndbnet/testNR4.run storage/ndb/test/ndbnet/testSRhang.run storage/ndb/test/ndbnet/testTR295.run storage/ndb/test/newtonapi/basic_test/basic/basic.cpp storage/ndb/test/newtonapi/basic_test/bulk_read/br_test.cpp storage/ndb/test/newtonapi/basic_test/common.cpp storage/ndb/test/newtonapi/basic_test/common.hpp storage/ndb/test/newtonapi/basic_test/ptr_binding/ptr_binding_test.cpp storage/ndb/test/newtonapi/basic_test/too_basic.cpp storage/ndb/test/newtonapi/perf_test/perf.cpp storage/ndb/test/odbc/SQL99_test/SQL99_test.cpp storage/ndb/test/odbc/SQL99_test/SQL99_test.h storage/ndb/test/odbc/client/NDBT_ALLOCHANDLE.cpp storage/ndb/test/odbc/client/NDBT_ALLOCHANDLE_HDBC.cpp storage/ndb/test/odbc/client/NDBT_SQLConnect.cpp storage/ndb/test/odbc/client/NDBT_SQLPrepare.cpp storage/ndb/test/odbc/client/SQLAllocEnvTest.cpp storage/ndb/test/odbc/client/SQLAllocHandleTest.cpp storage/ndb/test/odbc/client/SQLAllocHandleTest_bf.cpp storage/ndb/test/odbc/client/SQLBindColTest.cpp storage/ndb/test/odbc/client/SQLBindParameterTest.cpp storage/ndb/test/odbc/client/SQLCancelTest.cpp storage/ndb/test/odbc/client/SQLCloseCursorTest.cpp storage/ndb/test/odbc/client/SQLColAttributeTest.cpp storage/ndb/test/odbc/client/SQLColAttributeTest1.cpp storage/ndb/test/odbc/client/SQLColAttributeTest2.cpp storage/ndb/test/odbc/client/SQLColAttributeTest3.cpp storage/ndb/test/odbc/client/SQLConnectTest.cpp storage/ndb/test/odbc/client/SQLCopyDescTest.cpp storage/ndb/test/odbc/client/SQLDescribeColTest.cpp storage/ndb/test/odbc/client/SQLDisconnectTest.cpp storage/ndb/test/odbc/client/SQLDriverConnectTest.cpp storage/ndb/test/odbc/client/SQLEndTranTest.cpp storage/ndb/test/odbc/client/SQLErrorTest.cpp storage/ndb/test/odbc/client/SQLExecDirectTest.cpp storage/ndb/test/odbc/client/SQLExecuteTest.cpp storage/ndb/test/odbc/client/SQLFetchScrollTest.cpp storage/ndb/test/odbc/client/SQLFetchTest.cpp storage/ndb/test/odbc/client/SQLFreeHandleTest.cpp storage/ndb/test/odbc/client/SQLFreeStmtTest.cpp storage/ndb/test/odbc/client/SQLGetConnectAttrTest.cpp storage/ndb/test/odbc/client/SQLGetCursorNameTest.cpp storage/ndb/test/odbc/client/SQLGetDataTest.cpp storage/ndb/test/odbc/client/SQLGetDescFieldTest.cpp storage/ndb/test/odbc/client/SQLGetDescRecTest.cpp storage/ndb/test/odbc/client/SQLGetDiagFieldTest.cpp storage/ndb/test/odbc/client/SQLGetDiagRecSimpleTest.cpp storage/ndb/test/odbc/client/SQLGetDiagRecTest.cpp storage/ndb/test/odbc/client/SQLGetEnvAttrTest.cpp storage/ndb/test/odbc/client/SQLGetFunctionsTest.cpp storage/ndb/test/odbc/client/SQLGetInfoTest.cpp storage/ndb/test/odbc/client/SQLGetStmtAttrTest.cpp storage/ndb/test/odbc/client/SQLGetTypeInfoTest.cpp storage/ndb/test/odbc/client/SQLMoreResultsTest.cpp storage/ndb/test/odbc/client/SQLNumResultColsTest.cpp storage/ndb/test/odbc/client/SQLParamDataTest.cpp storage/ndb/test/odbc/client/SQLPrepareTest.cpp storage/ndb/test/odbc/client/SQLPutDataTest.cpp storage/ndb/test/odbc/client/SQLRowCountTest.cpp storage/ndb/test/odbc/client/SQLSetConnectAttrTest.cpp storage/ndb/test/odbc/client/SQLSetCursorNameTest.cpp storage/ndb/test/odbc/client/SQLSetDescFieldTest.cpp storage/ndb/test/odbc/client/SQLSetDescRecTest.cpp storage/ndb/test/odbc/client/SQLSetEnvAttrTest.cpp storage/ndb/test/odbc/client/SQLSetStmtAttrTest.cpp storage/ndb/test/odbc/client/SQLTablesTest.cpp storage/ndb/test/odbc/client/SQLTransactTest.cpp storage/ndb/test/odbc/client/common.hpp storage/ndb/test/odbc/client/main.cpp storage/ndb/test/odbc/driver/testOdbcDriver.cpp storage/ndb/test/odbc/test_compiler/test_compiler.cpp storage/ndb/test/run-test/atrt-analyze-result.sh storage/ndb/test/run-test/atrt-clear-result.sh storage/ndb/test/run-test/atrt-gather-result.sh storage/ndb/test/run-test/atrt-setup.sh storage/ndb/test/run-test/atrt-testBackup storage/ndb/test/run-test/atrt.hpp storage/ndb/test/run-test/main.cpp storage/ndb/test/run-test/make-index.sh storage/ndb/test/src/CpcClient.cpp storage/ndb/test/src/DbUtil.cpp storage/ndb/test/src/HugoAsynchTransactions.cpp storage/ndb/test/src/HugoCalculator.cpp storage/ndb/test/src/HugoOperations.cpp storage/ndb/test/src/HugoTransactions.cpp storage/ndb/test/src/NDBT_Error.cpp storage/ndb/test/src/NDBT_Output.cpp storage/ndb/test/src/NDBT_ResultRow.cpp storage/ndb/test/src/NDBT_ReturnCodes.cpp storage/ndb/test/src/NDBT_Table.cpp storage/ndb/test/src/NDBT_Tables.cpp storage/ndb/test/src/NDBT_Test.cpp storage/ndb/test/src/NDBT_Thread.cpp storage/ndb/test/src/NdbBackup.cpp storage/ndb/test/src/NdbConfig.cpp storage/ndb/test/src/NdbGrep.cpp storage/ndb/test/src/NdbMixRestarter.cpp storage/ndb/test/src/NdbRestarter.cpp storage/ndb/test/src/NdbRestarts.cpp storage/ndb/test/src/NdbSchemaCon.cpp storage/ndb/test/src/NdbSchemaOp.cpp storage/ndb/test/src/UtilTransactions.cpp storage/ndb/test/tools/connect.cpp storage/ndb/test/tools/copy_tab.cpp storage/ndb/test/tools/cpcc.cpp storage/ndb/test/tools/create_index.cpp storage/ndb/test/tools/hugoCalculator.cpp storage/ndb/test/tools/hugoFill.cpp storage/ndb/test/tools/hugoLoad.cpp storage/ndb/test/tools/hugoLockRecords.cpp storage/ndb/test/tools/hugoPkDelete.cpp storage/ndb/test/tools/hugoPkRead.cpp storage/ndb/test/tools/hugoPkReadRecord.cpp storage/ndb/test/tools/hugoPkUpdate.cpp storage/ndb/test/tools/hugoScanRead.cpp storage/ndb/test/tools/hugoScanUpdate.cpp storage/ndb/test/tools/listen.cpp storage/ndb/test/tools/rep_latency.cpp storage/ndb/test/tools/restart.cpp storage/ndb/test/tools/transproxy.cpp storage/ndb/test/tools/verify_index.cpp storage/ndb/tools/clean-links.sh storage/ndb/tools/delete_all.cpp storage/ndb/tools/desc.cpp storage/ndb/tools/drop_index.cpp storage/ndb/tools/drop_tab.cpp storage/ndb/tools/listTables.cpp storage/ndb/tools/make-errors.pl storage/ndb/tools/make-links.sh storage/ndb/tools/ndb_config.cpp storage/ndb/tools/ndb_error_reporter storage/ndb/tools/ndb_test_platform.cpp storage/ndb/tools/ndbsql.cpp storage/ndb/tools/restore/Restore.cpp storage/ndb/tools/restore/Restore.hpp storage/ndb/tools/restore/consumer.cpp storage/ndb/tools/restore/consumer.hpp storage/ndb/tools/restore/consumer_printer.cpp storage/ndb/tools/restore/consumer_printer.hpp storage/ndb/tools/restore/consumer_restore.cpp storage/ndb/tools/restore/consumer_restore.hpp storage/ndb/tools/restore/consumer_restorem.cpp storage/ndb/tools/restore/ndb_nodegroup_map.h storage/ndb/tools/restore/restore_main.cpp storage/ndb/tools/rgrep storage/ndb/tools/select_all.cpp storage/ndb/tools/select_count.cpp storage/ndb/tools/waiter.cpp storage/oqgraph/CMakeLists.txt storage/oqgraph/ha_oqgraph.cc storage/oqgraph/ha_oqgraph.h storage/oqgraph/mysql-test/oqgraph/boundary_conditions.result storage/oqgraph/mysql-test/oqgraph/boundary_conditions.test storage/oqgraph/mysql-test/oqgraph/invalid_operations.result storage/oqgraph/mysql-test/oqgraph/invalid_operations.test storage/oqgraph/mysql-test/oqgraph/isnull.result storage/oqgraph/mysql-test/oqgraph/isnull.test storage/oqgraph/mysql-test/oqgraph/regression_1233113.result storage/oqgraph/mysql-test/oqgraph/regression_1233113.test storage/oqgraph/mysql-test/oqgraph/regression_drop_after.result storage/oqgraph/mysql-test/oqgraph/regression_drop_after.test storage/oqgraph/mysql-test/oqgraph/suite.pm storage/perfschema/CMakeLists.txt storage/perfschema/pfs_check.cc storage/perfschema/pfs_events_waits.cc storage/perfschema/pfs_global.cc storage/perfschema/table_events_waits.cc storage/perfschema/unittest/CMakeLists.txt storage/sequence/mysql-test/sequence/simple.result storage/sequence/mysql-test/sequence/simple.test storage/sequence/sequence.cc storage/sphinx/ha_sphinx.cc storage/sphinx/mysql-test/sphinx/suite.pm storage/spider/ha_spider.cc storage/spider/ha_spider.h storage/spider/mysql-test/spider/bg/suite.opt storage/spider/scripts/install_spider.sql storage/spider/spd_conn.cc storage/spider/spd_conn.h storage/spider/spd_copy_tables.cc storage/spider/spd_copy_tables.h storage/spider/spd_db_conn.cc storage/spider/spd_db_conn.h storage/spider/spd_db_handlersocket.cc storage/spider/spd_db_handlersocket.h storage/spider/spd_db_include.h storage/spider/spd_db_mysql.cc storage/spider/spd_db_mysql.h storage/spider/spd_db_oracle.cc storage/spider/spd_db_oracle.h storage/spider/spd_direct_sql.cc storage/spider/spd_direct_sql.h storage/spider/spd_err.h storage/spider/spd_i_s.cc storage/spider/spd_include.h storage/spider/spd_malloc.cc storage/spider/spd_malloc.h storage/spider/spd_param.cc storage/spider/spd_param.h storage/spider/spd_ping_table.cc storage/spider/spd_ping_table.h storage/spider/spd_sys_table.cc storage/spider/spd_sys_table.h storage/spider/spd_table.cc storage/spider/spd_table.h storage/spider/spd_trx.cc storage/spider/spd_trx.h storage/spider/spd_udf.cc storage/spider/spd_udf.h storage/tokudb/CMakeLists.txt storage/tokudb/README.md storage/tokudb/ft-index/CMakeLists.txt storage/tokudb/ft-index/README.md storage/tokudb/ft-index/buildheader/CMakeLists.txt storage/tokudb/ft-index/buildheader/make_tdb.cc storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake storage/tokudb/ft-index/cmake_modules/TokuThirdParty.cmake storage/tokudb/ft-index/examples/CMakeLists.txt storage/tokudb/ft-index/ft/CMakeLists.txt storage/tokudb/ft-index/ft/bndata.cc storage/tokudb/ft-index/ft/bndata.h storage/tokudb/ft-index/ft/cachetable-internal.h storage/tokudb/ft-index/ft/cachetable.cc storage/tokudb/ft-index/ft/cachetable.h storage/tokudb/ft-index/ft/checkpoint.cc storage/tokudb/ft-index/ft/compress.cc storage/tokudb/ft-index/ft/fifo.cc storage/tokudb/ft-index/ft/fifo.h storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc storage/tokudb/ft-index/ft/ft-flusher.cc storage/tokudb/ft-index/ft/ft-flusher.h storage/tokudb/ft-index/ft/ft-hot-flusher.cc storage/tokudb/ft-index/ft/ft-internal.h storage/tokudb/ft-index/ft/ft-ops.cc storage/tokudb/ft-index/ft/ft-ops.h storage/tokudb/ft-index/ft/ft-serialize.cc storage/tokudb/ft-index/ft/ft-test-helpers.cc storage/tokudb/ft-index/ft/ft.cc storage/tokudb/ft-index/ft/ft.h storage/tokudb/ft-index/ft/ft_layout_version.h storage/tokudb/ft-index/ft/ft_node-serialize.cc storage/tokudb/ft-index/ft/ftloader-internal.h storage/tokudb/ft-index/ft/ftloader.cc storage/tokudb/ft-index/ft/fttypes.h storage/tokudb/ft-index/ft/leafentry.h storage/tokudb/ft-index/ft/log-internal.h storage/tokudb/ft-index/ft/logformat.cc storage/tokudb/ft-index/ft/logger.cc storage/tokudb/ft-index/ft/logger.h storage/tokudb/ft-index/ft/roll.cc storage/tokudb/ft-index/ft/rollback-apply.cc storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc storage/tokudb/ft-index/ft/rollback-ct-callbacks.h storage/tokudb/ft-index/ft/rollback.cc storage/tokudb/ft-index/ft/rollback.h storage/tokudb/ft-index/ft/rollback_log_node_cache.cc storage/tokudb/ft-index/ft/rollback_log_node_cache.h storage/tokudb/ft-index/ft/tests/cachetable-5097.cc storage/tokudb/ft-index/ft/tests/cachetable-5978.cc storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction2.cc storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction3.cc storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction4.cc storage/tokudb/ft-index/ft/tests/cachetable-eviction-close-test2.cc storage/tokudb/ft-index/ft/tests/cachetable-eviction-getandpin-test2.cc storage/tokudb/ft-index/ft/tests/cachetable-evictor-class.cc storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc storage/tokudb/ft-index/ft/tests/ft-clock-test.cc storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc storage/tokudb/ft-index/ft/tests/ftloader-test-bad-generate.cc storage/tokudb/ft-index/ft/tests/ftloader-test-extractor-errors.cc storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc storage/tokudb/ft-index/ft/tests/ftloader-test-merge-files-dbufio.cc storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc storage/tokudb/ft-index/ft/tests/ftloader-test-writer-errors.cc storage/tokudb/ft-index/ft/tests/ftloader-test-writer.cc storage/tokudb/ft-index/ft/tests/ftloader-test.cc storage/tokudb/ft-index/ft/tests/make-tree.cc storage/tokudb/ft-index/ft/tests/msnfilter.cc storage/tokudb/ft-index/ft/tests/orthopush-flush.cc storage/tokudb/ft-index/ft/tests/test-flushes-on-cleaner.cc storage/tokudb/ft-index/ft/tests/test-hot-with-bounds.cc storage/tokudb/ft-index/ft/tests/test-inc-split.cc storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc storage/tokudb/ft-index/ft/tests/test-pick-child-to-flush.cc storage/tokudb/ft-index/ft/tests/test.h storage/tokudb/ft-index/ft/tests/upgrade_test_simple.cc storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc storage/tokudb/ft-index/ft/tests/verify-dup-in-leaf.cc storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc storage/tokudb/ft-index/ft/txn.cc storage/tokudb/ft-index/ft/txn_manager.cc storage/tokudb/ft-index/ft/txn_manager.h storage/tokudb/ft-index/ft/ule.cc storage/tokudb/ft-index/ft/ule.h storage/tokudb/ft-index/locktree/lock_request.cc storage/tokudb/ft-index/locktree/lock_request.h storage/tokudb/ft-index/locktree/locktree.cc storage/tokudb/ft-index/locktree/locktree.h storage/tokudb/ft-index/locktree/manager.cc storage/tokudb/ft-index/locktree/tests/lock_request_create_set.cc storage/tokudb/ft-index/locktree/tests/lock_request_get_set_keys.cc storage/tokudb/ft-index/locktree/tests/lock_request_start_deadlock.cc storage/tokudb/ft-index/locktree/tests/lock_request_start_pending.cc storage/tokudb/ft-index/locktree/tests/lock_request_unit_test.h storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc storage/tokudb/ft-index/locktree/tests/locktree_simple_lock.cc storage/tokudb/ft-index/locktree/tests/locktree_single_txnid_optimization.cc storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc storage/tokudb/ft-index/locktree/tests/manager_params.cc storage/tokudb/ft-index/locktree/tests/manager_status.cc storage/tokudb/ft-index/portability/CMakeLists.txt storage/tokudb/ft-index/portability/file.cc storage/tokudb/ft-index/portability/os_malloc.cc storage/tokudb/ft-index/scripts/run.stress-tests.py storage/tokudb/ft-index/src/CMakeLists.txt storage/tokudb/ft-index/src/export.map storage/tokudb/ft-index/src/indexer-undo-do.cc storage/tokudb/ft-index/src/loader.cc storage/tokudb/ft-index/src/tests/CMakeLists.txt storage/tokudb/ft-index/src/tests/blocking-first-empty.cc storage/tokudb/ft-index/src/tests/blocking-first.cc storage/tokudb/ft-index/src/tests/blocking-last.cc storage/tokudb/ft-index/src/tests/blocking-next-prev-deadlock.cc storage/tokudb/ft-index/src/tests/blocking-prelock-range.cc storage/tokudb/ft-index/src/tests/blocking-put-timeout.cc storage/tokudb/ft-index/src/tests/blocking-put-wakeup.cc storage/tokudb/ft-index/src/tests/blocking-put.cc storage/tokudb/ft-index/src/tests/blocking-set-range-0.cc storage/tokudb/ft-index/src/tests/blocking-set-range-n.cc storage/tokudb/ft-index/src/tests/blocking-set-range-reverse-0.cc storage/tokudb/ft-index/src/tests/blocking-set.cc storage/tokudb/ft-index/src/tests/blocking-table-lock.cc storage/tokudb/ft-index/src/tests/db-put-simple-deadlock-threads.cc storage/tokudb/ft-index/src/tests/db-put-simple-lockwait.cc storage/tokudb/ft-index/src/tests/db-put-update-deadlock.cc storage/tokudb/ft-index/src/tests/env_loader_memory.cc storage/tokudb/ft-index/src/tests/filesize.cc storage/tokudb/ft-index/src/tests/hot-optimize-table-tests.cc storage/tokudb/ft-index/src/tests/test_4368.cc storage/tokudb/ft-index/src/tests/test_iterate_pending_lock_requests.cc storage/tokudb/ft-index/src/tests/test_kv_gen.h storage/tokudb/ft-index/src/tests/test_lock_timeout_callback.cc storage/tokudb/ft-index/src/tests/test_stress5.cc storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h storage/tokudb/ft-index/src/tests/update-multiple-with-indexer-array.cc storage/tokudb/ft-index/src/ydb-internal.h storage/tokudb/ft-index/src/ydb.cc storage/tokudb/ft-index/src/ydb_cursor.cc storage/tokudb/ft-index/src/ydb_db.cc storage/tokudb/ft-index/src/ydb_env_func.cc storage/tokudb/ft-index/src/ydb_row_lock.cc storage/tokudb/ft-index/src/ydb_txn.cc storage/tokudb/ft-index/src/ydb_txn.h storage/tokudb/ft-index/toku_include/CMakeLists.txt storage/tokudb/ft-index/util/CMakeLists.txt storage/tokudb/ft-index/util/frwlock.cc storage/tokudb/ft-index/util/frwlock.h storage/tokudb/ft-index/util/kibbutz.cc storage/tokudb/ft-index/util/kibbutz.h storage/tokudb/ft-index/util/mempool.cc storage/tokudb/ft-index/util/mempool.h storage/tokudb/ft-index/util/tests/test-kibbutz.cc storage/tokudb/ft-index/util/tests/test-kibbutz2.cc storage/tokudb/ft-index/util/tests/test-rwlock-cheapness.cc storage/tokudb/ft-index/util/tests/test-rwlock.cc storage/tokudb/ha_tokudb.cc storage/tokudb/ha_tokudb.h storage/tokudb/ha_tokudb_admin.cc storage/tokudb/ha_tokudb_alter_56.cc storage/tokudb/ha_tokudb_alter_common.cc storage/tokudb/ha_tokudb_update.cc storage/tokudb/hatoku_cmp.cc storage/tokudb/hatoku_cmp.h storage/tokudb/hatoku_defines.h storage/tokudb/hatoku_hton.cc storage/tokudb/hatoku_hton.h storage/tokudb/mysql-test/tokudb/locks-blocking-row-locks-testgen.py storage/tokudb/mysql-test/tokudb/r/auto_increment.result storage/tokudb/mysql-test/tokudb/r/auto_increment_boundary.result storage/tokudb/mysql-test/tokudb/r/auto_increment_boundary_traditional.result storage/tokudb/mysql-test/tokudb/r/change_column_char_default.result storage/tokudb/mysql-test/tokudb/r/change_column_int_default.result storage/tokudb/mysql-test/tokudb/r/change_column_varbin.result storage/tokudb/mysql-test/tokudb/r/change_column_varbin_default.result storage/tokudb/mysql-test/tokudb/r/change_column_varbin_multiple.result storage/tokudb/mysql-test/tokudb/r/change_column_varchar.result storage/tokudb/mysql-test/tokudb/r/change_column_varchar_default.result storage/tokudb/mysql-test/tokudb/r/change_column_varchar_prefix_a.result storage/tokudb/mysql-test/tokudb/r/change_column_varchar_prefix_b.result storage/tokudb/mysql-test/tokudb/r/change_column_varchar_sum_cross256.result storage/tokudb/mysql-test/tokudb/r/cluster_2968-0.result storage/tokudb/mysql-test/tokudb/r/cluster_2968-1.result storage/tokudb/mysql-test/tokudb/r/cluster_2968-2.result storage/tokudb/mysql-test/tokudb/r/cluster_2968-3.result storage/tokudb/mysql-test/tokudb/r/cluster_create_table.result storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar_and_int_hidden.result storage/tokudb/mysql-test/tokudb/r/ctype_collate.result storage/tokudb/mysql-test/tokudb/r/ctype_cp1250_ch.result storage/tokudb/mysql-test/tokudb/r/hotindex-del-fast.result storage/tokudb/mysql-test/tokudb/r/hotindex-del-slow.result storage/tokudb/mysql-test/tokudb/r/information-schema-global-status.result storage/tokudb/mysql-test/tokudb/r/locks-blocking-row-locks-getset.result storage/tokudb/mysql-test/tokudb/r/locks-blocking-row-locks.result storage/tokudb/mysql-test/tokudb/r/mvcc-10.result storage/tokudb/mysql-test/tokudb/r/mvcc-11.result storage/tokudb/mysql-test/tokudb/r/mvcc-12.result storage/tokudb/mysql-test/tokudb/r/mvcc-13.result storage/tokudb/mysql-test/tokudb/r/mvcc-14.result storage/tokudb/mysql-test/tokudb/r/mvcc-15.result storage/tokudb/mysql-test/tokudb/r/mvcc-16.result storage/tokudb/mysql-test/tokudb/r/mvcc-17.result storage/tokudb/mysql-test/tokudb/r/mvcc-18.result storage/tokudb/mysql-test/tokudb/r/mvcc-21.result storage/tokudb/mysql-test/tokudb/r/mvcc-22.result storage/tokudb/mysql-test/tokudb/r/mvcc-23.result storage/tokudb/mysql-test/tokudb/r/mvcc-25.result storage/tokudb/mysql-test/tokudb/r/mvcc-3.result storage/tokudb/mysql-test/tokudb/r/mvcc-33.result storage/tokudb/mysql-test/tokudb/r/mvcc-34.result storage/tokudb/mysql-test/tokudb/r/mvcc-35.result storage/tokudb/mysql-test/tokudb/r/mvcc-36.result storage/tokudb/mysql-test/tokudb/r/mvcc-37.result storage/tokudb/mysql-test/tokudb/r/mvcc-38.result storage/tokudb/mysql-test/tokudb/r/mvcc-39.result storage/tokudb/mysql-test/tokudb/r/mvcc-4.result storage/tokudb/mysql-test/tokudb/r/mvcc-40.result storage/tokudb/mysql-test/tokudb/r/mvcc-5.result storage/tokudb/mysql-test/tokudb/r/mvcc-6.result storage/tokudb/mysql-test/tokudb/r/mvcc-7.result storage/tokudb/mysql-test/tokudb/r/mvcc-8.result storage/tokudb/mysql-test/tokudb/r/mvcc-9.result storage/tokudb/mysql-test/tokudb/r/mvcc-checksum-locks.result storage/tokudb/mysql-test/tokudb/r/type_binary.result storage/tokudb/mysql-test/tokudb/r/type_bit.result storage/tokudb/mysql-test/tokudb/r/type_blob.result storage/tokudb/mysql-test/tokudb/r/type_datetime.result storage/tokudb/mysql-test/tokudb/r/type_decimal.result storage/tokudb/mysql-test/tokudb/r/type_enum.result storage/tokudb/mysql-test/tokudb/r/type_float.result storage/tokudb/mysql-test/tokudb/r/type_nchar.result storage/tokudb/mysql-test/tokudb/r/type_newdecimal.result storage/tokudb/mysql-test/tokudb/r/type_set.result storage/tokudb/mysql-test/tokudb/r/type_timestamp.result storage/tokudb/mysql-test/tokudb/r/type_varchar.result storage/tokudb/mysql-test/tokudb/t/auto_increment.test storage/tokudb/mysql-test/tokudb/t/auto_increment_boundary.test storage/tokudb/mysql-test/tokudb/t/auto_increment_boundary_traditional.test storage/tokudb/mysql-test/tokudb/t/bulk-fetch.test storage/tokudb/mysql-test/tokudb/t/bulk-fetch2.test storage/tokudb/mysql-test/tokudb/t/change_column_all_1000_1.test storage/tokudb/mysql-test/tokudb/t/change_column_all_1000_10.test storage/tokudb/mysql-test/tokudb/t/change_column_auto_inc.test storage/tokudb/mysql-test/tokudb/t/change_column_bin.test storage/tokudb/mysql-test/tokudb/t/change_column_bin_descriptor.test storage/tokudb/mysql-test/tokudb/t/change_column_bin_key.test storage/tokudb/mysql-test/tokudb/t/change_column_bin_pad.test storage/tokudb/mysql-test/tokudb/t/change_column_bin_rename.test storage/tokudb/mysql-test/tokudb/t/change_column_blob.test storage/tokudb/mysql-test/tokudb/t/change_column_char.test storage/tokudb/mysql-test/tokudb/t/change_column_char_binary.test storage/tokudb/mysql-test/tokudb/t/change_column_char_charbinary.test storage/tokudb/mysql-test/tokudb/t/change_column_char_charset.test storage/tokudb/mysql-test/tokudb/t/change_column_char_default.test storage/tokudb/mysql-test/tokudb/t/change_column_char_descriptor.test storage/tokudb/mysql-test/tokudb/t/change_column_char_key.test storage/tokudb/mysql-test/tokudb/t/change_column_char_null.test storage/tokudb/mysql-test/tokudb/t/change_column_char_rename.test storage/tokudb/mysql-test/tokudb/t/change_column_int.test storage/tokudb/mysql-test/tokudb/t/change_column_int_default.test storage/tokudb/mysql-test/tokudb/t/change_column_int_descriptor.test storage/tokudb/mysql-test/tokudb/t/change_column_int_key.test storage/tokudb/mysql-test/tokudb/t/change_column_int_not_supported.test storage/tokudb/mysql-test/tokudb/t/change_column_int_rename.test storage/tokudb/mysql-test/tokudb/t/change_column_multiple_columns.test storage/tokudb/mysql-test/tokudb/t/change_column_text.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin_cross256.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin_default.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin_descriptor.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin_key.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin_multiple.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin_null.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin_rename.test storage/tokudb/mysql-test/tokudb/t/change_column_varbin_varchar.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_charset.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_cross256.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_default.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_descriptor.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_key.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_null.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_prefix_a.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_prefix_b.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_rename.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_sum_cross256.test storage/tokudb/mysql-test/tokudb/t/change_column_varchar_varbin.test storage/tokudb/mysql-test/tokudb/t/cluster_1829.test storage/tokudb/mysql-test/tokudb/t/cluster_2968-0.test storage/tokudb/mysql-test/tokudb/t/cluster_2968-1.test storage/tokudb/mysql-test/tokudb/t/cluster_2968-2.test storage/tokudb/mysql-test/tokudb/t/cluster_2968-3.test storage/tokudb/mysql-test/tokudb/t/cluster_create_table.test storage/tokudb/mysql-test/tokudb/t/cluster_delete.test storage/tokudb/mysql-test/tokudb/t/cluster_delete2.test storage/tokudb/mysql-test/tokudb/t/cluster_filter.test storage/tokudb/mysql-test/tokudb/t/cluster_filter_hidden.test storage/tokudb/mysql-test/tokudb/t/cluster_filter_key.test storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar_and_int_hidden.test storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar_hidden.test storage/tokudb/mysql-test/tokudb/t/cluster_filter_varchar_prefix.test storage/tokudb/mysql-test/tokudb/t/cluster_key.test storage/tokudb/mysql-test/tokudb/t/cluster_query_plan.test storage/tokudb/mysql-test/tokudb/t/cluster_tokudb_bug_993.test storage/tokudb/mysql-test/tokudb/t/cluster_tokudb_bug_993_2.test storage/tokudb/mysql-test/tokudb/t/cluster_update.test storage/tokudb/mysql-test/tokudb/t/cluster_update2.test storage/tokudb/mysql-test/tokudb/t/ctype_ascii.test storage/tokudb/mysql-test/tokudb/t/ctype_collate.test storage/tokudb/mysql-test/tokudb/t/ctype_cp1250_ch.test storage/tokudb/mysql-test/tokudb/t/ctype_cp1251.test storage/tokudb/mysql-test/tokudb/t/hotindex-del-0.test storage/tokudb/mysql-test/tokudb/t/hotindex-del-1.test storage/tokudb/mysql-test/tokudb/t/hotindex-del-fast.test storage/tokudb/mysql-test/tokudb/t/hotindex-del-slow.test storage/tokudb/mysql-test/tokudb/t/hotindex-insert-0.test storage/tokudb/mysql-test/tokudb/t/hotindex-insert-1.test storage/tokudb/mysql-test/tokudb/t/hotindex-insert-2.test storage/tokudb/mysql-test/tokudb/t/hotindex-insert-bigchar.test storage/tokudb/mysql-test/tokudb/t/hotindex-update-0.test storage/tokudb/mysql-test/tokudb/t/hotindex-update-1.test storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_released.test storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks_released.test storage/tokudb/mysql-test/tokudb/t/information-schema-global-status.test storage/tokudb/mysql-test/tokudb/t/lockretry-insert.writelocktable.test storage/tokudb/mysql-test/tokudb/t/lockretry-writelocktable.insert.test storage/tokudb/mysql-test/tokudb/t/lockretry-writelocktable.insert2.test storage/tokudb/mysql-test/tokudb/t/locks-blocking-row-locks-getset.test storage/tokudb/mysql-test/tokudb/t/locks-blocking-row-locks.test storage/tokudb/mysql-test/tokudb/t/locks-delete-deadlock-1.test storage/tokudb/mysql-test/tokudb/t/locks-no-read-lock-serializable-autocommit.test storage/tokudb/mysql-test/tokudb/t/locks-select-update-1.test storage/tokudb/mysql-test/tokudb/t/locks-select-update-2.test storage/tokudb/mysql-test/tokudb/t/locks-select-update-3.test storage/tokudb/mysql-test/tokudb/t/locks-update-deadlock-1.test storage/tokudb/mysql-test/tokudb/t/mvcc-1.test storage/tokudb/mysql-test/tokudb/t/mvcc-10.test storage/tokudb/mysql-test/tokudb/t/mvcc-11.test storage/tokudb/mysql-test/tokudb/t/mvcc-12.test storage/tokudb/mysql-test/tokudb/t/mvcc-13.test storage/tokudb/mysql-test/tokudb/t/mvcc-14.test storage/tokudb/mysql-test/tokudb/t/mvcc-15.test storage/tokudb/mysql-test/tokudb/t/mvcc-16.test storage/tokudb/mysql-test/tokudb/t/mvcc-17.test storage/tokudb/mysql-test/tokudb/t/mvcc-18.test storage/tokudb/mysql-test/tokudb/t/mvcc-19.test storage/tokudb/mysql-test/tokudb/t/mvcc-2.test storage/tokudb/mysql-test/tokudb/t/mvcc-20.test storage/tokudb/mysql-test/tokudb/t/mvcc-21.test storage/tokudb/mysql-test/tokudb/t/mvcc-22.test storage/tokudb/mysql-test/tokudb/t/mvcc-23.test storage/tokudb/mysql-test/tokudb/t/mvcc-24.test storage/tokudb/mysql-test/tokudb/t/mvcc-25.test storage/tokudb/mysql-test/tokudb/t/mvcc-26.test storage/tokudb/mysql-test/tokudb/t/mvcc-27.test storage/tokudb/mysql-test/tokudb/t/mvcc-28.test storage/tokudb/mysql-test/tokudb/t/mvcc-2808-read-committed.test storage/tokudb/mysql-test/tokudb/t/mvcc-2808-read-uncommitted.test storage/tokudb/mysql-test/tokudb/t/mvcc-29.test storage/tokudb/mysql-test/tokudb/t/mvcc-3.test storage/tokudb/mysql-test/tokudb/t/mvcc-30.test storage/tokudb/mysql-test/tokudb/t/mvcc-31.test storage/tokudb/mysql-test/tokudb/t/mvcc-33.test storage/tokudb/mysql-test/tokudb/t/mvcc-34.test storage/tokudb/mysql-test/tokudb/t/mvcc-35.test storage/tokudb/mysql-test/tokudb/t/mvcc-36.test storage/tokudb/mysql-test/tokudb/t/mvcc-37.test storage/tokudb/mysql-test/tokudb/t/mvcc-38.test storage/tokudb/mysql-test/tokudb/t/mvcc-39.test storage/tokudb/mysql-test/tokudb/t/mvcc-4.test storage/tokudb/mysql-test/tokudb/t/mvcc-40.test storage/tokudb/mysql-test/tokudb/t/mvcc-5.test storage/tokudb/mysql-test/tokudb/t/mvcc-6.test storage/tokudb/mysql-test/tokudb/t/mvcc-7.test storage/tokudb/mysql-test/tokudb/t/mvcc-8.test storage/tokudb/mysql-test/tokudb/t/mvcc-9.test storage/tokudb/mysql-test/tokudb/t/mvcc-checksum-locks.test storage/tokudb/mysql-test/tokudb/t/nested_txn_autocommit.test storage/tokudb/mysql-test/tokudb/t/nested_txn_begin.test storage/tokudb/mysql-test/tokudb/t/nested_txn_implicit_commit.test storage/tokudb/mysql-test/tokudb/t/prim_key_1.test storage/tokudb/mysql-test/tokudb/t/prim_key_2.test storage/tokudb/mysql-test/tokudb/t/prim_key_3.test storage/tokudb/mysql-test/tokudb/t/prim_key_4.test storage/tokudb/mysql-test/tokudb/t/prim_key_5.test storage/tokudb/mysql-test/tokudb/t/prim_key_6.test storage/tokudb/mysql-test/tokudb/t/replace-ignore.test storage/tokudb/mysql-test/tokudb/t/rows-32m-0.test storage/tokudb/mysql-test/tokudb/t/rows-32m-1.test storage/tokudb/mysql-test/tokudb/t/rows-32m-rand-insert.test storage/tokudb/mysql-test/tokudb/t/rows-32m-seq-insert.test storage/tokudb/mysql-test/tokudb/t/savepoint-3.test storage/tokudb/mysql-test/tokudb/t/simple_delete_all.test storage/tokudb/mysql-test/tokudb/t/simple_join_tokudb_myisam.test storage/tokudb/mysql-test/tokudb/t/simple_truncate.test storage/tokudb/mysql-test/tokudb/t/truncate_row_count.test storage/tokudb/mysql-test/tokudb/t/truncate_txn_commit.test storage/tokudb/mysql-test/tokudb/t/truncate_txn_rollback.test storage/tokudb/mysql-test/tokudb/t/type_varchar.test storage/tokudb/mysql-test/tokudb_add_index/r/hot_create_unique_index.result storage/tokudb/mysql-test/tokudb_add_index/t/1522.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_1.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_10.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_11.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_12.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_13.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_14.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_16.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_17.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_18.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_2.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_3.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_4.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_6.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_7.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_8.test storage/tokudb/mysql-test/tokudb_add_index/t/add_index_9.test storage/tokudb/mysql-test/tokudb_add_index/t/falcon_bug_23691.test storage/tokudb/mysql-test/tokudb_add_index/t/falcon_bug_23692.test storage/tokudb/mysql-test/tokudb_add_index/t/hot_create_unique_index.test storage/tokudb/mysql-test/tokudb_add_index/t/tokudb_bug_1152.test storage/tokudb/mysql-test/tokudb_alter_table/r/ai_part.result storage/tokudb/mysql-test/tokudb_alter_table/r/alter_column_default.result storage/tokudb/mysql-test/tokudb_alter_table/r/auto_inc.result storage/tokudb/mysql-test/tokudb_alter_table/r/fractional_time_alter_table.result storage/tokudb/mysql-test/tokudb_alter_table/r/frm_discover.result storage/tokudb/mysql-test/tokudb_alter_table/r/hcad_and_rename_table.result storage/tokudb/mysql-test/tokudb_alter_table/r/hcad_part.result storage/tokudb/mysql-test/tokudb_alter_table/r/hcr.result storage/tokudb/mysql-test/tokudb_alter_table/r/hcr3.result storage/tokudb/mysql-test/tokudb_alter_table/r/other_alter.result storage/tokudb/mysql-test/tokudb_alter_table/r/other_alter2.result storage/tokudb/mysql-test/tokudb_alter_table/r/row_format_alter.result storage/tokudb/mysql-test/tokudb_alter_table/r/test_field_same_detection.result storage/tokudb/mysql-test/tokudb_alter_table/t/5260.test storage/tokudb/mysql-test/tokudb_alter_table/t/ai_di.test storage/tokudb/mysql-test/tokudb_alter_table/t/auto_inc.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_add.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_add2.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_add3.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_blob_add.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_blob_drop.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_drop.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_fixed_add.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_fixed_drop.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_var_add.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_all_var_drop.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_and_rename_table.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_clustering.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_clustering2.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_diff_num_offset_bytes.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_fixedblob_add.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_fixedblob_add2.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_fixedblob_drop.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_fixedvar_add.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_fixedvar_add2.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_fixedvar_drop.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_indexing_mix.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_null_bits.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_pk.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_pk2.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_template.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_tmp_tables.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_tmp_tables_56.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_varblob_add.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_varblob_add2.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_varblob_drop.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_with_dels.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_with_lock_sps.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcad_with_locks.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcr.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcr2.test storage/tokudb/mysql-test/tokudb_alter_table/t/hcr3.test storage/tokudb/mysql-test/tokudb_alter_table/t/hot_row_format_alter.test storage/tokudb/mysql-test/tokudb_alter_table/t/other_alter.test storage/tokudb/mysql-test/tokudb_alter_table/t/other_alter2.test storage/tokudb/mysql-test/tokudb_alter_table/t/row_format_alter.test storage/tokudb/mysql-test/tokudb_alter_table/t/test_field_same_detection.test storage/tokudb/mysql-test/tokudb_alter_table/t/virtual_columns.test storage/tokudb/mysql-test/tokudb_bugs/disabled.def storage/tokudb/mysql-test/tokudb_bugs/r/2952.result storage/tokudb/mysql-test/tokudb_bugs/r/2970.result storage/tokudb/mysql-test/tokudb_bugs/r/4676.result storage/tokudb/mysql-test/tokudb_bugs/r/5089.result storage/tokudb/mysql-test/tokudb_bugs/r/checkpoint_lock.result storage/tokudb/mysql-test/tokudb_bugs/r/checkpoint_lock_3.result storage/tokudb/mysql-test/tokudb_bugs/r/dict_leak_3518.result storage/tokudb/mysql-test/tokudb_bugs/r/expand_tinytext_text.result storage/tokudb/mysql-test/tokudb_bugs/r/fractional_time.result storage/tokudb/mysql-test/tokudb_bugs/r/frm_store.result storage/tokudb/mysql-test/tokudb_bugs/r/frm_store2.result storage/tokudb/mysql-test/tokudb_bugs/r/frm_store3.result storage/tokudb/mysql-test/tokudb_bugs/r/tokudb_drop_part_table_668.result storage/tokudb/mysql-test/tokudb_bugs/r/tokudb_drop_simple_table_668.result storage/tokudb/mysql-test/tokudb_bugs/r/tokudb_mrr.result storage/tokudb/mysql-test/tokudb_bugs/r/tokudb_mrr2.result storage/tokudb/mysql-test/tokudb_bugs/t/1913.test storage/tokudb/mysql-test/tokudb_bugs/t/1938.test storage/tokudb/mysql-test/tokudb_bugs/t/1949.test storage/tokudb/mysql-test/tokudb_bugs/t/2043.test storage/tokudb/mysql-test/tokudb_bugs/t/2219.test storage/tokudb/mysql-test/tokudb_bugs/t/2262.test storage/tokudb/mysql-test/tokudb_bugs/t/2383.test storage/tokudb/mysql-test/tokudb_bugs/t/2458.test storage/tokudb/mysql-test/tokudb_bugs/t/2548.test storage/tokudb/mysql-test/tokudb_bugs/t/2641.test storage/tokudb/mysql-test/tokudb_bugs/t/2952.test storage/tokudb/mysql-test/tokudb_bugs/t/2970.test storage/tokudb/mysql-test/tokudb_bugs/t/3014.test storage/tokudb/mysql-test/tokudb_bugs/t/3015.test storage/tokudb/mysql-test/tokudb_bugs/t/3083.test storage/tokudb/mysql-test/tokudb_bugs/t/4472.test storage/tokudb/mysql-test/tokudb_bugs/t/4656.test storage/tokudb/mysql-test/tokudb_bugs/t/4656_2.test storage/tokudb/mysql-test/tokudb_bugs/t/5089.test storage/tokudb/mysql-test/tokudb_bugs/t/5733_innodb.test storage/tokudb/mysql-test/tokudb_bugs/t/6053.test storage/tokudb/mysql-test/tokudb_bugs/t/6684.test storage/tokudb/mysql-test/tokudb_bugs/t/checkpoint_lock.test storage/tokudb/mysql-test/tokudb_bugs/t/checkpoint_lock_3.test storage/tokudb/mysql-test/tokudb_bugs/t/expand_tinytext_text.test storage/tokudb/mysql-test/tokudb_bugs/t/fileops-4.test storage/tokudb/mysql-test/tokudb_bugs/t/ft-index-40.test storage/tokudb/mysql-test/tokudb_bugs/t/index_read.test storage/tokudb/mysql-test/tokudb_bugs/t/tokudb_drop_part_table_668.test storage/tokudb/mysql-test/tokudb_bugs/t/tokudb_drop_simple_table_668.test storage/tokudb/mysql-test/tokudb_bugs/t/xa-1.test storage/tokudb/mysql-test/tokudb_bugs/t/xa-2.test storage/tokudb/mysql-test/tokudb_bugs/t/xa-6.test storage/tokudb/mysql-test/tokudb_mariadb/r/alter.result storage/tokudb/mysql-test/tokudb_mariadb/r/clustering.result storage/tokudb/mysql-test/tokudb_mariadb/r/compression.result storage/tokudb/mysql-test/tokudb_mariadb/t/compression.test storage/tokudb/scripts/common.sh storage/tokudb/scripts/make.mysql.bash storage/tokudb/scripts/make.mysql.debug.env.bash storage/tokudb/scripts/nightly.mysql.build.and.test.bash storage/tokudb/scripts/run.atc.ontime.bash storage/tokudb/scripts/run.mysql.tests.bash storage/tokudb/scripts/run.sql.bench.bash storage/tokudb/scripts/run.tpch.bash storage/tokudb/scripts/setup.mysql.bash storage/tokudb/scripts/tokutek.make.mysql.bash storage/tokudb/tokudb_card.h storage/tokudb/tokudb_update_fun.cc storage/xtradb/CMakeLists.txt storage/xtradb/api/api0api.cc storage/xtradb/btr/btr0btr.cc storage/xtradb/btr/btr0cur.cc storage/xtradb/btr/btr0pcur.cc storage/xtradb/buf/buf0buf.cc storage/xtradb/buf/buf0flu.cc storage/xtradb/dict/dict0crea.cc storage/xtradb/dict/dict0dict.cc storage/xtradb/dict/dict0load.cc storage/xtradb/dict/dict0mem.cc storage/xtradb/dict/dict0stats.cc storage/xtradb/fil/fil0fil.cc storage/xtradb/fts/fts0config.cc storage/xtradb/fts/fts0fts.cc storage/xtradb/fts/fts0opt.cc storage/xtradb/fts/fts0que.cc storage/xtradb/handler/ha_innodb.cc storage/xtradb/handler/handler0alter.cc storage/xtradb/handler/i_s.cc storage/xtradb/handler/xtradb_i_s.cc storage/xtradb/ibuf/ibuf0ibuf.cc storage/xtradb/include/api0api.h storage/xtradb/include/btr0cur.h storage/xtradb/include/btr0pcur.h storage/xtradb/include/btr0pcur.ic storage/xtradb/include/btr0sea.h storage/xtradb/include/buf0flu.h storage/xtradb/include/buf0flu.ic storage/xtradb/include/db0err.h storage/xtradb/include/dict0stats.ic storage/xtradb/include/dict0types.h storage/xtradb/include/fts0fts.h storage/xtradb/include/fts0types.h storage/xtradb/include/ibuf0ibuf.h storage/xtradb/include/log0log.h storage/xtradb/include/mtr0mtr.h storage/xtradb/include/mtr0mtr.ic storage/xtradb/include/os0file.h storage/xtradb/include/row0ftsort.h storage/xtradb/include/srv0conc.h storage/xtradb/include/srv0mon.h storage/xtradb/include/srv0mon.ic storage/xtradb/include/sync0arr.h storage/xtradb/include/sync0arr.ic storage/xtradb/include/sync0rw.h storage/xtradb/include/sync0rw.ic storage/xtradb/include/sync0sync.h storage/xtradb/include/sync0sync.ic storage/xtradb/include/sync0types.h storage/xtradb/include/trx0trx.h storage/xtradb/include/univ.i storage/xtradb/include/ut0bh.h storage/xtradb/include/ut0bh.ic storage/xtradb/log/log0log.cc storage/xtradb/log/log0online.cc storage/xtradb/log/log0recv.cc storage/xtradb/mtr/mtr0mtr.cc storage/xtradb/os/os0file.cc storage/xtradb/os/os0thread.cc storage/xtradb/row/row0ftsort.cc storage/xtradb/row/row0log.cc storage/xtradb/row/row0merge.cc storage/xtradb/row/row0mysql.cc storage/xtradb/row/row0quiesce.cc storage/xtradb/row/row0sel.cc storage/xtradb/srv/srv0mon.cc storage/xtradb/srv/srv0start.cc storage/xtradb/sync/sync0arr.cc storage/xtradb/sync/sync0rw.cc storage/xtradb/sync/sync0sync.cc storage/xtradb/trx/trx0purge.cc storage/xtradb/trx/trx0sys.cc storage/xtradb/trx/trx0trx.cc storage/xtradb/ut/ut0ut.cc strings/CMakeLists.txt strings/ctype-bin.c strings/ctype-mb.c strings/ctype-simple.c strings/ctype-uca.c strings/ctype-ucs2.c strings/ctype-utf8.c strings/ctype-win1250ch.c strings/ctype.c strings/decimal.c strings/dtoa.c strings/t_ctype.h support-files/MySQL-shared-compat.spec.sh support-files/compiler_warnings.supp support-files/mysql.server.sh support-files/rpm/server-postun.sh support-files/rpm/server-prein.sh tests/connect_test.c tests/fork_big.pl tests/fork_big2.pl tests/insert_test.c tests/list_test.c tests/mysql_client_test.c tests/select_test.c tests/showdb_test.c tests/ssl_test.c unittest/mysys/CMakeLists.txt unittest/mysys/bitmap-t.c unittest/mysys/ma_dyncol-t.c vio/CMakeLists.txt vio/vio.c vio/viosocket.c vio/viossl.c vio/viosslfactories.c zlib/CMakeLists.txt libmysql/libmysql_versions.ld.in mysql-test/suite/roles/grant_empty.result mysql-test/suite/roles/grant_empty.test pending merges: Olivier Bertrand 2014-04-22 - FIX a bug causing libxml2 not retrieving expanded multiple co...
Diffstat (limited to 'storage/tokudb/ft-index')
-rw-r--r--storage/tokudb/ft-index/CMakeLists.txt10
-rw-r--r--storage/tokudb/ft-index/README.md24
-rw-r--r--storage/tokudb/ft-index/buildheader/CMakeLists.txt2
-rw-r--r--storage/tokudb/ft-index/buildheader/make_tdb.cc19
-rw-r--r--storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake4
-rw-r--r--storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake1
-rw-r--r--storage/tokudb/ft-index/cmake_modules/TokuThirdParty.cmake35
-rw-r--r--storage/tokudb/ft-index/examples/CMakeLists.txt2
-rw-r--r--storage/tokudb/ft-index/ft/CMakeLists.txt2
-rw-r--r--storage/tokudb/ft-index/ft/bndata.cc10
-rw-r--r--storage/tokudb/ft-index/ft/bndata.h4
-rw-r--r--storage/tokudb/ft-index/ft/cachetable-internal.h16
-rw-r--r--storage/tokudb/ft-index/ft/cachetable.cc262
-rw-r--r--storage/tokudb/ft-index/ft/cachetable.h16
-rw-r--r--storage/tokudb/ft-index/ft/checkpoint.cc29
-rw-r--r--storage/tokudb/ft-index/ft/compress.cc6
-rw-r--r--storage/tokudb/ft-index/ft/fifo.cc17
-rw-r--r--storage/tokudb/ft-index/ft/fifo.h2
-rw-r--r--storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc5
-rw-r--r--storage/tokudb/ft-index/ft/ft-flusher.cc62
-rw-r--r--storage/tokudb/ft-index/ft/ft-flusher.h2
-rw-r--r--storage/tokudb/ft-index/ft/ft-hot-flusher.cc6
-rw-r--r--storage/tokudb/ft-index/ft/ft-internal.h49
-rw-r--r--storage/tokudb/ft-index/ft/ft-ops.cc568
-rw-r--r--storage/tokudb/ft-index/ft/ft-ops.h17
-rw-r--r--storage/tokudb/ft-index/ft/ft-serialize.cc2
-rw-r--r--storage/tokudb/ft-index/ft/ft-test-helpers.cc4
-rw-r--r--storage/tokudb/ft-index/ft/ft.cc20
-rw-r--r--storage/tokudb/ft-index/ft/ft.h7
-rw-r--r--storage/tokudb/ft-index/ft/ft_layout_version.h1
-rw-r--r--storage/tokudb/ft-index/ft/ft_node-serialize.cc160
-rw-r--r--storage/tokudb/ft-index/ft/ftloader-internal.h4
-rw-r--r--storage/tokudb/ft-index/ft/ftloader.cc23
-rw-r--r--storage/tokudb/ft-index/ft/fttypes.h4
-rw-r--r--storage/tokudb/ft-index/ft/leafentry.h10
-rw-r--r--storage/tokudb/ft-index/ft/log-internal.h5
-rw-r--r--storage/tokudb/ft-index/ft/logformat.cc2
-rw-r--r--storage/tokudb/ft-index/ft/logger.cc6
-rw-r--r--storage/tokudb/ft-index/ft/logger.h1
-rw-r--r--storage/tokudb/ft-index/ft/roll.cc44
-rw-r--r--storage/tokudb/ft-index/ft/rollback-apply.cc19
-rw-r--r--storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc13
-rw-r--r--storage/tokudb/ft-index/ft/rollback-ct-callbacks.h9
-rw-r--r--storage/tokudb/ft-index/ft/rollback.cc34
-rw-r--r--storage/tokudb/ft-index/ft/rollback.h6
-rw-r--r--storage/tokudb/ft-index/ft/rollback_log_node_cache.cc7
-rw-r--r--storage/tokudb/ft-index/ft/rollback_log_node_cache.h1
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-5097.cc7
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-5978.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction2.cc13
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction3.cc14
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction4.cc7
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-eviction-close-test2.cc7
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-eviction-getandpin-test2.cc7
-rw-r--r--storage/tokudb/ft-index/ft/tests/cachetable-evictor-class.cc4
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc25
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-clock-test.cc28
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc6
-rw-r--r--storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc28
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-bad-generate.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-extractor-errors.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-merge-files-dbufio.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc2
-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.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/ftloader-test.cc2
-rw-r--r--storage/tokudb/ft-index/ft/tests/make-tree.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/mempool-115.cc196
-rw-r--r--storage/tokudb/ft-index/ft/tests/msnfilter.cc9
-rw-r--r--storage/tokudb/ft-index/ft/tests/orthopush-flush.cc19
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-flushes-on-cleaner.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-hot-with-bounds.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-inc-split.cc14
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc7
-rw-r--r--storage/tokudb/ft-index/ft/tests/test-pick-child-to-flush.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/test.h14
-rw-r--r--storage/tokudb/ft-index/ft/tests/upgrade_test_simple.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-dup-in-leaf.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc3
-rw-r--r--storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc3
-rw-r--r--storage/tokudb/ft-index/ft/txn.cc14
-rw-r--r--storage/tokudb/ft-index/ft/txn_manager.cc26
-rw-r--r--storage/tokudb/ft-index/ft/txn_manager.h60
-rw-r--r--storage/tokudb/ft-index/ft/ule.cc159
-rw-r--r--storage/tokudb/ft-index/ft/ule.h3
-rw-r--r--storage/tokudb/ft-index/locktree/lock_request.cc64
-rw-r--r--storage/tokudb/ft-index/locktree/lock_request.h15
-rw-r--r--storage/tokudb/ft-index/locktree/locktree.cc13
-rw-r--r--storage/tokudb/ft-index/locktree/locktree.h80
-rw-r--r--storage/tokudb/ft-index/locktree/manager.cc222
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_create_set.cc4
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_get_set_keys.cc11
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc179
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_not_killed.cc175
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_start_deadlock.cc24
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_start_pending.cc8
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_unit_test.h3
-rw-r--r--storage/tokudb/ft-index/locktree/tests/lock_request_wait_time_callback.cc151
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc8
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_1big7lt_1small.cc304
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_1lt.cc250
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_2lt.cc250
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc204
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc87
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc38
-rw-r--r--storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc6
-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.cc4
-rw-r--r--storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc1
-rw-r--r--storage/tokudb/ft-index/locktree/tests/manager_params.cc4
-rw-r--r--storage/tokudb/ft-index/locktree/tests/manager_status.cc8
-rw-r--r--storage/tokudb/ft-index/portability/CMakeLists.txt13
-rw-r--r--storage/tokudb/ft-index/portability/file.cc24
-rw-r--r--storage/tokudb/ft-index/portability/os_malloc.cc1
-rw-r--r--storage/tokudb/ft-index/portability/tests/test-fair-rwlock.cc665
-rw-r--r--storage/tokudb/ft-index/portability/toku_fair_rwlock.cc361
-rw-r--r--storage/tokudb/ft-index/portability/toku_fair_rwlock.h237
-rwxr-xr-xstorage/tokudb/ft-index/scripts/run.stress-tests.py1
-rw-r--r--storage/tokudb/ft-index/src/CMakeLists.txt10
-rw-r--r--storage/tokudb/ft-index/src/export.map1
-rw-r--r--storage/tokudb/ft-index/src/indexer-undo-do.cc36
-rw-r--r--storage/tokudb/ft-index/src/loader.cc6
-rw-r--r--storage/tokudb/ft-index/src/tests/CMakeLists.txt13
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-first-empty.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-first.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-last.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-next-prev-deadlock.cc2
-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.cc2
-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.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-set-range-n.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-set-range-reverse-0.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-set.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/blocking-table-lock.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/db-put-simple-deadlock-threads.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/db-put-simple-lockwait.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/db-put-update-deadlock.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/env_loader_memory.cc9
-rw-r--r--storage/tokudb/ft-index/src/tests/env_nproc.cc143
-rw-r--r--storage/tokudb/ft-index/src/tests/filesize.cc3
-rw-r--r--storage/tokudb/ft-index/src/tests/get_last_key.cc299
-rw-r--r--storage/tokudb/ft-index/src/tests/hot-optimize-table-tests.cc3
-rw-r--r--storage/tokudb/ft-index/src/tests/locktree_escalation_stalls.cc312
-rw-r--r--storage/tokudb/ft-index/src/tests/recover-child-rollback.cc168
-rw-r--r--storage/tokudb/ft-index/src/tests/test_4368.cc3
-rw-r--r--storage/tokudb/ft-index/src/tests/test_bad_implicit_promotion.cc190
-rw-r--r--storage/tokudb/ft-index/src/tests/test_cursor_interrupt.cc202
-rw-r--r--storage/tokudb/ft-index/src/tests/test_insert_many_gc.cc157
-rw-r--r--storage/tokudb/ft-index/src/tests/test_iterate_pending_lock_requests.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test_kv_gen.h3
-rw-r--r--storage/tokudb/ft-index/src/tests/test_lock_timeout_callback.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/test_stress5.cc2
-rw-r--r--storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h21
-rw-r--r--storage/tokudb/ft-index/src/tests/update-multiple-with-indexer-array.cc158
-rw-r--r--storage/tokudb/ft-index/src/ydb-internal.h7
-rw-r--r--storage/tokudb/ft-index/src/ydb.cc77
-rw-r--r--storage/tokudb/ft-index/src/ydb_cursor.cc9
-rw-r--r--storage/tokudb/ft-index/src/ydb_db.cc81
-rw-r--r--storage/tokudb/ft-index/src/ydb_env_func.cc4
-rw-r--r--storage/tokudb/ft-index/src/ydb_row_lock.cc22
-rw-r--r--storage/tokudb/ft-index/src/ydb_txn.cc12
-rw-r--r--storage/tokudb/ft-index/src/ydb_txn.h3
-rw-r--r--storage/tokudb/ft-index/toku_include/CMakeLists.txt2
-rw-r--r--storage/tokudb/ft-index/util/CMakeLists.txt4
-rw-r--r--storage/tokudb/ft-index/util/context.cc242
-rw-r--r--storage/tokudb/ft-index/util/context.h204
-rw-r--r--storage/tokudb/ft-index/util/frwlock.cc70
-rw-r--r--storage/tokudb/ft-index/util/frwlock.h47
-rw-r--r--storage/tokudb/ft-index/util/kibbutz.cc19
-rw-r--r--storage/tokudb/ft-index/util/kibbutz.h2
-rw-r--r--storage/tokudb/ft-index/util/mempool.cc17
-rw-r--r--storage/tokudb/ft-index/util/mempool.h7
-rw-r--r--storage/tokudb/ft-index/util/scoped_malloc.cc265
-rw-r--r--storage/tokudb/ft-index/util/scoped_malloc.h153
-rw-r--r--storage/tokudb/ft-index/util/tests/test-frwlock-fair-writers.cc52
-rw-r--r--storage/tokudb/ft-index/util/tests/test-kibbutz.cc4
-rw-r--r--storage/tokudb/ft-index/util/tests/test-kibbutz2.cc4
-rw-r--r--storage/tokudb/ft-index/util/tests/test-rwlock-cheapness.cc11
-rw-r--r--storage/tokudb/ft-index/util/tests/test-rwlock-unfair-writers.cc60
-rw-r--r--storage/tokudb/ft-index/util/tests/test-rwlock.cc298
187 files changed, 6369 insertions, 2776 deletions
diff --git a/storage/tokudb/ft-index/CMakeLists.txt b/storage/tokudb/ft-index/CMakeLists.txt
index 22249b66522..e0fdad79103 100644
--- a/storage/tokudb/ft-index/CMakeLists.txt
+++ b/storage/tokudb/ft-index/CMakeLists.txt
@@ -18,10 +18,12 @@ include(TokuMergeLibs)
set(LIBTOKUPORTABILITY "tokuportability" CACHE STRING "Name of libtokuportability.so")
set(LIBTOKUDB "tokufractaltree" CACHE STRING "Name of libtokufractaltree.so")
-if(USE_VALGRIND)
-include_directories(
- ${VALGRIND_INCLUDE_DIR}
- )
+set(INSTALL_LIBDIR "lib" CACHE STRING "where to install libs")
+
+if (USE_VALGRIND AND NOT VALGRIND_INCLUDE_DIR MATCHES NOTFOUND)
+ include_directories(
+ ${VALGRIND_INCLUDE_DIR}
+ )
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
diff --git a/storage/tokudb/ft-index/README.md b/storage/tokudb/ft-index/README.md
index e45225d57df..72b8988165a 100644
--- a/storage/tokudb/ft-index/README.md
+++ b/storage/tokudb/ft-index/README.md
@@ -2,15 +2,18 @@ TokuKV
======
TokuKV is a high-performance, transactional key-value store, used in the
-TokuDB storage engine for MySQL and MariaDB.
+TokuDB storage engine for MySQL and MariaDB and in TokuMX, the
+high-performance MongoDB distribution.
TokuKV is provided as a shared library with an interface similar to
Berkeley DB.
To build the full MySQL product, see the instructions for
-[ft-engine][ft-engine]. This document covers TokuKV only.
+[Tokutek/ft-engine][ft-engine]. To build TokuMX, see the instructions
+for [Tokutek/mongo][mongo]. This document covers TokuKV only.
-[ft-engine]: http://github.com/Tokutek/ft-engine
+[ft-engine]: https://github.com/Tokutek/ft-engine
+[mongo]: https://github.com/Tokutek/mongo
Building
@@ -18,9 +21,8 @@ Building
TokuKV is built using CMake >= 2.8.9. Out-of-source builds are
recommended. You need a C++11 compiler, though only GCC >= 4.7 and
-Apple's Clang are tested. You also need zlib and valgrind development
-packages (`yum install valgrind-devel zlib-devel` or `apt-get install
-valgrind zlib1g-dev`).
+Apple's Clang are tested. You also need zlib development packages
+(`yum install zlib-devel` or `apt-get install zlib1g-dev`).
You will also need the source code for jemalloc, checked out in
`third_party/`.
@@ -35,6 +37,7 @@ CC=gcc47 CXX=g++47 cmake \
-D CMAKE_BUILD_TYPE=Debug \
-D USE_BDB=OFF \
-D BUILD_TESTING=OFF \
+ -D USE_VALGRIND=OFF \
-D CMAKE_INSTALL_PREFIX=../prefix/ \
..
cmake --build . --target install
@@ -102,13 +105,20 @@ Contributing
Please report bugs in TokuKV here on github.
-We have two publicly accessible mailing lists:
+We have two publicly accessible mailing lists for TokuDB:
- tokudb-user@googlegroups.com is for general and support related
questions about the use of TokuDB.
- tokudb-dev@googlegroups.com is for discussion of the development of
TokuDB.
+and two for TokuMX:
+
+ - tokumx-user@googlegroups.com is for general and support related
+ questions about the use of TokuMX.
+ - tokumx-dev@googlegroups.com is for discussion of the development of
+ TokuMX.
+
We are also available on IRC on freenode.net, in the #tokutek channel.
diff --git a/storage/tokudb/ft-index/buildheader/CMakeLists.txt b/storage/tokudb/ft-index/buildheader/CMakeLists.txt
index 8427f216fd4..5da3c98ff48 100644
--- a/storage/tokudb/ft-index/buildheader/CMakeLists.txt
+++ b/storage/tokudb/ft-index/buildheader/CMakeLists.txt
@@ -19,9 +19,11 @@ if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
FILES "${CMAKE_CURRENT_BINARY_DIR}/db.h"
DESTINATION include
RENAME tokudb.h
+ COMPONENT tokukv_headers
)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/db.h"
DESTINATION include
+ COMPONENT tokukv_headers
)
endif ()
diff --git a/storage/tokudb/ft-index/buildheader/make_tdb.cc b/storage/tokudb/ft-index/buildheader/make_tdb.cc
index 72da4d7998b..4fc00e6d9e7 100644
--- a/storage/tokudb/ft-index/buildheader/make_tdb.cc
+++ b/storage/tokudb/ft-index/buildheader/make_tdb.cc
@@ -207,6 +207,7 @@ enum {
TOKUDB_BAD_CHECKSUM = -100015,
TOKUDB_HUGE_PAGES_ENABLED = -100016,
TOKUDB_OUT_OF_RANGE = -100017,
+ TOKUDB_INTERRUPTED = -100018,
DONTUSE_I_JUST_PUT_THIS_HERE_SO_I_COULD_HAVE_A_COMMA_AFTER_EACH_ITEM
};
@@ -359,6 +360,7 @@ static void print_defines (void) {
dodefine(TOKUDB_BAD_CHECKSUM);
dodefine(TOKUDB_HUGE_PAGES_ENABLED);
dodefine(TOKUDB_OUT_OF_RANGE);
+ dodefine(TOKUDB_INTERRUPTED);
/* LOADER flags */
printf("/* LOADER flags */\n");
@@ -449,7 +451,7 @@ static void print_db_env_struct (void) {
"int (*set_lk_max_memory) (DB_ENV *env, uint64_t max)",
"int (*get_lk_max_memory) (DB_ENV *env, uint64_t *max)",
"void (*set_update) (DB_ENV *env, int (*update_function)(DB *, const DBT *key, const DBT *old_val, const DBT *extra, void (*set_val)(const DBT *new_val, void *set_extra), void *set_extra))",
- "int (*set_lock_timeout) (DB_ENV *env, uint64_t lock_wait_time_msec)",
+ "int (*set_lock_timeout) (DB_ENV *env, uint64_t default_lock_wait_time_msec, uint64_t (*get_lock_wait_time_cb)(uint64_t default_lock_wait_time))",
"int (*get_lock_timeout) (DB_ENV *env, uint64_t *lock_wait_time_msec)",
"int (*set_lock_timeout_callback) (DB_ENV *env, lock_timeout_callback callback)",
"int (*txn_xa_recover) (DB_ENV*, TOKU_XA_XID list[/*count*/], long count, /*out*/ long *retp, uint32_t flags)",
@@ -459,8 +461,9 @@ static void print_db_env_struct (void) {
"void (*change_fsync_log_period) (DB_ENV*, uint32_t)",
"int (*iterate_live_transactions) (DB_ENV *env, iterate_transactions_callback callback, void *extra)",
"int (*iterate_pending_lock_requests) (DB_ENV *env, iterate_requests_callback callback, void *extra)",
- "void (*set_loader_memory_size)(DB_ENV *env, uint64_t loader_memory_size)",
+ "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))",
NULL};
sort_and_dump_fields("db_env", true, extra);
@@ -529,7 +532,7 @@ static void print_db_struct (void) {
"int (*change_descriptor) (DB*, DB_TXN*, const DBT* descriptor, uint32_t) /* change row/dictionary descriptor for a db. Available only while db is open */",
"int (*getf_set)(DB*, DB_TXN*, uint32_t, DBT*, YDB_CALLBACK_FUNCTION, void*) /* same as DBC->c_getf_set without a persistent cursor) */",
"int (*optimize)(DB*) /* Run garbage collecion and promote all transactions older than oldest. Amortized (happens during flattening) */",
- "int (*hot_optimize)(DB*, DBT*, DBT*, int (*progress_callback)(void *progress_extra, float progress), void *progress_extra)",
+ "int (*hot_optimize)(DB*, DBT*, DBT*, int (*progress_callback)(void *progress_extra, float progress), void *progress_extra, uint64_t* loops_run)",
"int (*get_fragmentation)(DB*,TOKU_DB_FRAGMENTATION)",
"int (*change_pagesize)(DB*,uint32_t)",
"int (*change_readpagesize)(DB*,uint32_t)",
@@ -538,6 +541,9 @@ static void print_db_struct (void) {
"int (*change_compression_method)(DB*,TOKU_COMPRESSION_METHOD)",
"int (*get_compression_method)(DB*,TOKU_COMPRESSION_METHOD*)",
"int (*set_compression_method)(DB*,TOKU_COMPRESSION_METHOD)",
+ "int (*change_fanout)(DB *db, uint32_t fanout)",
+ "int (*get_fanout)(DB *db, uint32_t *fanout)",
+ "int (*set_fanout)(DB *db, uint32_t fanout)",
"int (*set_indexer)(DB*, DB_INDEXER*)",
"void (*get_indexer)(DB*, DB_INDEXER**)",
"int (*verify_with_progress)(DB *, int (*progress_callback)(void *progress_extra, float progress), void *progress_extra, int verbose, int keep_going)",
@@ -546,6 +552,7 @@ static void print_db_struct (void) {
"int (*get_fractal_tree_info64)(DB*,uint64_t*,uint64_t*,uint64_t*,uint64_t*)",
"int (*iterate_fractal_tree_block_map)(DB*,int(*)(uint64_t,int64_t,int64_t,int64_t,int64_t,void*),void*)",
"const char *(*get_dname)(DB *db)",
+ "int (*get_last_key)(DB *db, YDB_CALLBACK_FUNCTION func, void* extra)",
NULL};
sort_and_dump_fields("db", true, extra);
}
@@ -602,6 +609,7 @@ static void print_dbc_struct (void) {
"int (*c_getf_set_range)(DBC *, uint32_t, DBT *, YDB_CALLBACK_FUNCTION, void *)",
"int (*c_getf_set_range_reverse)(DBC *, uint32_t, DBT *, YDB_CALLBACK_FUNCTION, void *)",
"int (*c_set_bounds)(DBC*, const DBT*, const DBT*, bool pre_acquire, int out_of_range_error)",
+ "void (*c_set_check_interrupt_callback)(DBC*, bool (*)(void*), void *)",
"void (*c_remove_restriction)(DBC*)",
NULL};
sort_and_dump_fields("dbc", false, extra);
@@ -729,10 +737,10 @@ int main (int argc, char *const argv[] __attribute__((__unused__))) {
printf(" CHARSTR, // interpret as char * \n");
printf(" UNIXTIME, // interpret as time_t \n");
printf(" TOKUTIME, // interpret as tokutime_t \n");
- printf(" PARCOUNT // interpret as PARTITIONED_COUNTER\n");
+ printf(" PARCOUNT, // interpret as PARTITIONED_COUNTER\n");
+ printf(" DOUBLE // interpret as double\n");
printf("} toku_engine_status_display_type; \n");
-
printf("typedef enum {\n");
printf(" TOKU_ENGINE_STATUS = (1ULL<<0), // Include when asking for engine status\n");
printf(" TOKU_GLOBAL_STATUS = (1ULL<<1), // Include when asking for information_schema.global_status\n");
@@ -821,6 +829,7 @@ int main (int argc, char *const argv[] __attribute__((__unused__))) {
printf("int toku_set_trace_file (const char *fname) %s;\n", VISIBLE);
printf("int toku_close_trace_file (void) %s;\n", VISIBLE);
printf("void db_env_set_direct_io (bool direct_io_on) %s;\n", VISIBLE);
+ printf("void db_env_set_compress_buffers_before_eviction (bool compress_buffers) %s;\n", VISIBLE);
printf("void db_env_set_func_fsync (int (*)(int)) %s;\n", VISIBLE);
printf("void db_env_set_func_free (void (*)(void*)) %s;\n", VISIBLE);
printf("void db_env_set_func_malloc (void *(*)(size_t)) %s;\n", VISIBLE);
diff --git a/storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake b/storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake
index 5ca2fb64458..9e6c9d4834c 100644
--- a/storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake
+++ b/storage/tokudb/ft-index/cmake_modules/TokuSetupCTest.cmake
@@ -85,8 +85,8 @@ include(CTest)
set(TOKUDB_DATA "${TokuDB_SOURCE_DIR}/../tokudb.data" CACHE FILEPATH "Path to data files for tests")
if (BUILD_TESTING OR BUILD_FT_TESTS OR BUILD_SRC_TESTS)
- set(WARNED_ABOUT_DATA 1) # disable the warning below
- if (NOT EXISTS "${TOKUDB_DATA}/" AND NOT WARNED_ABOUT_DATA)
+ set(WARNED_ABOUT_DATA 0)
+ if (NOT EXISTS "${TOKUDB_DATA}/" AND NOT WARNED_ABOUT_DATA AND CMAKE_PROJECT_NAME STREQUAL TokuDB)
message(WARNING "Test data files are missing from ${TOKUDB_DATA}, which will cause some tests to fail. Please put them there or modify TOKUDB_DATA to avoid this.")
set(WARNED_ABOUT_DATA 1)
endif ()
diff --git a/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake
index 3bbb3722f7b..4b8a600f141 100644
--- a/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake
+++ b/storage/tokudb/ft-index/cmake_modules/TokuSetupCompiler.cmake
@@ -88,6 +88,7 @@ set_cflags_if_supported(
-Wno-error=missing-format-attribute
-Wno-error=address-of-array-temporary
-Wno-error=tautological-constant-out-of-range-compare
+ -Wno-ignored-attributes
-fno-rtti
-fno-exceptions
)
diff --git a/storage/tokudb/ft-index/cmake_modules/TokuThirdParty.cmake b/storage/tokudb/ft-index/cmake_modules/TokuThirdParty.cmake
index f661c7f6bb3..461390ffb7c 100644
--- a/storage/tokudb/ft-index/cmake_modules/TokuThirdParty.cmake
+++ b/storage/tokudb/ft-index/cmake_modules/TokuThirdParty.cmake
@@ -1,5 +1,40 @@
include(ExternalProject)
+if (CMAKE_PROJECT_NAME STREQUAL TokuDB)
+ ## add jemalloc with an external project
+ set(JEMALLOC_SOURCE_DIR "${TokuDB_SOURCE_DIR}/third_party/jemalloc" CACHE FILEPATH "Where to find jemalloc sources.")
+ if (NOT EXISTS "${JEMALLOC_SOURCE_DIR}/configure")
+ message(FATAL_ERROR "Can't find jemalloc sources. Please check them out to ${JEMALLOC_SOURCE_DIR} or modify JEMALLOC_SOURCE_DIR.")
+ endif ()
+ set(jemalloc_configure_opts "CC=${CMAKE_C_COMPILER}" "--with-jemalloc-prefix=" "--with-private-namespace=tokudb_jemalloc_internal_" "--enable-cc-silence")
+ option(JEMALLOC_DEBUG "Build jemalloc with --enable-debug." OFF)
+ if (JEMALLOC_DEBUG)
+ list(APPEND jemalloc_configure_opts --enable-debug)
+ endif ()
+ ExternalProject_Add(build_jemalloc
+ PREFIX jemalloc
+ SOURCE_DIR "${JEMALLOC_SOURCE_DIR}"
+ CONFIGURE_COMMAND
+ "${JEMALLOC_SOURCE_DIR}/configure" ${jemalloc_configure_opts}
+ "--prefix=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/jemalloc"
+ )
+
+ add_library(jemalloc STATIC IMPORTED GLOBAL)
+ set_target_properties(jemalloc PROPERTIES IMPORTED_LOCATION
+ "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/jemalloc/lib/libjemalloc_pic.a")
+ add_dependencies(jemalloc build_jemalloc)
+ add_library(jemalloc_nopic STATIC IMPORTED GLOBAL)
+ set_target_properties(jemalloc_nopic PROPERTIES IMPORTED_LOCATION
+ "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/jemalloc/lib/libjemalloc.a")
+ add_dependencies(jemalloc_nopic build_jemalloc)
+
+ # detect when we are being built as a subproject
+ if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
+ install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/jemalloc/lib" DESTINATION .
+ COMPONENT tokukv_libs_extra)
+ endif ()
+endif ()
+
## add lzma with an external project
set(xz_configure_opts --with-pic --enable-static)
if (APPLE)
diff --git a/storage/tokudb/ft-index/examples/CMakeLists.txt b/storage/tokudb/ft-index/examples/CMakeLists.txt
index c8d98d3d06e..01ad01aa8d2 100644
--- a/storage/tokudb/ft-index/examples/CMakeLists.txt
+++ b/storage/tokudb/ft-index/examples/CMakeLists.txt
@@ -10,5 +10,7 @@ if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
README.examples
DESTINATION
examples
+ COMPONENT
+ tokukv_examples
)
endif () \ No newline at end of file
diff --git a/storage/tokudb/ft-index/ft/CMakeLists.txt b/storage/tokudb/ft-index/ft/CMakeLists.txt
index a8de1ac2828..3627f1c3dfe 100644
--- a/storage/tokudb/ft-index/ft/CMakeLists.txt
+++ b/storage/tokudb/ft-index/ft/CMakeLists.txt
@@ -8,7 +8,7 @@ set_source_files_properties(
PROPERTIES GENERATED TRUE)
add_executable(logformat logformat.cc)
-target_link_libraries(logformat ${LIBTOKUPORTABILITY})
+target_link_libraries(logformat ${LIBTOKUPORTABILITY}_static)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/log_code.cc"
diff --git a/storage/tokudb/ft-index/ft/bndata.cc b/storage/tokudb/ft-index/ft/bndata.cc
index ef542a75ad8..8d33ca860fa 100644
--- a/storage/tokudb/ft-index/ft/bndata.cc
+++ b/storage/tokudb/ft-index/ft/bndata.cc
@@ -105,7 +105,7 @@ void bn_data::init_zero() {
void bn_data::initialize_empty() {
toku_mempool_zero(&m_buffer_mempool);
- m_buffer.create();
+ m_buffer.create_no_array();
}
void bn_data::initialize_from_data(uint32_t num_entries, unsigned char *buf, uint32_t data_size) {
@@ -230,11 +230,11 @@ static int move_it (const KLPAIR &klpair, const uint32_t idx, struct omt_compres
// 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;
- if (total_size_needed+total_size_needed >= m_buffer_mempool.size) {
- m_buffer_mempool.size = total_size_needed+total_size_needed;
- }
+ // 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, m_buffer_mempool.size);
+ 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 };
diff --git a/storage/tokudb/ft-index/ft/bndata.h b/storage/tokudb/ft-index/ft/bndata.h
index a173e94d759..37e80c32967 100644
--- a/storage/tokudb/ft-index/ft/bndata.h
+++ b/storage/tokudb/ft-index/ft/bndata.h
@@ -116,7 +116,7 @@ struct klpair_struct {
typedef struct klpair_struct *KLPAIR;
-static LEAFENTRY get_le_from_klpair(KLPAIR klpair){
+static inline LEAFENTRY get_le_from_klpair(KLPAIR klpair){
uint32_t keylen = klpair->keylen;
LEAFENTRY le = (LEAFENTRY)(klpair->key_le + keylen);
return le;
@@ -250,5 +250,7 @@ private:
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;
};
diff --git a/storage/tokudb/ft-index/ft/cachetable-internal.h b/storage/tokudb/ft-index/ft/cachetable-internal.h
index a4c9009561a..9a57bfcc8a1 100644
--- a/storage/tokudb/ft-index/ft/cachetable-internal.h
+++ b/storage/tokudb/ft-index/ft/cachetable-internal.h
@@ -458,7 +458,7 @@ private:
//
class checkpointer {
public:
- void init(pair_list *_pl, TOKULOGGER _logger, evictor *_ev, cachefile_list *files);
+ int init(pair_list *_pl, TOKULOGGER _logger, evictor *_ev, cachefile_list *files);
void destroy();
void set_checkpoint_period(uint32_t new_period);
uint32_t get_checkpoint_period();
@@ -480,6 +480,8 @@ private:
cachefile_list *m_cf_list;
pair_list *m_list;
evictor *m_ev;
+ bool m_checkpointer_cron_init;
+ bool m_checkpointer_init;
// variable used by the checkpoint thread to know
// when all work induced by cloning on client threads is done
@@ -512,7 +514,7 @@ const int EVICTION_PERIOD = 1;
//
class evictor {
public:
- void init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KIBBUTZ _kibbutz, uint32_t eviction_period);
+ int init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KIBBUTZ _kibbutz, uint32_t eviction_period);
void destroy();
void add_pair_attr(PAIR_ATTR attr);
void remove_pair_attr(PAIR_ATTR attr);
@@ -522,7 +524,7 @@ public:
uint64_t reserve_memory(double fraction, uint64_t upper_bound);
void release_reserved_memory(uint64_t reserved_memory);
void run_eviction_thread();
- void do_partial_eviction(PAIR p, bool pair_mutex_held);
+ void do_partial_eviction(PAIR p);
void evict_pair(PAIR p, bool checkpoint_pending);
void wait_for_cache_pressure_to_subside();
void signal_eviction_thread();
@@ -597,6 +599,10 @@ private:
// this variable is ONLY used for testing purposes
uint64_t m_num_eviction_thread_runs;
+
+ bool m_ev_thread_init;
+ bool m_evictor_init;
+
friend class evictor_test_helpers;
friend class evictor_unit_test;
};
@@ -608,7 +614,7 @@ private:
//
class cleaner {
public:
- void init(uint32_t cleaner_iterations, pair_list* _pl, CACHETABLE _ct);
+ int init(uint32_t cleaner_iterations, pair_list* _pl, CACHETABLE _ct);
void destroy(void);
uint32_t get_iterations(void);
void set_iterations(uint32_t new_iterations);
@@ -625,6 +631,8 @@ private:
// minimum period of 1s so if you want
// more frequent cleaner runs you must
// use this)
+ bool m_cleaner_cron_init;
+ bool m_cleaner_init;
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/storage/tokudb/ft-index/ft/cachetable.cc b/storage/tokudb/ft-index/ft/cachetable.cc
index 4bfe8d90379..fb427c5349b 100644
--- a/storage/tokudb/ft-index/ft/cachetable.cc
+++ b/storage/tokudb/ft-index/ft/cachetable.cc
@@ -106,6 +106,7 @@ PATENT RIGHTS GRANT:
#include <portability/toku_time.h>
#include <util/rwlock.h>
#include <util/status.h>
+#include <util/context.h>
///////////////////////////////////////////////////////////////////////////////////
// Engine status
@@ -291,7 +292,10 @@ uint32_t toku_get_cleaner_iterations_unlocked (CACHETABLE ct) {
// reserve 25% as "unreservable". The loader cannot have it.
#define unreservable_memory(size) ((size)/4)
-void toku_cachetable_create(CACHETABLE *result, long size_limit, LSN UU(initial_lsn), TOKULOGGER logger) {
+int toku_cachetable_create(CACHETABLE *ct_result, long size_limit, LSN UU(initial_lsn), TOKULOGGER logger) {
+ int result = 0;
+ int r;
+
if (size_limit == 0) {
size_limit = 128*1024*1024;
}
@@ -301,16 +305,46 @@ void toku_cachetable_create(CACHETABLE *result, long size_limit, LSN UU(initial_
ct->cf_list.init();
int num_processors = toku_os_get_number_active_processors();
- ct->client_kibbutz = toku_kibbutz_create(num_processors);
- ct->ct_kibbutz = toku_kibbutz_create(2*num_processors);
int checkpointing_nworkers = (num_processors/4) ? num_processors/4 : 1;
- ct->checkpointing_kibbutz = toku_kibbutz_create(checkpointing_nworkers);
+ r = toku_kibbutz_create(num_processors, &ct->client_kibbutz);
+ if (r != 0) {
+ result = r;
+ goto cleanup;
+ }
+ r = toku_kibbutz_create(2*num_processors, &ct->ct_kibbutz);
+ if (r != 0) {
+ result = r;
+ goto cleanup;
+ }
+ r = toku_kibbutz_create(checkpointing_nworkers, &ct->checkpointing_kibbutz);
+ if (r != 0) {
+ result = r;
+ goto cleanup;
+ }
// must be done after creating ct_kibbutz
- ct->ev.init(size_limit, &ct->list, &ct->cf_list, ct->ct_kibbutz, EVICTION_PERIOD);
- ct->cp.init(&ct->list, logger, &ct->ev, &ct->cf_list);
- ct->cl.init(1, &ct->list, ct); // by default, start with one iteration
+ r = ct->ev.init(size_limit, &ct->list, &ct->cf_list, ct->ct_kibbutz, EVICTION_PERIOD);
+ if (r != 0) {
+ result = r;
+ goto cleanup;
+ }
+ r = ct->cp.init(&ct->list, logger, &ct->ev, &ct->cf_list);
+ if (r != 0) {
+ result = r;
+ goto cleanup;
+ }
+ r = ct->cl.init(1, &ct->list, ct); // by default, start with one iteration
+ if (r != 0) {
+ result = r;
+ goto cleanup;
+ }
ct->env_dir = toku_xstrdup(".");
- *result = ct;
+cleanup:
+ if (result == 0) {
+ *ct_result = ct;
+ } else {
+ toku_cachetable_close(&ct);
+ }
+ return result;
}
// Returns a pointer to the checkpoint contained within
@@ -618,39 +652,6 @@ static void cachetable_free_pair(PAIR p) {
ctpair_destroy(p);
}
-// Maybe remove a pair from the cachetable and free it, depending on whether
-// or not there are any threads interested in the pair. The flush callback
-// is called with write_me and keep_me both false, and the pair is destroyed.
-// The sole purpose of this function is to remove the node, so the write_me
-// argument to the flush callback is false, and the flush callback won't do
-// anything except destroy the node.
-//
-// on input, pair_list's write lock is held and PAIR's mutex is held
-// on exit, only the pair_list's write lock is still held
-//
-static void cachetable_maybe_remove_and_free_pair (
- pair_list* pl,
- evictor* ev,
- PAIR p
- )
-{
- // this ensures that a clone running in the background first completes
- if (p->value_rwlock.users() == 0 && p->refcount == 0) {
- // assumption is that if we are about to remove the pair
- // that no one has grabbed the disk_nb_mutex,
- // and that there is no cloned_value_data, because
- // no one is writing a cloned value out.
- assert(nb_mutex_users(&p->disk_nb_mutex) == 0);
- assert(p->cloned_value_data == NULL);
- cachetable_remove_pair(pl, ev, p);
- pair_unlock(p);
- cachetable_free_pair(p);
- }
- else {
- pair_unlock(p);
- }
-}
-
// assumes value_rwlock and disk_nb_mutex held on entry
// responsibility of this function is to only write a locked PAIR to disk
// and NOTHING else. We do not manipulate the state of the PAIR
@@ -774,7 +775,7 @@ static void cachetable_evicter(void* extra) {
static void cachetable_partial_eviction(void* extra) {
PAIR p = (PAIR)extra;
CACHEFILE cf = p->cachefile;
- p->ev->do_partial_eviction(p, false);
+ p->ev->do_partial_eviction(p);
bjm_remove_background_job(cf->bjm);
}
@@ -1483,6 +1484,8 @@ static bool try_pin_pair(
bool partial_fetch_required = pf_req_callback(p->value_data,read_extraargs);
if (partial_fetch_required) {
+ toku::context pf_ctx(CTX_PARTIAL_FETCH);
+
if (ct->ev.should_client_thread_sleep() && !already_slept) {
pair_lock(p);
unpin_pair(p, (lock_type == PL_READ));
@@ -1634,6 +1637,8 @@ beginning:
}
}
else {
+ toku::context fetch_ctx(CTX_FULL_FETCH);
+
ct->list.pair_unlock_by_fullhash(fullhash);
// we only want to sleep once per call to get_and_pin. If we have already
// slept and there is still cache pressure, then we might as
@@ -2038,10 +2043,7 @@ maybe_pin_pair(
if (retval == TOKUDB_TRY_AGAIN) {
unpin_pair(p, (lock_type == PL_READ));
}
- else {
- // just a sanity check
- assert(retval == 0);
- }
+ pair_touch(p);
pair_unlock(p);
return retval;
}
@@ -2071,6 +2073,8 @@ try_again:
ct->list.pair_lock_by_fullhash(fullhash);
PAIR p = ct->list.find_pair(cf, key, fullhash);
if (p == NULL) {
+ toku::context fetch_ctx(CTX_FULL_FETCH);
+
// Not found
ct->list.pair_unlock_by_fullhash(fullhash);
ct->list.write_list_lock();
@@ -2146,6 +2150,8 @@ try_again:
// still check for partial fetch
bool partial_fetch_required = pf_req_callback(p->value_data,read_extraargs);
if (partial_fetch_required) {
+ toku::context fetch_ctx(CTX_PARTIAL_FETCH);
+
run_unlockers(unlockers);
// we are now getting an expensive write lock, because we
@@ -2428,10 +2434,10 @@ static void remove_pair_for_close(PAIR p, CACHETABLE ct, bool completely) {
assert(p->dirty == CACHETABLE_CLEAN);
assert(p->refcount == 0);
if (completely) {
- // TODO: maybe break up this function
- // so that write lock does not need to be held for entire
- // free
- cachetable_maybe_remove_and_free_pair(&ct->list, &ct->ev, p);
+ cachetable_remove_pair(&ct->list, &ct->ev, p);
+ pair_unlock(p);
+ // TODO: Eventually, we should not hold the write list lock during free
+ cachetable_free_pair(p);
}
else {
// if we are not evicting completely,
@@ -2587,9 +2593,12 @@ void toku_cachetable_close (CACHETABLE *ctp) {
ct->list.destroy();
ct->cf_list.destroy();
- toku_kibbutz_destroy(ct->client_kibbutz);
- toku_kibbutz_destroy(ct->ct_kibbutz);
- toku_kibbutz_destroy(ct->checkpointing_kibbutz);
+ if (ct->client_kibbutz)
+ toku_kibbutz_destroy(ct->client_kibbutz);
+ if (ct->ct_kibbutz)
+ toku_kibbutz_destroy(ct->ct_kibbutz);
+ if (ct->checkpointing_kibbutz)
+ toku_kibbutz_destroy(ct->checkpointing_kibbutz);
toku_free(ct->env_dir);
toku_free(ct);
*ctp = 0;
@@ -3074,20 +3083,29 @@ int toku_cleaner_thread (void *cleaner_v) {
//
ENSURE_POD(cleaner);
-void cleaner::init(uint32_t _cleaner_iterations, pair_list* _pl, CACHETABLE _ct) {
+int cleaner::init(uint32_t _cleaner_iterations, pair_list* _pl, CACHETABLE _ct) {
// default is no cleaner, for now
- toku_minicron_setup(&m_cleaner_cron, 0, toku_cleaner_thread, this);
+ m_cleaner_cron_init = false;
+ int r = toku_minicron_setup(&m_cleaner_cron, 0, toku_cleaner_thread, this);
+ if (r == 0) {
+ m_cleaner_cron_init = true;
+ }
TOKU_VALGRIND_HG_DISABLE_CHECKING(&m_cleaner_iterations, sizeof m_cleaner_iterations);
m_cleaner_iterations = _cleaner_iterations;
m_pl = _pl;
m_ct = _ct;
+ m_cleaner_init = true;
+ return r;
}
// this function is allowed to be called multiple times
void cleaner::destroy(void) {
- if (!toku_minicron_has_been_shutdown(&m_cleaner_cron)) {
+ if (!m_cleaner_init) {
+ return;
+ }
+ if (m_cleaner_cron_init && !toku_minicron_has_been_shutdown(&m_cleaner_cron)) {
// for test code only, production code uses toku_cachetable_minicron_shutdown()
- int r = toku_minicron_shutdown(&m_cleaner_cron);
+ int r = toku_minicron_shutdown(&m_cleaner_cron);
assert(r==0);
}
}
@@ -3122,6 +3140,8 @@ void cleaner::set_period(uint32_t new_period) {
// start). At this point, we can safely unlock the cachetable, do the
// work (callback), and unlock/release our claim to the cachefile.
int cleaner::run_cleaner(void) {
+ toku::context cleaner_ctx(CTX_CLEANER);
+
int r;
uint32_t num_iterations = this->get_iterations();
for (uint32_t i = 0; i < num_iterations; ++i) {
@@ -3662,7 +3682,7 @@ static void *eviction_thread(void *evictor_v) {
// Starts the eviction thread, assigns external object references,
// and initializes all counters and condition variables.
//
-void evictor::init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KIBBUTZ _kibbutz, uint32_t eviction_period) {
+int evictor::init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KIBBUTZ _kibbutz, uint32_t eviction_period) {
TOKU_VALGRIND_HG_DISABLE_CHECKING(&m_ev_thread_is_running, sizeof m_ev_thread_is_running);
TOKU_VALGRIND_HG_DISABLE_CHECKING(&m_size_evicting, sizeof m_size_evicting);
@@ -3716,8 +3736,13 @@ void evictor::init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, K
// start the background thread
m_run_thread = true;
m_num_eviction_thread_runs = 0;
+ m_ev_thread_init = false;
r = toku_pthread_create(&m_ev_thread, NULL, eviction_thread, this);
- assert_zero(r);
+ if (r == 0) {
+ m_ev_thread_init = true;
+ }
+ m_evictor_init = true;
+ return r;
}
//
@@ -3725,7 +3750,10 @@ void evictor::init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, K
//
// NOTE: This should only be called if there are no evictions in progress.
//
-void evictor::destroy() {
+void evictor::destroy() {
+ if (!m_evictor_init) {
+ return;
+ }
assert(m_size_evicting == 0);
//
// commented out of Ming, because we could not finish
@@ -3734,16 +3762,16 @@ void evictor::destroy() {
//assert(m_size_current == 0);
// Stop the eviction thread.
- toku_mutex_lock(&m_ev_thread_lock);
- m_run_thread = false;
- this->signal_eviction_thread();
- toku_mutex_unlock(&m_ev_thread_lock);
-
- void *ret;
- int r = toku_pthread_join(m_ev_thread, &ret);
- assert_zero(r);
- assert(!m_ev_thread_is_running);
-
+ if (m_ev_thread_init) {
+ toku_mutex_lock(&m_ev_thread_lock);
+ m_run_thread = false;
+ this->signal_eviction_thread();
+ toku_mutex_unlock(&m_ev_thread_lock);
+ void *ret;
+ int r = toku_pthread_join(m_ev_thread, &ret);
+ assert_zero(r);
+ assert(!m_ev_thread_is_running);
+ }
destroy_partitioned_counter(m_size_nonleaf);
m_size_nonleaf = NULL;
destroy_partitioned_counter(m_size_leaf);
@@ -4007,6 +4035,8 @@ bool evictor::run_eviction_on_pair(PAIR curr_in_clock) {
m_pl->read_list_unlock();
ret_val = true;
if (curr_in_clock->count > 0) {
+ toku::context pe_ctx(CTX_PARTIAL_EVICTION);
+
uint32_t curr_size = curr_in_clock->attr.size;
// if the size of this PAIR is greater than the average size of PAIRs
// in the cachetable, then decrement it, otherwise, decrement
@@ -4052,10 +4082,10 @@ bool evictor::run_eviction_on_pair(PAIR curr_in_clock) {
write_extraargs
);
if (cost == PE_CHEAP) {
+ pair_unlock(curr_in_clock);
curr_in_clock->size_evicting_estimate = 0;
- this->do_partial_eviction(curr_in_clock, true);
+ this->do_partial_eviction(curr_in_clock);
bjm_remove_background_job(cf->bjm);
- pair_unlock(curr_in_clock);
}
else if (cost == PE_EXPENSIVE) {
// only bother running an expensive partial eviction
@@ -4083,6 +4113,8 @@ bool evictor::run_eviction_on_pair(PAIR curr_in_clock) {
}
}
else {
+ toku::context pe_ctx(CTX_FULL_EVICTION);
+
// responsibility of try_evict_pair to eventually remove background job
// pair's mutex is still grabbed here
this->try_evict_pair(curr_in_clock);
@@ -4094,26 +4126,48 @@ exit:
return ret_val;
}
+struct pair_unpin_with_new_attr_extra {
+ pair_unpin_with_new_attr_extra(evictor *e, PAIR p) :
+ ev(e), pair(p) {
+ }
+ evictor *ev;
+ PAIR pair;
+};
+
+static void pair_unpin_with_new_attr(PAIR_ATTR new_attr, void *extra) {
+ struct pair_unpin_with_new_attr_extra *info =
+ reinterpret_cast<struct pair_unpin_with_new_attr_extra *>(extra);
+ PAIR p = info->pair;
+ evictor *ev = info->ev;
+
+ // change the attr in the evictor, then update the value in the pair
+ ev->change_pair_attr(p->attr, new_attr);
+ p->attr = new_attr;
+
+ // unpin
+ pair_lock(p);
+ p->value_rwlock.write_unlock();
+ pair_unlock(p);
+}
+
//
-// on entry and exit, pair's mutex is held if pair_mutex_held is true
+// on entry and exit, pair's mutex is not held
// on exit, PAIR is unpinned
//
-void evictor::do_partial_eviction(PAIR p, bool pair_mutex_held) {
- PAIR_ATTR new_attr;
+void evictor::do_partial_eviction(PAIR p) {
+ // Copy the old attr
PAIR_ATTR old_attr = p->attr;
-
- p->pe_callback(p->value_data, old_attr, &new_attr, p->write_extraargs);
+ long long size_evicting_estimate = p->size_evicting_estimate;
- this->change_pair_attr(old_attr, new_attr);
- p->attr = new_attr;
- this->decrease_size_evicting(p->size_evicting_estimate);
- if (!pair_mutex_held) {
- pair_lock(p);
- }
- p->value_rwlock.write_unlock();
- if (!pair_mutex_held) {
- pair_unlock(p);
- }
+ struct pair_unpin_with_new_attr_extra extra(this, p);
+ p->pe_callback(p->value_data, old_attr, p->write_extraargs,
+ // passed as the finalize continuation, which allows the
+ // pe_callback to unpin the node before doing expensive cleanup
+ pair_unpin_with_new_attr, &extra);
+
+ // now that the pe_callback (and its pair_unpin_with_new_attr continuation)
+ // have finished, we can safely decrease size_evicting
+ this->decrease_size_evicting(size_evicting_estimate);
}
//
@@ -4188,8 +4242,25 @@ void evictor::evict_pair(PAIR p, bool for_checkpoint) {
nb_mutex_unlock(&p->disk_nb_mutex);
// at this point, we have the pair list's write list lock
// and we have the pair's mutex (p->mutex) held
- cachetable_maybe_remove_and_free_pair(m_pl, this, p);
+
+ // this ensures that a clone running in the background first completes
+ bool removed = false;
+ if (p->value_rwlock.users() == 0 && p->refcount == 0) {
+ // assumption is that if we are about to remove the pair
+ // that no one has grabbed the disk_nb_mutex,
+ // and that there is no cloned_value_data, because
+ // no one is writing a cloned value out.
+ assert(nb_mutex_users(&p->disk_nb_mutex) == 0);
+ assert(p->cloned_value_data == NULL);
+ cachetable_remove_pair(m_pl, this, p);
+ removed = true;
+ }
+ pair_unlock(p);
m_pl->write_list_unlock();
+ // do not want to hold the write list lock while freeing a pair
+ if (removed) {
+ cachetable_free_pair(p);
+ }
}
//
@@ -4348,7 +4419,7 @@ ENSURE_POD(checkpointer);
//
// Sets the cachetable reference in this checkpointer class, this is temporary.
//
-void checkpointer::init(pair_list *_pl,
+int checkpointer::init(pair_list *_pl,
TOKULOGGER _logger,
evictor *_ev,
cachefile_list *files) {
@@ -4359,11 +4430,20 @@ void checkpointer::init(pair_list *_pl,
bjm_init(&m_checkpoint_clones_bjm);
// Default is no checkpointing.
- toku_minicron_setup(&m_checkpointer_cron, 0, checkpoint_thread, this);
+ m_checkpointer_cron_init = false;
+ int r = toku_minicron_setup(&m_checkpointer_cron, 0, checkpoint_thread, this);
+ if (r == 0) {
+ m_checkpointer_cron_init = true;
+ }
+ m_checkpointer_init = true;
+ return r;
}
void checkpointer::destroy() {
- if (!this->has_been_shutdown()) {
+ if (!m_checkpointer_init) {
+ return;
+ }
+ if (m_checkpointer_cron_init && !this->has_been_shutdown()) {
// for test code only, production code uses toku_cachetable_minicron_shutdown()
int r = this->shutdown();
assert(r == 0);
diff --git a/storage/tokudb/ft-index/ft/cachetable.h b/storage/tokudb/ft-index/ft/cachetable.h
index 478954032bf..c654927aa21 100644
--- a/storage/tokudb/ft-index/ft/cachetable.h
+++ b/storage/tokudb/ft-index/ft/cachetable.h
@@ -122,7 +122,7 @@ uint32_t toku_get_cleaner_iterations_unlocked (CACHETABLE ct);
// create and initialize a cache table
// size_limit is the upper limit on the size of the size of the values in the table
// pass 0 if you want the default
-void toku_cachetable_create(CACHETABLE *result, long size_limit, LSN initial_lsn, TOKULOGGER);
+int toku_cachetable_create(CACHETABLE *result, long size_limit, LSN initial_lsn, TOKULOGGER);
// Create a new cachetable.
// Effects: a new cachetable is created and initialized.
@@ -223,11 +223,15 @@ typedef void (*CACHETABLE_PARTIAL_EVICTION_EST_CALLBACK)(void *ftnode_pv, void*
// The cachetable calls the partial eviction callback is to possibly try and partially evict pieces
// of the PAIR. The callback determines the strategy for what to evict. The callback may choose to free
-// nothing, or may choose to free as much as possible.
-// old_attr is the PAIR_ATTR of the PAIR when the callback is called.
-// new_attr is set to the new PAIR_ATTR after the callback executes partial eviction
-// Requires a write lock to be held on the PAIR in the cachetable while this function is called
-typedef int (*CACHETABLE_PARTIAL_EVICTION_CALLBACK)(void *ftnode_pv, PAIR_ATTR old_attr, PAIR_ATTR* new_attr, void *write_extraargs);
+// nothing, or may choose to free as much as possible. When the partial eviction callback is finished,
+// it must call finalize with the new PAIR_ATTR and the given finalize_extra. After this point, the
+// write lock will be released on the PAIR and it is no longer safe to operate on any of the passed arguments.
+// This is useful for doing expensive cleanup work outside of the PAIR's write lock (such as destroying objects, etc)
+//
+// on entry, requires a write lock to be held on the PAIR in the cachetable while this function is called
+// on exit, the finalize continuation is called
+typedef int (*CACHETABLE_PARTIAL_EVICTION_CALLBACK)(void *ftnode_pv, PAIR_ATTR old_attr, void *write_extraargs,
+ void (*finalize)(PAIR_ATTR new_attr, void *extra), void *finalize_extra);
// The cachetable calls this function to determine if get_and_pin call requires a partial fetch. If this function returns true,
// then the cachetable will subsequently call CACHETABLE_PARTIAL_FETCH_CALLBACK to perform
diff --git a/storage/tokudb/ft-index/ft/checkpoint.cc b/storage/tokudb/ft-index/ft/checkpoint.cc
index 223f5177add..95ad0e1f0a4 100644
--- a/storage/tokudb/ft-index/ft/checkpoint.cc
+++ b/storage/tokudb/ft-index/ft/checkpoint.cc
@@ -136,6 +136,7 @@ PATENT RIGHTS GRANT:
#include "checkpoint.h"
#include <portability/toku_atomic.h>
#include <util/status.h>
+#include <util/frwlock.h>
///////////////////////////////////////////////////////////////////////////////////
// Engine status
@@ -187,7 +188,8 @@ toku_checkpoint_get_status(CACHETABLE ct, CHECKPOINT_STATUS statp) {
static LSN last_completed_checkpoint_lsn;
-static toku_pthread_rwlock_t checkpoint_safe_lock;
+static toku_mutex_t checkpoint_safe_mutex;
+static toku::frwlock checkpoint_safe_lock;
static toku_pthread_rwlock_t multi_operation_lock;
static toku_pthread_rwlock_t low_priority_multi_operation_lock;
@@ -237,28 +239,33 @@ multi_operation_checkpoint_unlock(void) {
static void
checkpoint_safe_lock_init(void) {
- toku_pthread_rwlock_init(&checkpoint_safe_lock, NULL);
+ toku_mutex_init(&checkpoint_safe_mutex, NULL);
+ checkpoint_safe_lock.init(&checkpoint_safe_mutex);
locked_cs = false;
}
static void
checkpoint_safe_lock_destroy(void) {
- toku_pthread_rwlock_destroy(&checkpoint_safe_lock);
+ checkpoint_safe_lock.deinit();
+ toku_mutex_destroy(&checkpoint_safe_mutex);
}
static void
checkpoint_safe_checkpoint_lock(void) {
- toku_pthread_rwlock_wrlock(&checkpoint_safe_lock);
+ toku_mutex_lock(&checkpoint_safe_mutex);
+ checkpoint_safe_lock.write_lock(false);
+ toku_mutex_unlock(&checkpoint_safe_mutex);
locked_cs = true;
}
static void
checkpoint_safe_checkpoint_unlock(void) {
locked_cs = false;
- toku_pthread_rwlock_wrunlock(&checkpoint_safe_lock);
+ toku_mutex_lock(&checkpoint_safe_mutex);
+ checkpoint_safe_lock.write_unlock();
+ toku_mutex_unlock(&checkpoint_safe_mutex);
}
-
// toku_xxx_client_(un)lock() functions are only called from client code,
// never from checkpoint code, and use the "reader" interface to the lock functions.
@@ -286,18 +293,20 @@ void
toku_checkpoint_safe_client_lock(void) {
if (locked_cs)
(void) toku_sync_fetch_and_add(&STATUS_VALUE(CP_CLIENT_WAIT_ON_CS), 1);
- toku_pthread_rwlock_rdlock(&checkpoint_safe_lock);
+ toku_mutex_lock(&checkpoint_safe_mutex);
+ checkpoint_safe_lock.read_lock();
+ toku_mutex_unlock(&checkpoint_safe_mutex);
toku_multi_operation_client_lock();
}
void
toku_checkpoint_safe_client_unlock(void) {
- toku_pthread_rwlock_rdunlock(&checkpoint_safe_lock);
+ toku_mutex_lock(&checkpoint_safe_mutex);
+ checkpoint_safe_lock.read_unlock();
+ toku_mutex_unlock(&checkpoint_safe_mutex);
toku_multi_operation_client_unlock();
}
-
-
// Initialize the checkpoint mechanism, must be called before any client operations.
void
toku_checkpoint_init(void) {
diff --git a/storage/tokudb/ft-index/ft/compress.cc b/storage/tokudb/ft-index/ft/compress.cc
index c929ac18658..2b0187e0b4f 100644
--- a/storage/tokudb/ft-index/ft/compress.cc
+++ b/storage/tokudb/ft-index/ft/compress.cc
@@ -89,6 +89,8 @@ PATENT RIGHTS GRANT:
#ident "$Id$"
#include <toku_portability.h>
+#include <util/scoped_malloc.h>
+
#include <zlib.h>
#include <lzma.h>
@@ -241,10 +243,10 @@ void toku_decompress (Bytef *dest, uLongf destLen,
}
case TOKU_QUICKLZ_METHOD:
if (sourceLen>1) {
- qlz_state_decompress *XCALLOC(qsd);
+ toku::scoped_calloc state_buf(sizeof(qlz_state_decompress));
+ qlz_state_decompress *qsd = reinterpret_cast<qlz_state_decompress *>(state_buf.get());
uLongf actual_destlen = qlz_decompress((char*)source+1, dest, qsd);
assert(actual_destlen == destLen);
- toku_free(qsd);
} else {
// length 1 means there is no data, so do nothing.
assert(destLen==0);
diff --git a/storage/tokudb/ft-index/ft/fifo.cc b/storage/tokudb/ft-index/ft/fifo.cc
index 3d55334e5c2..7f6e1778df6 100644
--- a/storage/tokudb/ft-index/ft/fifo.cc
+++ b/storage/tokudb/ft-index/ft/fifo.cc
@@ -135,6 +135,11 @@ int toku_fifo_create(FIFO *ptr) {
return 0;
}
+void toku_fifo_resize(FIFO fifo, size_t new_size) {
+ XREALLOC_N(new_size, fifo->memory);
+ fifo->memory_size = new_size;
+}
+
void toku_fifo_free(FIFO *ptr) {
FIFO fifo = *ptr;
if (fifo->memory) toku_free(fifo->memory);
@@ -162,16 +167,10 @@ int toku_fifo_enq(FIFO fifo, const void *key, unsigned int keylen, const void *d
+ xids_get_size(xids)
- sizeof(XIDS_S); //Prevent double counting
int need_space_total = fifo->memory_used+need_space_here;
- if (fifo->memory == NULL) {
- fifo->memory_size = next_power_of_two(need_space_total);
- XMALLOC_N(fifo->memory_size, fifo->memory);
- }
- if (need_space_total > fifo->memory_size) {
- // Out of memory at the end.
+ if (fifo->memory == NULL || need_space_total > fifo->memory_size) {
+ // resize the fifo to the next power of 2 greater than the needed space
int next_2 = next_power_of_two(need_space_total);
- // resize the fifo
- XREALLOC_N(next_2, fifo->memory);
- fifo->memory_size = next_2;
+ toku_fifo_resize(fifo, next_2);
}
struct fifo_entry *entry = (struct fifo_entry *)(fifo->memory + fifo->memory_used);
fifo_entry_set_msg_type(entry, type);
diff --git a/storage/tokudb/ft-index/ft/fifo.h b/storage/tokudb/ft-index/ft/fifo.h
index 00caa3d742f..e178ec6de24 100644
--- a/storage/tokudb/ft-index/ft/fifo.h
+++ b/storage/tokudb/ft-index/ft/fifo.h
@@ -136,6 +136,8 @@ typedef struct fifo *FIFO;
int toku_fifo_create(FIFO *);
+void toku_fifo_resize(FIFO fifo, size_t new_size);
+
void toku_fifo_free(FIFO *);
int toku_fifo_n_entries(FIFO);
diff --git a/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc b/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc
index fa1d000d16e..16edf068d4d 100644
--- a/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc
+++ b/storage/tokudb/ft-index/ft/ft-cachetable-wrappers.cc
@@ -94,7 +94,8 @@ PATENT RIGHTS GRANT:
#include <fttypes.h>
#include <ft-flusher.h>
#include <ft-internal.h>
-#include "ft.h"
+#include <ft.h>
+#include <util/context.h>
static void
ftnode_get_key_and_fullhash(
@@ -252,6 +253,8 @@ toku_pin_ftnode_batched(
bfe->child_to_read
);
if (needs_ancestors_messages) {
+ toku::context apply_messages_ctx(CTX_MESSAGE_APPLICATION);
+
toku_unpin_ftnode_read_only(brt->ft, node);
int rr = toku_cachetable_get_and_pin_nonblocking_batched(
brt->ft->cf,
diff --git a/storage/tokudb/ft-index/ft/ft-flusher.cc b/storage/tokudb/ft-index/ft/ft-flusher.cc
index 9d7369accd5..20975c7aa01 100644
--- a/storage/tokudb/ft-index/ft/ft-flusher.cc
+++ b/storage/tokudb/ft-index/ft/ft-flusher.cc
@@ -97,6 +97,7 @@ PATENT RIGHTS GRANT:
#include <toku_assert.h>
#include <portability/toku_atomic.h>
#include <util/status.h>
+#include <util/context.h>
/* Status is intended for display to humans to help understand system behavior.
* It does not need to be perfectly thread-safe.
@@ -544,11 +545,13 @@ ct_flusher_advice_init(struct flusher_advice *fa, struct flush_status_update_ext
// a leaf node that is not entirely in memory. If so, then
// we cannot be sure if the node is reactive.
//
-static bool may_node_be_reactive(FTNODE node)
+static bool may_node_be_reactive(FT ft, FTNODE node)
{
- if (node->height == 0) return true;
+ if (node->height == 0) {
+ return true;
+ }
else {
- return (get_nonleaf_reactivity(node) != RE_STABLE);
+ return (get_nonleaf_reactivity(node, ft->h->fanout) != RE_STABLE);
}
}
@@ -1541,11 +1544,7 @@ ft_merge_child(
}
}
-static void ft_flush_some_child(
- FT ft,
- FTNODE parent,
- struct flusher_advice *fa
- )
+void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa)
// Effect: This function does the following:
// - Pick a child of parent (the heaviest child),
// - flush from parent to child,
@@ -1559,7 +1558,7 @@ static void ft_flush_some_child(
NONLEAF_CHILDINFO bnc = NULL;
paranoid_invariant(parent->height>0);
toku_assert_entire_node_in_memory(parent);
- TXNID oldest_referenced_xid = parent->oldest_referenced_xid_known;
+ TXNID parent_oldest_referenced_xid_known = parent->oldest_referenced_xid_known;
// pick the child we want to flush to
int childnum = fa->pick_child(ft, parent, fa->extra);
@@ -1589,7 +1588,7 @@ static void ft_flush_some_child(
// Let's do a quick check to see if the child may be reactive
// If the child cannot be reactive, then we can safely unlock
// the parent before finishing reading in the entire child node.
- bool may_child_be_reactive = may_node_be_reactive(child);
+ bool may_child_be_reactive = may_node_be_reactive(ft, child);
paranoid_invariant(child->thisnodename.b!=0);
//VERIFY_NODE(brt, child);
@@ -1631,7 +1630,7 @@ static void ft_flush_some_child(
// we wont be splitting/merging child
// and we have already replaced the bnc
// for the root with a fresh one
- enum reactivity child_re = get_node_reactivity(child, ft->h->nodesize);
+ enum reactivity child_re = get_node_reactivity(ft, child);
if (parent && child_re == RE_STABLE) {
toku_unpin_ftnode_off_client_thread(ft, parent);
parent = NULL;
@@ -1652,7 +1651,7 @@ static void ft_flush_some_child(
ft,
bnc,
child,
- oldest_referenced_xid
+ parent_oldest_referenced_xid_known
);
destroy_nonleaf_childinfo(bnc);
}
@@ -1661,7 +1660,7 @@ static void ft_flush_some_child(
// let's get the reactivity of the child again,
// it is possible that the flush got rid of some values
// and now the parent is no longer reactive
- child_re = get_node_reactivity(child, ft->h->nodesize);
+ child_re = get_node_reactivity(ft, child);
// if the parent has been unpinned above, then
// this is our only option, even if the child is not stable
// if the child is not stable, we'll handle it the next
@@ -1676,10 +1675,10 @@ static void ft_flush_some_child(
parent = NULL;
}
//
- // it is the responsibility of ft_flush_some_child to unpin child
+ // it is the responsibility of toku_ft_flush_some_child to unpin child
//
if (child->height > 0 && fa->should_recursively_flush(child, fa->extra)) {
- ft_flush_some_child(ft, child, fa);
+ toku_ft_flush_some_child(ft, child, fa);
}
else {
toku_unpin_ftnode_off_client_thread(ft, child);
@@ -1706,13 +1705,6 @@ static void ft_flush_some_child(
}
}
-void toku_ft_flush_some_child(FT ft, FTNODE parent, struct flusher_advice *fa) {
- // Vanilla flush_some_child flushes from parent to child without
- // providing a meaningful oldest_referenced_xid. No simple garbage
- // collection is performed.
- return ft_flush_some_child(ft, parent, fa);
-}
-
static void
update_cleaner_status(
FTNODE node,
@@ -1854,7 +1846,7 @@ struct flusher_extra {
FT h;
FTNODE node;
NONLEAF_CHILDINFO bnc;
- TXNID oldest_referenced_xid;
+ TXNID parent_oldest_referenced_xid_known;
};
//
@@ -1864,6 +1856,7 @@ struct flusher_extra {
//
static void flush_node_fun(void *fe_v)
{
+ toku::context flush_ctx(CTX_FLUSH);
struct flusher_extra* fe = (struct flusher_extra *) fe_v;
// The node that has been placed on the background
// thread may not be fully in memory. Some message
@@ -1892,16 +1885,16 @@ static void flush_node_fun(void *fe_v)
fe->h,
fe->bnc,
fe->node,
- fe->oldest_referenced_xid
+ fe->parent_oldest_referenced_xid_known
);
destroy_nonleaf_childinfo(fe->bnc);
// after the flush has completed, now check to see if the node needs flushing
- // If so, call ft_flush_some_child on the node (because this flush intends to
+ // If so, call toku_ft_flush_some_child on the node (because this flush intends to
// pass a meaningful oldest referenced xid for simple garbage collection), and it is the
// responsibility of the flush to unlock the node. otherwise, we unlock it here.
if (fe->node->height > 0 && toku_ft_nonleaf_is_gorged(fe->node, fe->h->h->nodesize)) {
- ft_flush_some_child(fe->h, fe->node, &fa);
+ toku_ft_flush_some_child(fe->h, fe->node, &fa);
}
else {
toku_unpin_ftnode_off_client_thread(fe->h,fe->node);
@@ -1912,7 +1905,7 @@ static void flush_node_fun(void *fe_v)
// bnc, which means we are tasked with flushing some
// buffer in the node.
// It is the responsibility of flush some child to unlock the node
- ft_flush_some_child(fe->h, fe->node, &fa);
+ toku_ft_flush_some_child(fe->h, fe->node, &fa);
}
remove_background_job_from_cf(fe->h->cf);
toku_free(fe);
@@ -1923,13 +1916,13 @@ place_node_and_bnc_on_background_thread(
FT h,
FTNODE node,
NONLEAF_CHILDINFO bnc,
- TXNID oldest_referenced_xid)
+ TXNID parent_oldest_referenced_xid_known)
{
struct flusher_extra *XMALLOC(fe);
fe->h = h;
fe->node = node;
fe->bnc = bnc;
- fe->oldest_referenced_xid = oldest_referenced_xid;
+ fe->parent_oldest_referenced_xid_known = parent_oldest_referenced_xid_known;
cachefile_kibbutz_enq(h->cf, flush_node_fun, fe);
}
@@ -1948,7 +1941,8 @@ place_node_and_bnc_on_background_thread(
//
void toku_ft_flush_node_on_background_thread(FT h, FTNODE parent)
{
- TXNID oldest_referenced_xid_known = parent->oldest_referenced_xid_known;
+ toku::context flush_ctx(CTX_FLUSH);
+ TXNID parent_oldest_referenced_xid_known = parent->oldest_referenced_xid_known;
//
// first let's see if we can detach buffer on client thread
// and pick the child we want to flush to
@@ -1965,13 +1959,13 @@ void toku_ft_flush_node_on_background_thread(FT h, FTNODE parent)
// In this case, we could not lock the child, so just place the parent on the background thread
// In the callback, we will use toku_ft_flush_some_child, which checks to
// see if we should blow away the old basement nodes.
- place_node_and_bnc_on_background_thread(h, parent, NULL, oldest_referenced_xid_known);
+ place_node_and_bnc_on_background_thread(h, parent, NULL, parent_oldest_referenced_xid_known);
}
else {
//
// successfully locked child
//
- bool may_child_be_reactive = may_node_be_reactive(child);
+ bool may_child_be_reactive = may_node_be_reactive(h, child);
if (!may_child_be_reactive) {
// We're going to unpin the parent, so before we do, we must
// check to see if we need to blow away the basement nodes to
@@ -1994,7 +1988,7 @@ void toku_ft_flush_node_on_background_thread(FT h, FTNODE parent)
// so, because we know for sure the child is not
// reactive, we can unpin the parent
//
- place_node_and_bnc_on_background_thread(h, child, bnc, oldest_referenced_xid_known);
+ place_node_and_bnc_on_background_thread(h, child, bnc, parent_oldest_referenced_xid_known);
toku_unpin_ftnode(h, parent);
}
else {
@@ -2004,7 +1998,7 @@ void toku_ft_flush_node_on_background_thread(FT h, FTNODE parent)
toku_unpin_ftnode(h, child);
// Again, we'll have the parent on the background thread, so
// we don't need to destroy the basement nodes yet.
- place_node_and_bnc_on_background_thread(h, parent, NULL, oldest_referenced_xid_known);
+ place_node_and_bnc_on_background_thread(h, parent, NULL, parent_oldest_referenced_xid_known);
}
}
}
diff --git a/storage/tokudb/ft-index/ft/ft-flusher.h b/storage/tokudb/ft-index/ft/ft-flusher.h
index 86bdeee5b82..35371af99e8 100644
--- a/storage/tokudb/ft-index/ft/ft-flusher.h
+++ b/storage/tokudb/ft-index/ft/ft-flusher.h
@@ -232,6 +232,6 @@ void toku_ft_hot_get_status(FT_HOT_STATUS);
int
toku_ft_hot_optimize(FT_HANDLE brt, DBT* left, DBT* right,
int (*progress_callback)(void *extra, float progress),
- void *progress_extra);
+ void *progress_extra, uint64_t* loops_run);
#endif // End of header guardian.
diff --git a/storage/tokudb/ft-index/ft/ft-hot-flusher.cc b/storage/tokudb/ft-index/ft/ft-hot-flusher.cc
index b9036ae4968..0c9691b1e4d 100644
--- a/storage/tokudb/ft-index/ft/ft-hot-flusher.cc
+++ b/storage/tokudb/ft-index/ft/ft-hot-flusher.cc
@@ -96,6 +96,7 @@ PATENT RIGHTS GRANT:
#include <ft.h>
#include <portability/toku_atomic.h>
#include <util/status.h>
+#include <util/context.h>
// Member Descirption:
// 1. highest_pivot_key - this is the key that corresponds to the
@@ -299,8 +300,10 @@ hot_flusher_destroy(struct hot_flusher_extra *flusher)
int
toku_ft_hot_optimize(FT_HANDLE brt, DBT* left, DBT* right,
int (*progress_callback)(void *extra, float progress),
- void *progress_extra)
+ void *progress_extra, uint64_t* loops_run)
{
+ toku::context flush_ctx(CTX_FLUSH);
+
int r = 0;
struct hot_flusher_extra flusher;
struct flusher_advice advice;
@@ -403,6 +406,7 @@ toku_ft_hot_optimize(FT_HANDLE brt, DBT* left, DBT* right,
// Loop until the max key has been updated to positive
// infinity.
} while (!flusher.rightmost_leaf_seen);
+ *loops_run = loop_count;
// Cleanup.
hot_flusher_destroy(&flusher);
diff --git a/storage/tokudb/ft-index/ft/ft-internal.h b/storage/tokudb/ft-index/ft/ft-internal.h
index 9890f0b8c54..6dcde1687b4 100644
--- a/storage/tokudb/ft-index/ft/ft-internal.h
+++ b/storage/tokudb/ft-index/ft/ft-internal.h
@@ -117,15 +117,10 @@ PATENT RIGHTS GRANT:
#include <util/omt.h>
#include "bndata.h"
-#ifndef FT_FANOUT
-#define FT_FANOUT 16
-#endif
-enum { TREE_FANOUT = FT_FANOUT };
enum { KEY_VALUE_OVERHEAD = 8 }; /* Must store the two lengths. */
-enum { FT_CMD_OVERHEAD = (2 + sizeof(MSN)) // the type plus freshness plus MSN
-};
-
-enum { FT_DEFAULT_NODE_SIZE = 1 << 22 };
+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 };
//
@@ -234,16 +229,14 @@ long toku_bnc_memory_size(NONLEAF_CHILDINFO bnc);
long toku_bnc_memory_used(NONLEAF_CHILDINFO bnc);
void toku_bnc_insert_msg(NONLEAF_CHILDINFO bnc, const void *key, ITEMLEN keylen, const void *data, ITEMLEN datalen, enum ft_msg_type type, MSN msn, XIDS xids, bool is_fresh, DESCRIPTOR desc, ft_compare_func cmp);
void toku_bnc_empty(NONLEAF_CHILDINFO bnc);
-void toku_bnc_flush_to_child(FT h, NONLEAF_CHILDINFO bnc, FTNODE child, TXNID oldest_referenced_xid);
+void toku_bnc_flush_to_child(FT h, NONLEAF_CHILDINFO bnc, FTNODE child, TXNID parent_oldest_referenced_xid_known);
bool toku_bnc_should_promote(FT ft, NONLEAF_CHILDINFO bnc) __attribute__((const, nonnull));
bool toku_ft_nonleaf_is_gorged(FTNODE node, uint32_t nodesize);
-
-enum reactivity get_nonleaf_reactivity (FTNODE node);
-enum reactivity get_node_reactivity (FTNODE node, uint32_t nodesize);
+enum reactivity get_nonleaf_reactivity(FTNODE node, unsigned int fanout);
+enum reactivity get_node_reactivity(FT ft, FTNODE node);
uint32_t get_leaf_num_entries(FTNODE node);
-
// data of an available partition of a leaf ftnode
struct ftnode_leaf_basement_node {
bn_data data_buffer;
@@ -336,7 +329,7 @@ struct ftnode {
int height; /* height is always >= 0. 0 for leaf, >0 for nonleaf. */
int dirty;
uint32_t fullhash;
- int n_children; //for internal nodes, if n_children==TREE_FANOUT+1 then the tree needs to be rebalanced.
+ int n_children; //for internal nodes, if n_children==fanout+1 then the tree needs to be rebalanced.
// for leaf nodes, represents number of basement nodes
unsigned int totalchildkeylens;
DBT *childkeys; /* Pivot keys. Child 0's keys are <= childkeys[0]. Child 1's keys are <= childkeys[1].
@@ -509,6 +502,7 @@ struct ft_header {
unsigned int nodesize;
unsigned int basementnodesize;
enum toku_compression_method compression_method;
+ unsigned int fanout;
// 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
@@ -590,6 +584,7 @@ struct ft_options {
unsigned int nodesize;
unsigned int basementnodesize;
enum toku_compression_method compression_method;
+ unsigned int fanout;
unsigned int flags;
ft_compare_func compare_fun;
ft_update_func update_fun;
@@ -632,7 +627,7 @@ int toku_serialize_ftnode_to(int fd, BLOCKNUM, FTNODE node, FTNODE_DISK_DATA* nd
int toku_serialize_rollback_log_to (int fd, ROLLBACK_LOG_NODE log, SERIALIZED_ROLLBACK_LOG_NODE serialized_log, bool is_serialized,
FT h, bool for_checkpoint);
void toku_serialize_rollback_log_to_memory_uncompressed(ROLLBACK_LOG_NODE log, SERIALIZED_ROLLBACK_LOG_NODE serialized);
-int toku_deserialize_rollback_log_from (int fd, BLOCKNUM blocknum, uint32_t fullhash, ROLLBACK_LOG_NODE *logp, FT h);
+int toku_deserialize_rollback_log_from (int fd, BLOCKNUM blocknum, ROLLBACK_LOG_NODE *logp, FT h);
int toku_deserialize_bp_from_disk(FTNODE node, FTNODE_DISK_DATA ndd, int childnum, int fd, struct ftnode_fetch_extra* bfe);
int toku_deserialize_bp_from_compressed(FTNODE node, int childnum, struct ftnode_fetch_extra *bfe);
int toku_deserialize_ftnode_from (int fd, BLOCKNUM off, uint32_t /*fullhash*/, FTNODE *ftnode, FTNODE_DISK_DATA* ndd, struct ftnode_fetch_extra* bfe);
@@ -735,7 +730,8 @@ void toku_ftnode_checkpoint_complete_callback(void *value_data);
void toku_ftnode_flush_callback (CACHEFILE cachefile, int fd, BLOCKNUM nodename, void *ftnode_v, void** UU(disk_data), void *extraargs, PAIR_ATTR size, PAIR_ATTR* new_size, bool write_me, bool keep_me, bool for_checkpoint, bool is_clone);
int toku_ftnode_fetch_callback (CACHEFILE cachefile, PAIR p, int fd, BLOCKNUM nodename, uint32_t fullhash, void **ftnode_pv, void** UU(disk_data), PAIR_ATTR *sizep, int*dirty, void*extraargs);
void toku_ftnode_pe_est_callback(void* ftnode_pv, void* disk_data, long* bytes_freed_estimate, enum partial_eviction_cost *cost, void* write_extraargs);
-int toku_ftnode_pe_callback (void *ftnode_pv, PAIR_ATTR old_attr, PAIR_ATTR* new_attr, void *extraargs);
+int toku_ftnode_pe_callback(void *ftnode_pv, PAIR_ATTR old_attr, void *extraargs,
+ void (*finalize)(PAIR_ATTR new_attr, void *extra), void *finalize_extra);
bool toku_ftnode_pf_req_callback(void* ftnode_pv, void* read_extraargs);
int toku_ftnode_pf_callback(void* ftnode_pv, void* UU(disk_data), void* read_extraargs, int fd, PAIR_ATTR* sizep);
int toku_ftnode_cleaner_callback( void *ftnode_pv, BLOCKNUM blocknum, uint32_t fullhash, void *extraargs);
@@ -787,6 +783,8 @@ struct ft_cursor {
int out_of_range_error;
int direction;
TOKUTXN ttxn;
+ FT_CHECK_INTERRUPT_CALLBACK interrupt_cb;
+ void *interrupt_cb_extra;
};
//
@@ -1029,7 +1027,7 @@ int toku_testsetup_insert_to_nonleaf (FT_HANDLE brt, BLOCKNUM, enum ft_msg_type,
void toku_pin_node_with_min_bfe(FTNODE* node, BLOCKNUM b, FT_HANDLE t);
// 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, TXNID oldest_referenced_xid, GC_INFO gc_info);
+void toku_ft_root_put_cmd(FT h, FT_MSG_S * cmd, txn_gc_info *gc_info);
void
toku_get_node_for_verify(
@@ -1067,6 +1065,10 @@ typedef enum {
LE_MAX_PROVISIONAL_XR,
LE_EXPANDED,
LE_MAX_MEMSIZE,
+ LE_APPLY_GC_BYTES_IN,
+ LE_APPLY_GC_BYTES_OUT,
+ LE_NORMAL_GC_BYTES_IN,
+ LE_NORMAL_GC_BYTES_OUT,
LE_STATUS_NUM_ROWS
} le_status_entry;
@@ -1101,6 +1103,9 @@ typedef enum {
FT_DISK_FLUSH_NONLEAF_BYTES_FOR_CHECKPOINT,// number of nonleaf nodes flushed to disk for checkpoint
FT_DISK_FLUSH_NONLEAF_UNCOMPRESSED_BYTES_FOR_CHECKPOINT,// number of nonleaf nodes flushed to disk for checkpoint
FT_DISK_FLUSH_NONLEAF_TOKUTIME_FOR_CHECKPOINT,// number of nonleaf nodes flushed to disk for checkpoint
+ FT_DISK_FLUSH_LEAF_COMPRESSION_RATIO, // effective compression ratio for leaf bytes flushed to disk
+ FT_DISK_FLUSH_NONLEAF_COMPRESSION_RATIO, // effective compression ratio for nonleaf bytes flushed to disk
+ FT_DISK_FLUSH_OVERALL_COMPRESSION_RATIO, // effective compression ratio for all bytes flushed to disk
FT_PARTIAL_EVICTIONS_NONLEAF, // number of nonleaf node partial evictions
FT_PARTIAL_EVICTIONS_NONLEAF_BYTES, // number of nonleaf node partial evictions
FT_PARTIAL_EVICTIONS_LEAF, // number of leaf node partial evictions
@@ -1196,8 +1201,7 @@ toku_ft_bn_apply_cmd_once (
const FT_MSG cmd,
uint32_t idx,
LEAFENTRY le,
- TXNID oldest_referenced_xid,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
uint64_t *workdonep,
STAT64INFO stats_to_update
);
@@ -1209,8 +1213,7 @@ toku_ft_bn_apply_cmd (
DESCRIPTOR desc,
BASEMENTNODE bn,
FT_MSG cmd,
- TXNID oldest_referenced_xid,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
);
@@ -1223,7 +1226,7 @@ toku_ft_leaf_apply_cmd (
FTNODE node,
int target_childnum,
FT_MSG cmd,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
);
@@ -1237,7 +1240,7 @@ toku_ft_node_put_cmd (
int target_childnum,
FT_MSG cmd,
bool is_fresh,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
size_t flow_deltas[],
STAT64INFO stats_to_update
);
diff --git a/storage/tokudb/ft-index/ft/ft-ops.cc b/storage/tokudb/ft-index/ft/ft-ops.cc
index 27ee6ec8000..f6735f0bb45 100644
--- a/storage/tokudb/ft-index/ft/ft-ops.cc
+++ b/storage/tokudb/ft-index/ft/ft-ops.cc
@@ -213,15 +213,18 @@ basement nodes, bulk fetch, and partial fetch:
#include "leafentry.h"
#include "xids.h"
#include "ft_msg.h"
+#include "ule.h"
#include <toku_race_tools.h>
#include <portability/toku_atomic.h>
+#include <util/context.h>
#include <util/mempool.h>
#include <util/status.h>
#include <util/rwlock.h>
#include <util/sort.h>
+#include <util/scoped_malloc.h>
#include <stdint.h>
@@ -336,6 +339,9 @@ status_init(void)
STATUS_INIT(FT_DISK_FLUSH_NONLEAF_BYTES_FOR_CHECKPOINT, NONLEAF_NODES_FLUSHED_TO_DISK_CHECKPOINT_BYTES, PARCOUNT, "nonleaf nodes flushed to disk (for checkpoint) (bytes)", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(FT_DISK_FLUSH_NONLEAF_UNCOMPRESSED_BYTES_FOR_CHECKPOINT, NONLEAF_NODES_FLUSHED_TO_DISK_CHECKPOINT_UNCOMPRESSED_BYTES, PARCOUNT, "nonleaf nodes flushed to disk (for checkpoint) (uncompressed bytes)", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(FT_DISK_FLUSH_NONLEAF_TOKUTIME_FOR_CHECKPOINT, NONLEAF_NODES_FLUSHED_TO_DISK_CHECKPOINT_SECONDS, TOKUTIME, "nonleaf nodes flushed to disk (for checkpoint) (seconds)", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
+ STATUS_INIT(FT_DISK_FLUSH_LEAF_COMPRESSION_RATIO, LEAF_NODE_COMPRESSION_RATIO, DOUBLE, "uncompressed / compressed bytes written (leaf)", TOKU_GLOBAL_STATUS|TOKU_ENGINE_STATUS);
+ STATUS_INIT(FT_DISK_FLUSH_NONLEAF_COMPRESSION_RATIO, NONLEAF_NODE_COMPRESSION_RATIO, DOUBLE, "uncompressed / compressed bytes written (nonleaf)", TOKU_GLOBAL_STATUS|TOKU_ENGINE_STATUS);
+ STATUS_INIT(FT_DISK_FLUSH_OVERALL_COMPRESSION_RATIO, OVERALL_NODE_COMPRESSION_RATIO, DOUBLE, "uncompressed / compressed bytes written (overall)", TOKU_GLOBAL_STATUS|TOKU_ENGINE_STATUS);
// CPU time statistics for [de]serialization and [de]compression.
STATUS_INIT(FT_LEAF_COMPRESS_TOKUTIME, LEAF_COMPRESSION_TO_MEMORY_SECONDS, TOKUTIME, "leaf compression to memory (seconds)", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
@@ -373,9 +379,35 @@ static void status_destroy(void) {
}
#undef STATUS_INIT
+#define STATUS_VAL(x) \
+ (ft_status.status[x].type == PARCOUNT ? \
+ read_partitioned_counter(ft_status.status[x].value.parcount) : \
+ ft_status.status[x].value.num)
+
void
toku_ft_get_status(FT_STATUS s) {
*s = ft_status;
+
+ // Calculate compression ratios for leaf and nonleaf nodes
+ const double compressed_leaf_bytes = STATUS_VAL(FT_DISK_FLUSH_LEAF_BYTES) +
+ STATUS_VAL(FT_DISK_FLUSH_LEAF_BYTES_FOR_CHECKPOINT);
+ const double uncompressed_leaf_bytes = STATUS_VAL(FT_DISK_FLUSH_LEAF_UNCOMPRESSED_BYTES) +
+ STATUS_VAL(FT_DISK_FLUSH_LEAF_UNCOMPRESSED_BYTES_FOR_CHECKPOINT);
+ const double compressed_nonleaf_bytes = STATUS_VAL(FT_DISK_FLUSH_NONLEAF_BYTES) +
+ STATUS_VAL(FT_DISK_FLUSH_NONLEAF_BYTES_FOR_CHECKPOINT);
+ const double uncompressed_nonleaf_bytes = STATUS_VAL(FT_DISK_FLUSH_NONLEAF_UNCOMPRESSED_BYTES) +
+ STATUS_VAL(FT_DISK_FLUSH_NONLEAF_UNCOMPRESSED_BYTES_FOR_CHECKPOINT);
+
+ if (compressed_leaf_bytes > 0) {
+ s->status[FT_DISK_FLUSH_LEAF_COMPRESSION_RATIO].value.dnum = uncompressed_leaf_bytes / compressed_leaf_bytes;
+ }
+ if (compressed_nonleaf_bytes > 0) {
+ s->status[FT_DISK_FLUSH_NONLEAF_COMPRESSION_RATIO].value.dnum = uncompressed_nonleaf_bytes / compressed_nonleaf_bytes;
+ }
+ if (compressed_leaf_bytes > 0 || compressed_nonleaf_bytes > 0) {
+ s->status[FT_DISK_FLUSH_OVERALL_COMPRESSION_RATIO].value.dnum =
+ (uncompressed_leaf_bytes + uncompressed_nonleaf_bytes) / (compressed_leaf_bytes + compressed_nonleaf_bytes);
+ }
}
#define STATUS_INC(x, d) \
@@ -428,21 +460,21 @@ get_leaf_reactivity (FTNODE node, uint32_t nodesize) {
}
enum reactivity
-get_nonleaf_reactivity (FTNODE node) {
+get_nonleaf_reactivity(FTNODE node, unsigned int fanout) {
paranoid_invariant(node->height>0);
int n_children = node->n_children;
- if (n_children > TREE_FANOUT) return RE_FISSIBLE;
- if (n_children*4 < TREE_FANOUT) return RE_FUSIBLE;
+ if (n_children > (int) fanout) return RE_FISSIBLE;
+ if (n_children*4 < (int) fanout) return RE_FUSIBLE;
return RE_STABLE;
}
enum reactivity
-get_node_reactivity (FTNODE node, uint32_t nodesize) {
+get_node_reactivity(FT ft, FTNODE node) {
toku_assert_entire_node_in_memory(node);
if (node->height==0)
- return get_leaf_reactivity(node, nodesize);
+ return get_leaf_reactivity(node, ft->h->nodesize);
else
- return get_nonleaf_reactivity(node);
+ return get_nonleaf_reactivity(node, ft->h->fanout);
}
unsigned int
@@ -867,7 +899,7 @@ void toku_ftnode_clone_callback(
*cloned_value_data = cloned_node;
}
-static void ft_leaf_run_gc(FTNODE node, FT ft);
+static void ft_leaf_run_gc(FT ft, FTNODE node);
void toku_ftnode_flush_callback(
CACHEFILE UU(cachefile),
@@ -892,7 +924,7 @@ void toku_ftnode_flush_callback(
if (write_me) {
toku_assert_entire_node_in_memory(ftnode);
if (height == 0) {
- ft_leaf_run_gc(ftnode, h);
+ ft_leaf_run_gc(h, ftnode);
}
if (height == 0 && !is_clone) {
ftnode_update_disk_stats(ftnode, h, for_checkpoint);
@@ -979,6 +1011,12 @@ int toku_ftnode_fetch_callback (CACHEFILE UU(cachefile), PAIR p, int fd, BLOCKNU
return r;
}
+static bool ft_compress_buffers_before_eviction = true;
+
+void toku_ft_set_compress_buffers_before_eviction(bool compress_buffers) {
+ ft_compress_buffers_before_eviction = compress_buffers;
+}
+
void toku_ftnode_pe_est_callback(
void* ftnode_pv,
void* disk_data,
@@ -1010,16 +1048,20 @@ void toku_ftnode_pe_est_callback(
// we compress this node and add it to
// bytes_to_free
- // first get an estimate for how much space will be taken
- // after compression, it is simply the size of compressed
- // data on disk plus the size of the struct that holds it
- FTNODE_DISK_DATA ndd = (FTNODE_DISK_DATA) disk_data;
- uint32_t compressed_data_size = BP_SIZE(ndd, i);
- compressed_data_size += sizeof(struct sub_block);
-
- // now get the space taken now
- uint32_t decompressed_data_size = get_avail_internal_node_partition_size(node,i);
- bytes_to_free += (decompressed_data_size - compressed_data_size);
+ if (ft_compress_buffers_before_eviction) {
+ // first get an estimate for how much space will be taken
+ // after compression, it is simply the size of compressed
+ // data on disk plus the size of the struct that holds it
+ FTNODE_DISK_DATA ndd = (FTNODE_DISK_DATA) disk_data;
+ uint32_t compressed_data_size = BP_SIZE(ndd, i);
+ compressed_data_size += sizeof(struct sub_block);
+
+ // now get the space taken now
+ uint32_t decompressed_data_size = get_avail_internal_node_partition_size(node,i);
+ bytes_to_free += (decompressed_data_size - compressed_data_size);
+ } else {
+ bytes_to_free += get_avail_internal_node_partition_size(node, i);
+ }
}
}
@@ -1028,7 +1070,9 @@ exit:
return;
}
-static void
+// replace the child buffer with a compressed version of itself.
+// @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
@@ -1039,10 +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 free the old partition and replace it with this
- destroy_nonleaf_childinfo(BNC(node,i));
+ // 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) {
@@ -1064,9 +1109,21 @@ BASEMENTNODE toku_detach_bn(FTNODE node, int childnum) {
}
// callback for partially evicting a node
-int toku_ftnode_pe_callback (void *ftnode_pv, PAIR_ATTR UU(old_attr), PAIR_ATTR* new_attr, void* extraargs) {
- FTNODE node = (FTNODE)ftnode_pv;
- FT ft = (FT) extraargs;
+int toku_ftnode_pe_callback(void *ftnode_pv, PAIR_ATTR old_attr, void *write_extraargs,
+ void (*finalize)(PAIR_ATTR new_attr, void *extra), void *finalize_extra) {
+ FTNODE node = (FTNODE) ftnode_pv;
+ FT ft = (FT) write_extraargs;
+ int num_partial_evictions = 0;
+
+ // Hold things we intend to destroy here.
+ // They will be taken care of after finalize().
+ int num_basements_to_destroy = 0;
+ int num_buffers_to_destroy = 0;
+ int num_pointers_to_free = 0;
+ BASEMENTNODE basements_to_destroy[node->n_children];
+ NONLEAF_CHILDINFO buffers_to_destroy[node->n_children];
+ void *pointers_to_free[node->n_children * 2];
+
// Don't partially evict dirty nodes
if (node->dirty) {
goto exit;
@@ -1083,11 +1140,23 @@ int toku_ftnode_pe_callback (void *ftnode_pv, PAIR_ATTR UU(old_attr), PAIR_ATTR*
for (int i = 0; i < node->n_children; i++) {
if (BP_STATE(node,i) == PT_AVAIL) {
if (BP_SHOULD_EVICT(node,i)) {
- long size_before = ftnode_memory_size(node);
- compress_internal_node_partition(node, i, ft->h->compression_method);
- long delta = size_before - ftnode_memory_size(node);
- STATUS_INC(FT_PARTIAL_EVICTIONS_NONLEAF, 1);
- STATUS_INC(FT_PARTIAL_EVICTIONS_NONLEAF_BYTES, delta);
+ NONLEAF_CHILDINFO bnc;
+ if (ft_compress_buffers_before_eviction) {
+ // When partially evicting, always compress with quicklz
+ bnc = compress_internal_node_partition(
+ node,
+ i,
+ 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;
+ }
+ buffers_to_destroy[num_buffers_to_destroy++] = bnc;
+ num_partial_evictions++;
}
else {
BP_SWEEP_CLOCK(node,i);
@@ -1107,23 +1176,21 @@ int toku_ftnode_pe_callback (void *ftnode_pv, PAIR_ATTR UU(old_attr), PAIR_ATTR*
for (int i = 0; i < node->n_children; i++) {
// Get rid of compressed stuff no matter what.
if (BP_STATE(node,i) == PT_COMPRESSED) {
- long size_before = ftnode_memory_size(node);
SUB_BLOCK sb = BSB(node, i);
- toku_free(sb->compressed_ptr);
- toku_free(sb);
+ pointers_to_free[num_pointers_to_free++] = sb->compressed_ptr;
+ pointers_to_free[num_pointers_to_free++] = sb;
set_BNULL(node, i);
BP_STATE(node,i) = PT_ON_DISK;
- long delta = size_before - ftnode_memory_size(node);
- STATUS_INC(FT_PARTIAL_EVICTIONS_LEAF, 1);
- STATUS_INC(FT_PARTIAL_EVICTIONS_LEAF_BYTES, delta);
+ num_partial_evictions++;
}
else if (BP_STATE(node,i) == PT_AVAIL) {
if (BP_SHOULD_EVICT(node,i)) {
- long size_before = ftnode_memory_size(node);
- toku_evict_bn_from_memory(node, i, ft);
- long delta = size_before - ftnode_memory_size(node);
- STATUS_INC(FT_PARTIAL_EVICTIONS_LEAF, 1);
- STATUS_INC(FT_PARTIAL_EVICTIONS_LEAF_BYTES, delta);
+ BASEMENTNODE bn = BLB(node, i);
+ basements_to_destroy[num_basements_to_destroy++] = bn;
+ toku_ft_decrease_stats(&ft->in_memory_stats, bn->stat64_delta);
+ set_BNULL(node, i);
+ BP_STATE(node, i) = PT_ON_DISK;
+ num_partial_evictions++;
}
else {
BP_SWEEP_CLOCK(node,i);
@@ -1139,7 +1206,34 @@ int toku_ftnode_pe_callback (void *ftnode_pv, PAIR_ATTR UU(old_attr), PAIR_ATTR*
}
exit:
- *new_attr = make_ftnode_pair_attr(node);
+ // call the finalize callback with a new pair attr
+ int height = node->height;
+ PAIR_ATTR new_attr = make_ftnode_pair_attr(node);
+ finalize(new_attr, finalize_extra);
+
+ // destroy everything now that we've called finalize(),
+ // and, by contract, and it's safe to do expensive work.
+ for (int i = 0; i < num_basements_to_destroy; i++) {
+ destroy_basement_node(basements_to_destroy[i]);
+ }
+ for (int i = 0; i < num_buffers_to_destroy; i++) {
+ destroy_nonleaf_childinfo(buffers_to_destroy[i]);
+ }
+ for (int i = 0; i < num_pointers_to_free; i++) {
+ toku_free(pointers_to_free[i]);
+ }
+ // stats
+ if (num_partial_evictions > 0) {
+ if (height == 0) {
+ long delta = old_attr.leaf_size - new_attr.leaf_size;
+ STATUS_INC(FT_PARTIAL_EVICTIONS_LEAF, num_partial_evictions);
+ STATUS_INC(FT_PARTIAL_EVICTIONS_LEAF_BYTES, delta);
+ } else {
+ long delta = old_attr.nonleaf_size - new_attr.nonleaf_size;
+ STATUS_INC(FT_PARTIAL_EVICTIONS_NONLEAF, num_partial_evictions);
+ STATUS_INC(FT_PARTIAL_EVICTIONS_NONLEAF_BYTES, delta);
+ }
+ }
return 0;
}
@@ -1627,8 +1721,7 @@ toku_ft_bn_apply_cmd_once (
const FT_MSG cmd,
uint32_t idx,
LEAFENTRY le,
- TXNID oldest_referenced_xid,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
)
@@ -1654,7 +1747,6 @@ toku_ft_bn_apply_cmd_once (
le,
&bn->data_buffer,
idx,
- oldest_referenced_xid,
gc_info,
&new_le,
&numbytes_delta
@@ -1703,8 +1795,7 @@ struct setval_extra_s {
const DBT *key;
uint32_t idx;
LEAFENTRY le;
- TXNID oldest_referenced_xid;
- GC_INFO gc_info;
+ txn_gc_info *gc_info;
uint64_t * workdone; // set by toku_ft_bn_apply_cmd_once()
STAT64INFO stats_to_update;
};
@@ -1737,7 +1828,7 @@ static void setval_fun (const DBT *new_val, void *svextra_v) {
}
toku_ft_bn_apply_cmd_once(svextra->bn, &msg,
svextra->idx, svextra->le,
- svextra->oldest_referenced_xid, svextra->gc_info,
+ svextra->gc_info,
svextra->workdone, svextra->stats_to_update);
svextra->setval_r = 0;
}
@@ -1751,8 +1842,7 @@ static int do_update(ft_update_func update_fun, DESCRIPTOR desc, BASEMENTNODE bn
LEAFENTRY le,
void* keydata,
uint32_t keylen,
- TXNID oldest_referenced_xid,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
uint64_t * workdone,
STAT64INFO stats_to_update) {
LEAFENTRY le_for_update;
@@ -1797,7 +1887,8 @@ 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, cmd->msn, cmd->xids,
- keyp, idx, le_for_update, oldest_referenced_xid, gc_info, workdone, stats_to_update};
+ keyp, idx, le_for_update, gc_info,
+ workdone, stats_to_update};
// call handlerton's brt->update_fun(), which passes setval_extra to setval_fun()
FAKE_DB(db, desc);
int r = update_fun(
@@ -1820,8 +1911,7 @@ toku_ft_bn_apply_cmd (
DESCRIPTOR desc,
BASEMENTNODE bn,
FT_MSG cmd,
- TXNID oldest_referenced_xid_known,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
)
@@ -1868,7 +1958,7 @@ toku_ft_bn_apply_cmd (
} else {
assert_zero(r);
}
- toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, oldest_referenced_xid_known, 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
@@ -1900,7 +1990,7 @@ toku_ft_bn_apply_cmd (
);
if (r == DB_NOTFOUND) break;
assert_zero(r);
- toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, oldest_referenced_xid_known, gc_info, workdone, stats_to_update);
+ toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, gc_info, workdone, stats_to_update);
break;
}
@@ -1922,7 +2012,7 @@ toku_ft_bn_apply_cmd (
cmd->u.id.key = &curr_keydbt;
int deleted = 0;
if (!le_is_clean(storeddata)) { //If already clean, nothing to do.
- toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, oldest_referenced_xid_known, gc_info, workdone, stats_to_update);
+ 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);
@@ -1954,7 +2044,7 @@ toku_ft_bn_apply_cmd (
cmd->u.id.key = &curr_keydbt;
int deleted = 0;
if (le_has_xids(storeddata, cmd->xids)) {
- toku_ft_bn_apply_cmd_once(bn, cmd, idx, storeddata, oldest_referenced_xid_known, gc_info, workdone, stats_to_update);
+ 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);
@@ -1986,9 +2076,9 @@ toku_ft_bn_apply_cmd (
key = cmd->u.id.key->data;
keylen = cmd->u.id.key->size;
}
- r = do_update(update_fun, desc, bn, cmd, idx, NULL, NULL, 0, oldest_referenced_xid_known, 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, cmd, idx, storeddata, key, keylen, oldest_referenced_xid_known, 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;
}
@@ -2011,7 +2101,7 @@ toku_ft_bn_apply_cmd (
// This is broken below. Have a compilation error checked
// in as a reminder
- r = do_update(update_fun, desc, bn, cmd, idx, storeddata, curr_key, curr_keylen, oldest_referenced_xid_known, 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.omt_size()) {
@@ -2249,10 +2339,7 @@ ft_basement_node_gc_once(BASEMENTNODE bn,
void* keyp,
uint32_t keylen,
LEAFENTRY leaf_entry,
- const xid_omt_t &snapshot_xids,
- const rx_omt_t &referenced_xids,
- const xid_omt_t &live_root_txns,
- TXNID oldest_referenced_xid_known,
+ txn_gc_info *gc_info,
STAT64INFO_S * delta)
{
paranoid_invariant(leaf_entry);
@@ -2263,7 +2350,7 @@ ft_basement_node_gc_once(BASEMENTNODE bn,
}
// Don't run garbage collection if this leafentry decides it's not worth it.
- if (!toku_le_worth_running_garbage_collection(leaf_entry, oldest_referenced_xid_known)) {
+ if (!toku_le_worth_running_garbage_collection(leaf_entry, gc_info)) {
goto exit;
}
@@ -2285,11 +2372,8 @@ ft_basement_node_gc_once(BASEMENTNODE bn,
index,
keyp,
keylen,
+ gc_info,
&new_leaf_entry,
- snapshot_xids,
- referenced_xids,
- live_root_txns,
- oldest_referenced_xid_known,
&numbytes_delta);
numrows_delta = 0;
@@ -2318,10 +2402,7 @@ exit:
// Garbage collect all leaf entries for a given basement node.
static void
basement_node_gc_all_les(BASEMENTNODE bn,
- const xid_omt_t &snapshot_xids,
- const rx_omt_t &referenced_xids,
- const xid_omt_t &live_root_txns,
- TXNID oldest_referenced_xid_known,
+ txn_gc_info *gc_info,
STAT64INFO_S * delta)
{
int r = 0;
@@ -2331,7 +2412,7 @@ basement_node_gc_all_les(BASEMENTNODE bn,
void* keyp = NULL;
uint32_t keylen = 0;
LEAFENTRY leaf_entry;
- bn->data_buffer.fetch_klpair(index, &leaf_entry, &keylen, &keyp);
+ r = bn->data_buffer.fetch_klpair(index, &leaf_entry, &keylen, &keyp);
assert_zero(r);
ft_basement_node_gc_once(
bn,
@@ -2339,10 +2420,7 @@ basement_node_gc_all_les(BASEMENTNODE bn,
keyp,
keylen,
leaf_entry,
- snapshot_xids,
- referenced_xids,
- live_root_txns,
- oldest_referenced_xid_known,
+ gc_info,
delta
);
// Check if the leaf entry was deleted or not.
@@ -2354,12 +2432,7 @@ basement_node_gc_all_les(BASEMENTNODE bn,
// Garbage collect all leaf entires in all basement nodes.
static void
-ft_leaf_gc_all_les(FTNODE node,
- FT ft,
- const xid_omt_t &snapshot_xids,
- const rx_omt_t &referenced_xids,
- const xid_omt_t &live_root_txns,
- TXNID oldest_referenced_xid_known)
+ft_leaf_gc_all_les(FT ft, FTNODE node, txn_gc_info *gc_info)
{
toku_assert_entire_node_in_memory(node);
paranoid_invariant_zero(node->height);
@@ -2370,38 +2443,40 @@ ft_leaf_gc_all_les(FTNODE node,
STAT64INFO_S delta;
delta.numrows = 0;
delta.numbytes = 0;
- basement_node_gc_all_les(bn, snapshot_xids, referenced_xids, live_root_txns, oldest_referenced_xid_known, &delta);
+ basement_node_gc_all_les(bn, gc_info, &delta);
toku_ft_update_stats(&ft->in_memory_stats, delta);
}
}
static void
-ft_leaf_run_gc(FTNODE node, FT ft) {
+ft_leaf_run_gc(FT ft, FTNODE node) {
TOKULOGGER logger = toku_cachefile_logger(ft->cf);
if (logger) {
- xid_omt_t snapshot_txnids;
- rx_omt_t referenced_xids;
- xid_omt_t live_root_txns;
- toku_txn_manager_clone_state_for_gc(
- logger->txn_manager,
- &snapshot_txnids,
- &referenced_xids,
- &live_root_txns
- );
+ TXN_MANAGER txn_manager = toku_logger_get_txn_manager(logger);
+ txn_manager_state txn_state_for_gc(txn_manager);
+ txn_state_for_gc.init();
+ TXNID oldest_referenced_xid_for_simple_gc = toku_txn_manager_get_oldest_referenced_xid_estimate(txn_manager);
- // Perform garbage collection. Provide a full snapshot of the transaction
- // system plus the oldest known referenced xid that could have had messages
- // applied to this leaf.
+ // Perform full garbage collection.
//
- // Using the oldest xid in either the referenced_xids or live_root_txns
- // snapshots is not sufficient, because there could be something older that is neither
- // live nor referenced, but instead aborted somewhere above us as a message in the tree.
- ft_leaf_gc_all_les(node, ft, snapshot_txnids, referenced_xids, live_root_txns, node->oldest_referenced_xid_known);
-
- // Free the OMT's we used for garbage collecting.
- snapshot_txnids.destroy();
- referenced_xids.destroy();
- live_root_txns.destroy();
+ // - txn_state_for_gc
+ // a fresh snapshot of the transaction system.
+ // - oldest_referenced_xid_for_simple_gc
+ // the oldest xid in any live list as of right now - suitible for simple gc
+ // - node->oldest_referenced_xid_known
+ // the last known oldest referenced xid for this node and any unapplied messages.
+ // it is a lower bound on the actual oldest referenced xid - but becasue there
+ // may be abort messages above us, we need to be careful to only use this value
+ // for implicit promotion (as opposed to the oldest referenced xid for simple gc)
+ //
+ // The node has its own oldest referenced xid because it must be careful not to implicitly promote
+ // provisional entries for transactions that are no longer live, but may have abort messages
+ // somewhere above us in the tree.
+ txn_gc_info gc_info(&txn_state_for_gc,
+ oldest_referenced_xid_for_simple_gc,
+ node->oldest_referenced_xid_known,
+ true);
+ ft_leaf_gc_all_les(ft, node, &gc_info);
}
}
@@ -2409,12 +2484,27 @@ void toku_bnc_flush_to_child(
FT ft,
NONLEAF_CHILDINFO bnc,
FTNODE child,
- TXNID oldest_referenced_xid_known
+ TXNID parent_oldest_referenced_xid_known
)
{
paranoid_invariant(bnc);
STAT64INFO_S stats_delta = {0,0};
size_t remaining_memsize = toku_fifo_buffer_size_in_use(bnc->buffer);
+
+ TOKULOGGER logger = toku_cachefile_logger(ft->cf);
+ TXN_MANAGER txn_manager = logger != nullptr ? toku_logger_get_txn_manager(logger) : nullptr;
+ TXNID oldest_referenced_xid_for_simple_gc = TXNID_NONE;
+
+ txn_manager_state txn_state_for_gc(txn_manager);
+ bool do_garbage_collection = child->height == 0 && txn_manager != nullptr;
+ if (do_garbage_collection) {
+ txn_state_for_gc.init();
+ oldest_referenced_xid_for_simple_gc = toku_txn_manager_get_oldest_referenced_xid_estimate(txn_manager);
+ }
+ txn_gc_info gc_info(&txn_state_for_gc,
+ oldest_referenced_xid_for_simple_gc,
+ child->oldest_referenced_xid_known,
+ true);
FIFO_ITERATE(
bnc->buffer, key, keylen, val, vallen, type, msn, xids, is_fresh,
({
@@ -2439,20 +2529,19 @@ void toku_bnc_flush_to_child(
-1,
&ftcmd,
is_fresh,
- make_gc_info(true), // mvcc_needed
+ &gc_info,
flow_deltas,
&stats_delta
);
remaining_memsize -= FIFO_CURRENT_ENTRY_MEMSIZE;
}));
- child->oldest_referenced_xid_known = oldest_referenced_xid_known;
+ child->oldest_referenced_xid_known = parent_oldest_referenced_xid_known;
invariant(remaining_memsize == 0);
if (stats_delta.numbytes || stats_delta.numrows) {
toku_ft_update_stats(&ft->in_memory_stats, stats_delta);
}
- if (child->height == 0) {
- ft_leaf_run_gc(child, ft);
+ if (do_garbage_collection) {
size_t buffsize = toku_fifo_buffer_size_in_use(bnc->buffer);
STATUS_INC(FT_MSG_BYTES_OUT, buffsize);
// may be misleading if there's a broadcast message in there
@@ -2475,7 +2564,7 @@ toku_ft_node_put_cmd (
int target_childnum,
FT_MSG cmd,
bool is_fresh,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
size_t flow_deltas[],
STAT64INFO stats_to_update
)
@@ -2513,7 +2602,7 @@ void toku_ft_leaf_apply_cmd(
FTNODE node,
int target_childnum, // which child to inject to, or -1 if unknown
FT_MSG cmd,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
uint64_t *workdone,
STAT64INFO stats_to_update
)
@@ -2546,10 +2635,6 @@ void toku_ft_leaf_apply_cmd(
node->max_msn_applied_to_node_on_disk = cmd_msn;
}
- // Pass the oldest possible live xid value to each basementnode
- // when we apply messages to them.
- TXNID oldest_referenced_xid_known = node->oldest_referenced_xid_known;
-
if (ft_msg_applies_once(cmd)) {
unsigned int childnum = (target_childnum >= 0
? target_childnum
@@ -2562,7 +2647,6 @@ void toku_ft_leaf_apply_cmd(
desc,
bn,
cmd,
- oldest_referenced_xid_known,
gc_info,
workdone,
stats_to_update);
@@ -2575,14 +2659,13 @@ void toku_ft_leaf_apply_cmd(
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),
- cmd,
- oldest_referenced_xid_known,
- gc_info,
- workdone,
- stats_to_update);
+ update_fun,
+ desc,
+ BLB(node, childnum),
+ cmd,
+ gc_info,
+ workdone,
+ stats_to_update);
} else {
STATUS_INC(FT_MSN_DISCARDS, 1);
}
@@ -2600,8 +2683,7 @@ static void inject_message_in_locked_node(
int childnum,
FT_MSG_S *cmd,
size_t flow_deltas[],
- TXNID oldest_referenced_xid,
- GC_INFO gc_info
+ txn_gc_info *gc_info
)
{
// No guarantee that we're the writer, but oh well.
@@ -2611,11 +2693,14 @@ static void inject_message_in_locked_node(
invariant(toku_ctpair_is_write_locked(node->ct_pair));
toku_assert_entire_node_in_memory(node);
- // Update the oldest known referenced xid for this node if it is younger
- // than the one currently known. Otherwise, it's better to keep the heurstic
- // we have and ignore this one.
- if (oldest_referenced_xid >= node->oldest_referenced_xid_known) {
- node->oldest_referenced_xid_known = oldest_referenced_xid;
+ // Take the newer of the two oldest referenced xid values from the node and gc_info.
+ // The gc_info usually has a newer value, because we got it at the top of this call
+ // stack from the txn manager. But sometimes the node has a newer value, if some
+ // other thread sees a newer value and writes to this node before we got the lock.
+ if (gc_info->oldest_referenced_xid_for_implicit_promotion > node->oldest_referenced_xid_known) {
+ node->oldest_referenced_xid_known = gc_info->oldest_referenced_xid_for_implicit_promotion;
+ } else if (gc_info->oldest_referenced_xid_for_implicit_promotion < node->oldest_referenced_xid_known) {
+ gc_info->oldest_referenced_xid_for_implicit_promotion = node->oldest_referenced_xid_known;
}
// Get the MSN from the header. Now that we have a write lock on the
@@ -2689,7 +2774,7 @@ static bool process_maybe_reactive_child(FT ft, FTNODE parent, FTNODE child, int
// true if relocking is needed
// false otherwise
{
- enum reactivity re = get_node_reactivity(child, ft->h->nodesize);
+ enum reactivity re = get_node_reactivity(ft, child);
enum reactivity newre;
BLOCKNUM child_blocknum;
uint32_t child_fullhash;
@@ -2723,7 +2808,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_off_client_thread_batched(ft, child_blocknum, child_fullhash, &bfe, PL_WRITE_CHEAP, 1, &newparent, &newchild);
- newre = get_node_reactivity(newchild, ft->h->nodesize);
+ newre = get_node_reactivity(ft, newchild);
if (newre == RE_FISSIBLE) {
enum split_mode split_mode;
if (newparent->height == 1 && (loc & LEFT_EXTREME) && childnum == 0) {
@@ -2769,7 +2854,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_off_client_thread_batched(ft, child_blocknum, child_fullhash, &bfe, PL_READ, 1, &newparent, &newchild);
- newre = get_node_reactivity(newchild, ft->h->nodesize);
+ newre = get_node_reactivity(ft, newchild);
if (newre == RE_FUSIBLE && newparent->n_children >= 2) {
toku_unpin_ftnode_read_only(ft, newchild);
toku_ft_merge_child(ft, newparent, childnum);
@@ -2792,11 +2877,12 @@ 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 *cmd, size_t flow_deltas[], TXNID oldest_referenced_xid, 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 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);
@@ -2804,7 +2890,7 @@ static void inject_message_at_this_blocknum(FT ft, CACHEKEY cachekey, uint32_t f
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, cmd, flow_deltas, oldest_referenced_xid, gc_info);
+ inject_message_in_locked_node(ft, node, -1, cmd, flow_deltas, gc_info);
}
__attribute__((const))
@@ -2823,8 +2909,7 @@ static void push_something_in_subtree(
int target_childnum,
FT_MSG_S *cmd,
size_t flow_deltas[],
- TXNID oldest_referenced_xid,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
int depth,
seqinsert_loc loc,
bool just_did_split_or_merge
@@ -2865,7 +2950,7 @@ static void push_something_in_subtree(
default:
STATUS_INC(FT_PRO_NUM_INJECT_DEPTH_GT3, 1); break;
}
- inject_message_in_locked_node(ft, subtree_root, target_childnum, cmd, flow_deltas, oldest_referenced_xid, gc_info);
+ inject_message_in_locked_node(ft, subtree_root, target_childnum, cmd, flow_deltas, gc_info);
} else {
int r;
int childnum;
@@ -2921,7 +3006,15 @@ static void push_something_in_subtree(
// node locked.
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, ft);
- toku_pin_ftnode_off_client_thread_batched(ft, child_blocknum, child_fullhash, &bfe, lock_type, 0, nullptr, &child);
+ 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_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_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);
if (r != 0) {
@@ -2954,13 +3047,13 @@ static void push_something_in_subtree(
struct ftnode_fetch_extra bfe;
fill_bfe_for_full_read(&bfe, ft); // should be fully in memory, we just split it
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, oldest_referenced_xid, gc_info, depth, loc, true);
+ 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, cmd, flow_deltas, oldest_referenced_xid, 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.
@@ -2996,7 +3089,7 @@ 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, cmd, flow_deltas, oldest_referenced_xid, gc_info);
+ inject_message_at_this_blocknum(ft, subtree_root_blocknum, subtree_root_fullhash, cmd, flow_deltas, gc_info);
}
}
}
@@ -3004,8 +3097,7 @@ static void push_something_in_subtree(
void toku_ft_root_put_cmd(
FT ft,
FT_MSG_S *cmd,
- TXNID oldest_referenced_xid,
- GC_INFO gc_info
+ txn_gc_info *gc_info
)
// Effect:
// - assign msn to cmd and update msn in the header
@@ -3027,6 +3119,8 @@ void toku_ft_root_put_cmd(
// in any checkpoint that contains this put's logentry.
// Holding the mo lock throughout this function ensures that fact.
{
+ toku::context promo_ctx(CTX_PROMO);
+
// blackhole fractal trees drop all messages, so do nothing.
if (ft->blackhole) {
return;
@@ -3059,7 +3153,7 @@ void toku_ft_root_put_cmd(
// injection thread to change lock type back and forth, when only one
// of them needs to in order to handle the split. That's not great,
// but root splits are incredibly rare.
- enum reactivity re = get_node_reactivity(node, ft->h->nodesize);
+ enum reactivity re = get_node_reactivity(ft, node);
switch (re) {
case RE_STABLE:
case RE_FUSIBLE: // cannot merge anything at the root
@@ -3106,22 +3200,22 @@ void toku_ft_root_put_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, cmd, flow_deltas, oldest_referenced_xid, 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, cmd, flow_deltas, oldest_referenced_xid, 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, 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, cmd, flow_deltas, oldest_referenced_xid, 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, cmd, flow_deltas, oldest_referenced_xid, gc_info);
+ inject_message_at_this_blocknum(ft, root_key, fullhash, cmd, flow_deltas, gc_info);
}
}
}
@@ -3164,8 +3258,8 @@ void toku_ft_hot_index_recovery(TOKUTXN txn, FILENUMS filenums, int do_fsync, in
}
// Effect: Optimize the ft.
-void toku_ft_optimize (FT_HANDLE brt) {
- TOKULOGGER logger = toku_cachefile_logger(brt->ft->cf);
+void toku_ft_optimize (FT_HANDLE ft_h) {
+ TOKULOGGER logger = toku_cachefile_logger(ft_h->ft->cf);
if (logger) {
TXNID oldest = toku_txn_manager_get_oldest_living_xid(logger->txn_manager);
@@ -3184,7 +3278,17 @@ void toku_ft_optimize (FT_HANDLE brt) {
toku_init_dbt(&key);
toku_init_dbt(&val);
FT_MSG_S ftcmd = { FT_OPTIMIZE, ZERO_MSN, message_xids, .u = { .id = {&key,&val} } };
- toku_ft_root_put_cmd(brt->ft, &ftcmd, TXNID_NONE, make_gc_info(true));
+
+ 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);
+ toku_ft_root_put_cmd(ft_h->ft, &ftcmd, &gc_info);
xids_destroy(&message_xids);
}
}
@@ -3232,6 +3336,16 @@ toku_ft_log_put_multiple (TOKUTXN txn, FT_HANDLE src_ft, FT_HANDLE *brts, uint32
}
}
+TXN_MANAGER toku_ft_get_txn_manager(FT_HANDLE ft_h) {
+ TOKULOGGER logger = toku_cachefile_logger(ft_h->ft->cf);
+ return logger != nullptr ? toku_logger_get_txn_manager(logger) : nullptr;
+}
+
+TXNID toku_ft_get_oldest_referenced_xid_estimate(FT_HANDLE ft_h) {
+ TXN_MANAGER txn_manager = toku_ft_get_txn_manager(ft_h);
+ return txn_manager != nullptr ? toku_txn_manager_get_oldest_referenced_xid_estimate(txn_manager) : TXNID_NONE;
+}
+
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
@@ -3258,19 +3372,35 @@ void toku_ft_maybe_insert (FT_HANDLE ft_h, DBT *key, DBT *val, TOKUTXN txn, bool
if (oplsn_valid && oplsn.lsn <= (treelsn = toku_ft_checkpoint_lsn(ft_h->ft)).lsn) {
// do nothing
} else {
- TXNID oldest_referenced_xid = (txn) ? txn->oldest_referenced_xid : TXNID_NONE;
- toku_ft_send_insert(ft_h, key, val, message_xids, type, oldest_referenced_xid, make_gc_info(txn ? !txn->for_recovery : false));
+ 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,
+ txn != nullptr ? !txn->for_recovery : false);
+ toku_ft_send_insert(ft_h, key, val, message_xids, type, &gc_info);
}
}
static void
-ft_send_update_msg(FT_HANDLE brt, FT_MSG_S *msg, TOKUTXN txn) {
+ft_send_update_msg(FT_HANDLE ft_h, FT_MSG_S *msg, TOKUTXN txn) {
msg->xids = (txn
? toku_txn_get_xids(txn)
: xids_get_root_xids());
- TXNID oldest_referenced_xid = (txn) ? txn->oldest_referenced_xid : TXNID_NONE;
- toku_ft_root_put_cmd(brt->ft, msg, oldest_referenced_xid, make_gc_info(txn ? !txn->for_recovery : false));
+ 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,
+ txn != nullptr ? !txn->for_recovery : false);
+ 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,
@@ -3339,15 +3469,15 @@ void toku_ft_maybe_update_broadcast(FT_HANDLE ft_h, const DBT *update_function_e
}
}
-void toku_ft_send_insert(FT_HANDLE brt, DBT *key, DBT *val, XIDS xids, enum ft_msg_type type, TXNID oldest_referenced_xid, 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) {
FT_MSG_S ftcmd = { type, ZERO_MSN, xids, .u = { .id = { key, val } } };
- toku_ft_root_put_cmd(brt->ft, &ftcmd, oldest_referenced_xid, gc_info);
+ toku_ft_root_put_cmd(brt->ft, &ftcmd, gc_info);
}
-void toku_ft_send_commit_any(FT_HANDLE brt, DBT *key, XIDS xids, TXNID oldest_referenced_xid, 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 ftcmd = { FT_COMMIT_ANY, ZERO_MSN, xids, .u = { .id = { key, toku_init_dbt(&val) } } };
- toku_ft_root_put_cmd(brt->ft, &ftcmd, oldest_referenced_xid, gc_info);
+ toku_ft_root_put_cmd(brt->ft, &ftcmd, gc_info);
}
void toku_ft_delete(FT_HANDLE brt, DBT *key, TOKUTXN txn) {
@@ -3403,15 +3533,23 @@ void toku_ft_maybe_delete(FT_HANDLE ft_h, DBT *key, TOKUTXN txn, bool oplsn_vali
if (oplsn_valid && oplsn.lsn <= (treelsn = toku_ft_checkpoint_lsn(ft_h->ft)).lsn) {
// do nothing
} else {
- TXNID oldest_referenced_xid = (txn) ? txn->oldest_referenced_xid : TXNID_NONE;
- toku_ft_send_delete(ft_h, key, message_xids, oldest_referenced_xid, make_gc_info(txn ? !txn->for_recovery : false));
+ 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,
+ txn != nullptr ? !txn->for_recovery : false);
+ toku_ft_send_delete(ft_h, key, message_xids, &gc_info);
}
}
-void toku_ft_send_delete(FT_HANDLE brt, DBT *key, XIDS xids, TXNID oldest_referenced_xid, 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 ftcmd = { FT_DELETE_ANY, ZERO_MSN, xids, .u = { .id = { key, &val } } };
- toku_ft_root_put_cmd(brt->ft, &ftcmd, oldest_referenced_xid, gc_info);
+ toku_ft_root_put_cmd(brt->ft, &ftcmd, gc_info);
}
/* ******************** open,close and create ********************** */
@@ -3429,6 +3567,7 @@ int toku_open_ft_handle (const char *fname, int is_create, FT_HANDLE *ft_handle_
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(brt, fname, is_create, only_create, cachetable, txn);
@@ -3516,6 +3655,27 @@ toku_ft_handle_get_compression_method(FT_HANDLE t, enum toku_compression_method
}
}
+void
+toku_ft_handle_set_fanout(FT_HANDLE ft_handle, unsigned int fanout)
+{
+ if (ft_handle->ft) {
+ toku_ft_set_fanout(ft_handle->ft, fanout);
+ }
+ else {
+ ft_handle->options.fanout = fanout;
+ }
+}
+
+void
+toku_ft_handle_get_fanout(FT_HANDLE ft_handle, unsigned int *fanout)
+{
+ if (ft_handle->ft) {
+ toku_ft_get_fanout(ft_handle->ft, fanout);
+ }
+ else {
+ *fanout = ft_handle->options.fanout;
+ }
+}
static int
verify_builtin_comparisons_consistent(FT_HANDLE t, uint32_t flags) {
if ((flags & TOKU_DB_KEYCMP_BUILTIN) && (t->options.compare_fun != toku_builtin_compare_fun))
@@ -3582,6 +3742,7 @@ toku_ft_handle_inherit_options(FT_HANDLE t, FT ft) {
.nodesize = ft->h->nodesize,
.basementnodesize = ft->h->basementnodesize,
.compression_method = ft->h->compression_method,
+ .fanout = ft->h->fanout,
.flags = ft->h->flags,
.compare_fun = ft->compare_fun,
.update_fun = ft->update_fun
@@ -3937,6 +4098,7 @@ void toku_ft_handle_create(FT_HANDLE *ft_handle_ptr) {
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;
@@ -4039,6 +4201,12 @@ void toku_ft_cursor_remove_restriction(FT_CURSOR ftcursor) {
ftcursor->direction = 0;
}
+void toku_ft_cursor_set_check_interrupt_cb(FT_CURSOR ftcursor, FT_CHECK_INTERRUPT_CALLBACK cb, void *extra) {
+ ftcursor->interrupt_cb = cb;
+ ftcursor->interrupt_cb_extra = extra;
+}
+
+
void
toku_ft_cursor_set_temporary(FT_CURSOR ftcursor) {
ftcursor->is_temporary = true;
@@ -4193,7 +4361,7 @@ int fifo_offset_msn_cmp(FIFO &fifo, const int32_t &ao, const int32_t &bo)
* basement node.
*/
static void
-do_bn_apply_cmd(FT_HANDLE t, BASEMENTNODE bn, struct fifo_entry *entry, TXNID oldest_referenced_xid, 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
@@ -4218,8 +4386,7 @@ do_bn_apply_cmd(FT_HANDLE t, BASEMENTNODE bn, struct fifo_entry *entry, TXNID ol
&t->ft->cmp_descriptor,
bn,
&ftcmd,
- oldest_referenced_xid,
- make_gc_info(true), //mvcc is needed
+ gc_info,
workdone,
stats_to_update
);
@@ -4237,7 +4404,7 @@ struct iterate_do_bn_apply_cmd_extra {
FT_HANDLE t;
BASEMENTNODE bn;
NONLEAF_CHILDINFO bnc;
- TXNID oldest_referenced_xid;
+ txn_gc_info *gc_info;
uint64_t *workdone;
STAT64INFO stats_to_update;
};
@@ -4246,7 +4413,7 @@ int iterate_do_bn_apply_cmd(const int32_t &offset, const uint32_t UU(idx), struc
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_cmd(e->t, e->bn, entry, e->oldest_referenced_xid, 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;
}
@@ -4368,7 +4535,7 @@ bnc_apply_messages_to_basement_node(
FTNODE ancestor, // the ancestor node where we can find messages to apply
int childnum, // which child buffer of ancestor contains messages we want
struct pivot_bounds const * const bounds, // contains pivot key bounds of this basement node
- TXNID oldest_referenced_xid, // may be younger than what's in ancestor, we should grab the value from the highest node we have
+ txn_gc_info *gc_info,
bool* msgs_applied
)
{
@@ -4403,7 +4570,8 @@ bnc_apply_messages_to_basement_node(
// the relevant messages' offsets and sort them by MSN, then apply
// them in MSN order.
const int buffer_size = ((stale_ube - stale_lbi) + (fresh_ube - fresh_lbi) + bnc->broadcast_list.size());
- int32_t *XMALLOC_N(buffer_size, offsets);
+ toku::scoped_malloc offsets_buf(buffer_size * sizeof(int32_t));
+ int32_t *offsets = reinterpret_cast<int32_t *>(offsets_buf.get());
struct store_fifo_offset_extra sfo_extra = { .offsets = offsets, .i = 0 };
// Populate offsets array with offsets to stale messages
@@ -4427,13 +4595,11 @@ 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_cmd(t, bn, entry, oldest_referenced_xid, &workdone_this_ancestor, &stats_delta);
+ do_bn_apply_cmd(t, bn, entry, gc_info, &workdone_this_ancestor, &stats_delta);
}
-
- toku_free(offsets);
} 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_cmd_extra iter_extra = { .t = t, .bn = bn, .bnc = bnc, .oldest_referenced_xid = oldest_referenced_xid, .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_cmd_extra, iterate_do_bn_apply_cmd>(fresh_lbi, fresh_ube, &iter_extra);
assert_zero(r);
@@ -4442,7 +4608,7 @@ bnc_apply_messages_to_basement_node(
// No fresh messages to apply, we just apply stale messages.
if (stale_ube - stale_lbi > 0) *msgs_applied = true;
- struct iterate_do_bn_apply_cmd_extra iter_extra = { .t = t, .bn = bn, .bnc = bnc, .oldest_referenced_xid = oldest_referenced_xid, .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_cmd_extra, iterate_do_bn_apply_cmd>(stale_lbi, stale_ube, &iter_extra);
assert_zero(r);
@@ -4465,7 +4631,7 @@ apply_ancestors_messages_to_bn(
int childnum,
ANCESTORS ancestors,
struct pivot_bounds const * const bounds,
- TXNID oldest_referenced_xid,
+ txn_gc_info *gc_info,
bool* msgs_applied
)
{
@@ -4480,7 +4646,7 @@ apply_ancestors_messages_to_bn(
curr_ancestors->node,
curr_ancestors->childnum,
&curr_bounds,
- oldest_referenced_xid,
+ gc_info,
msgs_applied
);
// We don't want to check this ancestor node again if the
@@ -4517,13 +4683,14 @@ toku_apply_ancestors_messages_to_node (
VERIFY_NODE(t, node);
paranoid_invariant(node->height == 0);
- TXNID oldest_referenced_xid = ancestors->node->oldest_referenced_xid_known;
- for (ANCESTORS curr_ancestors = ancestors; curr_ancestors; curr_ancestors = curr_ancestors->next) {
- if (curr_ancestors->node->oldest_referenced_xid_known > oldest_referenced_xid) {
- oldest_referenced_xid = curr_ancestors->node->oldest_referenced_xid_known;
- }
- }
+ TXN_MANAGER txn_manager = toku_ft_get_txn_manager(t);
+ txn_manager_state txn_state_for_gc(txn_manager);
+ TXNID oldest_referenced_xid_for_simple_gc = toku_ft_get_oldest_referenced_xid_estimate(t);
+ txn_gc_info gc_info(&txn_state_for_gc,
+ oldest_referenced_xid_for_simple_gc,
+ node->oldest_referenced_xid_known,
+ true);
if (!node->dirty && child_to_read >= 0) {
paranoid_invariant(BP_STATE(node, child_to_read) == PT_AVAIL);
apply_ancestors_messages_to_bn(
@@ -4532,7 +4699,7 @@ toku_apply_ancestors_messages_to_node (
child_to_read,
ancestors,
bounds,
- oldest_referenced_xid,
+ &gc_info,
msgs_applied
);
}
@@ -4551,7 +4718,7 @@ toku_apply_ancestors_messages_to_node (
i,
ancestors,
bounds,
- oldest_referenced_xid,
+ &gc_info,
msgs_applied
);
}
@@ -4812,12 +4979,20 @@ ok: ;
switch (search->direction) {
case FT_SEARCH_LEFT:
idx++;
- if (idx >= bn->data_buffer.omt_size())
+ if (idx >= bn->data_buffer.omt_size()) {
+ if (ftcursor->interrupt_cb && ftcursor->interrupt_cb(ftcursor->interrupt_cb_extra)) {
+ return TOKUDB_INTERRUPTED;
+ }
return DB_NOTFOUND;
+ }
break;
case FT_SEARCH_RIGHT:
- if (idx == 0)
+ if (idx == 0) {
+ if (ftcursor->interrupt_cb && ftcursor->interrupt_cb(ftcursor->interrupt_cb_extra)) {
+ return TOKUDB_INTERRUPTED;
+ }
return DB_NOTFOUND;
+ }
idx--;
break;
default:
@@ -5244,6 +5419,8 @@ toku_ft_search (FT_HANDLE brt, ft_search_t *search, FT_GET_CALLBACK_FUNCTION get
uint trycount = 0; // How many tries did it take to get the result?
FT ft = brt->ft;
+ toku::context search_ctx(CTX_SEARCH);
+
try_again:
trycount++;
@@ -6280,22 +6457,25 @@ int toku_ft_layer_init(void) {
partitioned_counters_init();
status_init();
txn_status_init();
+ toku_ule_status_init();
toku_checkpoint_init();
toku_ft_serialize_layer_init();
toku_mutex_init(&ft_open_close_lock, NULL);
+ toku_scoped_malloc_init();
exit:
return r;
}
-
-
void toku_ft_layer_destroy(void) {
toku_mutex_destroy(&ft_open_close_lock);
toku_ft_serialize_layer_destroy();
toku_checkpoint_destroy();
status_destroy();
txn_status_destroy();
+ toku_ule_status_destroy();
+ toku_context_status_destroy();
partitioned_counters_destroy();
+ toku_scoped_malloc_destroy();
//Portability must be cleaned up last
toku_portability_destroy();
}
diff --git a/storage/tokudb/ft-index/ft/ft-ops.h b/storage/tokudb/ft-index/ft/ft-ops.h
index 7d84cdb5135..67482e3931b 100644
--- a/storage/tokudb/ft-index/ft/ft-ops.h
+++ b/storage/tokudb/ft-index/ft/ft-ops.h
@@ -114,6 +114,8 @@ PATENT RIGHTS GRANT:
// When lock_only is true, the callback only does optional lock tree locking.
typedef int(*FT_GET_CALLBACK_FUNCTION)(ITEMLEN keylen, bytevec key, ITEMLEN vallen, bytevec val, void *extra, bool lock_only);
+typedef bool(*FT_CHECK_INTERRUPT_CALLBACK)(void* extra);
+
int toku_open_ft_handle (const char *fname, int is_create, FT_HANDLE *, int nodesize, int basementnodesize, enum toku_compression_method compression_method, CACHETABLE, TOKUTXN, int(*)(DB *,const DBT*,const DBT*)) __attribute__ ((warn_unused_result));
// effect: changes the descriptor for the ft of the given handle.
@@ -135,6 +137,8 @@ void toku_ft_handle_set_basementnodesize(FT_HANDLE, unsigned int basementnodesiz
void toku_ft_handle_get_basementnodesize(FT_HANDLE, unsigned int *basementnodesize);
void toku_ft_handle_set_compression_method(FT_HANDLE, enum toku_compression_method);
void toku_ft_handle_get_compression_method(FT_HANDLE, enum toku_compression_method *);
+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 brt);
@@ -239,9 +243,12 @@ void toku_ft_delete (FT_HANDLE brt, DBT *k, TOKUTXN txn);
// 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);
-void toku_ft_send_insert(FT_HANDLE brt, DBT *key, DBT *val, XIDS xids, enum ft_msg_type type, TXNID oldest_referenced_xid, GC_INFO gc_info);
-void toku_ft_send_delete(FT_HANDLE brt, DBT *key, XIDS xids, TXNID oldest_referenced_xid, GC_INFO gc_info);
-void toku_ft_send_commit_any(FT_HANDLE brt, DBT *key, XIDS xids, TXNID oldest_referenced_xids, GC_INFO gc_info);
+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 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));
@@ -258,6 +265,7 @@ void toku_ft_cursor_set_leaf_mode(FT_CURSOR);
// the cursor duing a one query.
void toku_ft_cursor_set_temporary(FT_CURSOR);
void toku_ft_cursor_remove_restriction(FT_CURSOR);
+void toku_ft_cursor_set_check_interrupt_cb(FT_CURSOR ftcursor, FT_CHECK_INTERRUPT_CALLBACK cb, void *extra);
int toku_ft_cursor_is_leaf_mode(FT_CURSOR);
void toku_ft_cursor_set_range_lock(FT_CURSOR, const DBT *, const DBT *, bool, bool, int);
@@ -346,5 +354,8 @@ int toku_ft_strerror_r(int error, char *buf, size_t buflen);
extern bool garbage_collection_debug;
+// This is a poor place to put global options like these.
void toku_ft_set_direct_io(bool direct_io_on);
+void toku_ft_set_compress_buffers_before_eviction(bool compress_buffers);
+
#endif
diff --git a/storage/tokudb/ft-index/ft/ft-serialize.cc b/storage/tokudb/ft-index/ft/ft-serialize.cc
index f16544ba51a..e6fbe0a2ce4 100644
--- a/storage/tokudb/ft-index/ft/ft-serialize.cc
+++ b/storage/tokudb/ft-index/ft/ft-serialize.cc
@@ -404,6 +404,7 @@ int deserialize_ft_versioned(int fd, struct rbuf *rb, FT *ftp, uint32_t version)
.nodesize = nodesize,
.basementnodesize = basementnodesize,
.compression_method = compression_method,
+ .fanout = FT_DEFAULT_FANOUT, // fanout is not serialized, must be set at startup
.highest_unused_msn_for_upgrade = highest_unused_msn_for_upgrade,
.max_msn_in_ft = max_msn_in_ft,
.time_of_last_optimize_begin = time_of_last_optimize_begin,
@@ -461,6 +462,7 @@ serialize_ft_min_size (uint32_t version) {
size_t size = 0;
switch(version) {
+ case FT_LAYOUT_VERSION_25:
case FT_LAYOUT_VERSION_24:
case FT_LAYOUT_VERSION_23:
case FT_LAYOUT_VERSION_22:
diff --git a/storage/tokudb/ft-index/ft/ft-test-helpers.cc b/storage/tokudb/ft-index/ft/ft-test-helpers.cc
index 2fafe8feeec..135603147d9 100644
--- a/storage/tokudb/ft-index/ft/ft-test-helpers.cc
+++ b/storage/tokudb/ft-index/ft/ft-test-helpers.cc
@@ -142,7 +142,6 @@ int toku_testsetup_leaf(FT_HANDLE brt, BLOCKNUM *blocknum, int n_children, char
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);
- assert(n_children<=FT_FANOUT);
toku_create_new_ftnode(brt, &node, height, n_children);
int i;
for (i=0; i<n_children; i++) {
@@ -222,6 +221,7 @@ int toku_testsetup_insert_to_leaf (FT_HANDLE brt, BLOCKNUM blocknum, const char
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_cmd (
brt->ft->compare_fun,
brt->ft->update_fun,
@@ -230,7 +230,7 @@ int toku_testsetup_insert_to_leaf (FT_HANDLE brt, BLOCKNUM blocknum, const char
-1,
&cmd,
true,
- make_gc_info(true),
+ &gc_info,
zero_flow_deltas,
NULL
);
diff --git a/storage/tokudb/ft-index/ft/ft.cc b/storage/tokudb/ft-index/ft/ft.cc
index 4109b9b47b1..48a6912a74f 100644
--- a/storage/tokudb/ft-index/ft/ft.cc
+++ b/storage/tokudb/ft-index/ft/ft.cc
@@ -431,6 +431,7 @@ ft_header_create(FT_OPTIONS options, BLOCKNUM root_blocknum, TXNID root_xid_that
.nodesize = options->nodesize,
.basementnodesize = options->basementnodesize,
.compression_method = options->compression_method,
+ .fanout = options->fanout,
.highest_unused_msn_for_upgrade = { .msn = (MIN_MSN.msn - 1) },
.max_msn_in_ft = ZERO_MSN,
.time_of_last_optimize_begin = 0,
@@ -606,13 +607,16 @@ toku_ft_init(FT ft,
TXNID root_xid_that_created,
uint32_t target_nodesize,
uint32_t target_basementnodesize,
- enum toku_compression_method compression_method)
+ enum toku_compression_method compression_method,
+ uint32_t fanout
+ )
{
memset(ft, 0, sizeof *ft);
struct ft_options options = {
.nodesize = target_nodesize,
.basementnodesize = target_basementnodesize,
.compression_method = compression_method,
+ .fanout = fanout,
.flags = 0,
.compare_fun = NULL,
.update_fun = NULL
@@ -633,6 +637,7 @@ ft_handle_open_for_redirect(FT_HANDLE *new_ftp, const char *fname_in_env, TOKUTX
toku_ft_handle_set_nodesize(t, old_h->h->nodesize);
toku_ft_handle_set_basementnodesize(t, old_h->h->basementnodesize);
toku_ft_handle_set_compression_method(t, old_h->h->compression_method);
+ toku_ft_handle_set_fanout(t, old_h->h->fanout);
CACHETABLE ct = toku_cachefile_get_cachetable(old_h->cf);
int r = toku_ft_handle_open_with_dict_id(t, fname_in_env, 0, 0, ct, txn, old_h->dict_id);
if (r != 0) {
@@ -1022,6 +1027,19 @@ void toku_ft_get_compression_method(FT ft, enum toku_compression_method *methodp
toku_ft_unlock(ft);
}
+void toku_ft_set_fanout(FT ft, unsigned int fanout) {
+ toku_ft_lock(ft);
+ ft->h->fanout = fanout;
+ ft->h->dirty = 1;
+ toku_ft_unlock(ft);
+}
+
+void toku_ft_get_fanout(FT ft, unsigned int *fanout) {
+ toku_ft_lock(ft);
+ *fanout = ft->h->fanout;
+ toku_ft_unlock(ft);
+}
+
// mark the ft as a blackhole. any message injections will be a no op.
void toku_ft_set_blackhole(FT_HANDLE ft_handle) {
ft_handle->ft->blackhole = true;
diff --git a/storage/tokudb/ft-index/ft/ft.h b/storage/tokudb/ft-index/ft/ft.h
index 748c38aa138..92d1ba0b5ea 100644
--- a/storage/tokudb/ft-index/ft/ft.h
+++ b/storage/tokudb/ft-index/ft/ft.h
@@ -130,13 +130,14 @@ void toku_ft_note_hot_complete(FT_HANDLE brt, bool success, MSN msn_at_start_of_
void
toku_ft_init(
- FT h,
+ FT ft,
BLOCKNUM root_blocknum_on_disk,
LSN checkpoint_lsn,
TXNID root_xid_that_created,
uint32_t target_nodesize,
uint32_t target_basementnodesize,
- enum toku_compression_method compression_method
+ enum toku_compression_method compression_method,
+ uint32_t fanout
);
int toku_dictionary_redirect_abort(FT old_h, FT new_h, TOKUTXN txn) __attribute__ ((warn_unused_result));
@@ -186,6 +187,8 @@ void toku_ft_set_basementnodesize(FT ft, unsigned int basementnodesize);
void toku_ft_get_basementnodesize(FT ft, unsigned int *basementnodesize);
void toku_ft_set_compression_method(FT ft, enum toku_compression_method method);
void toku_ft_get_compression_method(FT ft, enum toku_compression_method *methodp);
+void toku_ft_set_fanout(FT ft, unsigned int fanout);
+void toku_ft_get_fanout(FT ft, unsigned int *fanout);
void toku_node_save_ct_pair(CACHEKEY UU(key), void *value_data, PAIR p);
// mark the ft as a blackhole. any message injections will be a no op.
diff --git a/storage/tokudb/ft-index/ft/ft_layout_version.h b/storage/tokudb/ft-index/ft/ft_layout_version.h
index 93c998f6a8f..da401ea7c55 100644
--- a/storage/tokudb/ft-index/ft/ft_layout_version.h
+++ b/storage/tokudb/ft-index/ft/ft_layout_version.h
@@ -118,6 +118,7 @@ enum ft_layout_version_e {
FT_LAYOUT_VERSION_22 = 22, // Ming: Add oldest known referenced xid to each ftnode, for better garbage collection
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_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 c1f6e01487a..6fb6774ee34 100644
--- a/storage/tokudb/ft-index/ft/ft_node-serialize.cc
+++ b/storage/tokudb/ft-index/ft/ft_node-serialize.cc
@@ -97,6 +97,7 @@ PATENT RIGHTS GRANT:
#include <util/threadpool.h>
#include "ft.h"
#include <util/status.h>
+#include <util/scoped_malloc.h>
static FT_UPGRADE_STATUS_S ft_upgrade_status;
@@ -217,12 +218,12 @@ toku_maybe_preallocate_in_file (int fd, int64_t size, int64_t expected_size, int
}
if (to_write > 0) {
assert(to_write%512==0);
- char *XMALLOC_N_ALIGNED(512, to_write, wbuf);
+ toku::scoped_malloc_aligned wbuf_aligned(to_write, 512);
+ char *wbuf = reinterpret_cast<char *>(wbuf_aligned.get());
memset(wbuf, 0, to_write);
toku_off_t start_write = alignup64(file_size, stripe_width);
invariant(start_write >= file_size);
toku_os_full_pwrite(fd, wbuf, to_write, start_write);
- toku_free(wbuf);
*new_size = start_write + to_write;
}
else {
@@ -356,10 +357,13 @@ serialize_nonleaf_childinfo(NONLEAF_CHILDINFO bnc, struct wbuf *wb)
//
static void
serialize_ftnode_partition(FTNODE node, int i, struct sub_block *sb) {
- assert(sb->uncompressed_size == 0);
- assert(sb->uncompressed_ptr == NULL);
- sb->uncompressed_size = serialize_ftnode_partition_size(node,i);
- sb->uncompressed_ptr = toku_xmalloc(sb->uncompressed_size);
+ if (sb->uncompressed_ptr == NULL) {
+ assert(sb->uncompressed_size == 0);
+ sb->uncompressed_size = serialize_ftnode_partition_size(node,i);
+ sb->uncompressed_ptr = toku_xmalloc(sb->uncompressed_size);
+ } else {
+ assert(sb->uncompressed_size > 0);
+ }
//
// Now put the data into sb->uncompressed_ptr
//
@@ -549,13 +553,21 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
// Create an array of OMTVALUE's that store all the pointers to all the data.
// Each element in leafpointers is a pointer to a leaf.
- LEAFENTRY *XMALLOC_N(num_alloc, leafpointers);
+ toku::scoped_malloc leafpointers_buf(sizeof(LEAFENTRY) * num_alloc);
+ LEAFENTRY *leafpointers = reinterpret_cast<LEAFENTRY *>(leafpointers_buf.get());
leafpointers[0] = NULL;
- const void **XMALLOC_N(num_alloc, key_pointers);
- uint32_t *XMALLOC_N(num_alloc, key_sizes);
+
+ toku::scoped_malloc key_pointers_buf(sizeof(void *) * num_alloc);
+ const void **key_pointers = reinterpret_cast<const void **>(key_pointers_buf.get());
+ key_pointers[0] = NULL;
+
+ toku::scoped_malloc key_sizes_buf(sizeof(uint32_t) * num_alloc);
+ uint32_t *key_sizes = reinterpret_cast<uint32_t *>(key_sizes_buf.get());
// Capture pointers to old mempools' buffers (so they can be destroyed)
- BASEMENTNODE *XMALLOC_N(num_orig_basements, old_bns);
+ toku::scoped_malloc old_bns_buf(sizeof(BASEMENTNODE) * num_orig_basements);
+ BASEMENTNODE *old_bns = reinterpret_cast<BASEMENTNODE *>(old_bns_buf.get());
+ old_bns[0] = NULL;
uint32_t curr_le = 0;
for (uint32_t i = 0; i < num_orig_basements; i++) {
@@ -568,22 +580,26 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
// Create an array that will store indexes of new pivots.
// Each element in new_pivots is the index of a pivot key.
// (Allocating num_le of them is overkill, but num_le is an upper bound.)
- uint32_t *XMALLOC_N(num_alloc, new_pivots);
+ toku::scoped_malloc new_pivots_buf(sizeof(uint32_t) * num_alloc);
+ uint32_t *new_pivots = reinterpret_cast<uint32_t *>(new_pivots_buf.get());
new_pivots[0] = 0;
// Each element in le_sizes is the size of the leafentry pointed to by leafpointers.
- size_t *XMALLOC_N(num_alloc, le_sizes);
+ toku::scoped_malloc le_sizes_buf(sizeof(size_t) * num_alloc);
+ size_t *le_sizes = reinterpret_cast<size_t *>(le_sizes_buf.get());
le_sizes[0] = 0;
// 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.
- size_t *XMALLOC_N(num_alloc, bn_sizes);
+ 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.)
- uint32_t *XMALLOC_N(num_alloc, num_les_this_bn);
+ toku::scoped_malloc num_les_this_bn_buf(sizeof(uint32_t) * num_alloc);
+ uint32_t *num_les_this_bn = reinterpret_cast<uint32_t *>(num_les_this_bn_buf.get());
num_les_this_bn[0] = 0;
// Figure out the new pivots.
@@ -696,14 +712,6 @@ rebalance_ftnode_leaf(FTNODE node, unsigned int basementnodesize)
for (uint32_t i = 0; i < num_orig_basements; i++) {
destroy_basement_node(old_bns[i]);
}
- toku_free(key_pointers);
- toku_free(key_sizes);
- toku_free(leafpointers);
- toku_free(old_bns);
- toku_free(new_pivots);
- toku_free(le_sizes);
- toku_free(bn_sizes);
- toku_free(num_les_this_bn);
} // end of rebalance_ftnode_leaf()
struct serialize_times {
@@ -737,32 +745,30 @@ toku_create_compressed_partition_from_available(
SUB_BLOCK sb
)
{
- struct serialize_times st;
- memset(&st, 0, sizeof(st));
+ tokutime_t t0 = toku_time_now();
- serialize_and_compress_partition(node, childnum, compression_method, sb, &st);
- toku_ft_status_update_serialize_times(node, st.serialize_time, st.compress_time);
+ // serialize
+ sb->uncompressed_size = serialize_ftnode_partition_size(node, childnum);
+ toku::scoped_malloc uncompressed_buf(sb->uncompressed_size);
+ sb->uncompressed_ptr = uncompressed_buf.get();
+ serialize_ftnode_partition(node, childnum, sb);
- //
- // now we have an sb that would be ready for being written out,
- // but we are not writing it out, we are storing it in cache for a potentially
- // long time, so we need to do some cleanup
- //
- // The buffer created above contains metadata in the first 8 bytes, and is overallocated
- // It allocates a bound on the compressed length (evaluated before compression) as opposed
- // to just the amount of the actual compressed data. So, we create a new buffer and copy
- // just the compressed data.
- //
- uint32_t compressed_size = toku_dtoh32(*(uint32_t *)sb->compressed_ptr);
- void* compressed_data = toku_xmalloc(compressed_size);
- memcpy(compressed_data, (char *)sb->compressed_ptr + 8, compressed_size);
- toku_free(sb->compressed_ptr);
- sb->compressed_ptr = compressed_data;
- sb->compressed_size = compressed_size;
- if (sb->uncompressed_ptr) {
- toku_free(sb->uncompressed_ptr);
- sb->uncompressed_ptr = NULL;
- }
+ tokutime_t t1 = toku_time_now();
+
+ // compress. no need to pad with extra bytes for sizes/xsum - we're not storing them
+ set_compressed_size_bound(sb, compression_method);
+ sb->compressed_ptr = toku_xmalloc(sb->compressed_size_bound);
+ sb->compressed_size = compress_nocrc_sub_block(
+ sb,
+ sb->compressed_ptr,
+ sb->compressed_size_bound,
+ compression_method
+ );
+ sb->uncompressed_ptr = NULL;
+
+ tokutime_t t2 = toku_time_now();
+
+ toku_ft_status_update_serialize_times(node, t1 - t0, t2 - t1);
}
static void
@@ -882,7 +888,8 @@ int toku_serialize_ftnode_to_memory(FTNODE node,
// Each partition represents a compressed sub block
// For internal nodes, a sub block is a message buffer
// For leaf nodes, a sub block is a basement node
- struct sub_block *XMALLOC_N(npartitions, sb);
+ toku::scoped_malloc sb_buf(sizeof(struct sub_block) * npartitions);
+ struct sub_block *sb = reinterpret_cast<struct sub_block *>(sb_buf.get());
XREALLOC_N(npartitions, *ndd);
struct sub_block sb_node_info;
for (int i = 0; i < npartitions; i++) {
@@ -983,7 +990,6 @@ int toku_serialize_ftnode_to_memory(FTNODE node,
assert(0 == (*n_bytes_to_write)%512);
assert(0 == ((unsigned long long)(*bytes_to_write))%512);
- toku_free(sb);
return 0;
}
@@ -1055,6 +1061,7 @@ deserialize_child_buffer(NONLEAF_CHILDINFO bnc, struct rbuf *rbuf,
XMALLOC_N(n_in_this_buffer, fresh_offsets);
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++) {
bytevec key; ITEMLEN keylen;
bytevec val; ITEMLEN vallen;
@@ -1171,9 +1178,9 @@ BASEMENTNODE toku_create_empty_bn_no_buffer(void) {
NONLEAF_CHILDINFO toku_create_empty_nl(void) {
NONLEAF_CHILDINFO XMALLOC(cn);
int r = toku_fifo_create(&cn->buffer); assert_zero(r);
- cn->fresh_message_tree.create();
- cn->stale_message_tree.create();
- cn->broadcast_list.create();
+ cn->fresh_message_tree.create_no_array();
+ cn->stale_message_tree.create_no_array();
+ cn->broadcast_list.create_no_array();
memset(cn->flow, 0, sizeof cn->flow);
return cn;
}
@@ -1545,7 +1552,6 @@ deserialize_ftnode_partition(
rb.ndone += data_size;
}
assert(rb.ndone == rb.size);
- toku_free(sb->uncompressed_ptr);
exit:
return r;
}
@@ -1563,6 +1569,8 @@ decompress_and_deserialize_worker(struct rbuf curr_rbuf, struct sub_block curr_s
r = deserialize_ftnode_partition(&curr_sb, node, child, desc, cmp);
}
*decompress_time = t1 - t0;
+
+ toku_free(curr_sb.uncompressed_ptr);
return r;
}
@@ -2451,7 +2459,8 @@ toku_deserialize_bp_from_disk(FTNODE node, FTNODE_DISK_DATA ndd, int childnum, i
uint32_t pad_at_beginning = (node_offset+curr_offset)%512;
uint32_t padded_size = roundup_to_multiple(512, pad_at_beginning + curr_size);
- uint8_t *XMALLOC_N_ALIGNED(512, padded_size, raw_block);
+ toku::scoped_malloc_aligned raw_block_buf(padded_size, 512);
+ uint8_t *raw_block = reinterpret_cast<uint8_t *>(raw_block_buf.get());
rbuf_init(&rb, pad_at_beginning+raw_block, curr_size);
tokutime_t t0 = toku_time_now();
@@ -2465,17 +2474,25 @@ toku_deserialize_bp_from_disk(FTNODE node, FTNODE_DISK_DATA ndd, int childnum, i
tokutime_t t1 = toku_time_now();
- // decompress
+ // read sub block
struct sub_block curr_sb;
sub_block_init(&curr_sb);
- r = read_and_decompress_sub_block(&rb, &curr_sb);
+ r = read_compressed_sub_block(&rb, &curr_sb);
+ if (r != 0) {
+ return r;
+ }
+ invariant(curr_sb.compressed_ptr != NULL);
+
+ // decompress
+ toku::scoped_malloc uncompressed_buf(curr_sb.uncompressed_size);
+ curr_sb.uncompressed_ptr = uncompressed_buf.get();
+ toku_decompress((Bytef *) curr_sb.uncompressed_ptr, curr_sb.uncompressed_size,
+ (Bytef *) curr_sb.compressed_ptr, curr_sb.compressed_size);
// deserialize
tokutime_t t2 = toku_time_now();
- if (r == 0) {
- // at this point, sb->uncompressed_ptr stores the serialized node partition
- r = deserialize_ftnode_partition(&curr_sb, node, childnum, &bfe->h->cmp_descriptor, bfe->h->compare_fun);
- }
+
+ r = deserialize_ftnode_partition(&curr_sb, node, childnum, &bfe->h->cmp_descriptor, bfe->h->compare_fun);
tokutime_t t3 = toku_time_now();
@@ -2490,7 +2507,6 @@ toku_deserialize_bp_from_disk(FTNODE node, FTNODE_DISK_DATA ndd, int childnum, i
bfe->bytes_read = rlen;
bfe->io_time = io_time;
- toku_free(raw_block);
return r;
}
@@ -2501,8 +2517,9 @@ toku_deserialize_bp_from_compressed(FTNODE node, int childnum, struct ftnode_fet
assert(BP_STATE(node, childnum) == PT_COMPRESSED);
SUB_BLOCK curr_sb = BSB(node, childnum);
+ toku::scoped_malloc uncompressed_buf(curr_sb->uncompressed_size);
assert(curr_sb->uncompressed_ptr == NULL);
- curr_sb->uncompressed_ptr = toku_xmalloc(curr_sb->uncompressed_size);
+ curr_sb->uncompressed_ptr = uncompressed_buf.get();
setup_available_ftnode_partition(node, childnum);
BP_STATE(node,childnum) = PT_AVAIL;
@@ -2763,8 +2780,7 @@ toku_serialize_rollback_log_to (int fd, ROLLBACK_LOG_NODE log, SERIALIZED_ROLLBA
}
static int
-deserialize_rollback_log_from_rbuf (BLOCKNUM blocknum, uint32_t fullhash, ROLLBACK_LOG_NODE *log_p,
- FT h, struct rbuf *rb) {
+deserialize_rollback_log_from_rbuf (BLOCKNUM blocknum, ROLLBACK_LOG_NODE *log_p, struct rbuf *rb) {
ROLLBACK_LOG_NODE MALLOC(result);
int r;
if (result==NULL) {
@@ -2793,13 +2809,7 @@ deserialize_rollback_log_from_rbuf (BLOCKNUM blocknum, uint32_t fullhash, ROLLBA
r = toku_db_badformat();
goto died0;
}
- result->hash = toku_cachetable_hash(h->cf, result->blocknum);
- if (result->hash != fullhash) {
- r = toku_db_badformat();
- goto died0;
- }
result->previous = rbuf_blocknum(rb);
- result->previous_hash = toku_cachetable_hash(h->cf, result->previous);
result->rollentry_resident_bytecount = rbuf_ulonglong(rb);
size_t arena_initial_size = rbuf_ulonglong(rb);
@@ -2840,13 +2850,13 @@ deserialize_rollback_log_from_rbuf (BLOCKNUM blocknum, uint32_t fullhash, ROLLBA
}
static int
-deserialize_rollback_log_from_rbuf_versioned (uint32_t version, BLOCKNUM blocknum, uint32_t fullhash,
+deserialize_rollback_log_from_rbuf_versioned (uint32_t version, BLOCKNUM blocknum,
ROLLBACK_LOG_NODE *log,
- FT h, struct rbuf *rb) {
+ struct rbuf *rb) {
int r = 0;
ROLLBACK_LOG_NODE rollback_log_node = NULL;
invariant(version==FT_LAYOUT_VERSION); //Rollback log nodes do not survive version changes.
- r = deserialize_rollback_log_from_rbuf(blocknum, fullhash, &rollback_log_node, h, rb);
+ r = deserialize_rollback_log_from_rbuf(blocknum, &rollback_log_node, rb);
if (r==0) {
*log = rollback_log_node;
}
@@ -3022,8 +3032,7 @@ cleanup:
// Read rollback log node from file into struct. Perform version upgrade if necessary.
int
-toku_deserialize_rollback_log_from (int fd, BLOCKNUM blocknum, uint32_t fullhash,
- ROLLBACK_LOG_NODE *logp, FT h) {
+toku_deserialize_rollback_log_from (int fd, BLOCKNUM blocknum, ROLLBACK_LOG_NODE *logp, FT h) {
int layout_version = 0;
int r;
struct rbuf rb = {.buf = NULL, .size = 0, .ndone = 0};
@@ -3037,7 +3046,6 @@ toku_deserialize_rollback_log_from (int fd, BLOCKNUM blocknum, uint32_t fullhash
ROLLBACK_LOG_NODE XMALLOC(log);
rollback_empty_log_init(log);
log->blocknum.b = blocknum.b;
- log->hash = fullhash;
r = 0;
*logp = log;
goto cleanup;
@@ -3054,7 +3062,7 @@ toku_deserialize_rollback_log_from (int fd, BLOCKNUM blocknum, uint32_t fullhash
}
}
- r = deserialize_rollback_log_from_rbuf_versioned(layout_version, blocknum, fullhash, logp, h, &rb);
+ r = deserialize_rollback_log_from_rbuf_versioned(layout_version, blocknum, logp, &rb);
cleanup:
if (rb.buf) toku_free(rb.buf);
diff --git a/storage/tokudb/ft-index/ft/ftloader-internal.h b/storage/tokudb/ft-index/ft/ftloader-internal.h
index ef8f618f22e..b8d55001641 100644
--- a/storage/tokudb/ft-index/ft/ftloader-internal.h
+++ b/storage/tokudb/ft-index/ft/ftloader-internal.h
@@ -288,6 +288,7 @@ struct fractal_thread_args {
uint32_t target_nodesize;
uint32_t target_basementnodesize;
enum toku_compression_method target_compression_method;
+ uint32_t target_fanout;
};
void toku_ft_loader_set_n_rows(FTLOADER bl, uint64_t n_rows);
@@ -319,7 +320,8 @@ int toku_loader_write_brt_from_q_in_C (FTLOADER bl,
int which_db,
uint32_t target_nodesize,
uint32_t target_basementnodesize,
- enum toku_compression_method target_compression_method);
+ 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 *);
diff --git a/storage/tokudb/ft-index/ft/ftloader.cc b/storage/tokudb/ft-index/ft/ftloader.cc
index 1a5b2ad3bf8..d5673ccfe0d 100644
--- a/storage/tokudb/ft-index/ft/ftloader.cc
+++ b/storage/tokudb/ft-index/ft/ftloader.cc
@@ -561,7 +561,7 @@ int toku_ft_loader_internal_init (/* out */ FTLOADER *blp,
}
bl->compress_intermediates = compress_intermediates;
if (0) { // debug
- fprintf(stderr, "%s Reserved memory=%ld\n", __FUNCTION__, bl->reserved_memory);
+ fprintf(stderr, "%s Reserved memory=%" PRId64 "\n", __FUNCTION__, bl->reserved_memory);
}
bl->src_db = src_db;
@@ -2405,7 +2405,8 @@ static int toku_loader_write_ft_from_q (FTLOADER bl,
int which_db,
uint32_t target_nodesize,
uint32_t target_basementnodesize,
- enum toku_compression_method target_compression_method)
+ enum toku_compression_method target_compression_method,
+ uint32_t target_fanout)
// Effect: Consume a sequence of rowsets work from a queue, creating a fractal tree. Closes fd.
{
// set the number of fractal tree writer threads so that we can partition memory in the merger
@@ -2434,7 +2435,7 @@ static int toku_loader_write_ft_from_q (FTLOADER bl,
// TODO: (Zardosht/Yoni/Leif), do this code properly
struct ft ft;
- toku_ft_init(&ft, (BLOCKNUM){0}, bl->load_lsn, root_xid_that_created, target_nodesize, target_basementnodesize, target_compression_method);
+ toku_ft_init(&ft, (BLOCKNUM){0}, bl->load_lsn, root_xid_that_created, target_nodesize, target_basementnodesize, target_compression_method, target_fanout);
struct dbout out;
ZERO_STRUCT(out);
@@ -2680,18 +2681,19 @@ int toku_loader_write_brt_from_q_in_C (FTLOADER bl,
int which_db,
uint32_t target_nodesize,
uint32_t target_basementnodesize,
- enum toku_compression_method target_compression_method)
+ 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;
target_basementnodesize = target_basementnodesize == 0 ? default_loader_basementnodesize : target_basementnodesize;
- return toku_loader_write_ft_from_q (bl, descriptor, fd, progress_allocation, q, total_disksize_estimate, which_db, target_nodesize, target_basementnodesize, target_compression_method);
+ return toku_loader_write_ft_from_q (bl, descriptor, fd, progress_allocation, q, total_disksize_estimate, which_db, target_nodesize, target_basementnodesize, target_compression_method, target_fanout);
}
static void* fractal_thread (void *ftav) {
struct fractal_thread_args *fta = (struct fractal_thread_args *)ftav;
- int r = toku_loader_write_ft_from_q (fta->bl, fta->descriptor, fta->fd, fta->progress_allocation, fta->q, fta->total_disksize_estimate, fta->which_db, fta->target_nodesize, fta->target_basementnodesize, fta->target_compression_method);
+ int r = toku_loader_write_ft_from_q (fta->bl, fta->descriptor, fta->fd, fta->progress_allocation, fta->q, fta->total_disksize_estimate, fta->which_db, fta->target_nodesize, fta->target_basementnodesize, fta->target_compression_method, fta->target_fanout);
fta->errno_result = r;
return NULL;
}
@@ -2727,7 +2729,7 @@ static int loader_do_i (FTLOADER bl,
r = get_error_errno(); goto error;
}
- uint32_t target_nodesize, target_basementnodesize;
+ uint32_t target_nodesize, target_basementnodesize, target_fanout;
enum toku_compression_method target_compression_method;
r = dest_db->get_pagesize(dest_db, &target_nodesize);
invariant_zero(r);
@@ -2735,6 +2737,8 @@ static int loader_do_i (FTLOADER bl,
invariant_zero(r);
r = dest_db->get_compression_method(dest_db, &target_compression_method);
invariant_zero(r);
+ r = dest_db->get_fanout(dest_db, &target_fanout);
+ invariant_zero(r);
// This structure must stay live until the join below.
struct fractal_thread_args fta = { bl,
@@ -2748,6 +2752,7 @@ static int loader_do_i (FTLOADER bl,
target_nodesize,
target_basementnodesize,
target_compression_method,
+ target_fanout
};
r = toku_pthread_create(bl->fractal_threads+which_db, NULL, fractal_thread, (void*)&fta);
@@ -2920,7 +2925,9 @@ static void add_pair_to_leafnode (struct leaf_buf *lbuf, unsigned char *key, int
.xids = lbuf->xids,
.u = { .id = { &thekey, &theval } } };
uint64_t workdone=0;
- toku_ft_bn_apply_cmd_once(BLB(leafnode,0), &cmd, idx, NULL, TXNID_NONE, make_gc_info(true), &workdone, stats_to_update);
+ // 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_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) {
diff --git a/storage/tokudb/ft-index/ft/fttypes.h b/storage/tokudb/ft-index/ft/fttypes.h
index 67e29363aaa..052d6342883 100644
--- a/storage/tokudb/ft-index/ft/fttypes.h
+++ b/storage/tokudb/ft-index/ft/fttypes.h
@@ -143,10 +143,6 @@ typedef TOKU_XA_XID *XIDP; // this is the type that's passed to the logger code
static inline BLOCKNUM make_blocknum(int64_t b) { BLOCKNUM result={b}; return result; }
-typedef struct gc_info_s { bool mvcc_needed; } GC_INFO;
-
-static inline GC_INFO make_gc_info(bool mvcc_needed) { GC_INFO result = {mvcc_needed}; return result; }
-
// This struct hold information about values stored in the cachetable.
// As one can tell from the names, we are probably violating an
// abstraction layer by placing names.
diff --git a/storage/tokudb/ft-index/ft/leafentry.h b/storage/tokudb/ft-index/ft/leafentry.h
index ecaa8d77e9b..b664d1675a1 100644
--- a/storage/tokudb/ft-index/ft/leafentry.h
+++ b/storage/tokudb/ft-index/ft/leafentry.h
@@ -247,12 +247,11 @@ toku_le_apply_msg(FT_MSG msg,
LEAFENTRY old_leafentry, // NULL if there was no stored data.
bn_data* data_buffer, // bn_data storing leafentry, if NULL, means there is no bn_data
uint32_t idx, // index in data_buffer where leafentry is stored (and should be replaced
- TXNID oldest_referenced_xid,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
LEAFENTRY *new_leafentry_p,
int64_t * numbytes_delta_p);
-bool toku_le_worth_running_garbage_collection(LEAFENTRY le, TXNID oldest_referenced_xid_known);
+bool toku_le_worth_running_garbage_collection(LEAFENTRY le, txn_gc_info *gc_info);
void
toku_le_garbage_collect(LEAFENTRY old_leaf_entry,
@@ -260,11 +259,8 @@ toku_le_garbage_collect(LEAFENTRY old_leaf_entry,
uint32_t idx,
void* keyp,
uint32_t keylen,
+ txn_gc_info *gc_info,
LEAFENTRY *new_leaf_entry,
- const xid_omt_t &snapshot_xids,
- const rx_omt_t &referenced_xids,
- const xid_omt_t &live_root_txns,
- TXNID oldest_referenced_xid_known,
int64_t * numbytes_delta_p);
#endif /* TOKU_LEAFENTRY_H */
diff --git a/storage/tokudb/ft-index/ft/log-internal.h b/storage/tokudb/ft-index/ft/log-internal.h
index e9af043737b..de2abe801dc 100644
--- a/storage/tokudb/ft-index/ft/log-internal.h
+++ b/storage/tokudb/ft-index/ft/log-internal.h
@@ -177,6 +177,7 @@ struct tokulogger {
uint64_t num_writes_to_disk; // how many times did we write to disk?
uint64_t bytes_written_to_disk; // how many bytes have been written to disk?
tokutime_t time_spent_writing_to_disk; // how much tokutime did we spend writing to disk?
+ uint64_t num_wait_buf_long; // how many times we waited >= 100ms for the in buf
void (*remove_finalize_callback) (DICTIONARY_ID, void*); // ydb-level callback to be called when a transaction that ...
void * remove_finalize_callback_extra; // ... deletes a file is committed or when one that creates a file is aborted.
@@ -209,15 +210,12 @@ struct txn_roll_info {
// the spilled rollback head is the block number of the first rollback node
// that makes up the rollback log chain
BLOCKNUM spilled_rollback_head;
- uint32_t spilled_rollback_head_hash;
// the spilled rollback is the block number of the last rollback node that
// makes up the rollback log chain.
BLOCKNUM spilled_rollback_tail;
- uint32_t spilled_rollback_tail_hash;
// the current rollback node block number we may use. if this is ROLLBACK_NONE,
// then we need to create one and set it here before using it.
BLOCKNUM current_rollback;
- uint32_t current_rollback_hash;
};
struct tokutxn {
@@ -249,7 +247,6 @@ struct tokutxn {
DB_TXN *container_db_txn; // reference to DB_TXN that contains this tokutxn
xid_omt_t *live_root_txn_list; // the root txns live when the root ancestor (self if a root) started.
XIDS xids; // Represents the xid list
- TXNID oldest_referenced_xid;
TOKUTXN snapshot_next;
TOKUTXN snapshot_prev;
diff --git a/storage/tokudb/ft-index/ft/logformat.cc b/storage/tokudb/ft-index/ft/logformat.cc
index fcc159cd4ee..aceedec4c5e 100644
--- a/storage/tokudb/ft-index/ft/logformat.cc
+++ b/storage/tokudb/ft-index/ft/logformat.cc
@@ -155,9 +155,7 @@ const struct logtype rollbacks[] = {
{"rollinclude", 'r', FA{{"TXNID_PAIR", "xid", 0},
{"uint64_t", "num_nodes", 0},
{"BLOCKNUM", "spilled_head", 0},
- {"uint32_t", "spilled_head_hash", 0},
{"BLOCKNUM", "spilled_tail", 0},
- {"uint32_t", "spilled_tail_hash", 0},
NULLFIELD}, LOG_BEGIN_ACTION_NA},
{"load", 'l', FA{{"FILENUM", "old_filenum", 0},
{"BYTESTRING", "new_iname", 0},
diff --git a/storage/tokudb/ft-index/ft/logger.cc b/storage/tokudb/ft-index/ft/logger.cc
index b4a60aad40d..9b4138b247d 100644
--- a/storage/tokudb/ft-index/ft/logger.cc
+++ b/storage/tokudb/ft-index/ft/logger.cc
@@ -422,9 +422,13 @@ wait_till_output_available (TOKULOGGER logger)
// Exit: Holds the output_condition_lock and logger->output_is_available
//
{
+ tokutime_t t0 = toku_time_now();
while (!logger->output_is_available) {
toku_cond_wait(&logger->output_condition, &logger->output_condition_lock);
}
+ if (tokutime_to_seconds(toku_time_now() - t0) >= 0.100) {
+ logger->num_wait_buf_long++;
+ }
}
static void
@@ -1397,6 +1401,7 @@ status_init(void) {
STATUS_INIT(LOGGER_BYTES_WRITTEN, LOGGER_WRITES_BYTES, UINT64, "writes (bytes)", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(LOGGER_UNCOMPRESSED_BYTES_WRITTEN, LOGGER_WRITES_UNCOMPRESSED_BYTES, UINT64, "writes (uncompressed bytes)", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
STATUS_INIT(LOGGER_TOKUTIME_WRITES, LOGGER_WRITES_SECONDS, TOKUTIME, "writes (seconds)", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
+ STATUS_INIT(LOGGER_WAIT_BUF_LONG, LOGGER_WAIT_LONG, UINT64, "count", TOKU_ENGINE_STATUS|TOKU_GLOBAL_STATUS);
logger_status.initialized = true;
}
#undef STATUS_INIT
@@ -1414,6 +1419,7 @@ toku_logger_get_status(TOKULOGGER logger, LOGGER_STATUS statp) {
// No compression on logfiles so the uncompressed size is just number of bytes written
STATUS_VALUE(LOGGER_UNCOMPRESSED_BYTES_WRITTEN) = logger->bytes_written_to_disk;
STATUS_VALUE(LOGGER_TOKUTIME_WRITES) = logger->time_spent_writing_to_disk;
+ STATUS_VALUE(LOGGER_WAIT_BUF_LONG) = logger->num_wait_buf_long;
}
*statp = logger_status;
}
diff --git a/storage/tokudb/ft-index/ft/logger.h b/storage/tokudb/ft-index/ft/logger.h
index 008637600ae..6488ec0707d 100644
--- a/storage/tokudb/ft-index/ft/logger.h
+++ b/storage/tokudb/ft-index/ft/logger.h
@@ -244,6 +244,7 @@ typedef enum {
LOGGER_BYTES_WRITTEN,
LOGGER_UNCOMPRESSED_BYTES_WRITTEN,
LOGGER_TOKUTIME_WRITES,
+ LOGGER_WAIT_BUF_LONG,
LOGGER_STATUS_NUM_ROWS
} logger_status_entry;
diff --git a/storage/tokudb/ft-index/ft/roll.cc b/storage/tokudb/ft-index/ft/roll.cc
index 88933f28b39..78fac7df875 100644
--- a/storage/tokudb/ft-index/ft/roll.cc
+++ b/storage/tokudb/ft-index/ft/roll.cc
@@ -96,6 +96,7 @@ PATENT RIGHTS GRANT:
#include "ft.h"
#include "ft-ops.h"
#include "log-internal.h"
+//#include "txn_manager.h"
#include "xids.h"
#include "rollback-apply.h"
@@ -115,6 +116,10 @@ PATENT RIGHTS GRANT:
// for each FT_DELETE_ANY message sent earlier by the transaction?
#define TOKU_DO_COMMIT_CMD_DELETE 1
+// When a transaction is committed, should we send a FT_COMMIT message
+// for each FT_UPDATE message sent earlier by the transaction?
+#define TOKU_DO_COMMIT_CMD_UPDATE 0
+
int
toku_commit_fdelete (FILENUM filenum,
TOKUTXN txn,
@@ -261,7 +266,16 @@ static int do_insertion (enum ft_msg_type type, FILENUM filenum, BYTESTRING key,
? toku_fill_dbt(&data_dbt, data->data, data->len)
: toku_init_dbt(&data_dbt) } } };
- toku_ft_root_put_cmd(h, &ftcmd, txn->oldest_referenced_xid, make_gc_info(!txn->for_recovery));
+ TXN_MANAGER txn_manager = toku_logger_get_txn_manager(txn->logger);
+ txn_manager_state txn_state_for_gc(txn_manager);
+
+ TXNID oldest_referenced_xid_estimate = toku_txn_manager_get_oldest_referenced_xid_estimate(txn_manager);
+ 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,
+ !txn->for_recovery);
+ 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);
@@ -296,11 +310,15 @@ toku_rollback_cmdinsert (FILENUM filenum,
int
toku_commit_cmdupdate(FILENUM filenum,
- BYTESTRING key,
+ BYTESTRING UU(key),
TOKUTXN txn,
- LSN oplsn)
+ LSN UU(oplsn))
{
+#if TOKU_DO_COMMIT_CMD_UPDATE
return do_insertion(FT_COMMIT_ANY, filenum, key, 0, txn, oplsn, false);
+#else
+ return do_nothing_with_filenum(txn, filenum);
+#endif
}
int
@@ -365,9 +383,7 @@ static int
toku_apply_rollinclude (TXNID_PAIR xid,
uint64_t num_nodes,
BLOCKNUM spilled_head,
- uint32_t spilled_head_hash __attribute__((__unused__)),
BLOCKNUM spilled_tail,
- uint32_t spilled_tail_hash,
TOKUTXN txn,
LSN oplsn,
apply_rollback_item func) {
@@ -375,7 +391,6 @@ toku_apply_rollinclude (TXNID_PAIR xid,
struct roll_entry *item;
BLOCKNUM next_log = spilled_tail;
- uint32_t next_log_hash = spilled_tail_hash;
uint64_t last_sequence = num_nodes;
bool found_head = false;
@@ -383,7 +398,7 @@ toku_apply_rollinclude (TXNID_PAIR xid,
while (next_log.b != ROLLBACK_NONE.b) {
//pin log
ROLLBACK_LOG_NODE log;
- toku_get_and_pin_rollback_log(txn, next_log, next_log_hash, &log);
+ toku_get_and_pin_rollback_log(txn, next_log, &log);
toku_rollback_verify_contents(log, xid, last_sequence - 1);
last_sequence = log->sequence;
@@ -400,16 +415,13 @@ toku_apply_rollinclude (TXNID_PAIR xid,
assert(log->sequence == 0);
}
next_log = log->previous;
- next_log_hash = log->previous_hash;
{
//Clean up transaction structure to prevent
//toku_txn_close from double-freeing
spilled_tail = next_log;
- spilled_tail_hash = next_log_hash;
if (found_head) {
assert(next_log.b == ROLLBACK_NONE.b);
spilled_head = next_log;
- spilled_head_hash = next_log_hash;
}
}
toku_rollback_log_unpin_and_remove(txn, log);
@@ -421,15 +433,13 @@ int
toku_commit_rollinclude (TXNID_PAIR xid,
uint64_t num_nodes,
BLOCKNUM spilled_head,
- uint32_t spilled_head_hash,
BLOCKNUM spilled_tail,
- uint32_t spilled_tail_hash,
TOKUTXN txn,
LSN oplsn) {
int r;
r = toku_apply_rollinclude(xid, num_nodes,
- spilled_head, spilled_head_hash,
- spilled_tail, spilled_tail_hash,
+ spilled_head,
+ spilled_tail,
txn, oplsn,
toku_commit_rollback_item);
return r;
@@ -439,15 +449,13 @@ int
toku_rollback_rollinclude (TXNID_PAIR xid,
uint64_t num_nodes,
BLOCKNUM spilled_head,
- uint32_t spilled_head_hash,
BLOCKNUM spilled_tail,
- uint32_t spilled_tail_hash,
TOKUTXN txn,
LSN oplsn) {
int r;
r = toku_apply_rollinclude(xid, num_nodes,
- spilled_head, spilled_head_hash,
- spilled_tail, spilled_tail_hash,
+ spilled_head,
+ spilled_tail,
txn, oplsn,
toku_abort_rollback_item);
return r;
diff --git a/storage/tokudb/ft-index/ft/rollback-apply.cc b/storage/tokudb/ft-index/ft/rollback-apply.cc
index 4e5b2b2b27e..4f062f4e734 100644
--- a/storage/tokudb/ft-index/ft/rollback-apply.cc
+++ b/storage/tokudb/ft-index/ft/rollback-apply.cc
@@ -143,17 +143,14 @@ apply_txn(TOKUTXN txn, LSN lsn, apply_rollback_item func) {
//printf("%s:%d abort\n", __FILE__, __LINE__);
BLOCKNUM next_log = ROLLBACK_NONE;
- uint32_t next_log_hash = 0;
bool is_current = false;
if (txn_has_current_rollback_log(txn)) {
next_log = txn->roll_info.current_rollback;
- next_log_hash = txn->roll_info.current_rollback_hash;
is_current = true;
}
else if (txn_has_spilled_rollback_logs(txn)) {
next_log = txn->roll_info.spilled_rollback_tail;
- next_log_hash = txn->roll_info.spilled_rollback_tail_hash;
}
uint64_t last_sequence = txn->roll_info.num_rollback_nodes;
@@ -161,7 +158,7 @@ apply_txn(TOKUTXN txn, LSN lsn, apply_rollback_item func) {
while (next_log.b != ROLLBACK_NONE.b) {
ROLLBACK_LOG_NODE log;
//pin log
- toku_get_and_pin_rollback_log(txn, next_log, next_log_hash, &log);
+ toku_get_and_pin_rollback_log(txn, next_log, &log);
toku_rollback_verify_contents(log, txn->txnid, last_sequence - 1);
toku_maybe_prefetch_previous_rollback_log(txn, log);
@@ -180,23 +177,19 @@ apply_txn(TOKUTXN txn, LSN lsn, apply_rollback_item func) {
assert(log->sequence == 0);
}
next_log = log->previous;
- next_log_hash = log->previous_hash;
{
//Clean up transaction structure to prevent
//toku_txn_close from double-freeing
if (is_current) {
txn->roll_info.current_rollback = ROLLBACK_NONE;
- txn->roll_info.current_rollback_hash = 0;
is_current = false;
}
else {
txn->roll_info.spilled_rollback_tail = next_log;
- txn->roll_info.spilled_rollback_tail_hash = next_log_hash;
}
if (found_head) {
assert(next_log.b == ROLLBACK_NONE.b);
txn->roll_info.spilled_rollback_head = next_log;
- txn->roll_info.spilled_rollback_head_hash = next_log_hash;
}
}
bool give_back = false;
@@ -228,13 +221,11 @@ int toku_rollback_commit(TOKUTXN txn, LSN lsn) {
num_nodes--; //Don't count the in-progress rollback log.
}
toku_logger_save_rollback_rollinclude(txn->parent, txn->txnid, num_nodes,
- txn->roll_info.spilled_rollback_head, txn->roll_info.spilled_rollback_head_hash,
- txn->roll_info.spilled_rollback_tail, txn->roll_info.spilled_rollback_tail_hash);
+ txn->roll_info.spilled_rollback_head,
+ txn->roll_info.spilled_rollback_tail);
//Remove ownership from child.
txn->roll_info.spilled_rollback_head = ROLLBACK_NONE;
- txn->roll_info.spilled_rollback_head_hash = 0;
txn->roll_info.spilled_rollback_tail = ROLLBACK_NONE;
- txn->roll_info.spilled_rollback_tail_hash = 0;
}
// if we're commiting a child rollback, put its entries into the parent
// by pinning both child and parent and then linking the child log entry
@@ -247,8 +238,7 @@ int toku_rollback_commit(TOKUTXN txn, LSN lsn) {
//Pin child log
ROLLBACK_LOG_NODE child_log;
- toku_get_and_pin_rollback_log(txn, txn->roll_info.current_rollback,
- txn->roll_info.current_rollback_hash, &child_log);
+ toku_get_and_pin_rollback_log(txn, txn->roll_info.current_rollback, &child_log);
toku_rollback_verify_contents(child_log, txn->txnid, txn->roll_info.num_rollback_nodes - 1);
// Append the list to the front of the parent.
@@ -284,7 +274,6 @@ int toku_rollback_commit(TOKUTXN txn, LSN lsn) {
toku_rollback_log_unpin_and_remove(txn, child_log);
}
txn->roll_info.current_rollback = ROLLBACK_NONE;
- txn->roll_info.current_rollback_hash = 0;
toku_maybe_spill_rollbacks(txn->parent, parent_log);
toku_rollback_log_unpin(txn->parent, parent_log);
diff --git a/storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc b/storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc
index c1ca79be7a4..bea70a5155e 100644
--- a/storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc
+++ b/storage/tokudb/ft-index/ft/rollback-ct-callbacks.cc
@@ -219,13 +219,13 @@ void toku_rollback_flush_callback (
}
}
-int toku_rollback_fetch_callback (CACHEFILE cachefile, PAIR p, int fd, BLOCKNUM logname, uint32_t fullhash,
+int toku_rollback_fetch_callback (CACHEFILE cachefile, PAIR p, int fd, BLOCKNUM logname, uint32_t fullhash UU(),
void **rollback_pv, void** UU(disk_data), PAIR_ATTR *sizep, int * UU(dirtyp), void *extraargs) {
int r;
FT CAST_FROM_VOIDP(h, extraargs);
assert(h->cf == cachefile);
ROLLBACK_LOG_NODE *result = (ROLLBACK_LOG_NODE*)rollback_pv;
- r = toku_deserialize_rollback_log_from(fd, logname, fullhash, result, h);
+ r = toku_deserialize_rollback_log_from(fd, logname, result, h);
if (r==0) {
(*result)->ct_pair = p;
*sizep = rollback_memory_size(*result);
@@ -249,13 +249,14 @@ void toku_rollback_pe_est_callback(
// callback for partially evicting a cachetable entry
int toku_rollback_pe_callback (
void *rollback_v,
- PAIR_ATTR UU(old_attr),
- PAIR_ATTR* new_attr,
- void* UU(extraargs)
+ PAIR_ATTR old_attr,
+ void* UU(extraargs),
+ void (*finalize)(PAIR_ATTR new_attr, void * extra),
+ void *finalize_extra
)
{
assert(rollback_v != NULL);
- *new_attr = old_attr;
+ finalize(old_attr, finalize_extra);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/rollback-ct-callbacks.h b/storage/tokudb/ft-index/ft/rollback-ct-callbacks.h
index e3469404a9a..aeb4650e17d 100644
--- a/storage/tokudb/ft-index/ft/rollback-ct-callbacks.h
+++ b/storage/tokudb/ft-index/ft/rollback-ct-callbacks.h
@@ -107,10 +107,11 @@ void toku_rollback_pe_est_callback(
);
int toku_rollback_pe_callback (
void *rollback_v,
- PAIR_ATTR UU(old_attr),
- PAIR_ATTR* new_attr,
- void* UU(extraargs)
- ) ;
+ PAIR_ATTR old_attr,
+ void* UU(extraargs),
+ void (*finalize)(PAIR_ATTR new_attr, void * extra),
+ void *finalize_extra
+ );
bool toku_rollback_pf_req_callback(void* UU(ftnode_pv), void* UU(read_extraargs)) ;
int toku_rollback_pf_callback(void* UU(ftnode_pv), void* UU(disk_data), void* UU(read_extraargs), int UU(fd), PAIR_ATTR* UU(sizep));
void toku_rollback_clone_callback(void* value_data, void** cloned_value_data, long* clone_size, PAIR_ATTR* new_attr, bool for_checkpoint, void* write_extraargs);
diff --git a/storage/tokudb/ft-index/ft/rollback.cc b/storage/tokudb/ft-index/ft/rollback.cc
index 87654ec5207..3b57049a33e 100644
--- a/storage/tokudb/ft-index/ft/rollback.cc
+++ b/storage/tokudb/ft-index/ft/rollback.cc
@@ -158,7 +158,7 @@ static void toku_rollback_node_save_ct_pair(CACHEKEY UU(key), void *value_data,
//
// initializes an empty rollback log node
-// Does not touch the blocknum or hash, that is the
+// Does not touch the blocknum, that is the
// responsibility of the caller
//
void rollback_empty_log_init(ROLLBACK_LOG_NODE log) {
@@ -173,7 +173,6 @@ void rollback_empty_log_init(ROLLBACK_LOG_NODE log) {
log->dirty = true;
log->sequence = 0;
log->previous = make_blocknum(0);
- log->previous_hash = 0;
log->oldest_logentry = NULL;
log->newest_logentry = NULL;
log->rollentry_arena = NULL;
@@ -185,14 +184,12 @@ void rollback_empty_log_init(ROLLBACK_LOG_NODE log) {
static void rollback_initialize_for_txn(
ROLLBACK_LOG_NODE log,
TOKUTXN txn,
- BLOCKNUM previous,
- uint32_t previous_hash
+ BLOCKNUM previous
)
{
log->txnid = txn->txnid;
log->sequence = txn->roll_info.num_rollback_nodes++;
log->previous = previous;
- log->previous_hash = previous_hash;
log->oldest_logentry = NULL;
log->newest_logentry = NULL;
log->rollentry_arena = memarena_create();
@@ -206,12 +203,11 @@ void make_rollback_log_empty(ROLLBACK_LOG_NODE log) {
}
// create and pin a new rollback log node. chain it to the other rollback nodes
-// by providing a previous blocknum/ hash and assigning the new rollback log
+// by providing a previous blocknum and assigning the new rollback log
// node the next sequence number
static void rollback_log_create (
TOKUTXN txn,
BLOCKNUM previous,
- uint32_t previous_hash,
ROLLBACK_LOG_NODE *result
)
{
@@ -220,16 +216,15 @@ static void rollback_log_create (
CACHEFILE cf = txn->logger->rollback_cachefile;
FT CAST_FROM_VOIDP(ft, toku_cachefile_get_userdata(cf));
- rollback_initialize_for_txn(log, txn, previous, previous_hash);
+ rollback_initialize_for_txn(log, txn, previous);
toku_allocate_blocknum(ft->blocktable, &log->blocknum, ft);
- log->hash = toku_cachetable_hash(ft->cf, log->blocknum);
+ const uint32_t hash = toku_cachetable_hash(ft->cf, log->blocknum);
*result = log;
- toku_cachetable_put(cf, log->blocknum, log->hash,
+ toku_cachetable_put(cf, log->blocknum, hash,
log, rollback_memory_size(log),
get_write_callbacks_for_rollback_log(ft),
toku_rollback_node_save_ct_pair);
txn->roll_info.current_rollback = log->blocknum;
- txn->roll_info.current_rollback_hash = log->hash;
}
void toku_rollback_log_unpin(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
@@ -255,14 +250,11 @@ void toku_maybe_spill_rollbacks(TOKUTXN txn, ROLLBACK_LOG_NODE log) {
if (!txn_has_spilled_rollback_logs(txn)) {
//First spilled. Copy to head.
txn->roll_info.spilled_rollback_head = txn->roll_info.current_rollback;
- txn->roll_info.spilled_rollback_head_hash = txn->roll_info.current_rollback_hash;
}
//Unconditionally copy to tail. Old tail does not need to be cached anymore.
txn->roll_info.spilled_rollback_tail = txn->roll_info.current_rollback;
- txn->roll_info.spilled_rollback_tail_hash = txn->roll_info.current_rollback_hash;
txn->roll_info.current_rollback = ROLLBACK_NONE;
- txn->roll_info.current_rollback_hash = 0;
}
}
@@ -311,8 +303,8 @@ void toku_maybe_prefetch_previous_rollback_log(TOKUTXN txn, ROLLBACK_LOG_NODE lo
BLOCKNUM name = log->previous;
int r = 0;
if (name.b != ROLLBACK_NONE.b) {
- uint32_t hash = log->previous_hash;
CACHEFILE cf = txn->logger->rollback_cachefile;
+ uint32_t hash = toku_cachetable_hash(cf, name);
FT CAST_FROM_VOIDP(h, toku_cachefile_get_userdata(cf));
bool doing_prefetch = false;
r = toku_cachefile_prefetch(cf, name, hash,
@@ -334,10 +326,11 @@ void toku_rollback_verify_contents(ROLLBACK_LOG_NODE log,
assert(log->sequence == sequence);
}
-void toku_get_and_pin_rollback_log(TOKUTXN txn, BLOCKNUM blocknum, uint32_t hash, ROLLBACK_LOG_NODE *log) {
+void toku_get_and_pin_rollback_log(TOKUTXN txn, BLOCKNUM blocknum, ROLLBACK_LOG_NODE *log) {
void * value;
CACHEFILE cf = txn->logger->rollback_cachefile;
FT CAST_FROM_VOIDP(h, toku_cachefile_get_userdata(cf));
+ uint32_t hash = toku_cachetable_hash(cf, blocknum);
int r = toku_cachetable_get_and_pin_with_dep_pairs(cf, blocknum, hash,
&value, NULL,
get_write_callbacks_for_rollback_log(h),
@@ -351,7 +344,6 @@ void toku_get_and_pin_rollback_log(TOKUTXN txn, BLOCKNUM blocknum, uint32_t hash
assert(r == 0);
ROLLBACK_LOG_NODE CAST_FROM_VOIDP(pinned_log, value);
assert(pinned_log->blocknum.b == blocknum.b);
- assert(pinned_log->hash == hash);
*log = pinned_log;
}
@@ -359,7 +351,7 @@ void toku_get_and_pin_rollback_log_for_new_entry (TOKUTXN txn, ROLLBACK_LOG_NODE
ROLLBACK_LOG_NODE pinned_log = NULL;
invariant(txn->state == TOKUTXN_LIVE || txn->state == TOKUTXN_PREPARING); // hot indexing may call this function for prepared transactions
if (txn_has_current_rollback_log(txn)) {
- toku_get_and_pin_rollback_log(txn, txn->roll_info.current_rollback, txn->roll_info.current_rollback_hash, &pinned_log);
+ toku_get_and_pin_rollback_log(txn, txn->roll_info.current_rollback, &pinned_log);
toku_rollback_verify_contents(pinned_log, txn->txnid, txn->roll_info.num_rollback_nodes - 1);
} else {
// For each transaction, we try to acquire the first rollback log
@@ -378,15 +370,13 @@ void toku_get_and_pin_rollback_log_for_new_entry (TOKUTXN txn, ROLLBACK_LOG_NODE
rollback_initialize_for_txn(
pinned_log,
txn,
- txn->roll_info.spilled_rollback_tail,
- txn->roll_info.spilled_rollback_tail_hash
+ txn->roll_info.spilled_rollback_tail
);
txn->roll_info.current_rollback = pinned_log->blocknum;
- txn->roll_info.current_rollback_hash = pinned_log->hash;
}
}
if (pinned_log == NULL) {
- rollback_log_create(txn, txn->roll_info.spilled_rollback_tail, txn->roll_info.spilled_rollback_tail_hash, &pinned_log);
+ rollback_log_create(txn, txn->roll_info.spilled_rollback_tail, &pinned_log);
}
}
assert(pinned_log->txnid.parent_id64 == txn->txnid.parent_id64);
diff --git a/storage/tokudb/ft-index/ft/rollback.h b/storage/tokudb/ft-index/ft/rollback.h
index a1c8b575290..2e9493b0e6b 100644
--- a/storage/tokudb/ft-index/ft/rollback.h
+++ b/storage/tokudb/ft-index/ft/rollback.h
@@ -103,8 +103,8 @@ void toku_poll_txn_progress_function(TOKUTXN txn, uint8_t is_commit, uint8_t sta
// is a current rollback node to use, pin it, otherwise create one.
void toku_get_and_pin_rollback_log_for_new_entry(TOKUTXN txn, ROLLBACK_LOG_NODE *log);
-// get a specific rollback by blocknum and hash
-void toku_get_and_pin_rollback_log(TOKUTXN txn, BLOCKNUM blocknum, uint32_t hash, ROLLBACK_LOG_NODE *log);
+// get a specific rollback by blocknum
+void toku_get_and_pin_rollback_log(TOKUTXN txn, BLOCKNUM blocknum, ROLLBACK_LOG_NODE *log);
// unpin a rollback node from the cachetable
void toku_rollback_log_unpin(TOKUTXN txn, ROLLBACK_LOG_NODE log);
@@ -155,11 +155,9 @@ struct rollback_log_node {
// the sequence is between 0 and totalnodes-1
uint64_t sequence;
BLOCKNUM blocknum; // on which block does this node live?
- uint32_t hash;
// which block number is the previous in the chain of rollback nodes
// that make up this rollback log?
BLOCKNUM previous;
- uint32_t previous_hash;
struct roll_entry *oldest_logentry;
struct roll_entry *newest_logentry;
MEMARENA rollentry_arena;
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 44cc3a6cf98..b45e4c03bb8 100644
--- a/storage/tokudb/ft-index/ft/rollback_log_node_cache.cc
+++ b/storage/tokudb/ft-index/ft/rollback_log_node_cache.cc
@@ -96,7 +96,6 @@ PATENT RIGHTS GRANT:
void rollback_log_node_cache::init (uint32_t max_num_avail_nodes) {
XMALLOC_N(max_num_avail_nodes, m_avail_blocknums);
- XMALLOC_N(max_num_avail_nodes, m_hashes);
m_max_num_avail = max_num_avail_nodes;
m_first = 0;
m_num_avail = 0;
@@ -110,7 +109,6 @@ void rollback_log_node_cache::init (uint32_t max_num_avail_nodes) {
void rollback_log_node_cache::destroy() {
toku_mutex_destroy(&m_mutex);
toku_free(m_avail_blocknums);
- toku_free(m_hashes);
}
// returns true if rollback log node was successfully added,
@@ -125,7 +123,6 @@ bool rollback_log_node_cache::give_rollback_log_node(TOKUTXN txn, ROLLBACK_LOG_N
index -= m_max_num_avail;
}
m_avail_blocknums[index].b = log->blocknum.b;
- m_hashes[index] = log->hash;
m_num_avail++;
}
toku_mutex_unlock(&m_mutex);
@@ -144,11 +141,9 @@ bool rollback_log_node_cache::give_rollback_log_node(TOKUTXN txn, ROLLBACK_LOG_N
// for getting a rollback log node
void rollback_log_node_cache::get_rollback_log_node(TOKUTXN txn, ROLLBACK_LOG_NODE* log){
BLOCKNUM b = ROLLBACK_NONE;
- uint32_t hash;
toku_mutex_lock(&m_mutex);
if (m_num_avail > 0) {
b.b = m_avail_blocknums[m_first].b;
- hash = m_hashes[m_first];
m_num_avail--;
if (++m_first >= m_max_num_avail) {
m_first = 0;
@@ -156,7 +151,7 @@ void rollback_log_node_cache::get_rollback_log_node(TOKUTXN txn, ROLLBACK_LOG_NO
}
toku_mutex_unlock(&m_mutex);
if (b.b != ROLLBACK_NONE.b) {
- toku_get_and_pin_rollback_log(txn, b, hash, log);
+ toku_get_and_pin_rollback_log(txn, b, log);
invariant(rollback_log_is_unused(*log));
} else {
*log = NULL;
diff --git a/storage/tokudb/ft-index/ft/rollback_log_node_cache.h b/storage/tokudb/ft-index/ft/rollback_log_node_cache.h
index 73578444bfa..0db99faf23b 100644
--- a/storage/tokudb/ft-index/ft/rollback_log_node_cache.h
+++ b/storage/tokudb/ft-index/ft/rollback_log_node_cache.h
@@ -108,7 +108,6 @@ public:
private:
BLOCKNUM* m_avail_blocknums;
- uint32_t* m_hashes;
uint32_t m_first;
uint32_t m_num_avail;
uint32_t m_max_num_avail;
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-5097.cc b/storage/tokudb/ft-index/ft/tests/cachetable-5097.cc
index 4352499875e..7c958dd3049 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-5097.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-5097.cc
@@ -103,15 +103,16 @@ static int
pe_callback (
void *ftnode_pv __attribute__((__unused__)),
PAIR_ATTR bytes_to_free __attribute__((__unused__)),
- PAIR_ATTR* bytes_freed,
- void* extraargs __attribute__((__unused__))
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR bytes_freed, void *extra),
+ void *finalize_extra
)
{
- *bytes_freed = make_pair_attr(1);
if (check_pe_callback) {
pe_callback_called = true;
}
usleep(4*1024*1024);
+ finalize(make_pair_attr(1), finalize_extra);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-5978.cc b/storage/tokudb/ft-index/ft/tests/cachetable-5978.cc
index fb8273eef72..c72d67909e1 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-5978.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-5978.cc
@@ -97,7 +97,7 @@ PATENT RIGHTS GRANT:
// #5978 is fixed. Here is what we do. We have four pairs with
// blocknums and fullhashes of 1,2,3,4. The cachetable has only
// two bucket mutexes, so 1 and 3 share a pair mutex, as do 2 and 4.
-// We pin all four with expensive write locks. Then, on backgroud threads,
+// We pin all four with expensive write locks. Then, on backgroud threads,
// we call get_and_pin_nonblocking on 3, where the unlockers unpins 2, and
// we call get_and_pin_nonblocking on 4, where the unlockers unpins 1. Run this
// enough times, and we should see a deadlock before the fix, and no deadlock
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction2.cc b/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction2.cc
index 7704a5b3c63..23926241b97 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction2.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction2.cc
@@ -155,15 +155,16 @@ static int
pe_callback (
void *ftnode_pv,
PAIR_ATTR UU(bytes_to_free),
- PAIR_ATTR* bytes_freed,
- void* extraargs __attribute__((__unused__))
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR bytes_freed, void *extra),
+ void *finalize_extra
)
{
- *bytes_freed = make_pair_attr(bytes_to_free.size-1);
expected_bytes_to_free--;
int* CAST_FROM_VOIDP(foo, ftnode_pv);
int blah = *foo;
*foo = blah-1;
+ finalize(make_pair_attr(bytes_to_free.size-1), finalize_extra);
return 0;
}
@@ -171,10 +172,12 @@ static int
other_pe_callback (
void *ftnode_pv __attribute__((__unused__)),
PAIR_ATTR bytes_to_free __attribute__((__unused__)),
- PAIR_ATTR* bytes_freed __attribute__((__unused__)),
- void* extraargs __attribute__((__unused__))
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR bytes_freed, void *extra),
+ void *finalize_extra
)
{
+ finalize(bytes_to_free, finalize_extra);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction3.cc b/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction3.cc
index 99e5c3e5c5e..735bde724d0 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction3.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction3.cc
@@ -169,17 +169,18 @@ static int
pe_callback (
void *ftnode_pv,
PAIR_ATTR UU(bytes_to_free),
- PAIR_ATTR* bytes_freed,
- void* extraargs __attribute__((__unused__))
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR bytes_freed, void *extra),
+ void *finalize_extra
)
{
- *bytes_freed = make_pair_attr(bytes_to_free.size-1);
usleep(1*1024*1024);
if (verbose) printf("calling pe_callback\n");
expected_bytes_to_free--;
int* CAST_FROM_VOIDP(foo, ftnode_pv);
int blah = *foo;
*foo = blah-1;
+ finalize(make_pair_attr(bytes_to_free.size-1), finalize_extra);
return 0;
}
@@ -187,11 +188,12 @@ static int
other_pe_callback (
void *ftnode_pv __attribute__((__unused__)),
PAIR_ATTR bytes_to_free __attribute__((__unused__)),
- PAIR_ATTR* bytes_freed __attribute__((__unused__)),
- void* extraargs __attribute__((__unused__))
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR bytes_freed, void *extra),
+ void *finalize_extra
)
{
- *bytes_freed = bytes_to_free;
+ finalize(bytes_to_free, finalize_extra);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction4.cc b/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction4.cc
index e5db222964b..9dc1f1a5218 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction4.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-clock-eviction4.cc
@@ -164,12 +164,13 @@ static int
pe_callback (
void *ftnode_pv __attribute__((__unused__)),
PAIR_ATTR bytes_to_free __attribute__((__unused__)),
- PAIR_ATTR* bytes_freed,
- void* extraargs __attribute__((__unused__))
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR bytes_freed, void *extra),
+ void *finalize_extra
)
{
assert(false);
- *bytes_freed = bytes_to_free;
+ finalize(bytes_to_free, finalize_extra);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-eviction-close-test2.cc b/storage/tokudb/ft-index/ft/tests/cachetable-eviction-close-test2.cc
index 1d228bf0d6c..c8004ca1cb1 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-eviction-close-test2.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-eviction-close-test2.cc
@@ -154,12 +154,13 @@ static int
pe_callback (
void *ftnode_pv __attribute__((__unused__)),
PAIR_ATTR bytes_to_free __attribute__((__unused__)),
- PAIR_ATTR* bytes_freed,
- void* extraargs __attribute__((__unused__))
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR bytes_freed, void *extra),
+ void *finalize_extra
)
{
- *bytes_freed = make_pair_attr(bytes_to_free.size-7);
sleep(2);
+ finalize(bytes_to_free, finalize_extra);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-eviction-getandpin-test2.cc b/storage/tokudb/ft-index/ft/tests/cachetable-eviction-getandpin-test2.cc
index e91b59fe8f8..d65048f797a 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-eviction-getandpin-test2.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-eviction-getandpin-test2.cc
@@ -110,12 +110,13 @@ static int
pe_callback (
void *ftnode_pv __attribute__((__unused__)),
PAIR_ATTR bytes_to_free __attribute__((__unused__)),
- PAIR_ATTR* bytes_freed,
- void* extraargs __attribute__((__unused__))
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR new_attr, void *extra),
+ void *finalize_extra
)
{
sleep(3);
- *bytes_freed = make_pair_attr(bytes_to_free.size-7);
+ finalize(make_pair_attr(bytes_to_free.size - 7), finalize_extra);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/tests/cachetable-evictor-class.cc b/storage/tokudb/ft-index/ft/tests/cachetable-evictor-class.cc
index 792fced4cad..d0dff7d9570 100644
--- a/storage/tokudb/ft-index/ft/tests/cachetable-evictor-class.cc
+++ b/storage/tokudb/ft-index/ft/tests/cachetable-evictor-class.cc
@@ -116,7 +116,9 @@ void evictor_unit_test::init() {
ZERO_STRUCT(m_cf_list);
m_pl.init();
m_cf_list.init();
- m_kb = toku_kibbutz_create(1);
+ m_kb = NULL;
+ int r = toku_kibbutz_create(1, &m_kb);
+ assert(r == 0);
}
// destroy class after tests have run
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 e5e8dcc8643..4bf02021d23 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-bfe-query.cc
@@ -146,7 +146,7 @@ test_prefetch_read(int fd, FT_HANDLE UU(brt), FT brt_h) {
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), &attr, brt_h);
+ 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);
@@ -168,7 +168,7 @@ test_prefetch_read(int fd, FT_HANDLE UU(brt), FT brt_h) {
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), &attr, brt_h);
+ 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);
@@ -190,7 +190,7 @@ test_prefetch_read(int fd, FT_HANDLE UU(brt), FT brt_h) {
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), &attr, brt_h);
+ 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);
@@ -211,7 +211,7 @@ test_prefetch_read(int fd, FT_HANDLE UU(brt), FT brt_h) {
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), &attr, brt_h);
+ 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);
@@ -232,7 +232,7 @@ test_prefetch_read(int fd, FT_HANDLE UU(brt), FT brt_h) {
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), &attr, brt_h);
+ 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);
@@ -292,11 +292,11 @@ test_subset_read(int fd, FT_HANDLE UU(brt), FT brt_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), &attr, brt_h);
+ 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), &attr, brt_h);
+ 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(brt), FT brt_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), &attr, brt_h);
+ 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), &attr, brt_h);
+ 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(brt), FT brt_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), &attr, brt_h);
+ 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), &attr, brt_h);
+ 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);
@@ -420,7 +420,8 @@ test_prefetching(void) {
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
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 606832a5df6..25daccfd120 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-clock-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-clock-test.cc
@@ -154,12 +154,12 @@ test1(int fd, FT brt_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, &attr, brt_h);
+ 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, &attr, brt_h);
+ 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);
@@ -172,12 +172,12 @@ test1(int fd, FT brt_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, &attr, brt_h);
+ 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, &attr, brt_h);
+ 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);
@@ -190,15 +190,15 @@ test1(int fd, FT brt_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, &attr, brt_h);
+ 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, &attr, brt_h);
- toku_ftnode_pe_callback(*dn, attr, &attr, brt_h);
- toku_ftnode_pe_callback(*dn, attr, &attr, brt_h);
- toku_ftnode_pe_callback(*dn, attr, &attr, brt_h);
+ 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);
}
@@ -252,11 +252,11 @@ test2(int fd, FT brt_h, FTNODE *dn) {
assert(!BP_SHOULD_EVICT(*dn, 1));
PAIR_ATTR attr;
memset(&attr,0,sizeof(attr));
- toku_ftnode_pe_callback(*dn, attr, &attr, brt_h);
+ 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, &attr, brt_h);
+ 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);
@@ -355,7 +355,8 @@ test_serialize_nonleaf(void) {
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
@@ -438,7 +439,8 @@ test_serialize_leaf(void) {
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
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 a5cbc2f684e..42351e3108d 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-serialize-benchmark.cc
@@ -189,7 +189,8 @@ test_serialize_leaf(int valsize, int nelts, double entropy) {
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
brt_h->compare_fun = long_key_cmp;
@@ -319,7 +320,8 @@ test_serialize_nonleaf(int valsize, int nelts, double entropy) {
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
brt_h->compare_fun = long_key_cmp;
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 774948ddf95..adfd2b7efd4 100644
--- a/storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc
+++ b/storage/tokudb/ft-index/ft/tests/ft-serialize-test.cc
@@ -187,8 +187,7 @@ setup_dn(enum ftnode_verify_type bft, int fd, FT brt_h, FTNODE *dn, FTNODE_DISK_
// if read_none, get rid of the compressed bp's
if (bft == read_none) {
if ((*dn)->height == 0) {
- PAIR_ATTR attr;
- toku_ftnode_pe_callback(*dn, make_pair_attr(0xffffffff), &attr, brt_h);
+ 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) {
@@ -213,14 +212,14 @@ setup_dn(enum ftnode_verify_type bft, int fd, FT brt_h, FTNODE *dn, FTNODE_DISK_
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), &attr, brt_h);
+ 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), &attr, brt_h);
+ 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);
}
@@ -306,7 +305,8 @@ test_serialize_leaf_check_msn(enum ftnode_verify_type bft, bool do_clone) {
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
@@ -449,7 +449,8 @@ test_serialize_leaf_with_large_pivots(enum ftnode_verify_type bft, bool do_clone
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
{ int r_truncate = ftruncate(fd, 0); CKERR(r_truncate); }
@@ -586,7 +587,8 @@ test_serialize_leaf_with_many_rows(enum ftnode_verify_type bft, bool do_clone) {
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
@@ -733,7 +735,8 @@ test_serialize_leaf_with_large_rows(enum ftnode_verify_type bft, bool do_clone)
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
@@ -881,7 +884,8 @@ test_serialize_leaf_with_empty_basement_nodes(enum ftnode_verify_type bft, bool
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
@@ -1009,7 +1013,8 @@ test_serialize_leaf_with_multiple_empty_basement_nodes(enum ftnode_verify_type b
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
@@ -1134,7 +1139,8 @@ test_serialize_nonleaf(enum ftnode_verify_type bft, bool do_clone) {
TXNID_NONE,
4*1024*1024,
128*1024,
- TOKU_DEFAULT_COMPRESSION_METHOD);
+ TOKU_DEFAULT_COMPRESSION_METHOD,
+ 16);
brt->ft = brt_h;
toku_blocktable_create_new(&brt_h->blocktable);
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 d7b3504e8ad..98a8efc8393 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
@@ -170,7 +170,7 @@ static void test_extractor(int nrows, int nrowsets, bool expect_fail) {
}
FTLOADER loader;
- r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, brts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, TXNID_NONE, true, 0, false);
+ r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, brts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, nullptr, true, 0, false);
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 b4ff9265c02..93fdd308ce1 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
@@ -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, brts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, TXNID_NONE, true, 0, false);
+ r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, brts, dbs, fnames, compares, "tempXXXXXX", ZERO_LSN, nullptr, true, 0, false);
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 67591c92cd1..ee4e0f99aa1 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-extractor.cc
@@ -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, brts, dbs, fnames, compares, temp, ZERO_LSN, TXNID_NONE, true, 0, false);
+ r = toku_ft_loader_open(&loader, NULL, generate, NULL, N, brts, dbs, fnames, compares, temp, ZERO_LSN, nullptr, true, 0, false);
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 80326584c35..6f495bfb496 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
@@ -412,7 +412,7 @@ static void test (const char *directory, bool is_error) {
bt_compare_functions,
"tempxxxxxx",
*lsnp,
- TXNID_NONE, true, 0, false);
+ nullptr, true, 0, false);
assert(r==0);
}
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 a2f39e1bfe1..f351185a525 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-open.cc
@@ -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, brts, dbs, fnames, compares, "", ZERO_LSN, TXNID_NONE, true, 0, false);
+ r = toku_ft_loader_open(&loader, NULL, NULL, NULL, ndbs, brts, dbs, fnames, compares, "", ZERO_LSN, nullptr, true, 0, false);
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 5f0728cc02c..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_brt_from_q_in_C(&bl, &desc, fd, 1000, q2, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD);
+ 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 67bb47a7c5e..53d6bde27a0 100644
--- a/storage/tokudb/ft-index/ft/tests/ftloader-test-writer.cc
+++ b/storage/tokudb/ft-index/ft/tests/ftloader-test-writer.cc
@@ -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_brt_from_q_in_C(&bl, &desc, fd, 1000, q2, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD);
+ 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 4b7a3139adb..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_brt_from_q_in_C(&bl, &desc, fd, 1000, q, size_est, 0, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD);
+ 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/make-tree.cc b/storage/tokudb/ft-index/ft/tests/make-tree.cc
index 9451c7e3448..56df485173d 100644
--- a/storage/tokudb/ft-index/ft/tests/make-tree.cc
+++ b/storage/tokudb/ft-index/ft/tests/make-tree.cc
@@ -124,8 +124,9 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
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 cmd = { FT_INSERT, msn, xids_get_root_xids(), .u = {.id = { &thekey, &theval }} };
- toku_ft_bn_apply_cmd_once(BLB(leafnode,0), &cmd, idx, NULL, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ 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;
diff --git a/storage/tokudb/ft-index/ft/tests/mempool-115.cc b/storage/tokudb/ft-index/ft/tests/mempool-115.cc
new file mode 100644
index 00000000000..8b5d2d69195
--- /dev/null
+++ b/storage/tokudb/ft-index/ft/tests/mempool-115.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, 2008 Tokutek Inc. All rights reserved."
+
+#include "test.h"
+#include "bndata.h"
+
+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);
+ bn->get_space_for_insert(
+ idx,
+ key,
+ keysize,
+ size_needed,
+ &r
+ );
+ resource_assert(r);
+ r->type = LE_CLEAN;
+ r->u.clean.vallen = valsize;
+ memcpy(r->u.clean.val, val, valsize);
+}
+
+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);
+ bn->get_space_for_overwrite(
+ idx,
+ key,
+ keysize,
+ size_needed, // old_le_size
+ size_needed,
+ &r
+ );
+ resource_assert(r);
+ r->type = LE_CLEAN;
+ r->u.clean.vallen = valsize;
+ memcpy(r->u.clean.val, val, valsize);
+}
+
+
+class bndata_bugfix_test {
+public:
+ void
+ run_test(void) {
+ // struct ft_handle source_ft;
+ struct ftnode sn;
+
+ // just copy this code from a previous test
+ // don't care what it does, just want to get a node up and running
+ sn.flags = 0x11223344;
+ sn.thisnodename.b = 20;
+ sn.layout_version = FT_LAYOUT_VERSION;
+ sn.layout_version_original = FT_LAYOUT_VERSION;
+ sn.height = 0;
+ sn.n_children = 2;
+ sn.dirty = 1;
+ sn.oldest_referenced_xid_known = TXNID_NONE;
+ MALLOC_N(sn.n_children, sn.bp);
+ MALLOC_N(1, sn.childkeys);
+ toku_memdup_dbt(&sn.childkeys[0], "b", 2);
+ sn.totalchildkeylens = 2;
+ BP_STATE(&sn,0) = PT_AVAIL;
+ BP_STATE(&sn,1) = PT_AVAIL;
+ set_BLB(&sn, 0, toku_create_empty_bn());
+ set_BLB(&sn, 1, toku_create_empty_bn());
+ 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);
+
+
+
+ // now this is the test. If I keep getting space for overwrite
+ // like crazy, it should expose the bug
+ bn_data* bnd = BLB_DATA(&sn, 0);
+ size_t old_size = bnd->m_buffer_mempool.size;
+ if (verbose) printf("frag size: %zu\n", bnd->m_buffer_mempool.frag_size);
+ if (verbose) printf("size: %zu\n", bnd->m_buffer_mempool.size);
+ for (uint32_t i = 0; i < 1000000; i++) {
+ le_overwrite(bnd, 0, "a", 2, "aval", 5);
+ }
+ if (verbose) printf("frag size: %zu\n", bnd->m_buffer_mempool.frag_size);
+ if (verbose) printf("size: %zu\n", bnd->m_buffer_mempool.size);
+ size_t new_size = bnd->m_buffer_mempool.size;
+ // just a crude test to make sure we did not grow unbounded.
+ // if this assert ever fails, revisit the code and see what is going
+ // on. It may be that some algorithm has changed.
+ assert(new_size < 5*old_size);
+
+
+ for (int i = 0; i < sn.n_children-1; ++i) {
+ toku_free(sn.childkeys[i].data);
+ }
+ for (int i = 0; i < sn.n_children; i++) {
+ destroy_basement_node(BLB(&sn, i));
+ }
+ toku_free(sn.bp);
+ toku_free(sn.childkeys);
+ }
+};
+
+int
+test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute__((__unused__))) {
+ bndata_bugfix_test t;
+ t.run_test();
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/ft/tests/msnfilter.cc b/storage/tokudb/ft-index/ft/tests/msnfilter.cc
index 0b7bd426208..1c1cba86f1c 100644
--- a/storage/tokudb/ft-index/ft/tests/msnfilter.cc
+++ b/storage/tokudb/ft-index/ft/tests/msnfilter.cc
@@ -132,8 +132,9 @@ append_leaf(FT_HANDLE brt, FTNODE leafnode, void *key, uint32_t keylen, void *va
MSN msn = next_dummymsn();
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_cmd(brt->ft->compare_fun, brt->ft->update_fun, &brt->ft->cmp_descriptor, leafnode, -1, &cmd, make_gc_info(false), 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(brt, &thekey, lookup_checkf, &pair);
assert(r==0);
@@ -141,7 +142,7 @@ append_leaf(FT_HANDLE brt, FTNODE leafnode, void *key, uint32_t keylen, void *va
}
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, make_gc_info(false), nullptr, nullptr);
+ 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
{
@@ -154,7 +155,7 @@ append_leaf(FT_HANDLE brt, FTNODE leafnode, void *key, uint32_t keylen, void *va
msn = next_dummymsn();
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, make_gc_info(false), nullptr, nullptr);
+ 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
{
@@ -166,7 +167,7 @@ append_leaf(FT_HANDLE brt, FTNODE leafnode, void *key, uint32_t keylen, void *va
// now verify that message with lesser (older) msn is rejected
msn.msn = msn.msn - 10;
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, make_gc_info(false), nullptr, nullptr);
+ 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
{
diff --git a/storage/tokudb/ft-index/ft/tests/orthopush-flush.cc b/storage/tokudb/ft-index/ft/tests/orthopush-flush.cc
index c2827ddf29b..cfac10fb921 100644
--- a/storage/tokudb/ft-index/ft/tests/orthopush-flush.cc
+++ b/storage/tokudb/ft-index/ft/tests/orthopush-flush.cc
@@ -96,6 +96,7 @@ PATENT RIGHTS GRANT:
static TOKUTXN const null_txn = 0;
static DB * const null_db = 0;
static const char *fname = TOKU_TEST_FILENAME;
+static txn_gc_info non_mvcc_gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
static int dummy_cmp(DB *db __attribute__((unused)),
const DBT *a, const DBT *b) {
@@ -217,8 +218,8 @@ insert_random_message_to_bn(
*keylenp = keydbt->size;
*keyp = toku_xmemdup(keydbt->data, keydbt->size);
int64_t numbytes;
- toku_le_apply_msg(&msg, NULL, NULL, 0, TXNID_NONE, make_gc_info(false), save, &numbytes);
- toku_ft_bn_apply_cmd(t->ft->compare_fun, t->ft->update_fun, NULL, blb, &msg, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ toku_le_apply_msg(&msg, NULL, NULL, 0, &non_mvcc_gc_info, save, &numbytes);
+ 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;
}
@@ -267,12 +268,12 @@ insert_same_message_to_bns(
*keylenp = keydbt->size;
*keyp = toku_xmemdup(keydbt->data, keydbt->size);
int64_t numbytes;
- toku_le_apply_msg(&msg, NULL, NULL, 0, TXNID_NONE, make_gc_info(false), save, &numbytes);
- toku_ft_bn_apply_cmd(t->ft->compare_fun, t->ft->update_fun, NULL, blb1, &msg, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ toku_le_apply_msg(&msg, NULL, NULL, 0, &non_mvcc_gc_info, save, &numbytes);
+ 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_cmd(t->ft->compare_fun, t->ft->update_fun, NULL, blb2, &msg, TXNID_NONE, make_gc_info(false), 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;
}
@@ -684,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_cmd(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child, -1, parent_messages[i], make_gc_info(false), 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) {
@@ -908,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_cmd(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child, -1, parent_messages[i], make_gc_info(false), 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) {
@@ -1104,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_cmd(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child1, -1, parent_messages[i], make_gc_info(false), NULL, NULL);
- toku_ft_leaf_apply_cmd(t->ft->compare_fun, t->ft->update_fun, &t->ft->descriptor, child2, -1, parent_messages[i], make_gc_info(false), 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) {
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 d0997cca25c..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
@@ -260,8 +260,7 @@ doit (bool keep_other_bn_in_memory) {
assert(node->n_children == 2);
// a hack to get the basement nodes evicted
for (int i = 0; i < 20; i++) {
- PAIR_ATTR attr;
- toku_ftnode_pe_callback(node, make_pair_attr(0xffffffff), &attr, brt->ft);
+ 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
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 01b9629c94d..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
@@ -205,7 +205,8 @@ doit (void) {
toku_fill_dbt(&left, "g", 2);
DBT right;
toku_fill_dbt(&right, "n", 2);
- r = toku_ft_hot_optimize(t, &left, &right, NULL, NULL);
+ uint64_t loops_run = 0;
+ r = toku_ft_hot_optimize(t, &left, &right, NULL, NULL, &loops_run);
assert(r==0);
// at this point, we have should have flushed
diff --git a/storage/tokudb/ft-index/ft/tests/test-inc-split.cc b/storage/tokudb/ft-index/ft/tests/test-inc-split.cc
index 6d0a6349b5c..cafcb496f7a 100644
--- a/storage/tokudb/ft-index/ft/tests/test-inc-split.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-inc-split.cc
@@ -130,10 +130,10 @@ const char *fname = TOKU_TEST_FILENAME;
static void
doit (int ksize __attribute__((__unused__))) {
- BLOCKNUM cnodes[FT_FANOUT], bnode, anode;
+ BLOCKNUM cnodes[16], bnode, anode;
- char *keys[FT_FANOUT-1];
- int keylens[FT_FANOUT-1];
+ char *keys[16-1];
+ int keylens[16-1];
int i;
int r;
@@ -144,7 +144,7 @@ doit (int ksize __attribute__((__unused__))) {
toku_testsetup_initialize(); // must precede any other toku_testsetup calls
- for (i=0; i<FT_FANOUT; i++) {
+ for (i=0; i<16; i++) {
r=toku_testsetup_leaf(t, &cnodes[i], 1, NULL, NULL);
assert(r==0);
char key[KSIZE+10];
@@ -156,16 +156,16 @@ doit (int ksize __attribute__((__unused__))) {
}
// Now we have a bunch of leaves, all of which are with 100 bytes of full.
- for (i=0; i+1<FT_FANOUT; i++) {
+ for (i=0; i+1<16; i++) {
char key[TOKU_PSIZE];
keylens[i]=1+snprintf(key, TOKU_PSIZE, "%08d", (i+1)*10000);
keys[i]=toku_strdup(key);
}
- r = toku_testsetup_nonleaf(t, 1, &bnode, FT_FANOUT, cnodes, keys, keylens);
+ r = toku_testsetup_nonleaf(t, 1, &bnode, 16, cnodes, keys, keylens);
assert(r==0);
- for (i=0; i+1<FT_FANOUT; i++) {
+ for (i=0; i+1<16; i++) {
toku_free(keys[i]);
}
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 2b6a1ee8488..b0a5dfe7817 100644
--- a/storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc
+++ b/storage/tokudb/ft-index/ft/tests/test-leafentry-nested.cc
@@ -453,12 +453,12 @@ test_le_apply(ULE ule_initial, FT_MSG msg, ULE ule_expected) {
size_t result_memsize = 0;
int64_t ignoreme;
+ txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, true);
toku_le_apply_msg(msg,
le_initial,
nullptr,
0,
- TXNID_NONE,
- make_gc_info(true),
+ &gc_info,
&le_result,
&ignoreme);
if (le_result) {
@@ -751,7 +751,8 @@ static bool ule_worth_running_garbage_collection(ULE ule, TXNID oldest_reference
LEAFENTRY le;
int r = le_pack(ule, nullptr, 0, nullptr, 0, 0, &le); CKERR(r);
invariant_notnull(le);
- bool worth_running = toku_le_worth_running_garbage_collection(le, oldest_referenced_xid_known);
+ 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);
toku_free(le);
return worth_running;
}
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 a8c36557e00..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
@@ -369,8 +369,7 @@ doit (void) {
assert_zero(r);
toku_pin_node_with_min_bfe(&node, node_internal, t);
for (int i = 0; i < 20; i++) {
- PAIR_ATTR attr;
- toku_ftnode_pe_callback(node, make_pair_attr(0xffffffff), &attr, t->ft);
+ toku_ftnode_pe_callback(node, make_pair_attr(0xffffffff), t->ft, def_pe_finalize_impl, nullptr);
}
assert(BP_STATE(node,0) == PT_COMPRESSED);
toku_unpin_ftnode(t->ft, node);
diff --git a/storage/tokudb/ft-index/ft/tests/test.h b/storage/tokudb/ft-index/ft/tests/test.h
index 4a1bd64354f..ad1fc7c148e 100644
--- a/storage/tokudb/ft-index/ft/tests/test.h
+++ b/storage/tokudb/ft-index/ft/tests/test.h
@@ -239,17 +239,21 @@ def_pe_est_callback(
}
static UU() int
-def_pe_callback (
+def_pe_callback(
void *ftnode_pv __attribute__((__unused__)),
PAIR_ATTR bytes_to_free __attribute__((__unused__)),
- PAIR_ATTR* bytes_freed,
- void* extraargs __attribute__((__unused__))
- )
+ void* extraargs __attribute__((__unused__)),
+ void (*finalize)(PAIR_ATTR bytes_freed, void *extra),
+ void *finalize_extra
+ )
{
- *bytes_freed = bytes_to_free;
+ finalize(bytes_to_free, finalize_extra);
return 0;
}
+static UU() void
+def_pe_finalize_impl(PAIR_ATTR UU(bytes_freed), void *UU(extra)) { }
+
static UU() bool def_pf_req_callback(void* UU(ftnode_pv), void* UU(read_extraargs)) {
return false;
}
diff --git a/storage/tokudb/ft-index/ft/tests/upgrade_test_simple.cc b/storage/tokudb/ft-index/ft/tests/upgrade_test_simple.cc
index 918d48d3c5b..31811527aa2 100644
--- a/storage/tokudb/ft-index/ft/tests/upgrade_test_simple.cc
+++ b/storage/tokudb/ft-index/ft/tests/upgrade_test_simple.cc
@@ -144,7 +144,8 @@ static int
do_hot_optimize(FT_HANDLE t, CACHETABLE UU(ct), void *extra)
{
float *CAST_FROM_VOIDP(fraction, extra);
- int r = toku_ft_hot_optimize(t, NULL, NULL, progress, extra);
+ uint64_t loops_run = 0;
+ int r = toku_ft_hot_optimize(t, NULL, NULL, progress, extra, &loops_run);
if (*fraction < 1.0) {
CKERR2(r, 1);
} else {
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 1b90d8975fa..edb1b6262a3 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-bad-msn.cc
@@ -128,7 +128,8 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
// apply an insert to the leaf node
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, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
+ 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;
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 155cf67ad3e..156fc36666f 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-bad-pivots.cc
@@ -116,7 +116,8 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
// apply an insert to the leaf node
MSN msn = next_dummymsn();
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, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
+ 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;
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 c5b69bab74c..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
@@ -117,7 +117,8 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
// apply an insert to the leaf node
MSN msn = next_dummymsn();
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, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
+ 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;
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 2a2f4079632..219f1f7da59 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-dup-pivots.cc
@@ -116,7 +116,8 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
// apply an insert to the leaf node
MSN msn = next_dummymsn();
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, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
+ 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;
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 a3290028ac4..f68b4d72e53 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-misrouted-msgs.cc
@@ -117,7 +117,8 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
// apply an insert to the leaf node
MSN msn = next_dummymsn();
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, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
+ 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;
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 ebcf429ab4f..c1e9f6f5727 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-unsorted-leaf.cc
@@ -119,7 +119,8 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
// apply an insert to the leaf node
MSN msn = next_dummymsn();
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, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
+ 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;
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 acadb9d8111..c209e679072 100644
--- a/storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc
+++ b/storage/tokudb/ft-index/ft/tests/verify-unsorted-pivots.cc
@@ -116,7 +116,8 @@ append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen)
// apply an insert to the leaf node
MSN msn = next_dummymsn();
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, TXNID_NONE, make_gc_info(false), NULL, NULL);
+ txn_gc_info gc_info(nullptr, TXNID_NONE, TXNID_NONE, false);
+ 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;
diff --git a/storage/tokudb/ft-index/ft/txn.cc b/storage/tokudb/ft-index/ft/txn.cc
index 29fcd28f155..403c8e92c45 100644
--- a/storage/tokudb/ft-index/ft/txn.cc
+++ b/storage/tokudb/ft-index/ft/txn.cc
@@ -239,7 +239,6 @@ toku_txn_begin_with_xid (
}
else {
parent->child_manager->start_child_txn_for_recovery(txn, parent, xid);
- txn->oldest_referenced_xid = parent->oldest_referenced_xid;
}
}
else {
@@ -255,7 +254,6 @@ toku_txn_begin_with_xid (
}
else {
parent->child_manager->start_child_txn(txn, parent);
- txn->oldest_referenced_xid = parent->oldest_referenced_xid;
toku_txn_manager_handle_snapshot_create_for_child_txn(
txn,
logger->txn_manager,
@@ -308,11 +306,8 @@ static void toku_txn_create_txn (
.num_rollentries_processed = 0,
.rollentry_raw_count = 0,
.spilled_rollback_head = ROLLBACK_NONE,
- .spilled_rollback_head_hash = 0,
.spilled_rollback_tail = ROLLBACK_NONE,
- .spilled_rollback_tail_hash = 0,
.current_rollback = ROLLBACK_NONE,
- .current_rollback_hash = 0,
};
static txn_child_manager tcm;
@@ -330,7 +325,6 @@ static txn_child_manager tcm;
.container_db_txn = container_db_txn,
.live_root_txn_list = nullptr,
.xids = NULL,
- .oldest_referenced_xid = TXNID_NONE,
.snapshot_next = NULL,
.snapshot_prev = NULL,
.begin_was_logged = false,
@@ -405,17 +399,9 @@ toku_txn_load_txninfo (TOKUTXN txn, TXNINFO info) {
txn->roll_info.num_rollback_nodes = info->num_rollback_nodes;
txn->roll_info.num_rollentries = info->num_rollentries;
- CACHEFILE rollback_cachefile = txn->logger->rollback_cachefile;
-
txn->roll_info.spilled_rollback_head = info->spilled_rollback_head;
- txn->roll_info.spilled_rollback_head_hash = toku_cachetable_hash(rollback_cachefile,
- txn->roll_info.spilled_rollback_head);
txn->roll_info.spilled_rollback_tail = info->spilled_rollback_tail;
- txn->roll_info.spilled_rollback_tail_hash = toku_cachetable_hash(rollback_cachefile,
- txn->roll_info.spilled_rollback_tail);
txn->roll_info.current_rollback = info->current_rollback;
- txn->roll_info.current_rollback_hash = toku_cachetable_hash(rollback_cachefile,
- txn->roll_info.current_rollback);
return 0;
}
diff --git a/storage/tokudb/ft-index/ft/txn_manager.cc b/storage/tokudb/ft-index/ft/txn_manager.cc
index 53842f87855..a155db493c1 100644
--- a/storage/tokudb/ft-index/ft/txn_manager.cc
+++ b/storage/tokudb/ft-index/ft/txn_manager.cc
@@ -291,6 +291,7 @@ void toku_txn_manager_init(TXN_MANAGER* txn_managerp) {
txn_manager->last_xid = 0;
txn_manager->last_xid_seen_for_recover = TXNID_NONE;
+ txn_manager->last_calculated_oldest_referenced_xid = TXNID_NONE;
*txn_managerp = txn_manager;
}
@@ -324,6 +325,10 @@ toku_txn_manager_get_oldest_living_xid(TXN_MANAGER txn_manager) {
return rval;
}
+TXNID toku_txn_manager_get_oldest_referenced_xid_estimate(TXN_MANAGER txn_manager) {
+ return txn_manager->last_calculated_oldest_referenced_xid;
+}
+
int live_root_txn_list_iter(const TOKUTXN &live_xid, const uint32_t UU(index), TXNID **const referenced_xids);
int live_root_txn_list_iter(const TOKUTXN &live_xid, const uint32_t UU(index), TXNID **const referenced_xids){
(*referenced_xids)[index] = live_xid->txnid.parent_id64;
@@ -371,7 +376,7 @@ max_xid(TXNID a, TXNID b) {
return a < b ? b : a;
}
-static TXNID get_oldest_referenced_xid_unlocked(TXN_MANAGER txn_manager) {
+static void set_oldest_referenced_xid(TXN_MANAGER txn_manager) {
TXNID oldest_referenced_xid = TXNID_MAX;
int r;
if (txn_manager->live_root_ids.size() > 0) {
@@ -397,8 +402,8 @@ static TXNID get_oldest_referenced_xid_unlocked(TXN_MANAGER txn_manager) {
if (txn_manager->last_xid < oldest_referenced_xid) {
oldest_referenced_xid = txn_manager->last_xid;
}
- paranoid_invariant(oldest_referenced_xid != TXNID_MAX);
- return oldest_referenced_xid;
+ invariant(oldest_referenced_xid != TXNID_MAX);
+ txn_manager->last_calculated_oldest_referenced_xid = oldest_referenced_xid;
}
//Heaviside function to find a TOKUTXN by TOKUTXN (used to find the index)
@@ -610,7 +615,6 @@ void toku_txn_manager_start_txn_for_recovery(
// using xid that is passed in
txn_manager->last_xid = max_xid(txn_manager->last_xid, xid);
toku_txn_update_xids_in_txn(txn, xid);
- txn->oldest_referenced_xid = TXNID_NONE;
uint32_t idx;
int r = txn_manager->live_root_txns.find_zero<TOKUTXN, find_xid>(txn, nullptr, &idx);
@@ -672,7 +676,7 @@ void toku_txn_manager_start_txn(
r = txn_manager->live_root_ids.insert_at(txn->txnid.parent_id64, idx);
invariant_zero(r);
}
- txn->oldest_referenced_xid = get_oldest_referenced_xid_unlocked(txn_manager);
+ set_oldest_referenced_xid(txn_manager);
if (needs_snapshot) {
txn_manager_create_snapshot_unlocked(
@@ -825,7 +829,17 @@ void toku_txn_manager_clone_state_for_gc(
txn_manager_unlock(txn_manager);
}
-
+void txn_manager_state::init() {
+ invariant(!initialized);
+ invariant_notnull(txn_manager);
+ toku_txn_manager_clone_state_for_gc(
+ txn_manager,
+ &snapshot_xids,
+ &referenced_xids,
+ &live_root_txns
+ );
+ initialized = true;
+}
void toku_txn_manager_id2txn_unlocked(TXN_MANAGER txn_manager, TXNID_PAIR txnid, TOKUTXN *result) {
TOKUTXN txn;
diff --git a/storage/tokudb/ft-index/ft/txn_manager.h b/storage/tokudb/ft-index/ft/txn_manager.h
index ab9b4f44d5e..12267297a0e 100644
--- a/storage/tokudb/ft-index/ft/txn_manager.h
+++ b/storage/tokudb/ft-index/ft/txn_manager.h
@@ -121,14 +121,74 @@ struct txn_manager {
TXNID last_xid;
TXNID last_xid_seen_for_recover;
+ TXNID last_calculated_oldest_referenced_xid;
};
+struct txn_manager_state {
+ txn_manager_state(TXN_MANAGER mgr) :
+ txn_manager(mgr),
+ initialized(false) {
+ snapshot_xids.create_no_array();
+ referenced_xids.create_no_array();
+ live_root_txns.create_no_array();
+ }
+
+ // should not copy construct
+ txn_manager_state &operator=(txn_manager_state &rhs) = delete;
+ txn_manager_state(txn_manager_state &rhs) = delete;
+
+ ~txn_manager_state() {
+ snapshot_xids.destroy();
+ referenced_xids.destroy();
+ live_root_txns.destroy();
+ }
+
+ void init();
+
+ TXN_MANAGER txn_manager;
+ bool initialized;
+
+ // a snapshot of the txn manager's mvcc state
+ // only valid if initialized = true
+ xid_omt_t snapshot_xids;
+ rx_omt_t referenced_xids;
+ xid_omt_t live_root_txns;
+};
+
+// represents all of the information needed to run garbage collection
+struct txn_gc_info {
+ txn_gc_info(txn_manager_state *st, TXNID xid_sgc, TXNID xid_ip, bool mvcc)
+ : txn_state_for_gc(st),
+ oldest_referenced_xid_for_simple_gc(xid_sgc),
+ oldest_referenced_xid_for_implicit_promotion(xid_ip),
+ mvcc_needed(mvcc) {
+ }
+
+ // a snapshot of the transcation system. may be null.
+ txn_manager_state *txn_state_for_gc;
+
+ // the oldest xid in any live list
+ //
+ // suitible for simple garbage collection that cleans up multiple committed
+ // transaction records into one. not suitible for implicit promotions, which
+ // must be correct in the face of abort messages - see ftnode->oldest_referenced_xid
+ TXNID oldest_referenced_xid_for_simple_gc;
+
+ // lower bound on the oldest xid in any live when the messages to be cleaned
+ // had no messages above them. suitable for implicitly promoting a provisonal uxr.
+ TXNID oldest_referenced_xid_for_implicit_promotion;
+
+ // whether or not mvcc is actually needed - false during recovery and non-transactional systems
+ const bool mvcc_needed;
+};
void toku_txn_manager_init(TXN_MANAGER* txn_manager);
void toku_txn_manager_destroy(TXN_MANAGER txn_manager);
TXNID toku_txn_manager_get_oldest_living_xid(TXN_MANAGER txn_manager);
+TXNID toku_txn_manager_get_oldest_referenced_xid_estimate(TXN_MANAGER txn_manager);
+
void toku_txn_manager_handle_snapshot_create_for_child_txn(
TOKUTXN txn,
TXN_MANAGER txn_manager,
diff --git a/storage/tokudb/ft-index/ft/ule.cc b/storage/tokudb/ft-index/ft/ule.cc
index ab6327f7c03..dc4198bda3d 100644
--- a/storage/tokudb/ft-index/ft/ule.cc
+++ b/storage/tokudb/ft-index/ft/ule.cc
@@ -115,7 +115,8 @@ PATENT RIGHTS GRANT:
#include "txn_manager.h"
#include "ule-internal.h"
#include <util/status.h>
-
+#include <util/scoped_malloc.h>
+#include <util/partitioned_counter.h>
#define ULE_DEBUG 0
@@ -132,26 +133,42 @@ static LE_STATUS_S le_status;
#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(le_status, k, c, t, "le: " l, inc)
-static void
-status_init(void) {
+void toku_ule_status_init(void) {
// Note, this function initializes the keyname, type, and legend fields.
// Value fields are initialized to zero by compiler.
STATUS_INIT(LE_MAX_COMMITTED_XR, nullptr, UINT64, "max committed xr", TOKU_ENGINE_STATUS);
STATUS_INIT(LE_MAX_PROVISIONAL_XR, nullptr, UINT64, "max provisional xr", TOKU_ENGINE_STATUS);
STATUS_INIT(LE_EXPANDED, nullptr, UINT64, "expanded", TOKU_ENGINE_STATUS);
STATUS_INIT(LE_MAX_MEMSIZE, nullptr, UINT64, "max memsize", TOKU_ENGINE_STATUS);
+ STATUS_INIT(LE_APPLY_GC_BYTES_IN, nullptr, PARCOUNT, "size of leafentries before garbage collection (during message application)", TOKU_ENGINE_STATUS);
+ STATUS_INIT(LE_APPLY_GC_BYTES_OUT, nullptr, PARCOUNT, "size of leafentries after garbage collection (during message application)", TOKU_ENGINE_STATUS);
+ STATUS_INIT(LE_NORMAL_GC_BYTES_IN, nullptr, PARCOUNT, "size of leafentries before garbage collection (outside message application)", TOKU_ENGINE_STATUS);
+ STATUS_INIT(LE_NORMAL_GC_BYTES_OUT,nullptr, PARCOUNT, "size of leafentries after garbage collection (outside message application)", TOKU_ENGINE_STATUS);
le_status.initialized = true;
}
#undef STATUS_INIT
-void
-toku_le_get_status(LE_STATUS statp) {
- if (!le_status.initialized)
- status_init();
+void toku_ule_status_destroy(void) {
+ for (int i = 0; i < LE_STATUS_NUM_ROWS; ++i) {
+ if (le_status.status[i].type == PARCOUNT) {
+ destroy_partitioned_counter(le_status.status[i].value.parcount);
+ }
+ }
+}
+
+void toku_le_get_status(LE_STATUS statp) {
*statp = le_status;
}
#define STATUS_VALUE(x) le_status.status[x].value.num
+#define STATUS_INC(x, d) \
+ do { \
+ if (le_status.status[x].type == PARCOUNT) { \
+ increment_partitioned_counter(le_status.status[x].value.parcount, d); \
+ } else { \
+ toku_sync_fetch_and_add(&le_status.status[x].value.num, d); \
+ } \
+ } while (0)
///////////////////////////////////////////////////////////////////////////////////
@@ -308,18 +325,18 @@ xid_reads_committed_xid(TXNID tl1, TXNID xc, const xid_omt_t &snapshot_txnids, c
// so we get rid of them.
//
static void
-ule_simple_garbage_collection(ULE ule, TXNID oldest_referenced_xid, GC_INFO gc_info) {
+ule_simple_garbage_collection(ULE ule, txn_gc_info *gc_info) {
uint32_t curr_index = 0;
uint32_t num_entries;
if (ule->num_cuxrs == 1) {
goto done;
}
- if (gc_info.mvcc_needed) {
+ if (gc_info->mvcc_needed) {
// starting at the top of the committed stack, find the first
// uxr with a txnid that is less than oldest_referenced_xid
for (uint32_t i = 0; i < ule->num_cuxrs; i++) {
curr_index = ule->num_cuxrs - i - 1;
- if (ule->uxrs[curr_index].xid < oldest_referenced_xid) {
+ if (ule->uxrs[curr_index].xid < gc_info->oldest_referenced_xid_for_simple_gc) {
break;
}
}
@@ -440,6 +457,25 @@ ule_garbage_collect(ULE ule, const xid_omt_t &snapshot_xids, const rx_omt_t &ref
done:;
}
+static size_t ule_packed_memsize(ULE ule) {
+// Returns: The size 'ule' would be when packed into a leafentry, or 0 if the
+// topmost committed value is a delete.
+ if (ule->num_cuxrs == 1 && ule->num_puxrs == 0) {
+ UXR uxr = ule_get_innermost_uxr(ule);
+ if (uxr_is_delete(uxr)) {
+ return 0;
+ }
+ }
+ return le_memsize_from_ule(ule);
+}
+
+// Heuristics to control when we decide to initialize
+// txn manager state (possibly expensive) and run gc.
+enum {
+ ULE_MIN_STACK_SIZE_TO_FORCE_GC = 5,
+ ULE_MIN_MEMSIZE_TO_FORCE_GC = 1024 * 1024
+};
+
/////////////////////////////////////////////////////////////////////////////////
// This is the big enchilada. (Bring Tums.) Note that this level of abstraction
// has no knowledge of the inner structure of either leafentry or msg. It makes
@@ -459,26 +495,21 @@ toku_le_apply_msg(FT_MSG msg,
LEAFENTRY old_leafentry, // NULL if there was no stored data.
bn_data* data_buffer, // bn_data storing leafentry, if NULL, means there is no bn_data
uint32_t idx, // index in data_buffer where leafentry is stored (and should be replaced
- TXNID oldest_referenced_xid,
- GC_INFO gc_info,
+ txn_gc_info *gc_info,
LEAFENTRY *new_leafentry_p,
int64_t * numbytes_delta_p) { // change in total size of key and val, not including any overhead
+ invariant_notnull(gc_info);
+ paranoid_invariant_notnull(new_leafentry_p);
ULE_S ule;
int64_t oldnumbytes = 0;
int64_t newnumbytes = 0;
uint64_t oldmemsize = 0;
uint32_t keylen = ft_msg_get_keylen(msg);
LEAFENTRY copied_old_le = NULL;
- bool old_le_malloced = false;
+ 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) {
- size_t old_le_size = leafentry_memsize(old_leafentry);
- if (old_le_size > 100*1024) { // completely arbitrary limit
- CAST_FROM_VOIDP(copied_old_le, toku_malloc(old_le_size));
- old_le_malloced = true;
- }
- else {
- CAST_FROM_VOIDP(copied_old_le, alloca(old_le_size));
- }
+ CAST_FROM_VOIDP(copied_old_le, copied_old_le_buf.get());
memcpy(copied_old_le, old_leafentry, old_le_size);
}
@@ -490,7 +521,35 @@ toku_le_apply_msg(FT_MSG msg,
oldnumbytes = ule_get_innermost_numbytes(&ule, keylen);
}
msg_modify_ule(&ule, msg); // modify unpacked leafentry
- ule_simple_garbage_collection(&ule, oldest_referenced_xid, gc_info);
+
+ // - we may be able to immediately promote the newly-apllied outermost provisonal uxr
+ // - either way, run simple gc first, and then full gc if there are still some committed uxrs.
+ ule_try_promote_provisional_outermost(&ule, gc_info->oldest_referenced_xid_for_implicit_promotion);
+ ule_simple_garbage_collection(&ule, gc_info);
+ txn_manager_state *txn_state_for_gc = gc_info->txn_state_for_gc;
+ size_t size_before_gc = 0;
+ if (ule.num_cuxrs > 1 && txn_state_for_gc != nullptr && // there is garbage to clean, and our caller gave us state..
+ // ..and either the state is pre-initialized, or the committed stack is large enough
+ (txn_state_for_gc->initialized || ule.num_cuxrs >= ULE_MIN_STACK_SIZE_TO_FORCE_GC ||
+ // ..or the ule's raw memsize is sufficiently large
+ (size_before_gc = ule_packed_memsize(&ule)) >= ULE_MIN_MEMSIZE_TO_FORCE_GC)) {
+ // ..then it's worth running gc, possibly initializing the txn manager state, if it isn't already
+ if (!txn_state_for_gc->initialized) {
+ txn_state_for_gc->init();
+ }
+
+ size_before_gc = size_before_gc != 0 ? size_before_gc : // it's already been calculated above
+ ule_packed_memsize(&ule);
+ ule_garbage_collect(&ule,
+ txn_state_for_gc->snapshot_xids,
+ txn_state_for_gc->referenced_xids,
+ txn_state_for_gc->live_root_txns
+ );
+ size_t size_after_gc = ule_packed_memsize(&ule);
+
+ STATUS_INC(LE_APPLY_GC_BYTES_IN, size_before_gc);
+ STATUS_INC(LE_APPLY_GC_BYTES_OUT, size_after_gc);
+ }
int rval = le_pack(
&ule, // create packed leafentry
data_buffer,
@@ -501,17 +560,14 @@ toku_le_apply_msg(FT_MSG msg,
new_leafentry_p
);
invariant_zero(rval);
- if (new_leafentry_p) {
+ if (*new_leafentry_p) {
newnumbytes = ule_get_innermost_numbytes(&ule, keylen);
}
*numbytes_delta_p = newnumbytes - oldnumbytes;
ule_cleanup(&ule);
- if (old_le_malloced) {
- toku_free(copied_old_le);
- }
}
-bool toku_le_worth_running_garbage_collection(LEAFENTRY le, TXNID oldest_referenced_xid_known) {
+bool toku_le_worth_running_garbage_collection(LEAFENTRY le, txn_gc_info *gc_info) {
// Effect: Quickly determines if it's worth trying to run garbage collection on a leafentry
// Return: True if it makes sense to try garbage collection, false otherwise.
// Rationale: Garbage collection is likely to clean up under two circumstances:
@@ -527,7 +583,8 @@ bool toku_le_worth_running_garbage_collection(LEAFENTRY le, TXNID oldest_referen
} else {
paranoid_invariant(le->u.mvcc.num_cxrs == 1);
}
- return le->u.mvcc.num_pxrs > 0 && le_outermost_uncommitted_xid(le) < oldest_referenced_xid_known;
+ return le->u.mvcc.num_pxrs > 0 &&
+ le_outermost_uncommitted_xid(le) < gc_info->oldest_referenced_xid_for_implicit_promotion;
}
// Garbage collect one leaf entry, using the given OMT's.
@@ -554,26 +611,21 @@ toku_le_garbage_collect(LEAFENTRY old_leaf_entry,
uint32_t idx,
void* keyp,
uint32_t keylen,
+ txn_gc_info *gc_info,
LEAFENTRY *new_leaf_entry,
- const xid_omt_t &snapshot_xids,
- const rx_omt_t &referenced_xids,
- const xid_omt_t &live_root_txns,
- TXNID oldest_referenced_xid_known,
int64_t * numbytes_delta_p) {
+ // We shouldn't want to run gc without having provided a snapshot of the txn system.
+ invariant_notnull(gc_info);
+ invariant_notnull(gc_info->txn_state_for_gc);
+ paranoid_invariant_notnull(new_leaf_entry);
ULE_S ule;
int64_t oldnumbytes = 0;
int64_t newnumbytes = 0;
LEAFENTRY copied_old_le = NULL;
- bool old_le_malloced = false;
+ 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) {
- size_t old_le_size = leafentry_memsize(old_leaf_entry);
- if (old_le_size > 100*1024) { // completely arbitrary limit
- CAST_FROM_VOIDP(copied_old_le, toku_malloc(old_le_size));
- old_le_malloced = true;
- }
- else {
- CAST_FROM_VOIDP(copied_old_le, alloca(old_le_size));
- }
+ CAST_FROM_VOIDP(copied_old_le, copied_old_le_buf.get());
memcpy(copied_old_le, old_leaf_entry, old_le_size);
}
@@ -584,14 +636,24 @@ toku_le_garbage_collect(LEAFENTRY old_leaf_entry,
// Before running garbage collection, try to promote the outermost provisional
// entries to committed if its xid is older than the oldest possible live xid.
- //
+ //
// The oldest known refeferenced xid is a lower bound on the oldest possible
// live xid, so we use that. It's usually close enough to get rid of most
// garbage in leafentries.
- TXNID oldest_possible_live_xid = oldest_referenced_xid_known;
- ule_try_promote_provisional_outermost(&ule, oldest_possible_live_xid);
- ule_garbage_collect(&ule, snapshot_xids, referenced_xids, live_root_txns);
-
+ ule_try_promote_provisional_outermost(&ule, gc_info->oldest_referenced_xid_for_implicit_promotion);
+ // No need to run simple gc here if we're going straight for full gc.
+ if (ule.num_cuxrs > 1) {
+ size_t size_before_gc = ule_packed_memsize(&ule);
+ ule_garbage_collect(&ule,
+ gc_info->txn_state_for_gc->snapshot_xids,
+ gc_info->txn_state_for_gc->referenced_xids,
+ gc_info->txn_state_for_gc->live_root_txns);
+ size_t size_after_gc = ule_packed_memsize(&ule);
+
+ STATUS_INC(LE_APPLY_GC_BYTES_IN, size_before_gc);
+ STATUS_INC(LE_APPLY_GC_BYTES_OUT, size_after_gc);
+ }
+
int r = le_pack(
&ule,
data_buffer,
@@ -602,14 +664,11 @@ toku_le_garbage_collect(LEAFENTRY old_leaf_entry,
new_leaf_entry
);
assert(r == 0);
- if (new_leaf_entry) {
+ if (*new_leaf_entry) {
newnumbytes = ule_get_innermost_numbytes(&ule, keylen);
}
*numbytes_delta_p = newnumbytes - oldnumbytes;
ule_cleanup(&ule);
- if (old_le_malloced) {
- toku_free(copied_old_le);
- }
}
/////////////////////////////////////////////////////////////////////////////////
diff --git a/storage/tokudb/ft-index/ft/ule.h b/storage/tokudb/ft-index/ft/ule.h
index 0d5600b8df4..0dd34212ff1 100644
--- a/storage/tokudb/ft-index/ft/ule.h
+++ b/storage/tokudb/ft-index/ft/ule.h
@@ -102,6 +102,9 @@ PATENT RIGHTS GRANT:
#include "txn_manager.h"
#include <util/mempool.h>
+void toku_ule_status_init(void);
+void toku_ule_status_destroy(void);
+
// opaque handles used by outside world (i.e. indexer)
typedef struct ule *ULEHANDLE;
typedef struct uxr *UXRHANDLE;
diff --git a/storage/tokudb/ft-index/locktree/lock_request.cc b/storage/tokudb/ft-index/locktree/lock_request.cc
index 079f5351f7d..362f9bfa98d 100644
--- a/storage/tokudb/ft-index/locktree/lock_request.cc
+++ b/storage/tokudb/ft-index/locktree/lock_request.cc
@@ -99,7 +99,7 @@ PATENT RIGHTS GRANT:
namespace toku {
// initialize a lock request's internals
-void lock_request::create(uint64_t wait_time) {
+void lock_request::create(void) {
m_txnid = TXNID_NONE;
m_conflicting_txnid = TXNID_NONE;
m_start_time = 0;
@@ -114,7 +114,6 @@ void lock_request::create(uint64_t wait_time) {
m_complete_r = 0;
m_state = state::UNINITIALIZED;
- m_wait_time = wait_time;
toku_cond_init(&m_wait_cond, nullptr);
}
@@ -126,9 +125,7 @@ void lock_request::destroy(void) {
}
// set the lock request parameters. this API allows a lock request to be reused.
-void lock_request::set(locktree *lt, TXNID txnid,
- const DBT *left_key, const DBT *right_key,
- lock_request::type lock_type) {
+void lock_request::set(locktree *lt, TXNID txnid, const DBT *left_key, const DBT *right_key, lock_request::type lock_type, bool big_txn) {
invariant(m_state != state::PENDING);
m_lt = lt;
m_txnid = txnid;
@@ -139,6 +136,7 @@ void lock_request::set(locktree *lt, TXNID txnid,
m_type = lock_type;
m_state = state::INITIALIZED;
m_info = lt->get_lock_request_info();
+ m_big_txn = big_txn;
}
// get rid of any stored left and right key copies and
@@ -208,10 +206,10 @@ int lock_request::start(void) {
txnid_set conflicts;
conflicts.create();
if (m_type == type::WRITE) {
- r = m_lt->acquire_write_lock(m_txnid, m_left_key, m_right_key, &conflicts);
+ r = m_lt->acquire_write_lock(m_txnid, m_left_key, m_right_key, &conflicts, m_big_txn);
} else {
invariant(m_type == type::READ);
- r = m_lt->acquire_read_lock(m_txnid, m_left_key, m_right_key, &conflicts);
+ r = m_lt->acquire_read_lock(m_txnid, m_left_key, m_right_key, &conflicts, m_big_txn);
}
// if the lock is not granted, save it to the set of lock requests
@@ -236,38 +234,50 @@ int lock_request::start(void) {
return m_state == state::COMPLETE ? m_complete_r : r;
}
-void lock_request::calculate_cond_wakeup_time(struct timespec *ts) {
- struct timeval now;
- int r = gettimeofday(&now, NULL);
- invariant_zero(r);
- int64_t sec = now.tv_sec + (m_wait_time / 1000);
- int64_t usec = now.tv_usec + ((m_wait_time % 1000) * 1000);
- int64_t d_sec = usec / 1000000;
- int64_t d_usec = usec % 1000000;
- ts->tv_sec = sec + d_sec;
- ts->tv_nsec = d_usec * 1000;
+// sleep on the lock request until it becomes resolved or the wait time has elapsed.
+int lock_request::wait(uint64_t wait_time_ms) {
+ return wait(wait_time_ms, 0, nullptr);
}
-// sleep on the lock request until it becomes resolved or the wait time has elapsed.
-int lock_request::wait(void) {
- uint64_t t_start = toku_current_time_microsec();
+int lock_request::wait(uint64_t wait_time_ms, uint64_t killed_time_ms, int (*killed_callback)(void)) {
+ uint64_t t_now = toku_current_time_microsec();
+ uint64_t t_start = t_now;
+ uint64_t t_end = t_start + wait_time_ms * 1000;
+
toku_mutex_lock(&m_info->mutex);
+
while (m_state == state::PENDING) {
- struct timespec ts;
- calculate_cond_wakeup_time(&ts);
+
+ // compute next wait time
+ uint64_t t_wait;
+ if (killed_time_ms == 0) {
+ t_wait = t_end;
+ } else {
+ t_wait = t_now + killed_time_ms * 1000;
+ if (t_wait > t_end)
+ t_wait = t_end;
+ }
+ struct timespec ts = {};
+ ts.tv_sec = t_wait / 1000000;
+ ts.tv_nsec = (t_wait % 1000000) * 1000;
int r = toku_cond_timedwait(&m_wait_cond, &m_info->mutex, &ts);
invariant(r == 0 || r == ETIMEDOUT);
- if (r == ETIMEDOUT && m_state == state::PENDING) {
+
+ t_now = toku_current_time_microsec();
+ if (m_state == state::PENDING && (t_now >= t_end || (killed_callback && killed_callback()))) {
m_info->counters.timeout_count += 1;
+
// if we're still pending and we timed out, then remove our
// request from the set of lock requests and fail.
remove_from_lock_requests();
+
// complete sets m_state to COMPLETE, breaking us out of the loop
complete(DB_LOCK_NOTGRANTED);
}
}
- uint64_t t_end = toku_current_time_microsec();
- uint64_t duration = t_end - t_start;
+
+ uint64_t t_real_end = toku_current_time_microsec();
+ uint64_t duration = t_real_end - t_start;
m_info->counters.wait_count += 1;
m_info->counters.wait_time += duration;
if (duration >= 1000000) {
@@ -311,9 +321,9 @@ int lock_request::retry(void) {
invariant(m_state == state::PENDING);
if (m_type == type::WRITE) {
- r = m_lt->acquire_write_lock(m_txnid, m_left_key, m_right_key, nullptr);
+ r = m_lt->acquire_write_lock(m_txnid, m_left_key, m_right_key, nullptr, m_big_txn);
} else {
- r = m_lt->acquire_read_lock(m_txnid, m_left_key, m_right_key, nullptr);
+ r = m_lt->acquire_read_lock(m_txnid, m_left_key, m_right_key, nullptr, m_big_txn);
}
// if the acquisition succeeded then remove ourselves from the
diff --git a/storage/tokudb/ft-index/locktree/lock_request.h b/storage/tokudb/ft-index/locktree/lock_request.h
index 140e49974ec..48956826547 100644
--- a/storage/tokudb/ft-index/locktree/lock_request.h
+++ b/storage/tokudb/ft-index/locktree/lock_request.h
@@ -125,16 +125,15 @@ public:
WRITE
};
- // effect: Initializes a lock request with a given wait time.
- void create(uint64_t wait_time);
+ // effect: Initializes a lock request.
+ void create(void);
// effect: Destroys a lock request.
void destroy(void);
// effect: Resets the lock request parameters, allowing it to be reused.
// requires: Lock request was already created at some point
- void set(locktree *lt, TXNID txnid,
- const DBT *left_key, const DBT *right_key, type lock_type);
+ void set(locktree *lt, TXNID txnid, const DBT *left_key, const DBT *right_key, type lock_type, bool big_txn);
// effect: Tries to acquire a lock described by this lock request.
// returns: The return code of locktree::acquire_[write,read]_lock()
@@ -144,7 +143,8 @@ public:
// effect: Sleeps until either the request is granted or the wait time expires.
// returns: The return code of locktree::acquire_[write,read]_lock()
// or simply DB_LOCK_NOTGRANTED if the wait time expired.
- int wait(void);
+ int wait(uint64_t wait_time_ms);
+ int wait(uint64_t wait_time_ms, uint64_t killed_time_ms, int (*killed_callback)(void));
// return: left end-point of the lock range
const DBT *get_left_key(void) const;
@@ -196,9 +196,10 @@ private:
int m_complete_r;
state m_state;
- uint64_t m_wait_time;
toku_cond_t m_wait_cond;
+ bool m_big_txn;
+
// the lock request info state stored in the
// locktree that this lock request is for.
struct locktree::lt_lock_request_info *m_info;
@@ -235,8 +236,6 @@ private:
void copy_keys(void);
- void calculate_cond_wakeup_time(struct timespec *ts);
-
static int find_by_txnid(lock_request * const &request, const TXNID &txnid);
friend class lock_request_unit_test;
diff --git a/storage/tokudb/ft-index/locktree/locktree.cc b/storage/tokudb/ft-index/locktree/locktree.cc
index 36c35eec185..21b0aaa1426 100644
--- a/storage/tokudb/ft-index/locktree/locktree.cc
+++ b/storage/tokudb/ft-index/locktree/locktree.cc
@@ -119,6 +119,7 @@ namespace toku {
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
@@ -410,8 +411,8 @@ int locktree::acquire_lock(bool is_write_request, TXNID txnid,
}
int locktree::try_acquire_lock(bool is_write_request, TXNID txnid,
- const DBT *left_key, const DBT *right_key, txnid_set *conflicts) {
- int r = m_mem_tracker->check_current_lock_constraints();
+ 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);
}
@@ -420,13 +421,13 @@ int locktree::try_acquire_lock(bool is_write_request, TXNID txnid,
// 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) {
- return acquire_write_lock(txnid, left_key, right_key, conflicts);
+ 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) {
- return try_acquire_lock(true, txnid, left_key, right_key, conflicts);
+ 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,
diff --git a/storage/tokudb/ft-index/locktree/locktree.h b/storage/tokudb/ft-index/locktree/locktree.h
index 1f94a1feb6a..a3c3b566fcf 100644
--- a/storage/tokudb/ft-index/locktree/locktree.h
+++ b/storage/tokudb/ft-index/locktree/locktree.h
@@ -105,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,
@@ -164,15 +169,13 @@ public:
// 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);
+ 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);
+ 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]
@@ -215,6 +218,25 @@ public:
// 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
@@ -236,10 +258,6 @@ public:
int set_max_lock_memory(size_t max_lock_memory);
- uint64_t get_lock_wait_time(void);
-
- void set_lock_wait_time(uint64_t lock_wait_time);
-
// 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
@@ -265,6 +283,7 @@ public:
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.
@@ -273,6 +292,8 @@ public:
// 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);
@@ -297,6 +318,7 @@ public:
// 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);
@@ -311,9 +333,22 @@ public:
void *extra);
int iterate_pending_lock_requests(lock_request_iterate_callback cb, void *extra);
+ int check_current_lock_constraints(bool big_txn);
+
+ // Escalate locktrees touched by a txn
+ void escalate_lock_trees_for_txn(TXNID, locktree *lt);
+
+ // Escalate all locktrees
+ void escalate_all_locktrees(void);
+
+ // Escalate a set of locktrees
+ void escalate_locktrees(locktree **locktrees, int num_locktrees);
+
+ // Add time t to the escalator's wait time statistics
+ void add_escalator_wait_time(uint64_t t);
+
private:
static const uint64_t DEFAULT_MAX_LOCK_MEMORY = 64L * 1024 * 1024;
- static const uint64_t DEFAULT_LOCK_WAIT_TIME = 0;
// tracks the current number of locks and lock memory
uint64_t m_max_lock_memory;
@@ -322,9 +357,6 @@ public:
struct lt_counters m_lt_counters;
- // lock wait time for blocking row locks, in ms
- uint64_t m_lock_wait_time_ms;
-
// the create and destroy callbacks for the locktrees
lt_create_cb m_lt_create_callback;
lt_destroy_cb m_lt_destroy_callback;
@@ -356,23 +388,14 @@ public:
// requires: Manager's mutex is held
void locktree_map_remove(locktree *lt);
- // effect: Runs escalation on all locktrees.
- void run_escalation(void);
-
static int find_by_dict_id(locktree *const &lt, const DICTIONARY_ID &dict_id);
void escalator_init(void);
void escalator_destroy(void);
- // effect: Add time t to the escalator's wait time statistics
- void add_escalator_wait_time(uint64_t t);
-
- // effect: escalate's the locks in each locktree
- // requires: manager's mutex is held
- void escalate_all_locktrees(void);
-
// statistics about lock escalation.
+ toku_mutex_t m_escalation_mutex;
uint64_t m_escalation_count;
tokutime_t m_escalation_time;
uint64_t m_escalation_latest_result;
@@ -381,22 +404,16 @@ public:
uint64_t m_long_wait_escalation_count;
uint64_t m_long_wait_escalation_time;
- toku_mutex_t m_escalator_mutex;
- toku_cond_t m_escalator_work; // signal the escalator to run
- toku_cond_t m_escalator_done; // signal that escalation is done
- bool m_escalator_killed;
- toku_pthread_t m_escalator_id;
+ escalator m_escalator;
friend class manager_unit_test;
-
- public:
- void escalator_work(void);
};
ENSURE_POD(manager);
manager::memory_tracker *get_mem_tracker(void) const;
private:
+ manager *m_mgr;
manager::memory_tracker *m_mem_tracker;
DICTIONARY_ID m_dict_id;
@@ -414,7 +431,6 @@ private:
uint32_t m_reference_count;
- // the locktree stores locks in a concurrent, non-overlapping rangetree
concurrent_tree *m_rangetree;
void *m_userdata;
@@ -586,7 +602,7 @@ private:
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);
+ 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);
diff --git a/storage/tokudb/ft-index/locktree/manager.cc b/storage/tokudb/ft-index/locktree/manager.cc
index e4317f30fc0..8086d9049f7 100644
--- a/storage/tokudb/ft-index/locktree/manager.cc
+++ b/storage/tokudb/ft-index/locktree/manager.cc
@@ -103,8 +103,6 @@ namespace toku {
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;
- escalator_init();
- m_lock_wait_time_ms = DEFAULT_LOCK_WAIT_TIME;
m_mem_tracker.set_manager(this);
m_locktree_map.create();
@@ -118,6 +116,8 @@ void locktree::manager::create(lt_create_cb create_cb, lt_destroy_cb destroy_cb,
ZERO_STRUCT(status);
ZERO_STRUCT(m_lt_counters);
+
+ escalator_init();
}
void locktree::manager::destroy(void) {
@@ -152,14 +152,6 @@ int locktree::manager::set_max_lock_memory(size_t max_lock_memory) {
return r;
}
-uint64_t locktree::manager::get_lock_wait_time(void) {
- return m_lock_wait_time_ms;
-}
-
-void locktree::manager::set_lock_wait_time(uint64_t lock_wait_time_ms) {
- m_lock_wait_time_ms = lock_wait_time_ms;
-}
-
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;
@@ -312,33 +304,45 @@ void locktree::manager::release_lt(locktree *lt) {
}
// 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();
+}
+
+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::run_escalation(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();
- if (1) {
- // run escalation on the background thread
- int r;
- toku_mutex_lock(&m_escalator_mutex);
- toku_cond_broadcast(&m_escalator_work);
- struct timeval tv;
- r = gettimeofday(&tv, 0);
- assert_zero(r);
- uint64_t t = tv.tv_sec * 1000000 + tv.tv_usec;
- t += 100000; // 100 milliseconds
- toku_timespec_t wakeup_time;
- wakeup_time.tv_sec = t / 1000000;
- wakeup_time.tv_nsec = (t % 1000000) * 1000;
- r = toku_cond_timedwait(&m_escalator_done, &m_escalator_mutex, &wakeup_time);
- toku_mutex_unlock(&m_escalator_mutex);
- } else {
- // run escalation on this thread
- mutex_lock();
- escalate_all_locktrees();
- mutex_unlock();
+
+ // get all locktrees
+ mutex_lock();
+ int num_locktrees = m_locktree_map.size();
+ locktree **locktrees = new locktree *[num_locktrees];
+ for (int i = 0; i < num_locktrees; i++) {
+ int r = m_locktree_map.fetch(i, &locktrees[i]);
+ invariant_zero(r);
+ reference_lt(locktrees[i]);
}
+ mutex_unlock();
+
+ // escalate them
+ escalate_locktrees(locktrees, num_locktrees);
+
+ delete [] locktrees;
+
uint64_t t1 = toku_current_time_microsec();
add_escalator_wait_time(t1 - t0);
}
@@ -347,6 +351,10 @@ 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
@@ -374,6 +382,10 @@ 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::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) {
mutex_lock();
@@ -403,18 +415,23 @@ int locktree::manager::iterate_pending_lock_requests(
return r;
}
-static void *escalator_thread(void *arg) {
- locktree::manager *mgr = reinterpret_cast<locktree::manager*>(arg);
- mgr->escalator_work();
- return arg;
+int locktree::manager::check_current_lock_constraints(bool big_txn) {
+ int r = 0;
+ if (big_txn && m_mem_tracker.over_big_threshold()) {
+ run_escalation();
+ if (m_mem_tracker.over_big_threshold()) {
+ r = TOKUDB_OUT_OF_LOCKS;
+ }
+ }
+ if (r == 0) {
+ r = m_mem_tracker.check_current_lock_constraints();
+ }
+ return r;
}
void locktree::manager::escalator_init(void) {
- ZERO_STRUCT(m_escalator_mutex);
- toku_mutex_init(&m_escalator_mutex, nullptr);
- toku_cond_init(&m_escalator_work, nullptr);
- toku_cond_init(&m_escalator_done, nullptr);
- m_escalator_killed = false;
+ ZERO_STRUCT(m_escalation_mutex);
+ toku_mutex_init(&m_escalation_mutex, nullptr);
m_escalation_count = 0;
m_escalation_time = 0;
m_wait_escalation_count = 0;
@@ -422,24 +439,27 @@ void locktree::manager::escalator_init(void) {
m_long_wait_escalation_count = 0;
m_long_wait_escalation_time = 0;
m_escalation_latest_result = 0;
- int r = toku_pthread_create(&m_escalator_id, nullptr, escalator_thread, this);
- assert_zero(r);
+ m_escalator.create();
}
void locktree::manager::escalator_destroy(void) {
- toku_mutex_lock(&m_escalator_mutex);
- m_escalator_killed = true;
- toku_cond_broadcast(&m_escalator_work);
- toku_mutex_unlock(&m_escalator_mutex);
- void *ret;
- int r = toku_pthread_join(m_escalator_id, &ret);
- assert_zero(r);
- toku_mutex_destroy(&m_escalator_mutex);
- toku_cond_destroy(&m_escalator_work);
- toku_cond_destroy(&m_escalator_done);
+ m_escalator.destroy();
+ toku_mutex_destroy(&m_escalation_mutex);
}
-void locktree::manager::escalate_all_locktrees(void) {
+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;
+ if (t >= 1000000) {
+ m_long_wait_escalation_count += 1;
+ m_long_wait_escalation_time += t;
+ }
+ toku_mutex_unlock(&m_escalation_mutex);
+}
+
+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
@@ -448,47 +468,87 @@ void locktree::manager::escalate_all_locktrees(void) {
// and more complicated locking. for now, just escalate each
// locktree individually, in-place.
tokutime_t t0 = toku_time_now();
- 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);
- lt->escalate(m_lt_escalate_callback, m_lt_escalate_callback_extra);
+ for (int i = 0; i < num_locktrees; i++) {
+ locktrees[i]->escalate(m_lt_escalate_callback, m_lt_escalate_callback_extra);
+ release_lt(locktrees[i]);
}
tokutime_t t1 = toku_time_now();
- toku_mutex_lock(&m_escalator_mutex);
+ toku_mutex_lock(&m_escalation_mutex);
m_escalation_count++;
m_escalation_time += (t1 - t0);
m_escalation_latest_result = m_current_lock_memory;
- toku_mutex_unlock(&m_escalator_mutex);
+ toku_mutex_unlock(&m_escalation_mutex);
}
-void locktree::manager::add_escalator_wait_time(uint64_t t) {
- toku_mutex_lock(&m_escalator_mutex);
- m_wait_escalation_count += 1;
- m_wait_escalation_time += t;
- if (t >= 1000000) {
- m_long_wait_escalation_count += 1;
- m_long_wait_escalation_time += t;
- }
- toku_mutex_unlock(&m_escalator_mutex);
+#if !TOKU_LOCKTREE_ESCALATOR_LAMBDA
+struct escalate_args {
+ locktree::manager *mgr;
+ locktree **locktrees;
+ int num_locktrees;
+};
+
+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::escalator_work(void) {
+void locktree::escalator::destroy(void) {
+ toku_cond_destroy(&m_escalator_done);
+ toku_mutex_destroy(&m_escalator_mutex);
+}
+
+#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);
- while (!m_escalator_killed) {
- toku_cond_wait(&m_escalator_work, &m_escalator_mutex);
- if (!m_escalator_killed) {
- toku_mutex_unlock(&m_escalator_mutex);
- mutex_lock();
- escalate_all_locktrees();
- mutex_unlock();
- toku_mutex_lock(&m_escalator_mutex);
- toku_cond_broadcast(&m_escalator_done);
- }
+ 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);
+ } else {
+ toku_cond_wait(&m_escalator_done, &m_escalator_mutex);
}
toku_mutex_unlock(&m_escalator_mutex);
+ uint64_t t1 = toku_current_time_microsec();
+ mgr->add_escalator_wait_time(t1 - t0);
}
#define STATUS_INIT(k,c,t,l,inc) TOKUDB_STATUS_INIT(status, k, c, t, "locktree: " l, inc)
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_create_set.cc b/storage/tokudb/ft-index/locktree/tests/lock_request_create_set.cc
index 9741c2a0e8c..b309d9b6fd8 100644
--- a/storage/tokudb/ft-index/locktree/tests/lock_request_create_set.cc
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_create_set.cc
@@ -96,8 +96,7 @@ namespace toku {
// create and set the object's internals, destroy should not crash.
void lock_request_unit_test::test_create_destroy(void) {
lock_request request;
- const uint64_t wait_time_magic = 5016342;
- request.create(wait_time_magic);
+ request.create();
invariant(request.m_txnid == TXNID_NONE);
invariant(request.m_left_key == nullptr);
@@ -112,7 +111,6 @@ void lock_request_unit_test::test_create_destroy(void) {
invariant(request.m_complete_r == 0);
invariant(request.m_state == lock_request::state::UNINITIALIZED);
- invariant(request.m_wait_time = wait_time_magic);
request.destroy();
}
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_get_set_keys.cc b/storage/tokudb/ft-index/locktree/tests/lock_request_get_set_keys.cc
index 52bf89affdf..60300a138df 100644
--- a/storage/tokudb/ft-index/locktree/tests/lock_request_get_set_keys.cc
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_get_set_keys.cc
@@ -98,8 +98,7 @@ namespace toku {
// when appropriate and plays nice with +/- infinity.
void lock_request_unit_test::test_get_set_keys(void) {
lock_request request;
- const uint64_t lock_wait_time = 10;
- request.create(lock_wait_time);
+ request.create();
locktree *const null_lt = nullptr;
@@ -112,20 +111,20 @@ void lock_request_unit_test::test_get_set_keys(void) {
// request should not copy dbts for neg/pos inf, so get_left
// and get_right should return the same pointer given
- request.set(null_lt, txnid_a, neg_inf, pos_inf, lock_request::type::WRITE);
+ request.set(null_lt, txnid_a, neg_inf, pos_inf, lock_request::type::WRITE, false);
invariant(request.get_left_key() == neg_inf);
invariant(request.get_right_key() == pos_inf);
// request should make copies of non-infinity-valued keys.
- request.set(null_lt, txnid_a, neg_inf, one, lock_request::type::WRITE);
+ request.set(null_lt, txnid_a, neg_inf, one, lock_request::type::WRITE, false);
invariant(request.get_left_key() == neg_inf);
invariant(request.get_right_key() == one);
- request.set(null_lt, txnid_a, two, pos_inf, lock_request::type::WRITE);
+ request.set(null_lt, txnid_a, two, pos_inf, lock_request::type::WRITE, false);
invariant(request.get_left_key() == two);
invariant(request.get_right_key() == pos_inf);
- request.set(null_lt, txnid_a, one, two, lock_request::type::WRITE);
+ request.set(null_lt, txnid_a, one, two, lock_request::type::WRITE, false);
invariant(request.get_left_key() == one);
invariant(request.get_right_key() == two);
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc b/storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc
new file mode 100644
index 00000000000..742165c59dc
--- /dev/null
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_killed.cc
@@ -0,0 +1,179 @@
+/* -*- 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) 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."
+
+// test the kill callback. the lock wait is killed 1/2 of the way through the wait.
+
+#include "lock_request_unit_test.h"
+
+namespace toku {
+
+const uint64_t my_lock_wait_time = 10 * 1000; // 10 seconds
+const uint64_t my_killed_time = 1 * 1000;
+
+static int killed_calls = 0;
+static uint64_t t_last_kill;
+static uint64_t t_do_kill;
+
+static int my_killed_callback(void) {
+ uint64_t t_now = toku_current_time_microsec();
+ assert(t_now >= t_last_kill);
+ assert(t_now - t_last_kill >= my_killed_time * 1000 / 2); // div by 2 for valgrind which is not very accurate
+ t_last_kill = t_now;
+ killed_calls++;
+ if (t_now >= t_do_kill)
+ return 1;
+ else
+ return 0;
+}
+
+// make sure deadlocks are detected when a lock request starts
+void lock_request_unit_test::test_wait_time_callback(void) {
+ int r;
+ locktree::manager mgr;
+ locktree *lt;
+
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+
+ DICTIONARY_ID dict_id = { 1 };
+ lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
+
+ TXNID txnid_a = 1001;
+ lock_request request_a;
+ request_a.create();
+
+ TXNID txnid_b = 2001;
+ lock_request request_b;
+ request_b.create();
+
+ const DBT *one = get_dbt(1);
+
+ // a locks 'one'
+ 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);
+ r = request_b.start();
+ assert(r == DB_LOCK_NOTGRANTED);
+
+ uint64_t t_start = toku_current_time_microsec();
+ t_last_kill = t_start;
+ t_do_kill = t_start + my_lock_wait_time * 1000 / 2;
+ r = request_b.wait(my_lock_wait_time, my_killed_time, my_killed_callback);
+ assert(r == DB_LOCK_NOTGRANTED);
+
+ uint64_t t_end = toku_current_time_microsec();
+ assert(t_end > t_start);
+ uint64_t t_delta = t_end - t_start;
+ // fprintf(stderr, "delta=%" PRIu64 "\n", t_delta);
+ assert(t_delta >= my_lock_wait_time / 2);
+
+ // fprintf(stderr, "killed_calls=%d\n", killed_calls);
+ assert(killed_calls > 0);
+
+ request_b.destroy();
+
+ release_lock_and_retry_requests(lt, txnid_a, one, one);
+ request_a.destroy();
+
+ mgr.release_lt(lt);
+ mgr.destroy();
+}
+
+} /* namespace toku */
+
+int main(void) {
+ toku::lock_request_unit_test test;
+ test.test_wait_time_callback();
+ return 0;
+}
+
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
new file mode 100644
index 00000000000..e49b88f9d79
--- /dev/null
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_not_killed.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) 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."
+
+// test the kill callback. the kill callback never kills the lock wait in this test.
+// the test verifies that the kill callback is called close to its requested frequency.
+
+#include "lock_request_unit_test.h"
+
+namespace toku {
+
+const uint64_t my_lock_wait_time = 10 * 1000; // 10 seconds
+const uint64_t my_killed_time = 1 * 1000;
+
+static int killed_calls = 0;
+static uint64_t t_last_kill;
+
+static int my_killed_callback(void) {
+ uint64_t t_now = toku_current_time_microsec();
+ assert(t_now >= t_last_kill);
+ assert(t_now - t_last_kill >= my_killed_time * 1000 / 2); // div by 2 for valgrind which is not very accurate
+ t_last_kill = t_now;
+ killed_calls++;
+ return 0;
+}
+
+// make sure deadlocks are detected when a lock request starts
+void lock_request_unit_test::test_wait_time_callback(void) {
+ int r;
+ locktree::manager mgr;
+ locktree *lt;
+
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+
+ DICTIONARY_ID dict_id = { 1 };
+ lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
+
+ TXNID txnid_a = 1001;
+ lock_request request_a;
+ request_a.create();
+
+ TXNID txnid_b = 2001;
+ lock_request request_b;
+ request_b.create();
+
+ const DBT *one = get_dbt(1);
+
+ // a locks 'one'
+ 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);
+ r = request_b.start();
+ assert(r == DB_LOCK_NOTGRANTED);
+
+ uint64_t t_start = toku_current_time_microsec();
+ t_last_kill = t_start;
+ r = request_b.wait(my_lock_wait_time, my_killed_time, my_killed_callback);
+ assert(r == DB_LOCK_NOTGRANTED);
+
+ uint64_t t_end = toku_current_time_microsec();
+ assert(t_end > t_start);
+ uint64_t t_delta = t_end - t_start;
+ // fprintf(stderr, "delta=%" PRIu64 "\n", t_delta);
+ assert(t_delta >= my_lock_wait_time);
+
+ // fprintf(stderr, "killed_calls=%d\n", killed_calls);
+ assert(killed_calls > 0);
+
+ request_b.destroy();
+
+ release_lock_and_retry_requests(lt, txnid_a, one, one);
+ request_a.destroy();
+
+ mgr.release_lt(lt);
+ mgr.destroy();
+}
+
+} /* namespace toku */
+
+int main(void) {
+ toku::lock_request_unit_test test;
+ test.test_wait_time_callback();
+ return 0;
+}
+
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 d170e08dedd..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
@@ -111,48 +111,48 @@ void lock_request_unit_test::test_start_deadlock(void) {
lock_request request_a;
lock_request request_b;
lock_request request_c;
- request_a.create(lock_wait_time);
- request_b.create(lock_wait_time);
- request_c.create(lock_wait_time);
+ request_a.create();
+ request_b.create();
+ request_c.create();
const DBT *one = get_dbt(1);
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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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();
+ r = request_c.wait(lock_wait_time);
invariant(r == DB_LOCK_NOTGRANTED);
- request_c.set(lt, txnid_c, two, two, lock_request::type::WRITE);
+ 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();
+ r = request_c.wait(lock_wait_time);
invariant(r == DB_LOCK_NOTGRANTED);
// 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);
- r = request_a.wait();
+ r = request_a.wait(lock_wait_time);
invariant_zero(r);
release_lock_and_retry_requests(lt, txnid_a, two, two);
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 04679c22ce9..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
@@ -100,8 +100,6 @@ void lock_request_unit_test::test_start_pending(void) {
locktree::manager mgr;
locktree *lt;
lock_request request;
- // bogus, just has to be something.
- const uint64_t lock_wait_time = 0;
mgr.create(nullptr, nullptr, nullptr, nullptr);
DICTIONARY_ID dict_id = { 1 };
@@ -115,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);
+ r = lt->acquire_write_lock(txnid_b, zero, two, nullptr, false);
invariant_zero(r);
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(lock_wait_time);
- request.set(lt, txnid_a, one, one, lock_request::type::WRITE);
+ request.create();
+ 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);
diff --git a/storage/tokudb/ft-index/locktree/tests/lock_request_unit_test.h b/storage/tokudb/ft-index/locktree/tests/lock_request_unit_test.h
index 6ec451ed108..3183bf2b734 100644
--- a/storage/tokudb/ft-index/locktree/tests/lock_request_unit_test.h
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_unit_test.h
@@ -116,6 +116,9 @@ public:
// make sure deadlocks are detected when a lock request starts
void test_start_deadlock(void);
+ // test that the get_wait_time callback works
+ void test_wait_time_callback(void);
+
private:
// releases a single range lock and retries all lock requests.
// this is kind of like what the ydb layer does, except that
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
new file mode 100644
index 00000000000..e077d461399
--- /dev/null
+++ b/storage/tokudb/ft-index/locktree/tests/lock_request_wait_time_callback.cc
@@ -0,0 +1,151 @@
+/* -*- 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 "lock_request_unit_test.h"
+
+namespace toku {
+
+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::manager mgr;
+ locktree *lt;
+
+ mgr.create(nullptr, nullptr, nullptr, nullptr);
+ DICTIONARY_ID dict_id = { 1 };
+ lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
+
+ TXNID txnid_a = 1001;
+ lock_request request_a;
+ request_a.create();
+
+ TXNID txnid_b = 2001;
+ lock_request request_b;
+ request_b.create();
+
+ const DBT *one = get_dbt(1);
+ const DBT *two = get_dbt(2);
+
+ // a locks 'one'
+ 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);
+ r = request_b.start();
+ assert(r == DB_LOCK_NOTGRANTED);
+ uint64_t t_start = toku_current_time_microsec();
+ r = request_b.wait(my_lock_wait_time);
+ uint64_t t_end = toku_current_time_microsec();
+ assert(r == DB_LOCK_NOTGRANTED);
+ assert(t_end > t_start);
+ uint64_t t_delta = t_end - t_start;
+ assert(t_delta >= my_lock_wait_time);
+ request_b.destroy();
+
+ release_lock_and_retry_requests(lt, txnid_a, one, one);
+ request_a.destroy();
+
+ mgr.release_lt(lt);
+ mgr.destroy();
+}
+
+} /* namespace toku */
+
+int main(void) {
+ toku::lock_request_unit_test test;
+ test.test_wait_time_callback();
+ return 0;
+}
+
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc b/storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc
index 9c684a9057a..70f3a6249c4 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_conflicts.cc
@@ -125,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) \
- : lt->acquire_write_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)
// acquire some locks for txnid_a
r = ACQUIRE_LOCK(txnid_a, one, one, nullptr);
@@ -142,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) \
- : lt->acquire_write_lock(txn, left, right, conflicts)
+ 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);
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
new file mode 100644
index 00000000000..7c4af67e6f8
--- /dev/null
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_1big7lt_1small.cc
@@ -0,0 +1,304 @@
+/* -*- 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 "locktree.h"
+#include "test.h"
+
+// ensure that small transactions do not get stalled by a big transaction that has lots of locks
+// ./locktree_escalation_big7_small1 --stalls 100 --max_lock_memory 1000000000 --verbose
+
+using namespace toku;
+
+static int verbose = 0;
+static int killed = 0;
+static pthread_t big_id, small_id;
+
+static void locktree_release_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k) {
+ range_buffer buffer;
+ buffer.create();
+ DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
+ DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
+ buffer.append(&left, &right);
+ lt->release_locks(txn_id, &buffer);
+ buffer.destroy();
+}
+
+// grab a write range lock on int64 keys bounded by left_k and right_k
+static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k, bool big_txn) {
+ DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
+ DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
+ return lt->acquire_write_lock(txn_id, &left, &right, nullptr, big_txn);
+}
+
+#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++) {
+ uint64_t t_start = toku_current_time_microsec();
+ int r = locktree_write_lock(lt[j], txn_id, i, i, true);
+ assert(r == 0);
+ last_i = i;
+ uint64_t t_end = toku_current_time_microsec();
+ uint64_t t_duration = t_end - t_start;
+ if (t_duration > 100000) {
+ printf("%u %s %" PRId64 " %" PRIu64 "\n", toku_os_gettid(), __FUNCTION__, i, t_duration);
+ }
+ }
+ toku_pthread_yield();
+ }
+ if (last_i != -1)
+ for (int j = 0; j < n_lt; j++)
+ locktree_release_lock(lt[j], txn_id, 0, last_i); // release the range 0 .. last_i
+ if (verbose)
+ printf("%u %s %" PRId64 "\n", toku_os_gettid(), __FUNCTION__, last_i);
+}
+
+struct big_arg {
+ locktree::manager *mgr;
+ locktree **lt;
+ int n_lt;
+ TXNID txn_id;
+};
+
+static void *big_f(void *_arg) {
+ struct big_arg *arg = (struct big_arg *) _arg;
+ assert(pthread_equal(pthread_self(), big_id));
+ printf("%u %s\n", toku_os_gettid(), __FUNCTION__);
+ run_big_txn(arg->mgr, arg->lt, arg->n_lt, arg->txn_id);
+ return arg;
+}
+
+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();
+ int r = locktree_write_lock(lt, txn_id, k, k, false);
+ assert(r == 0);
+ uint64_t t_end = toku_current_time_microsec();
+ uint64_t t_duration = t_end - t_start;
+ if (t_duration > 100000) {
+ printf("%u %s %" PRId64 " %" PRIu64 "\n", toku_os_gettid(), __FUNCTION__, i, t_duration);
+ }
+ locktree_release_lock(lt, txn_id, k, k);
+ toku_pthread_yield();
+ }
+ if (verbose)
+ printf("%u %s %" PRId64 "\n", toku_os_gettid(), __FUNCTION__, i);
+}
+
+struct small_arg {
+ locktree::manager *mgr;
+ locktree *lt;
+ TXNID txn_id;
+ int64_t k;
+};
+
+static void *small_f(void *_arg) {
+ struct small_arg *arg = (struct small_arg *) _arg;
+ printf("%u %s\n", toku_os_gettid(), __FUNCTION__);
+ run_small_txn(arg->mgr, arg->lt, arg->txn_id, arg->k);
+ return arg;
+}
+
+static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buffer, void *extra) {
+ assert(pthread_equal(pthread_self(), big_id));
+ if (verbose)
+ 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) {
+ LTM_STATUS_S ltm_status;
+ mgr.get_status(&ltm_status);
+
+ TOKU_ENGINE_STATUS_ROW key_status = NULL;
+ // lookup keyname in status
+ for (int i = 0; ; i++) {
+ TOKU_ENGINE_STATUS_ROW status = &ltm_status.status[i];
+ if (status->keyname == NULL)
+ break;
+ if (strcmp(status->keyname, "LTM_ESCALATION_COUNT") == 0) {
+ key_status = status;
+ break;
+ }
+ }
+ assert(key_status);
+ return key_status->value.num;
+}
+
+int main(int argc, const char *argv[]) {
+ uint64_t stalls = 1;
+ int n_big = 7;
+ uint64_t max_lock_memory = 1000000;
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "--stalls") == 0 && i+1 < argc) {
+ stalls = atoll(argv[++i]);
+ continue;
+ }
+ if (strcmp(argv[i], "--max_lock_memory") == 0 && i+1 < argc) {
+ max_lock_memory = atoll(argv[++i]);
+ continue;
+ }
+ }
+
+ int r;
+
+ // create a manager
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, e_callback, nullptr);
+ mgr.set_max_lock_memory(max_lock_memory);
+
+ // create lock trees
+ uint64_t next_dict_id = 1;
+ DICTIONARY_ID dict_id;
+ locktree *big_lt[n_big];
+ for (int i = 0; i < n_big; i++) {
+ dict_id = { next_dict_id }; next_dict_id++;
+ 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);
+
+ // create the worker threads
+ struct big_arg big_arg = { &mgr, big_lt, n_big, 1000 };
+ r = toku_pthread_create(&big_id, nullptr, big_f, &big_arg);
+ assert(r == 0);
+
+ struct small_arg small_arg = { &mgr, small_lt, 2000, 0 };
+ r = toku_pthread_create(&small_id, nullptr, small_f, &small_arg);
+ assert(r == 0);
+
+ // wait for some escalations to occur
+ while (get_escalation_count(mgr) < stalls) {
+ sleep(1);
+ }
+ killed = 1;
+
+ // cleanup
+ void *ret;
+ r = toku_pthread_join(big_id, &ret);
+ assert(r == 0);
+
+ r = toku_pthread_join(small_id, &ret);
+ assert(r == 0);
+
+ for (int i = 0; i < n_big; i++)
+ mgr.release_lt(big_lt[i]);
+ mgr.release_lt(small_lt);
+ mgr.destroy();
+
+ return 0;
+}
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
new file mode 100644
index 00000000000..ab1818d2fd3
--- /dev/null
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_1lt.cc
@@ -0,0 +1,250 @@
+/* -*- 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 "locktree.h"
+#include "test.h"
+
+// One client locks 1,2,3...
+// The other client locks -1,-2,-3...
+// Eventually lock escalation runs.
+
+using namespace toku;
+
+static int verbose = 0;
+static int killed = 0;
+
+static void locktree_release_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k) {
+ range_buffer buffer;
+ buffer.create();
+ DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
+ DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
+ buffer.append(&left, &right);
+ lt->release_locks(txn_id, &buffer);
+ buffer.destroy();
+}
+
+// grab a write range lock on int64 keys bounded by left_k and right_k
+static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k, bool big_txn) {
+ DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
+ DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
+ 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) {
+ 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++) {
+ if (0)
+ printf("%u %" PRId64 "\n", toku_os_gettid(), i);
+ uint64_t t_start = toku_current_time_microsec();
+ int r = locktree_write_lock(lt, txn_id, i, i, true);
+ if (r != 0)
+ break;
+ last_i = i;
+ uint64_t t_end = toku_current_time_microsec();
+ uint64_t t_duration = t_end - t_start;
+ if (t_duration > 100000) {
+ printf("%u %s %" PRId64 " %" PRIu64 "\n", toku_os_gettid(), __FUNCTION__, i, t_duration);
+ }
+ toku_pthread_yield();
+ }
+ if (last_i != -1)
+ locktree_release_lock(lt, txn_id, start_i, last_i); // release the range start_i .. last_i
+}
+
+struct arg {
+ locktree::manager *mgr;
+ locktree *lt;
+ TXNID txn_id;
+ int64_t start_i;
+};
+
+static void *big_f(void *_arg) {
+ struct arg *arg = (struct arg *) _arg;
+ run_big_txn(arg->mgr, arg->lt, arg->txn_id, arg->start_i);
+ return arg;
+}
+
+static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buffer, void *extra) {
+ if (verbose)
+ 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) {
+ LTM_STATUS_S ltm_status;
+ mgr.get_status(&ltm_status);
+
+ TOKU_ENGINE_STATUS_ROW key_status = NULL;
+ // lookup keyname in status
+ for (int i = 0; ; i++) {
+ TOKU_ENGINE_STATUS_ROW status = &ltm_status.status[i];
+ if (status->keyname == NULL)
+ break;
+ if (strcmp(status->keyname, "LTM_ESCALATION_COUNT") == 0) {
+ key_status = status;
+ break;
+ }
+ }
+ assert(key_status);
+ return key_status->value.num;
+}
+
+int main(int argc, const char *argv[]) {
+ const int n_big = 2;
+ int n_lt = 1;
+ uint64_t stalls = 1;
+ uint64_t max_lock_memory = 1000000;
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "--stalls") == 0 && i+1 < argc) {
+ stalls = atoll(argv[++i]);
+ continue;
+ }
+ if (strcmp(argv[i], "--n_lt") == 0 && i+1 < argc) {
+ n_lt = atoi(argv[++i]);
+ continue;
+ }
+ if (strcmp(argv[i], "--max_lock_memory") == 0 && i+1 < argc) {
+ max_lock_memory = atoll(argv[++i]);
+ continue;
+ }
+ }
+
+ int r;
+
+ // create a manager
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, e_callback, nullptr);
+ mgr.set_max_lock_memory(max_lock_memory);
+
+ // create lock trees
+ DESCRIPTOR desc[n_lt];
+ DICTIONARY_ID dict_id[n_lt];
+ locktree *lt[n_big];
+ for (int i = 0; i < n_lt; i++) {
+ desc[i] = nullptr;
+ dict_id[i] = { (uint64_t)i };
+ lt[i] = mgr.get_lt(dict_id[i], desc[i], compare_dbts, nullptr);
+ assert(lt[i]);
+ }
+
+ // create the worker threads
+ struct arg big_arg[n_big];
+ pthread_t big_ids[n_big];
+ for (int i = 0; i < n_big; i++) {
+ big_arg[i] = { &mgr, lt[i % n_lt], (TXNID)(1000+i), i == 0 ? 1 : -1000000000 };
+ r = toku_pthread_create(&big_ids[i], nullptr, big_f, &big_arg[i]);
+ assert(r == 0);
+ }
+
+ // wait for some escalations to occur
+ while (get_escalation_count(mgr) < stalls) {
+ sleep(1);
+ }
+ killed = 1;
+
+ // cleanup
+ for (int i = 0; i < n_big; i++) {
+ void *ret;
+ r = toku_pthread_join(big_ids[i], &ret);
+ assert(r == 0);
+ }
+ for (int i = 0; i < n_lt ; i++) {
+ mgr.release_lt(lt[i]);
+ }
+ mgr.destroy();
+
+ return 0;
+}
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
new file mode 100644
index 00000000000..d9f62ca29f3
--- /dev/null
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_2big_2lt.cc
@@ -0,0 +1,250 @@
+/* -*- 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 "locktree.h"
+#include "test.h"
+
+// One client locks 1,2,3...
+// The other client locks -1,-2,-3...
+// Eventually lock escalation runs.
+
+using namespace toku;
+
+static int verbose = 0;
+static int killed = 0;
+
+static void locktree_release_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k) {
+ range_buffer buffer;
+ buffer.create();
+ DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
+ DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
+ buffer.append(&left, &right);
+ lt->release_locks(txn_id, &buffer);
+ buffer.destroy();
+}
+
+// grab a write range lock on int64 keys bounded by left_k and right_k
+static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k, bool big_txn) {
+ DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
+ DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
+ 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) {
+ 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++) {
+ if (0)
+ printf("%u %" PRId64 "\n", toku_os_gettid(), i);
+ uint64_t t_start = toku_current_time_microsec();
+ int r = locktree_write_lock(lt, txn_id, i, i, true);
+ if (r != 0)
+ break;
+ last_i = i;
+ uint64_t t_end = toku_current_time_microsec();
+ uint64_t t_duration = t_end - t_start;
+ if (t_duration > 100000) {
+ printf("%u %s %" PRId64 " %" PRIu64 "\n", toku_os_gettid(), __FUNCTION__, i, t_duration);
+ }
+ toku_pthread_yield();
+ }
+ if (last_i != -1)
+ locktree_release_lock(lt, txn_id, start_i, last_i); // release the range start_i .. last_i
+}
+
+struct arg {
+ locktree::manager *mgr;
+ locktree *lt;
+ TXNID txn_id;
+ int64_t start_i;
+};
+
+static void *big_f(void *_arg) {
+ struct arg *arg = (struct arg *) _arg;
+ run_big_txn(arg->mgr, arg->lt, arg->txn_id, arg->start_i);
+ return arg;
+}
+
+static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buffer, void *extra) {
+ if (verbose)
+ 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) {
+ LTM_STATUS_S ltm_status;
+ mgr.get_status(&ltm_status);
+
+ TOKU_ENGINE_STATUS_ROW key_status = NULL;
+ // lookup keyname in status
+ for (int i = 0; ; i++) {
+ TOKU_ENGINE_STATUS_ROW status = &ltm_status.status[i];
+ if (status->keyname == NULL)
+ break;
+ if (strcmp(status->keyname, "LTM_ESCALATION_COUNT") == 0) {
+ key_status = status;
+ break;
+ }
+ }
+ assert(key_status);
+ return key_status->value.num;
+}
+
+int main(int argc, const char *argv[]) {
+ const int n_big = 2;
+ int n_lt = 2;
+ uint64_t stalls = 1;
+ uint64_t max_lock_memory = 1000000;
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "--stalls") == 0 && i+1 < argc) {
+ stalls = atoll(argv[++i]);
+ continue;
+ }
+ if (strcmp(argv[i], "--n_lt") == 0 && i+1 < argc) {
+ n_lt = atoi(argv[++i]);
+ continue;
+ }
+ if (strcmp(argv[i], "--max_lock_memory") == 0 && i+1 < argc) {
+ max_lock_memory = atoll(argv[++i]);
+ continue;
+ }
+ }
+
+ int r;
+
+ // create a manager
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, e_callback, nullptr);
+ mgr.set_max_lock_memory(max_lock_memory);
+
+ // create lock trees
+ DESCRIPTOR desc[n_lt];
+ DICTIONARY_ID dict_id[n_lt];
+ locktree *lt[n_big];
+ for (int i = 0; i < n_lt; i++) {
+ desc[i] = nullptr;
+ dict_id[i] = { (uint64_t)i };
+ lt[i] = mgr.get_lt(dict_id[i], desc[i], compare_dbts, nullptr);
+ assert(lt[i]);
+ }
+
+ // create the worker threads
+ struct arg big_arg[n_big];
+ pthread_t big_ids[n_big];
+ for (int i = 0; i < n_big; i++) {
+ big_arg[i] = { &mgr, lt[i % n_lt], (TXNID)(1000+i), i == 0 ? 1 : -1000000000 };
+ r = toku_pthread_create(&big_ids[i], nullptr, big_f, &big_arg[i]);
+ assert(r == 0);
+ }
+
+ // wait for some escalations to occur
+ while (get_escalation_count(mgr) < stalls) {
+ sleep(1);
+ }
+ killed = 1;
+
+ // cleanup
+ for (int i = 0; i < n_big; i++) {
+ void *ret;
+ r = toku_pthread_join(big_ids[i], &ret);
+ assert(r == 0);
+ }
+ for (int i = 0; i < n_lt ; i++) {
+ mgr.release_lt(lt[i]);
+ }
+ mgr.destroy();
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc
new file mode 100644
index 00000000000..cdee8b9d333
--- /dev/null
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_impossible.cc
@@ -0,0 +1,204 @@
+/* -*- 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 "locktree.h"
+#include "test.h"
+
+// Two big txn's grab alternating locks in a single lock tree.
+// Eventually lock escalation runs.
+// Since the locks can not be consolidated, the out of locks error should be returned.
+
+using namespace toku;
+
+static int verbose = 0;
+
+static inline void locktree_release_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k) {
+ range_buffer buffer;
+ buffer.create();
+ DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
+ DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
+ buffer.append(&left, &right);
+ lt->release_locks(txn_id, &buffer);
+ buffer.destroy();
+}
+
+// grab a write range lock on int64 keys bounded by left_k and right_k
+static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k, bool big_txn) {
+ DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
+ DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
+ return lt->acquire_write_lock(txn_id, &left, &right, nullptr, big_txn);
+}
+
+static void e_callback(TXNID txnid, const locktree *lt, const range_buffer &buffer, void *extra) {
+ if (verbose)
+ 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) {
+ LTM_STATUS_S ltm_status;
+ mgr.get_status(&ltm_status);
+
+ TOKU_ENGINE_STATUS_ROW key_status = NULL;
+ // lookup keyname in status
+ for (int i = 0; ; i++) {
+ TOKU_ENGINE_STATUS_ROW status = &ltm_status.status[i];
+ if (status->keyname == NULL)
+ break;
+ if (strcmp(status->keyname, "LTM_ESCALATION_COUNT") == 0) {
+ key_status = status;
+ break;
+ }
+ }
+ assert(key_status);
+ return key_status->value.num;
+}
+
+int main(int argc, const char *argv[]) {
+ uint64_t max_lock_memory = 1000000;
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "--max_lock_memory") == 0 && i+1 < argc) {
+ max_lock_memory = atoll(argv[++i]);
+ continue;
+ }
+ }
+
+ int r;
+
+ // create a manager
+ locktree::manager mgr;
+ mgr.create(nullptr, nullptr, e_callback, nullptr);
+ mgr.set_max_lock_memory(max_lock_memory);
+
+ const TXNID txn_a = 10;
+ const TXNID txn_b = 100;
+
+ // create lock trees
+ DESCRIPTOR desc = nullptr;
+ DICTIONARY_ID dict_id = { 1 };
+ locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
+
+ int64_t last_i = -1;
+ for (int64_t i = 0; ; i++) {
+ if (verbose)
+ printf("%" PRId64 "\n", i);
+ int64_t k = 2*i;
+ r = locktree_write_lock(lt, txn_a, k, k, true);
+ if (r != 0) {
+ assert(r == TOKUDB_OUT_OF_LOCKS);
+ break;
+ }
+ last_i = i;
+ r = locktree_write_lock(lt, txn_b, k+1, k+1, true);
+ if (r != 0) {
+ assert(r == TOKUDB_OUT_OF_LOCKS);
+ break;
+ }
+ }
+
+ // wait for an escalation to occur
+ assert(get_escalation_count(mgr) > 0);
+
+ if (last_i != -1) {
+ locktree_release_lock(lt, txn_a, 0, 2*last_i);
+ locktree_release_lock(lt, txn_b, 0, 2*last_i+1);
+ }
+
+ mgr.release_lt(lt);
+ mgr.destroy();
+
+ return 0;
+}
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 a41040410b0..28ae88cb3a8 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_escalation_stalls.cc
@@ -89,6 +89,17 @@ 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 verifies that small txn's do not get stalled for a long time by lock escalation.
+// Two lock trees are used by the test: a big lock tree and a small lock tree.
+// One big txn grabs lots of write locks on the big lock tree.
+// Several small txn's grab a single write lock on the small lock tree.
+// None of the locks conflict.
+// Eventually, the locks for the big txn consume all of the lock tree memory, so lock escalation runs.
+// The test measures the lock acquisition time and makes sure that the small txn's are not blocked for
+
+// locktree_escalation_stalls -v --stalls 10
+// verify that only big txn's get tagged with > 1 second stalls
+
#include <stdio.h>
#include "locktree.h"
#include "test.h"
@@ -96,6 +107,7 @@ PATENT RIGHTS GRANT:
using namespace toku;
static int verbose = 0;
+static int killed = 0;
static void locktree_release_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k) {
range_buffer buffer;
@@ -108,38 +120,42 @@ static void locktree_release_lock(locktree *lt, TXNID txn_id, int64_t left_k, in
}
// grab a write range lock on int64 keys bounded by left_k and right_k
-static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k) {
+static int locktree_write_lock(locktree *lt, TXNID txn_id, int64_t left_k, int64_t right_k, bool big_txn) {
DBT left; toku_fill_dbt(&left, &left_k, sizeof left_k);
DBT right; toku_fill_dbt(&right, &right_k, sizeof right_k);
- return lt->acquire_write_lock(txn_id, &left, &right, nullptr);
+ return lt->acquire_write_lock(txn_id, &left, &right, nullptr, big_txn);
}
-static void run_big_txn(locktree::manager *mgr, locktree *lt, TXNID txn_id) {
- mgr = mgr;
- for (int64_t i = 0; 1; i++) {
+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();
- int r = locktree_write_lock(lt, txn_id, i, i);
+ int r = locktree_write_lock(lt, txn_id, i, i, true);
assert(r == 0);
+ last_i = i;
uint64_t t_end = toku_current_time_microsec();
uint64_t t_duration = t_end - t_start;
if (t_duration > 100000) {
printf("%u %s %" PRId64 " %" PRIu64 "\n", toku_os_gettid(), __FUNCTION__, i, t_duration);
}
+ toku_pthread_yield();
}
+ if (last_i != -1)
+ locktree_release_lock(lt, txn_id, 0, last_i); // release the range 0 .. last_i
}
-static void run_small_txn(locktree::manager *mgr, locktree *lt, TXNID txn_id, int64_t k) {
- mgr = mgr;
- for (int64_t i = 0; 1; i++) {
+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);
+ int r = locktree_write_lock(lt, txn_id, k, k, false);
assert(r == 0);
uint64_t t_end = toku_current_time_microsec();
uint64_t t_duration = t_end - t_start;
if (t_duration > 100000) {
printf("%u %s %" PRId64 " %" PRIu64 "\n", toku_os_gettid(), __FUNCTION__, i, t_duration);
}
- locktree_release_lock(lt, txn_id, i, i);
+ locktree_release_lock(lt, txn_id, k, k);
+ toku_pthread_yield();
}
}
@@ -167,15 +183,49 @@ 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) {
+ LTM_STATUS_S ltm_status;
+ mgr.get_status(&ltm_status);
+
+ TOKU_ENGINE_STATUS_ROW key_status = NULL;
+ // lookup keyname in status
+ for (int i = 0; ; i++) {
+ TOKU_ENGINE_STATUS_ROW status = &ltm_status.status[i];
+ if (status->keyname == NULL)
+ break;
+ if (strcmp(status->keyname, "LTM_ESCALATION_COUNT") == 0) {
+ key_status = status;
+ break;
+ }
+ }
+ assert(key_status);
+ return key_status->value.num;
+}
+
int main(int argc, const char *argv[]) {
- if (argc == 1 || argv == nullptr)
- return 0;
+ uint64_t stalls = 0;
+ uint64_t max_lock_memory = 1000000000;
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "--stalls") == 0 && i+1 < argc) {
+ stalls = atoll(argv[++i]);
+ continue;
+ }
+ if (strcmp(argv[i], "--max_lock_memory") == 0 && i+1 < argc) {
+ max_lock_memory = atoll(argv[++i]);
+ continue;
+ }
+ }
+
int r;
// create a manager
locktree::manager mgr;
mgr.create(nullptr, nullptr, e_callback, nullptr);
- mgr.set_max_lock_memory(1000000000);
+ mgr.set_max_lock_memory(max_lock_memory);
// create lock trees
DESCRIPTOR desc_0 = nullptr;
@@ -186,6 +236,7 @@ int main(int argc, const char *argv[]) {
DICTIONARY_ID dict_id_1 = { 2 };
locktree *lt_1 = mgr.get_lt(dict_id_1, desc_1, compare_dbts, nullptr);
+ // create the worker threads
struct arg big_arg = { &mgr, lt_0, 1000 };
pthread_t big_id;
r = toku_pthread_create(&big_id, nullptr, big_f, &big_arg);
@@ -201,6 +252,13 @@ int main(int argc, const char *argv[]) {
assert(r == 0);
}
+ // wait for some escalations to occur
+ while (get_escalation_count(mgr) < stalls) {
+ sleep(1);
+ }
+ killed = 1;
+
+ // cleanup
void *ret;
r = toku_pthread_join(big_id, &ret);
assert(r == 0);
@@ -210,7 +268,6 @@ int main(int argc, const char *argv[]) {
assert(r == 0);
}
- // cleanup
mgr.release_lt(lt_0);
mgr.release_lt(lt_1);
mgr.destroy();
diff --git a/storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc b/storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc
index fd3dd1ca605..142e50992a6 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_infinity.cc
@@ -112,54 +112,54 @@ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
// txn A will lock 1, +inf
- r = lt->acquire_write_lock(txnid_a, one, toku_dbt_positive_infinity(), nullptr);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
// txn A will lock -inf, +inf
- r = lt->acquire_write_lock(txnid_a, toku_dbt_negative_infinity(), toku_dbt_positive_infinity(), nullptr);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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());
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 4567b90a420..ecb710517e1 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_overlapping_relock.cc
@@ -121,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);
+ 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) \
- : lt->acquire_write_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)
// lock [1,1] and [2,2]. then lock [1,2].
// ensure only [1,2] exists in the tree
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 44fe0c578a0..549a44a1479 100644
--- a/storage/tokudb/ft-index/locktree/tests/locktree_simple_lock.cc
+++ b/storage/tokudb/ft-index/locktree/tests/locktree_simple_lock.cc
@@ -115,8 +115,8 @@ void locktree_unit_test::test_simple_lock(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) \
- : lt->acquire_write_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)
// four txns, four points
r = ACQUIRE_LOCK(txnid_a, one, one, nullptr);
@@ -178,7 +178,7 @@ void locktree_unit_test::test_simple_lock(void) {
for (int64_t i = 0; i < num_locks; i++) {
k.data = (void *) &keys[i];
- r = lt->acquire_read_lock(txnid_a, &k, &k, nullptr);
+ r = lt->acquire_read_lock(txnid_a, &k, &k, nullptr, false);
invariant(r == 0);
}
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 1c9e80f57d5..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
@@ -124,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); \
+ 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); \
+ r = lt->acquire_write_lock(txnid_b, one, one, nullptr, false); \
invariant_zero(r); \
}
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 c0c218c8a3e..6f667c04a74 100644
--- a/storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc
+++ b/storage/tokudb/ft-index/locktree/tests/manager_create_destroy.cc
@@ -109,7 +109,6 @@ void manager_unit_test::test_create_destroy(void) {
invariant(mgr.m_escalation_count == 0);
invariant(mgr.m_escalation_time == 0);
invariant(mgr.m_escalation_latest_result == 0);
- invariant(mgr.m_lock_wait_time_ms == locktree::manager::DEFAULT_LOCK_WAIT_TIME);
invariant(mgr.m_locktree_map.size() == 0);
invariant(mgr.m_lt_create_callback == create_callback);
diff --git a/storage/tokudb/ft-index/locktree/tests/manager_params.cc b/storage/tokudb/ft-index/locktree/tests/manager_params.cc
index e0f18d75df8..95642db5121 100644
--- a/storage/tokudb/ft-index/locktree/tests/manager_params.cc
+++ b/storage/tokudb/ft-index/locktree/tests/manager_params.cc
@@ -103,10 +103,6 @@ void manager_unit_test::test_params(void) {
invariant(r == 0);
invariant(mgr.get_max_lock_memory() == new_max_lock_memory);
- uint64_t new_lock_wait_time = 62345234;
- mgr.set_lock_wait_time(new_lock_wait_time);
- invariant(mgr.get_lock_wait_time() == new_lock_wait_time);
-
mgr.m_current_lock_memory = 100000;
r = mgr.set_max_lock_memory(mgr.m_current_lock_memory - 1);
invariant(r == EDOM);
diff --git a/storage/tokudb/ft-index/locktree/tests/manager_status.cc b/storage/tokudb/ft-index/locktree/tests/manager_status.cc
index 0551dd3b3e0..6803b5a22b3 100644
--- a/storage/tokudb/ft-index/locktree/tests/manager_status.cc
+++ b/storage/tokudb/ft-index/locktree/tests/manager_status.cc
@@ -130,16 +130,16 @@ void manager_unit_test::test_status(void) {
const DBT *one = get_dbt(1);
// txn a write locks one
- r = lt->acquire_write_lock(txnid_a, one, one, nullptr);
+ r = lt->acquire_write_lock(txnid_a, one, one, nullptr, false);
assert(r == 0);
// txn b tries to write lock one, conflicts, waits, and fails to lock one
lock_request request_b;
- request_b.create(1000);
- request_b.set(lt, txnid_b, one, one, lock_request::type::WRITE);
+ request_b.create();
+ request_b.set(lt, txnid_b, one, one, lock_request::type::WRITE, false);
r = request_b.start();
assert(r == DB_LOCK_NOTGRANTED);
- r = request_b.wait();
+ r = request_b.wait(1000);
assert(r == DB_LOCK_NOTGRANTED);
request_b.destroy();
diff --git a/storage/tokudb/ft-index/portability/CMakeLists.txt b/storage/tokudb/ft-index/portability/CMakeLists.txt
index 1d64878675e..e4364357fb0 100644
--- a/storage/tokudb/ft-index/portability/CMakeLists.txt
+++ b/storage/tokudb/ft-index/portability/CMakeLists.txt
@@ -8,7 +8,6 @@ set(tokuportability_srcs
portability
toku_assert
toku_crash
- toku_fair_rwlock
toku_path
toku_pthread
toku_time
@@ -20,6 +19,7 @@ target_link_libraries(${LIBTOKUPORTABILITY} LINK_PUBLIC ${CMAKE_THREAD_LIBS_INIT
add_library(tokuportability_static_conv STATIC ${tokuportability_srcs})
set_target_properties(tokuportability_static_conv PROPERTIES POSITION_INDEPENDENT_CODE ON)
+add_dependencies(tokuportability_static_conv build_jemalloc)
set(tokuportability_source_libs tokuportability_static_conv ${LIBJEMALLOC} ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_SYSTEM_LIBS})
toku_merge_static_libs(${LIBTOKUPORTABILITY}_static ${LIBTOKUPORTABILITY}_static "${tokuportability_source_libs}")
@@ -34,10 +34,17 @@ if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
install(
FILES toku_os_types.h toku_time.h
DESTINATION include
+ COMPONENT tokukv_headers
)
install(
- TARGETS ${LIBTOKUPORTABILITY} ${LIBTOKUPORTABILITY}_static
- DESTINATION lib
+ TARGETS ${LIBTOKUPORTABILITY}_static
+ DESTINATION ${INSTALL_LIBDIR}
+ COMPONENT tokukv_libs_static
+ )
+ install(
+ TARGETS ${LIBTOKUPORTABILITY}
+ DESTINATION ${INSTALL_LIBDIR}
+ COMPONENT tokukv_libs_shared
)
endif ()
diff --git a/storage/tokudb/ft-index/portability/file.cc b/storage/tokudb/ft-index/portability/file.cc
index 99a7d6c64ca..b351141fe29 100644
--- a/storage/tokudb/ft-index/portability/file.cc
+++ b/storage/tokudb/ft-index/portability/file.cc
@@ -449,6 +449,8 @@ static uint64_t toku_fsync_time;
static uint64_t toku_long_fsync_threshold = 1000000;
static uint64_t toku_long_fsync_count;
static uint64_t toku_long_fsync_time;
+static uint64_t toku_long_fsync_eintr_count;
+static int toku_fsync_debug = 0;
void toku_set_func_fsync(int (*fsync_function)(int)) {
t_fsync = fsync_function;
@@ -458,6 +460,7 @@ void toku_set_func_fsync(int (*fsync_function)(int)) {
static void file_fsync_internal (int fd) {
uint64_t tstart = toku_current_time_microsec();
int r = -1;
+ uint64_t eintr_count = 0;
while (r != 0) {
if (t_fsync) {
r = t_fsync(fd);
@@ -466,6 +469,7 @@ static void file_fsync_internal (int fd) {
}
if (r) {
assert(get_error_errno() == EINTR);
+ eintr_count++;
}
}
toku_sync_fetch_and_add(&toku_fsync_count, 1);
@@ -474,6 +478,26 @@ static void file_fsync_internal (int fd) {
if (duration >= toku_long_fsync_threshold) {
toku_sync_fetch_and_add(&toku_long_fsync_count, 1);
toku_sync_fetch_and_add(&toku_long_fsync_time, duration);
+ toku_sync_fetch_and_add(&toku_long_fsync_eintr_count, eintr_count);
+ if (toku_fsync_debug) {
+ const int tstr_length = 26;
+ char tstr[tstr_length];
+ time_t t = time(0);
+#if __linux__
+ char fdname[256];
+ snprintf(fdname, sizeof fdname, "/proc/%d/fd/%d", getpid(), fd);
+ char lname[256];
+ ssize_t s = readlink(fdname, lname, sizeof lname);
+ if (0 < s && s < (ssize_t) sizeof lname)
+ lname[s] = 0;
+ fprintf(stderr, "%.24s toku_file_fsync %s fd=%d %s duration=%" PRIu64 " usec eintr=%" PRIu64 "\n",
+ ctime_r(&t, tstr), __FUNCTION__, fd, s > 0 ? lname : "?", duration, eintr_count);
+#else
+ fprintf(stderr, "%.24s toku_file_fsync %s fd=%d duration=%" PRIu64 " usec eintr=%" PRIu64 "\n",
+ ctime_r(&t, tstr), __FUNCTION__, fd, duration, eintr_count);
+#endif
+ fflush(stderr);
+ }
}
}
diff --git a/storage/tokudb/ft-index/portability/os_malloc.cc b/storage/tokudb/ft-index/portability/os_malloc.cc
index 0b2b5f64967..ecc5ea9ca3c 100644
--- a/storage/tokudb/ft-index/portability/os_malloc.cc
+++ b/storage/tokudb/ft-index/portability/os_malloc.cc
@@ -93,7 +93,6 @@ PATENT RIGHTS GRANT:
#include <toku_portability.h>
#include <stdlib.h>
-//#include <jemalloc/include/jemalloc/jemalloc.h>
#if defined(HAVE_MALLOC_H)
# include <malloc.h>
#elif defined(HAVE_SYS_MALLOC_H)
diff --git a/storage/tokudb/ft-index/portability/tests/test-fair-rwlock.cc b/storage/tokudb/ft-index/portability/tests/test-fair-rwlock.cc
deleted file mode 100644
index fa549d3f2d8..00000000000
--- a/storage/tokudb/ft-index/portability/tests/test-fair-rwlock.cc
+++ /dev/null
@@ -1,665 +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) 2010-2013 Tokutek Inc. All rights reserved."
-
-// Here are some timing numbers:
-// (Note: The not-quite-working version with cas can be found in r22519 of https://svn.tokutek.com/tokudb/toku/tokudb.2825/) It's about as fast as "Best cas".)
-//
-// On ramie (2.53GHz E5540)
-// Best nop time= 1.074300ns
-// Best cas time= 8.595600ns
-// Best mutex time= 19.340201ns
-// Best rwlock time= 34.024799ns
-// Best ft rwlock time= 38.680500ns
-// Best prelocked time= 2.148700ns
-// Best fair rwlock time= 45.127600ns
-// On laptop
-// Best nop time= 2.876000ns
-// Best cas time= 15.362500ns
-// Best mutex time= 51.951498ns
-// Best rwlock time= 97.721201ns
-// Best ft rwlock time=110.456800ns
-// Best prelocked time= 4.240100ns
-// Best fair rwlock time=113.119102ns
-//
-// Analysis: If the mutex can be prelocked (as cachetable does, it uses the same mutex for the cachetable and for the condition variable protecting the cache table)
-// then you can save quite a bit. What does the cachetable do?
-// During pin: (In the common case:) It grabs the mutex, grabs a read lock, and releases the mutex.
-// During unpin: It grabs the mutex, unlocks the rwlock lock in the pair, and releases the mutex.
-// Both actions must acquire a cachetable lock during that time, so definitely saves time to do it that way.
-
-#include <sys/time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-
-#include <toku_pthread.h>
-#include <toku_portability.h>
-#include <toku_time.h>
-#include <toku_assert.h>
-#include <util/rwlock.h>
-#include <util/frwlock.h>
-#include <portability/toku_atomic.h>
-#include "toku_fair_rwlock.h"
-
-#include "rwlock_condvar.h"
-
-static int verbose=1;
-static int timing_only=0;
-
-static void parse_args (int argc, const char *argv[]) {
- const char *progname = argv[0];
- argc--; argv++;
- while (argc>0) {
- if (strcmp(argv[0], "-v")==0) {
- verbose++;
- } else if (strcmp(argv[0], "-q")==0) {
- verbose--;
- } else if (strcmp(argv[0], "--timing-only")==0) {
- timing_only=1;
- } else {
- fprintf(stderr, "Usage: %s {-q}* {-v}* {--timing-only}\n", progname);
- exit(1);
- }
- argc--; argv++;
- }
-}
-
-static const int T=6;
-static const int N=10000000;
-
-static double best_nop_time=1e12;
-static double best_fcall_time=1e12;
-static double best_cas_time=1e12;
-static double best_mutex_time=1e12;
-static double best_rwlock_time=1e12;
-static double best_ft_time=1e12;
-static double best_prelocked_time=1e12;
-static double best_cv_fair_rwlock_time=1e12; // fair from condition variables
-static double best_fair_rwlock_time=1e12;
-static double mind(double a, double b) { if (a<b) return a; else return b; }
-
-#if 0
-// gcc 4.4.4 (fedora 12) doesn't introduce memory barriers on these writes, so I think that volatile is not enough for sequential consistency.
-// Intel guarantees that writes are seen in the same order as they were performed on one processor. But if there were two processors, funny things could happen.
-volatile int sc_a, sc_b;
-void sequential_consistency (void) {
- sc_a = 1;
- sc_b = 0;
-}
-#endif
-
-// Declaring val to be volatile produces essentially identical code as putting the asm volatile memory statements in.
-// gcc is not introducing memory barriers to force sequential consistency on volatile memory writes.
-// That's probably good enough for us, since we'll have a barrier instruction anywhere it matters.
-volatile int val = 0;
-
-static
-void time_nop (void) {
- struct timeval start,end;
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- if (val!=0) abort();
- val=1;
- //__asm__ volatile ("" : : : "memory");
- val=0;
- //__asm__ volatile ("" : : : "memory");
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "nop = %.6fns/(lock+unlock)\n", diff);
- best_nop_time=mind(best_nop_time,diff);
- }
-}
-
-static
-void time_fcall (void) {
- struct timeval start,end;
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- fcall_nop(i);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "fcall = %.6fns/(lock+unlock)\n", diff);
- best_fcall_time=mind(best_fcall_time,diff);
- }
-}
-
-static
-void time_cas (void) {
- volatile int64_t myval = 0;
- struct timeval start,end;
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- { int r = toku_sync_val_compare_and_swap(&myval, 0, 1); assert(r==0); }
- { int r = toku_sync_val_compare_and_swap(&myval, 1, 0); assert(r==1); }
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "cas = %.6fns/(lock+unlock)\n", diff);
- best_cas_time=mind(best_cas_time,diff);
- }
-}
-
-
-static
-void time_pthread_mutex (void) {
- pthread_mutex_t mutex;
- { int r = pthread_mutex_init(&mutex, NULL); assert(r==0); }
- struct timeval start,end;
- pthread_mutex_lock(&mutex);
- pthread_mutex_unlock(&mutex);
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- pthread_mutex_lock(&mutex);
- pthread_mutex_unlock(&mutex);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "pthread_mutex = %.6fns/(lock+unlock)\n", diff);
- best_mutex_time=mind(best_mutex_time,diff);
- }
- { int r = pthread_mutex_destroy(&mutex); assert(r==0); }
-}
-
-static
-void time_pthread_rwlock (void) {
- pthread_rwlock_t mutex;
- { int r = pthread_rwlock_init(&mutex, NULL); assert(r==0); }
- struct timeval start,end;
- pthread_rwlock_rdlock(&mutex);
- pthread_rwlock_unlock(&mutex);
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- pthread_rwlock_rdlock(&mutex);
- pthread_rwlock_unlock(&mutex);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "pthread_rwlock(r) = %.6fns/(lock+unlock)\n", diff);
- best_rwlock_time=mind(best_rwlock_time,diff);
- }
- { int r = pthread_rwlock_destroy(&mutex); assert(r==0); }
-}
-
-static void ft_rwlock_lock (RWLOCK rwlock, toku_mutex_t *mutex) {
- toku_mutex_lock(mutex);
- rwlock_read_lock(rwlock, mutex);
- toku_mutex_unlock(mutex);
-}
-
-static void ft_rwlock_unlock (RWLOCK rwlock, toku_mutex_t *mutex) {
- toku_mutex_lock(mutex);
- rwlock_read_unlock(rwlock);
- toku_mutex_unlock(mutex);
-}
-
-// Time the read lock that's in ft/rwlock.h
-static
-void time_ft_rwlock (void) {
- struct rwlock rwlock;
- toku_mutex_t external_mutex;
- toku_mutex_init(&external_mutex, NULL);
- rwlock_init(&rwlock);
- struct timeval start,end;
-
- ft_rwlock_lock(&rwlock, &external_mutex);
- ft_rwlock_unlock(&rwlock, &external_mutex);
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- ft_rwlock_lock(&rwlock, &external_mutex);
- ft_rwlock_unlock(&rwlock, &external_mutex);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "ft_rwlock(r) = %.6fns/(lock+unlock)\n", diff);
- best_ft_time=mind(best_ft_time,diff);
- }
- rwlock_destroy(&rwlock);
- toku_mutex_destroy(&external_mutex);
-}
-
-// Time the read lock that's in ft/rwlock.h, assuming the mutex is already held.
-static
-void time_ft_prelocked_rwlock (void) {
- struct rwlock rwlock;
- toku_mutex_t external_mutex;
- toku_mutex_init(&external_mutex, NULL);
- toku_mutex_lock(&external_mutex);
- rwlock_init(&rwlock);
- struct timeval start,end;
-
- rwlock_read_lock(&rwlock, &external_mutex);
- rwlock_read_unlock(&rwlock);
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- rwlock_read_lock(&rwlock, &external_mutex);
- rwlock_read_unlock(&rwlock);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "ft_rwlock(r) = %.6fns/(lock+unlock)\n", diff);
- best_prelocked_time=mind(best_prelocked_time,diff);
- }
- rwlock_destroy(&rwlock);
- toku_mutex_unlock(&external_mutex);
- toku_mutex_destroy(&external_mutex);
-}
-
-static
-void time_toku_fair_rwlock (void) {
- toku_fair_rwlock_t mutex;
- toku_fair_rwlock_init(&mutex);
- struct timeval start,end;
- toku_fair_rwlock_rdlock(&mutex);
- toku_fair_rwlock_unlock(&mutex);
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- toku_fair_rwlock_rdlock(&mutex);
- toku_fair_rwlock_unlock(&mutex);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "pthread_fair(r) = %.6fns/(lock+unlock)\n", diff);
- best_fair_rwlock_time=mind(best_fair_rwlock_time,diff);
- }
- toku_fair_rwlock_destroy(&mutex);
-}
-
-static
-void time_toku_cv_fair_rwlock (void) {
- toku_cv_fair_rwlock_t mutex;
- toku_cv_fair_rwlock_init(&mutex);
- struct timeval start,end;
- toku_cv_fair_rwlock_rdlock(&mutex);
- toku_cv_fair_rwlock_unlock(&mutex);
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- toku_cv_fair_rwlock_rdlock(&mutex);
- toku_cv_fair_rwlock_unlock(&mutex);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "pthread_fair(r) = %.6fns/(lock+unlock)\n", diff);
- best_cv_fair_rwlock_time=mind(best_cv_fair_rwlock_time,diff);
- }
- toku_cv_fair_rwlock_destroy(&mutex);
-}
-
-#define N 6
-#define T 100000
-#define L 5
-#define N_LOG_ENTRIES (L*N*4)
-
-static toku_fair_rwlock_t rwlock;
-static toku::frwlock frwlock;
-static toku_mutex_t fmutex;
-
-static bool use_frwlock_for_locking;
-
-static struct log_s {
- int threadid, loopid;
- char action;
-} actionlog[N_LOG_ENTRIES];
-static int log_counter=0;
-
-static void logit (int threadid, int loopid, char action) {
- //printf("%d %d %c\n", threadid, loopid, action);
- int my_log_counter = toku_sync_fetch_and_add(&log_counter, 1);
- assert(my_log_counter<N_LOG_ENTRIES);
- actionlog[my_log_counter].threadid = threadid;
- actionlog[my_log_counter].loopid = loopid;
- actionlog[my_log_counter].action = action;
-}
-
-// The action should look like this:
-// Threads 0-2 are reader threads.
-// Threads 3-6 are writer threads.
-// The threads all repeatedly grab the lock, wait T steps, and release.
-// If the readers can starve the writers, then most of the writers will be at the end.
-// If the writers can starve the readers, then most of the readers will be at the end.
-// The reader threads all grab the lock, wait T*2 steps, and release the lock.
-// The writer threads
-// First the writer threads wait time T while the reader threads all go for the lock.
-// Before the first one lets go, the writer threads wake up and try to grab the lock. But the readers are still
-
-// 3 threads (0-2) try to grab the lock all at once. They'll get it. They each sleep for time T*2
-// 3 threads (3-6) try to grab the write lock. They'll get it one after another.
-
-
-static void grab_rdlock (int threadid, int iteration) {
- logit(threadid, iteration, 't');
- if (use_frwlock_for_locking) {
- toku_mutex_lock(&fmutex);
- frwlock.read_lock();
- toku_mutex_unlock(&fmutex);
- }
- else { int r = toku_fair_rwlock_rdlock(&rwlock); assert(r==0); }
- logit(threadid, iteration, 'R');
-}
-
-static void release_rdlock (int threadid, int iteration) {
- logit(threadid, iteration, 'u');
- if (use_frwlock_for_locking) {
- toku_mutex_lock(&fmutex);
- frwlock.read_unlock();
- toku_mutex_unlock(&fmutex);
- }
- else { int r = toku_fair_rwlock_unlock(&rwlock); assert(r==0); }
-}
-
-static void grab_wrlock (int threadid, int iteration) {
- logit(threadid, iteration, 'T');
- if (use_frwlock_for_locking) {
- toku_mutex_lock(&fmutex);
- frwlock.write_lock(true);
- toku_mutex_unlock(&fmutex);
- }
- else { int r = toku_fair_rwlock_wrlock(&rwlock); assert(r==0); }
- logit(threadid, iteration, 'W');
-}
-
-static void release_wrlock (int threadid, int iteration) {
- logit(threadid, iteration, 'U');
- if (use_frwlock_for_locking) {
- toku_mutex_lock(&fmutex);
- frwlock.write_unlock();
- toku_mutex_unlock(&fmutex);
- }
- else { int r = toku_fair_rwlock_unlock(&rwlock); assert(r==0);}
-}
-
-static void *start_thread (void *vv) {
- int *vp=(int*)vv;
- int v=*vp;
-
- //printf("T%d=%ld\n", v, pthread_self());
- switch(v) {
- case 0:
- case 1:
- case 2:
- for (int i=0; i<L; i++) {
- grab_rdlock(v, i);
- usleep(T);
- release_rdlock(v, i);
- }
- break;
- case 3:
- case 4:
- case 5:
- for (int i=0; i<L; i++) {
- grab_wrlock(v, i);
- usleep(T);
- release_wrlock(v, i);
- }
- }
- return NULL;
-}
-
-static void *start_thread_random (void *vv) {
- int *vp=(int*)vv;
- int v=*vp;
- int wait;
-
- for (int i=0; i<L; i++) {
- if (random()%2==0) {
- grab_rdlock(v, i);
- wait = random() % 20;
- for (int j=0; j<wait; j++) sched_yield();
- release_rdlock(v, i);
- wait = random() % 20;
- for (int j=0; j<wait; j++) sched_yield();
- } else {
- grab_wrlock(v, i);
- wait = random() % 20;
- for (int j=0; j<wait; j++) sched_yield();
- release_wrlock(v, i);
- wait = random() % 20;
- for (int j=0; j<wait; j++) sched_yield();
- }
- }
- return NULL;
-}
-
-static void check_actionlog (int expected_writer_max_count,
- int expected_reader_parallelism_min,
- int expected_reader_parallelism_max)
-// Effect:
-// Make sure that writers are exclusive.
-// Make sure that anyone who asks for a lock doesn't have one.
-// Make sure that anyone granted a lock actually asked for a lock.
-// Make sure that anyone who releases a lock has it.
-// Make sure that readers don't starve writers, and writers don't starve readers. (Not sure how to code this up...)
-{
- int reader_max=0;
- int writer_max=0;
- int state=0;
- char tstate[N];
- for (int i=0; i<N; i++) tstate[i]=0;
- for (int i=0; i<log_counter; i++) {
- switch (actionlog[i].action) {
- case 't': // fall through to 'T'
- case 'T':
- assert(tstate[actionlog[i].threadid]==0);
- tstate[actionlog[i].threadid]=actionlog[i].action;
- break;
- case 'W':
- assert(tstate[actionlog[i].threadid]=='T');
- tstate[actionlog[i].threadid]=actionlog[i].action;
- assert(state==0);
- state=-1;
- writer_max = 1;
- break;
- case 'U':
- assert(tstate[actionlog[i].threadid]=='W');
- tstate[actionlog[i].threadid]=0;
- assert(state==-1);
- state=0;
- break;
- case 'R':
- assert(tstate[actionlog[i].threadid]=='t');
- tstate[actionlog[i].threadid]=actionlog[i].action;
- if (state<0) { printf("On step %d\n", i); }
- assert(state>=0);
- state++;
- if (state>reader_max) reader_max=state;
- break;
- case 'u':
- assert(tstate[actionlog[i].threadid]=='R');
- tstate[actionlog[i].threadid]=0;
- assert(state>=0);
- state--;
- break;
- default:
- abort();
- }
- }
- assert(reader_max>=expected_reader_parallelism_min);
- assert(reader_max<=expected_reader_parallelism_max);
- assert(writer_max==expected_writer_max_count);
-}
-
-
-static void test_rwlock_internal (void *(*start_th)(void*), bool use_frwlock, int max_wr, int min_rd, int max_rd) {
- if (verbose>=2) printf("Running threads:\n");
- log_counter=0;
- pthread_t threads[N];
- int v[N];
- use_frwlock_for_locking = use_frwlock;
- if (use_frwlock_for_locking) {
- fmutex = TOKU_MUTEX_INITIALIZER;
- frwlock.init(&fmutex);
- }
- else {
- toku_fair_rwlock_init(&rwlock);
- }
- for (int i=0; i<N; i++) {
- v[i]=i;
- int r = pthread_create(&threads[i], NULL, start_th, &v[i]);
- assert(r==0);
- }
- for (int i=0; i<N; i++) {
- void *rv;
- int r = pthread_join(threads[i], &rv);
- assert(rv==NULL);
- assert(r==0);
- }
- if (verbose>1) {
- for (int i=0; i<log_counter; i++) {
- printf("%d: %*s%c%d\n", i, actionlog[i].threadid*4, "", actionlog[i].action, actionlog[i].loopid);
- }
- }
- check_actionlog(max_wr, min_rd, max_rd);
- if (use_frwlock_for_locking) {
- frwlock.deinit();
- toku_mutex_destroy(&fmutex);
- }
- else {
- toku_fair_rwlock_destroy(&rwlock);
- }
- if (verbose>2) printf("OK\n");
-}
-
-static void test_rwlock (bool use_frwlock) {
- test_rwlock_internal(start_thread, use_frwlock, 1, 2, 3);
- for (int i=0; i<10; i++) {
- test_rwlock_internal(start_thread_random, use_frwlock, 1, 0, N);
- }
-}
-int main (int argc, const char *argv[]) {
- parse_args(argc, argv);
- if (timing_only) {
- time_nop();
- time_fcall();
- time_cas();
- time_pthread_mutex();
- time_pthread_rwlock();
- time_ft_rwlock();
- time_ft_prelocked_rwlock();
- time_toku_cv_fair_rwlock();
- time_toku_fair_rwlock();
- if (verbose>0) {
- printf("// Best nop time=%10.6fns\n", best_nop_time);
- printf("// Best fcall time=%10.6fns\n", best_fcall_time);
- printf("// Best cas time=%10.6fns\n", best_cas_time);
- printf("// Best mutex time=%10.6fns\n", best_mutex_time);
- printf("// Best rwlock time=%10.6fns\n", best_rwlock_time);
- printf("// Best ft rwlock time=%10.6fns\n", best_ft_time);
- printf("// Best prelocked time=%10.6fns\n", best_prelocked_time);
- printf("// Best fair cv rwlock time=%10.6fns\n", best_cv_fair_rwlock_time);
- printf("// Best fair fast rwlock time=%10.6fns\n", best_fair_rwlock_time);
- }
- } else {
- test_rwlock(true);
- test_rwlock(false);
- }
- return 0;
-}
-
diff --git a/storage/tokudb/ft-index/portability/toku_fair_rwlock.cc b/storage/tokudb/ft-index/portability/toku_fair_rwlock.cc
deleted file mode 100644
index d89b49307d1..00000000000
--- a/storage/tokudb/ft-index/portability/toku_fair_rwlock.cc
+++ /dev/null
@@ -1,361 +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) 2010-2013 Tokutek Inc. All rights reserved."
-
-#include "toku_config.h"
-
-#include <pthread.h>
-#include <toku_assert.h>
-#include "toku_pthread.h"
-#include "toku_fair_rwlock.h"
-
-#include <stdio.h>
-#include <memory.h>
-#include <portability/toku_atomic.h>
-
-struct toku_fair_rwlock_waiter_state {
- char is_read;
- struct toku_fair_rwlock_waiter_state *next;
- toku_cond_t cond;
-};
-
-#if defined(HAVE_GNU_TLS)
-static __thread struct toku_fair_rwlock_waiter_state waitstate_var = {0, NULL, { PTHREAD_COND_INITIALIZER } };
-#define GET_WAITSTATE(name) name = &waitstate_var
-#else
-static pthread_key_t waitstate_key;
-static bool waitstate_key_initialized = false;
-
-void
-toku_rwlock_init(void)
-{
- assert(!waitstate_key_initialized);
- int r = toku_pthread_key_create(&waitstate_key, toku_free);
- assert_zero(r);
- waitstate_key_initialized = true;
-}
-
-void
-toku_rwlock_destroy(void)
-{
- assert(waitstate_key_initialized);
- int r = toku_pthread_key_delete(waitstate_key);
- assert_zero(r);
- waitstate_key_initialized = false;
-}
-
-static struct toku_fair_rwlock_waiter_state *
-get_waitstate(void)
-{
- assert(waitstate_key_initialized);
- struct toku_fair_rwlock_waiter_state *waitstate = NULL;
- void *p = toku_pthread_getspecific(waitstate_key);
- if (!p) {
- p = toku_xmalloc(sizeof *waitstate);
- int r = toku_pthread_setspecific(waitstate_key, p);
- assert_zero(r);
- }
- waitstate = static_cast<struct toku_fair_rwlock_waiter_state *>(p);
- return waitstate;
-}
-
-#define GET_WAITSTATE(name) name = get_waitstate()
-#endif
-
-void toku_fair_rwlock_init (toku_fair_rwlock_t *rwlock) {
- rwlock->state=0LL;
- rwlock->waiters_head = NULL;
- rwlock->waiters_tail = NULL;
- toku_mutex_init(&rwlock->mutex, NULL);
-}
-
-void toku_fair_rwlock_destroy (toku_fair_rwlock_t *rwlock) {
- assert(rwlock->state==0); // no one can hold the mutex, and no one can hold any lock.
- toku_mutex_destroy(&rwlock->mutex);
-}
-
-#ifdef RW_DEBUG
-static __thread int tid=-1;
-static int next_tid=0;
-static int get_tid (void) {
- if (tid==-1) {
- tid = toku_sync_fetch_and_add(&next_tid, 1);
- }
- return tid;
-}
-#define L(l) printf("t%02d %s:%d %s\n", get_tid(), __FILE__, __LINE__, #l)
-#define LP(l,s) printf("t%02d %s:%d %s %lx (wlock=%d rcount=%d qcount=%d)\n", get_tid(), __FILE__, __LINE__, #l, s, s_get_wlock(s), s_get_rcount(s), s_get_qcount(s))
-#else
-#define L(l) ((void)0)
-#define LP(l,s) ((void)s)
-#endif
-
-void foo (void);
-void foo (void) {
- printf("%llx\n", RWS_QCOUNT_MASK|RWS_WLOCK_MASK);
-}
-
-int toku_fair_rwlock_rdlock_slow (toku_fair_rwlock_t *rwlock) {
- uint64_t s;
- struct toku_fair_rwlock_waiter_state *GET_WAITSTATE(waitstate);
- goto ML; // we start in the ML state.
- ML:
- toku_mutex_lock(&rwlock->mutex);
- goto R2;
- R2:
- s = rwlock->state;
- if (s_get_qcount(s)==0 && !s_get_wlock(s)) goto C2;
- else goto C3;
- C2:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_incr_rcount(s))) goto MU;
- else goto R2;
- C3:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_incr_qcount(s))) goto E;
- else goto R2;
- E:
- // Put me into the queue.
- if (rwlock->waiters_tail) {
- rwlock->waiters_tail->next = waitstate;
- } else {
- rwlock->waiters_head = waitstate;
- }
- rwlock->waiters_tail = waitstate;
- waitstate->next = NULL;
- waitstate->is_read = 1;
- goto W;
- W:
- toku_cond_wait(&waitstate->cond, &rwlock->mutex);
- // must wait till we are at the head of the queue because of the possiblity of spurious wakeups.
- if (rwlock->waiters_head==waitstate) goto D;
- else goto W;
- D:
- rwlock->waiters_head = waitstate->next;
- if (waitstate->next==NULL) {
- rwlock->waiters_tail = NULL;
- }
- goto WN;
- WN:
- // If the next guy is a reader then wake him up.
- if (waitstate->next!=NULL && waitstate->next->is_read) {
- toku_cond_signal(&rwlock->waiters_head->cond);
- }
- goto R4;
- R4:
- s = rwlock->state;
- goto C4;
- C4:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_incr_rcount(s_decr_qcount(s)))) goto MU;
- else goto R4;
- MU:
- toku_mutex_unlock(&rwlock->mutex);
- goto DONE;
- DONE:
- return 0;
-}
-
-int toku_fair_rwlock_wrlock_slow (toku_fair_rwlock_t *rwlock) {
- uint64_t s;
- struct toku_fair_rwlock_waiter_state *GET_WAITSTATE(waitstate);
- goto ML;
- ML:
- L(ML);
- toku_mutex_lock(&rwlock->mutex);
- goto R2;
- R2:
- s = rwlock->state;
- LP(R2, s);
- if (s_get_qcount(s)==0 && !s_get_wlock(s) && s_get_rcount(s)==0) goto C2;
- else goto C3;
- C2:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_set_wlock(s))) goto MU;
- else goto R2;
- C3:
- L(C3);
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_incr_qcount(s))) goto E;
- else goto R2;
- E:
- LP(E, rwlock->state);
- // Put me into the queue.
- if (rwlock->waiters_tail) {
- rwlock->waiters_tail->next = waitstate;
- } else {
- rwlock->waiters_head = waitstate;
- }
- rwlock->waiters_tail = waitstate;
- waitstate->next = NULL;
- waitstate->is_read = 0;
- goto W;
- W:
- toku_cond_wait(&waitstate->cond, &rwlock->mutex);
- // must wait till we are at the head of the queue because of the possiblity of spurious wakeups.
- if (rwlock->waiters_head==waitstate) goto D;
- else goto W;
- D:
- rwlock->waiters_head = waitstate->next;
- if (waitstate->next==NULL) {
- rwlock->waiters_tail = NULL;
- }
- goto R4;
- R4:
- s = rwlock->state;
- assert(!s_get_wlock(s));
- goto C4;
- C4:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_set_wlock(s_decr_qcount(s)))) goto MU;
- else goto R4;
- MU:
- toku_mutex_unlock(&rwlock->mutex);
- goto DONE;
- DONE:
- return 0;
-}
-
-int toku_fair_rwlock_unlock_r_slow (toku_fair_rwlock_t *rwlock) {
- uint64_t s;
- goto ML;
- ML:
- toku_mutex_lock(&rwlock->mutex);
- goto R2;
- R2:
- s = rwlock->state;
- LP(R2, s);
- if (s_get_rcount(s)>1 || s_get_qcount(s)==0) goto C2;
- else goto C3;
- C2:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_decr_rcount(s))) goto MU;
- else goto R2;
- C3:
- // rcount==1 and qcount>0
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_decr_rcount(s))) goto WN;
- else goto R2;
- WN:
- LP(WN, rwlock->state);
- toku_cond_signal(&rwlock->waiters_head->cond);
- goto MU;
- MU:
- toku_mutex_unlock(&rwlock->mutex);
- goto DONE;
- DONE:
- return 0;
-}
-
-int toku_fair_rwlock_unlock_w_slow (toku_fair_rwlock_t *rwlock) {
- uint64_t s;
- //assert(s_get_rcount(s)==0 && s_get_wlock(s));
- goto ML;
- ML:
- toku_mutex_lock(&rwlock->mutex);
- goto R2;
- R2:
- LP(R2, rwlock->state);
- s = rwlock->state;
- if (s_get_qcount(s)==0) goto C2;
- else goto C3;
- C2:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_clear_wlock(s))) goto MU;
- else goto R2;
- C3:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_clear_wlock(s))) goto WN;
- else goto R2;
- WN:
- LP(WN, rwlock->state);
- toku_cond_signal(&rwlock->waiters_head->cond);
- goto MU;
- MU:
- toku_mutex_unlock(&rwlock->mutex);
- goto DONE;
- DONE:
- return 0;
-}
-
-// This function is defined so we can measure the cost of a function call.
-int fcall_nop (int i) {
- return i;
-}
diff --git a/storage/tokudb/ft-index/portability/toku_fair_rwlock.h b/storage/tokudb/ft-index/portability/toku_fair_rwlock.h
deleted file mode 100644
index 92793b1444d..00000000000
--- a/storage/tokudb/ft-index/portability/toku_fair_rwlock.h
+++ /dev/null
@@ -1,237 +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."
-#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_pthread.h"
-#include <portability/toku_atomic.h>
-
-// Fair readers/writer locks. These are fair (meaning first-come first-served. No reader starvation, and no writer starvation). And they are
-// probably faster than the linux readers/writer locks (pthread_rwlock_t).
-struct toku_fair_rwlock_waiter_state; // this structure is used internally.
-typedef struct toku_fair_rwlock_s {
- // Try to put enough state into STATE so that in many cases, a compare-and-swap will work.
- // The 64-bit state bits are as follows:
- // bit 0: 1 iff someone has exclusive ownership of the entire state. (This is a spin lock).
- // bit 1: 1 iff someone holds a write lock.
- // bit 2: 1 iff the queue is not empty (if the queue is not empty, then you cannot use the fast path.)
- // bits 3--31 how many read locks are held.
- uint64_t volatile state;
- // The waiters each provide a condition variable. This is the mutex they are all using.
- // If anyone holds this mutex, they must set the RWS_MUTEXED bit first. Then they grab the mutex. Then they clear the bit indicating that they don't have the mutex. No one else can change anything while the RWS_MUTEXED bit is set.
- toku_mutex_t mutex;
- struct toku_fair_rwlock_waiter_state *waiters_head, *waiters_tail;
-} toku_fair_rwlock_t;
-
-void toku_rwlock_init(void) __attribute__((constructor));
-void toku_rwlock_destroy(void) __attribute__((destructor));
-
-#define RWS_WLOCK_MASK 1LL
-
-#define RWS_QCOUNT_OFF 1
-#define RWS_QCOUNT_LEN 31
-#define RWS_QCOUNT_INCR 2LL
-#define RWS_QCOUNT_MASK (((1L<<RWS_QCOUNT_LEN)-1)<<RWS_QCOUNT_OFF)
-
-#define RWS_RCOUNT_OFF (RWS_QCOUNT_OFF+RWS_QCOUNT_LEN)
-#define RWS_RCOUNT_LEN 31
-#define RWS_RCOUNT_INCR (1LL<<32)
-
-static inline int s_get_wlock(uint64_t s) {
- return (s&RWS_WLOCK_MASK)!=0;
-}
-static inline unsigned int s_get_qcount(uint64_t s) {
- return (s>>RWS_QCOUNT_OFF)&((1LL<<RWS_QCOUNT_LEN)-1);
-}
-static inline unsigned int s_get_rcount(uint64_t s) {
- return (s>>RWS_RCOUNT_OFF)&((1LL<<RWS_RCOUNT_LEN)-1);
-}
-
-static inline uint64_t s_set_wlock (uint64_t s) {
- return s | RWS_WLOCK_MASK;
-}
-static inline uint64_t s_clear_wlock (uint64_t s) {
- return s & ~RWS_WLOCK_MASK;
-}
-static inline uint64_t s_incr_qcount (uint64_t s) {
- //printf("%s:%d (%s) s=%lx, get_qcount=%d 1u<<%d=%u\n", __FILE__, __LINE__, __FUNCTION__, s, s_get_qcount(s), RWS_QCOUNT_LEN, 1u<<RWS_QCOUNT_LEN);
- //assert(s_get_qcount(s)+1 < (1u<<RWS_QCOUNT_LEN));
- return s+RWS_QCOUNT_INCR;
-}
-static inline uint64_t s_decr_qcount (uint64_t s) {
- //assert(s_get_qcount(s) > 0);
- return s-RWS_QCOUNT_INCR;
-}
-static inline uint64_t s_incr_rcount (uint64_t s) {
- //assert(s_get_rcount(s)+1 < (1u<<RWS_RCOUNT_LEN));
- return s+RWS_RCOUNT_INCR;
-}
-static inline uint64_t s_decr_rcount (uint64_t s) {
- //assert(s_get_rcount(s) > 0);
- return s-RWS_RCOUNT_INCR;
-}
-
-void toku_fair_rwlock_init (toku_fair_rwlock_t *rwlock);
-void toku_fair_rwlock_destroy (toku_fair_rwlock_t *rwlock);
-int toku_fair_rwlock_rdlock_slow (toku_fair_rwlock_t *rwlock); // this is the slow internal version that grabs the mutex.
-
-// Inline the fast path to avoid function call overhead.
-static inline int toku_fair_rwlock_rdlock (toku_fair_rwlock_t *rwlock) {
- uint64_t s = rwlock->state;
- START:
- s = rwlock->state;
- if (0==(s&(RWS_QCOUNT_MASK | RWS_WLOCK_MASK))) goto C1;
- //if (s_get_qcount(s)==0 && !s_get_wlock(s)) goto C1;
- else goto ML;
- C1:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_incr_rcount(s))) goto DONE;
- else goto START;
- DONE:
- return 0;
- ML:
- return toku_fair_rwlock_rdlock_slow(rwlock);
-}
-
-int toku_fair_rwlock_wrlock_slow (toku_fair_rwlock_t *rwlock);
-
-// Inline the fast path to avoid function call overhead.
-static inline int toku_fair_rwlock_wrlock (toku_fair_rwlock_t *rwlock) {
- uint64_t s;
- START:
- s = rwlock->state;
- if (s_get_qcount(s)==0 && !s_get_wlock(s) && s_get_rcount(s)==0) goto C1;
- else goto ML;
- C1:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_set_wlock(s))) goto DONE;
- else goto START;
- DONE:
- return 0;
- ML:
- return toku_fair_rwlock_wrlock_slow(rwlock);
-}
-
-int toku_fair_rwlock_unlock_r_slow (toku_fair_rwlock_t *rwlock);
-int toku_fair_rwlock_unlock_w_slow (toku_fair_rwlock_t *rwlock);
-
-static inline int toku_fair_rwlock_unlock (toku_fair_rwlock_t *rwlock) {
- uint64_t s;
- s = rwlock->state;
- if (s_get_wlock(s)) {
- goto wSTART0; // we already have s.
- wSTART:
- s = rwlock->state;
- goto wSTART0;
- wSTART0:
- if (s_get_qcount(s)==0) goto wC1;
- else goto wML;
- wC1:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_clear_wlock(s))) goto wDONE;
- else goto wSTART;
- wDONE:
- return 0;
- wML:
- return toku_fair_rwlock_unlock_w_slow (rwlock);
- } else {
- goto rSTART0; // we already have s.
- rSTART:
- s = rwlock->state;
- goto rSTART0;
- rSTART0:
- if (s_get_rcount(s)>1 || s_get_qcount(s)==0) goto rC1;
- else goto rML;
- rC1:
- if (toku_sync_bool_compare_and_swap(&rwlock->state, s, s_decr_rcount(s))) goto rDONE;
- else goto rSTART;
- rDONE:
- return 0;
- rML:
- return toku_fair_rwlock_unlock_r_slow (rwlock);
- }
-}
-int fcall_nop(int);
diff --git a/storage/tokudb/ft-index/scripts/run.stress-tests.py b/storage/tokudb/ft-index/scripts/run.stress-tests.py
index cca286e192d..fbbf5ee6472 100755
--- a/storage/tokudb/ft-index/scripts/run.stress-tests.py
+++ b/storage/tokudb/ft-index/scripts/run.stress-tests.py
@@ -739,6 +739,7 @@ if __name__ == '__main__':
default_recover_testnames = ['recover-test_stress1.tdb',
'recover-test_stress2.tdb',
'recover-test_stress3.tdb',
+ 'recover-child-rollback.tdb',
'recover-test_stress_openclose.tdb']
build_group = OptionGroup(parser, 'Build Options', 'Control how the fractal tree and tests get built.')
build_group.add_option('--skip_build', action='store_false', dest='build', default=True,
diff --git a/storage/tokudb/ft-index/src/CMakeLists.txt b/storage/tokudb/ft-index/src/CMakeLists.txt
index 394d120beaa..7487d1880aa 100644
--- a/storage/tokudb/ft-index/src/CMakeLists.txt
+++ b/storage/tokudb/ft-index/src/CMakeLists.txt
@@ -42,8 +42,14 @@ endif ()
# detect when we are being built as a subproject
if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
install(
- TARGETS ${LIBTOKUDB} ${LIBTOKUDB}_static
- DESTINATION lib
+ TARGETS ${LIBTOKUDB}
+ DESTINATION ${INSTALL_LIBDIR}
+ COMPONENT tokukv_libs_shared
+ )
+ install(
+ TARGETS ${LIBTOKUDB}_static
+ DESTINATION ${INSTALL_LIBDIR}
+ COMPONENT tokukv_libs_static
)
endif ()
diff --git a/storage/tokudb/ft-index/src/export.map b/storage/tokudb/ft-index/src/export.map
index 566e751bd74..3f2c7569ea4 100644
--- a/storage/tokudb/ft-index/src/export.map
+++ b/storage/tokudb/ft-index/src/export.map
@@ -5,6 +5,7 @@
db_strerror;
db_version;
db_env_set_direct_io;
+ db_env_set_compress_buffers_before_eviction;
db_env_set_func_fsync;
db_env_set_func_malloc;
db_env_set_func_realloc;
diff --git a/storage/tokudb/ft-index/src/indexer-undo-do.cc b/storage/tokudb/ft-index/src/indexer-undo-do.cc
index a9a2c52bf98..2201c4f37e3 100644
--- a/storage/tokudb/ft-index/src/indexer-undo-do.cc
+++ b/storage/tokudb/ft-index/src/indexer-undo-do.cc
@@ -615,7 +615,16 @@ indexer_ft_delete_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xi
} else {
result = toku_ydb_check_avail_fs_space(indexer->i->env);
if (result == 0) {
- toku_ft_send_delete(db_struct_i(hotdb)->ft_handle, hotkey, xids, TXNID_NONE, make_gc_info(true));
+ FT_HANDLE ft_h = db_struct_i(hotdb)->ft_handle;
+ 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,
+ oldest_referenced_xid_estimate,
+ true);
+ toku_ft_send_delete(db_struct_i(hotdb)->ft_handle, hotkey, xids, &gc_info);
}
}
return result;
@@ -651,7 +660,16 @@ indexer_ft_insert_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, DBT *ho
} else {
result = toku_ydb_check_avail_fs_space(indexer->i->env);
if (result == 0) {
- toku_ft_send_insert(db_struct_i(hotdb)->ft_handle, hotkey, hotval, xids, FT_INSERT, TXNID_NONE, make_gc_info(true));
+ FT_HANDLE ft_h = db_struct_i(hotdb)->ft_handle;
+ 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,
+ oldest_referenced_xid_estimate,
+ true);
+ toku_ft_send_insert(db_struct_i(hotdb)->ft_handle, hotkey, hotval, xids, FT_INSERT, &gc_info);
}
}
return result;
@@ -670,8 +688,18 @@ indexer_ft_commit(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xids) {
result = indexer->i->test_commit_any(indexer, hotdb, hotkey, xids);
} else {
result = toku_ydb_check_avail_fs_space(indexer->i->env);
- if (result == 0)
- toku_ft_send_commit_any(db_struct_i(hotdb)->ft_handle, hotkey, xids, TXNID_NONE, make_gc_info(true));
+ if (result == 0) {
+ FT_HANDLE ft_h = db_struct_i(hotdb)->ft_handle;
+ 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,
+ oldest_referenced_xid_estimate,
+ true);
+ toku_ft_send_commit_any(db_struct_i(hotdb)->ft_handle, hotkey, xids, &gc_info);
+ }
}
}
return result;
diff --git a/storage/tokudb/ft-index/src/loader.cc b/storage/tokudb/ft-index/src/loader.cc
index 57beee3810f..93ac551632e 100644
--- a/storage/tokudb/ft-index/src/loader.cc
+++ b/storage/tokudb/ft-index/src/loader.cc
@@ -319,8 +319,8 @@ toku_loader_create_loader(DB_ENV *env,
}
TOKUTXN ttxn = txn ? db_txn_struct_i(txn)->tokutxn : NULL;
rval = toku_ft_loader_open(&loader->i->ft_loader,
- loader->i->env->i->cachetable,
- loader->i->env->i->generate_row_for_put,
+ env->i->cachetable,
+ env->i->generate_row_for_put,
src_db,
N,
brts, dbs,
@@ -330,7 +330,7 @@ toku_loader_create_loader(DB_ENV *env,
load_lsn,
ttxn,
puts_allowed,
- loader->i->env->i->loader_memory_size,
+ env->get_loader_memory_size(env),
compress_intermediates);
if ( rval!=0 ) {
toku_free(new_inames_in_env);
diff --git a/storage/tokudb/ft-index/src/tests/CMakeLists.txt b/storage/tokudb/ft-index/src/tests/CMakeLists.txt
index af04123ca93..d85d24be001 100644
--- a/storage/tokudb/ft-index/src/tests/CMakeLists.txt
+++ b/storage/tokudb/ft-index/src/tests/CMakeLists.txt
@@ -67,10 +67,12 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
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
@@ -105,6 +107,7 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
loader-stress-del
loader-stress-test
loader-tpch-load
+ locktree_escalation_stalls
lock-pressure
manyfiles
maxsize-for-loader
@@ -146,6 +149,7 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
recover-2483
recover-3113
recover-5146
+ recover-child-rollback
recover-compare-db
recover-compare-db-descriptor
recover-del-multiple
@@ -252,10 +256,12 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
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
@@ -264,6 +270,7 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
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
@@ -578,7 +585,7 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
foreach(oldver 4.2.0 5.0.8 5.2.7 6.0.0 6.1.0 6.5.1 6.6.3)
set(versiondir ${TOKUDB_DATA}/old-stress-test-envs/${oldver})
- if (NOT EXISTS "${versiondir}/" AND NOT WARNED_ABOUT_DATA)
+ if (NOT EXISTS "${versiondir}/" AND NOT WARNED_ABOUT_DATA AND CMAKE_PROJECT_NAME STREQUAL TokuDB)
message(WARNING "Test data for upgrade tests for version ${oldver} doesn't exist, check out ${versiondir}/*-2000-dir first or upgrade stress tests may fail.")
set(WARNED_ABOUT_DATA 1)
endif ()
@@ -612,7 +619,7 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
endif ()
endforeach(src)
- if (NOT EXISTS "${TOKUDB_DATA}/test_5902/" AND NOT WARNED_ABOUT_DATA)
+ if (NOT EXISTS "${TOKUDB_DATA}/test_5902/" AND NOT WARNED_ABOUT_DATA AND CMAKE_PROJECT_NAME STREQUAL TokuDB)
message(WARNING "Test data for dump-env.tdb doesn't exist, check out ${TOKUDB_DATA}/test_5902 first or dump-env.tdb may fail.")
set(WARNED_ABOUT_DATA 1)
endif ()
@@ -653,7 +660,7 @@ if(BUILD_TESTING OR BUILD_SRC_TESTS)
endforeach(num)
set(old_loader_upgrade_data "${TOKUDB_DATA}/env_preload.4.2.0.emptydictionaries.cleanshutdown")
- if (NOT EXISTS "${old_loader_upgrade_data}/" AND NOT WARNED_ABOUT_DATA)
+ if (NOT EXISTS "${old_loader_upgrade_data}/" AND NOT WARNED_ABOUT_DATA AND CMAKE_PROJECT_NAME STREQUAL TokuDB)
message(WARNING "Test data for loader upgrade tests doesn't exist, check out ${old_loader_upgrade_data} first, or loader-stress-test3.tdb may fail.")
set(WARNED_ABOUT_DATA 1)
endif ()
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 442ccfd112d..72267437a4a 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-first-empty.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-first-empty.cc
@@ -220,7 +220,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
diff --git a/storage/tokudb/ft-index/src/tests/blocking-first.cc b/storage/tokudb/ft-index/src/tests/blocking-first.cc
index 9be783d2a04..1bd414a90aa 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-first.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-first.cc
@@ -237,7 +237,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
diff --git a/storage/tokudb/ft-index/src/tests/blocking-last.cc b/storage/tokudb/ft-index/src/tests/blocking-last.cc
index 9166a07aa28..5ca6ce5ec6a 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-last.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-last.cc
@@ -237,7 +237,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
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 c85996275bd..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
@@ -306,7 +306,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ 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
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 561f2550bb9..cece47cbeec 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-prelock-range.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-prelock-range.cc
@@ -182,7 +182,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
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 cffb164fba3..c43bcfad5f0 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-put-timeout.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-put-timeout.cc
@@ -233,7 +233,7 @@ int test_main(int argc, char * const argv[]) {
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); assert(r == 0);
+ 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
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 f2f7ea0e825..9c8ad60787b 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-put-wakeup.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-put-wakeup.cc
@@ -209,7 +209,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
diff --git a/storage/tokudb/ft-index/src/tests/blocking-put.cc b/storage/tokudb/ft-index/src/tests/blocking-put.cc
index d377e86c236..afd083986d8 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-put.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-put.cc
@@ -181,7 +181,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
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 a97d6d2f935..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
@@ -247,7 +247,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
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 ee2787554f4..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
@@ -242,7 +242,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
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 829672dedae..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
@@ -245,7 +245,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
diff --git a/storage/tokudb/ft-index/src/tests/blocking-set.cc b/storage/tokudb/ft-index/src/tests/blocking-set.cc
index 70c17da513f..d229321aa43 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-set.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-set.cc
@@ -227,7 +227,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
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 91626773f35..2ae82319a7e 100644
--- a/storage/tokudb/ft-index/src/tests/blocking-table-lock.cc
+++ b/storage/tokudb/ft-index/src/tests/blocking-table-lock.cc
@@ -175,7 +175,7 @@ int test_main(int argc, char * const argv[]) {
}
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
// create the db
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 e78c95cb2e3..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
@@ -273,7 +273,7 @@ int test_main(int argc, char * const argv[]) {
#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); assert(r == 0); // no wait
+ 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);
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 d89235d7f59..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
@@ -214,7 +214,7 @@ int test_main(int argc, char * const argv[]) {
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); assert(r == 0);
+ 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
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 21ae8d853f1..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
@@ -275,7 +275,7 @@ int test_main(int argc, char * const argv[]) {
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); assert(r == 0);
+ r = db_env->set_lock_timeout(db_env, 30 * 1000, nullptr); assert(r == 0);
#endif
#if defined(USE_BDB)
if (!poll_deadlock) {
diff --git a/storage/tokudb/ft-index/src/tests/env_loader_memory.cc b/storage/tokudb/ft-index/src/tests/env_loader_memory.cc
index 1cbdc1b16f5..106bdefd3a9 100644
--- a/storage/tokudb/ft-index/src/tests/env_loader_memory.cc
+++ b/storage/tokudb/ft-index/src/tests/env_loader_memory.cc
@@ -91,14 +91,21 @@ PATENT RIGHTS GRANT:
#include "test.h"
#include <db.h>
+static uint64_t my_loader_memory_size;
+
+static uint64_t get_loader_memory_size(void) {
+ return my_loader_memory_size;
+}
+
int test_main (int argc, char * const argv[]) {
parse_args(argc, argv);
int r;
DB_ENV *env;
r = db_env_create(&env, 0);
assert_zero(r);
+ env->set_loader_memory_size(env, get_loader_memory_size);
for (uint64_t n = 0 ; n < 10000000000; n += 1000000000) {
- env->set_loader_memory_size(env, n);
+ my_loader_memory_size = n;
assert(env->get_loader_memory_size(env) == n);
}
r = env->close(env, 0);
diff --git a/storage/tokudb/ft-index/src/tests/env_nproc.cc b/storage/tokudb/ft-index/src/tests/env_nproc.cc
new file mode 100644
index 00000000000..29bc216f9c8
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/env_nproc.cc
@@ -0,0 +1,143 @@
+/* -*- 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) 2009-2013 Tokutek Inc. All rights reserved."
+#ident "$Id$"
+
+#include "test.h"
+#include <db.h>
+#include <sys/resource.h>
+
+static void env_open_close(void) {
+ int r;
+
+ DB_ENV *env = NULL;
+ r = db_env_create(&env, 0);
+ assert(r == 0);
+ env->set_errfile(env, stderr);
+ r = env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK+DB_INIT_MPOOL+DB_INIT_TXN+DB_INIT_LOG + DB_CREATE + DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ if (r != 0) {
+ fprintf(stderr, "%s:%u r=%d\n", __FILE__, __LINE__, r);
+ }
+ r = env->close(env, 0);
+ assert(r == 0);
+}
+
+int test_main (int argc, char * const argv[]) {
+ int r;
+ int limit = 1;
+
+ // parse_args(argc, argv);
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0) {
+ verbose++;
+ continue;
+ }
+ if (strcmp(argv[i], "-q") == 0) {
+ if (verbose > 0) verbose--;
+ continue;
+ }
+ limit = atoi(argv[i]);
+ continue;
+ }
+
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+
+ struct rlimit nproc_rlimit;
+ r = getrlimit(RLIMIT_NPROC, &nproc_rlimit);
+ assert(r == 0);
+
+ nproc_rlimit.rlim_cur = limit;
+ r = setrlimit(RLIMIT_NPROC, &nproc_rlimit);
+ assert(r == 0);
+
+ env_open_close();
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/filesize.cc b/storage/tokudb/ft-index/src/tests/filesize.cc
index e03bcee4a15..c1b7ad2df30 100644
--- a/storage/tokudb/ft-index/src/tests/filesize.cc
+++ b/storage/tokudb/ft-index/src/tests/filesize.cc
@@ -206,7 +206,8 @@ delete_n (uint32_t ah)
static void
optimize(void) {
if (verbose) printf("Filesize: begin optimize dictionary\n");
- int r = db->hot_optimize(db, NULL, NULL, NULL, NULL);
+ uint64_t loops_run;
+ int r = db->hot_optimize(db, NULL, NULL, NULL, NULL, &loops_run);
CKERR(r);
if (verbose) printf("Filesize: end optimize dictionary\n");
}
diff --git a/storage/tokudb/ft-index/src/tests/get_last_key.cc b/storage/tokudb/ft-index/src/tests/get_last_key.cc
new file mode 100644
index 00000000000..36c7ab63259
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/get_last_key.cc
@@ -0,0 +1,299 @@
+/* -*- 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 that various queries behave correctly
+ *
+ * Zardosht says:
+ *
+ * write a test that inserts a bunch of elements into the tree,
+ * and then verify that the following types of queries work:
+ * - db->get
+ * - next
+ * - prev
+ * - set_range
+ * - set_range_reverse
+ * - first
+ * - last
+ * - current
+ *
+ * do it on a table with:
+ * - just a leaf node
+ * - has internal nodes (make node size 4K and bn size 1K)
+ * - big cachetable such that everything fits
+ * - small cachetable such that not a lot fits
+ *
+ * make sure APIs are the callback APIs (getf_XXX)
+ * make sure your callbacks all return TOKUDB_CURSOR_CONTINUE,
+ * so we ensure that returning TOKUDB_CURSOR_CONTINUE does not
+ * mess anything up.
+ */
+
+#include "test.h"
+
+/**
+ * Calculate or verify that a value for a given key is correct
+ * Returns 0 if the value is correct, nonzero otherwise.
+ */
+static void get_value_by_key(DBT * key, DBT * value)
+{
+ // keys/values are always stored in the DBT in net order
+ int * CAST_FROM_VOIDP(k, key->data);
+ int v = toku_ntohl(*k) * 2 + 1;
+ memcpy(value->data, &v, sizeof(int));
+}
+
+static void prepare_for_env(void) {
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ int r = toku_os_mkdir(TOKU_TEST_FILENAME, 0755); { int chk_r = r; CKERR(chk_r); }
+}
+
+static void init_env(DB_ENV ** env, size_t ct_size)
+{
+ int r;
+ const int envflags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD |
+ DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN | DB_PRIVATE;
+
+ printf("initializing environment\n");
+
+ r = db_env_create(env, 0); { int chk_r = r; CKERR(chk_r); }
+ assert(ct_size < 1024 * 1024 * 1024L);
+ r = (*env)->set_cachesize(*env, 0, ct_size, 1); { int chk_r = r; CKERR(chk_r); }
+ r = (*env)->open(*env, TOKU_TEST_FILENAME, envflags, 0755); { int chk_r = r; CKERR(chk_r); }
+}
+
+static void init_db(DB_ENV * env, DB ** db)
+{
+ int r;
+ const int node_size = 4096;
+ const int bn_size = 1024;
+
+ printf("initializing db\n");
+
+ DB_TXN * txn;
+ r = db_create(db, env, 0); { int chk_r = r; CKERR(chk_r); }
+ r = (*db)->set_readpagesize(*db, bn_size); { int chk_r = r; CKERR(chk_r); }
+ r = (*db)->set_pagesize(*db, node_size); { int chk_r = r; CKERR(chk_r); }
+ r = env->txn_begin(env, nullptr, &txn, 0); { int chk_r = r; CKERR(chk_r); }
+ r = (*db)->open(*db, txn, "db", nullptr, DB_BTREE, DB_CREATE, 0644); { int chk_r = r; CKERR(chk_r); }
+ r = txn->commit(txn, 0); { int chk_r = r; CKERR(chk_r); }
+}
+
+static void cleanup_env_and_db(DB_ENV * env, DB * db)
+{
+ int r;
+
+ printf("cleaning up environment and db\n");
+ r = db->close(db, 0); { int chk_r = r; CKERR(chk_r); }
+ r = env->close(env, 0); { int chk_r = r; CKERR(chk_r); }
+}
+
+static int get_last_key_cb(const DBT *key, const DBT *value, void *extra) {
+ if (key->data) {
+ invariant_null(value);
+ int expected_key = *(int*)extra;
+ int found_key = *(int*)key->data;
+ invariant(expected_key == (int)ntohl(found_key));
+ }
+ return 0;
+}
+
+
+static void check_last_key_matches(DB *db, int expect_r, int key) {
+ int r = db->get_last_key(db, get_last_key_cb, &key);
+ CKERR2(r, expect_r);
+}
+
+static void do_test(size_t ct_size, int num_keys)
+{
+ int i, r;
+ DB * db;
+ DB_ENV * env;
+ DB_TXN *txn = nullptr;
+ DB_TXN *txn2 = nullptr;
+ uint64_t loops_run = 0;
+
+
+ printf("doing tests for ct_size %lu, num_keys %d\n",
+ ct_size, num_keys);
+
+ // initialize everything and insert data
+ prepare_for_env();
+ init_env(&env, ct_size);
+ assert(env != nullptr);
+ init_db(env, &db);
+ assert(db != nullptr);
+
+ r = env->txn_begin(env, nullptr, &txn, 0);
+ CKERR(r);
+ DBT key, value;
+ for (i = 0; i < num_keys; i++) {
+ int v, k = toku_htonl(i);
+ dbt_init(&key, &k, sizeof(int));
+ dbt_init(&value, &v, sizeof(int));
+ get_value_by_key(&key, &value);
+ r = db->put(db, txn, &key, &value, 0);
+ CKERR(r);
+ }
+ CKERR(r);
+
+ int expect_r = num_keys == 0 ? DB_NOTFOUND : 0;
+ check_last_key_matches(db, expect_r, num_keys - 1);
+
+ r = txn->commit(txn, 0);
+ check_last_key_matches(db, expect_r, num_keys - 1);
+
+ if (num_keys == 0) {
+ goto cleanup;
+ }
+ r = env->txn_begin(env, nullptr, &txn2, 0);
+ CKERR(r);
+ r = env->txn_begin(env, nullptr, &txn, 0);
+ CKERR(r);
+
+ r = db->del(db, txn, &key, 0);
+ check_last_key_matches(db, 0, num_keys - 1);
+
+ r = txn->commit(txn, 0);
+ check_last_key_matches(db, 0, num_keys - 1);
+
+ r = txn2->commit(txn2, 0);
+ check_last_key_matches(db, 0, num_keys - 1);
+
+ //Run Garbage collection (NOTE does not work when everything fits in root??? WHY)
+ r = db->hot_optimize(db, nullptr, nullptr, nullptr, nullptr, &loops_run);
+ CKERR(r);
+
+ r = env->txn_checkpoint(env, 0, 0, 0);
+ CKERR(r);
+
+ //Run Garbage collection (NOTE does not work when everything fits in root??? WHY)
+ r = db->hot_optimize(db, nullptr, nullptr, nullptr, nullptr, &loops_run);
+ CKERR(r);
+
+ r = env->txn_checkpoint(env, 0, 0, 0);
+ CKERR(r);
+
+ //Fully close and reopen
+ //This clears cachetable
+ //note that closing a db and reopening may not flush the cachetable so we close env as well
+ cleanup_env_and_db(env, db);
+ init_env(&env, ct_size);
+ assert(env != nullptr);
+ init_db(env, &db);
+ assert(db != nullptr);
+
+ //NOTE: tried overkill (double optimize, double checkpoint.. gc still doesn't happen for everything in root in single basement
+
+ if (num_keys >= 2) {
+ // At least one key remains.
+ check_last_key_matches(db, 0, num_keys - 2);
+ } else {
+ //no key remains. Should find nothing.
+ check_last_key_matches(db, DB_NOTFOUND, -1);
+ }
+cleanup:
+ cleanup_env_and_db(env, db);
+}
+
+int test_main(int argc, char * const argv[])
+{
+ default_parse_args(argc, argv);
+
+ for (int i = 0; i <= 2; i++) {
+ do_test(1024*1024, i);
+ }
+ for (int i = 4; i <= 1024; i*=2) {
+ do_test(1024*1024, i);
+ }
+
+ return 0;
+}
+
diff --git a/storage/tokudb/ft-index/src/tests/hot-optimize-table-tests.cc b/storage/tokudb/ft-index/src/tests/hot-optimize-table-tests.cc
index ce245ce69f9..6a00afa4a51 100644
--- a/storage/tokudb/ft-index/src/tests/hot-optimize-table-tests.cc
+++ b/storage/tokudb/ft-index/src/tests/hot-optimize-table-tests.cc
@@ -247,7 +247,8 @@ hot_test(DB* db, unsigned int size)
// Flatten the tree.
verbose ? printf("Calling hot optimize...\n") : 0;
- r = db->hot_optimize(db, NULL, NULL, NULL, NULL);
+ uint64_t loops_run;
+ r = db->hot_optimize(db, NULL, NULL, NULL, NULL, &loops_run);
assert(r == 0);
verbose ? printf("HOT Finished!\n") : 0;
for (unsigned int i = 0; i < size; ++i) {
diff --git a/storage/tokudb/ft-index/src/tests/locktree_escalation_stalls.cc b/storage/tokudb/ft-index/src/tests/locktree_escalation_stalls.cc
new file mode 100644
index 00000000000..037d2fc46a9
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/locktree_escalation_stalls.cc
@@ -0,0 +1,312 @@
+/* -*- 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) 2009-2013 Tokutek Inc. All rights reserved."
+#ident "$Id$"
+
+// This test ensures that lock escalation occurs on the big transaction thread.
+// locktree_escalation_stalls --max_i 1000000000 --n_small 16 --verbose
+
+#include "test.h"
+#include <db.h>
+#include "toku_time.h"
+#include "toku_pthread.h"
+
+// from #include "threaded_stress_test_helpers.h"
+// For each line of engine status output, look for lines that contain substrings
+// that match any of the strings in the pattern string. The pattern string contains
+// 0 or more strings separated by the '|' character, kind of like a regex.
+static void print_matching_engine_status_rows(DB_ENV *env, const char *pattern) {
+ uint64_t num_rows;
+ env->get_engine_status_num_rows(env, &num_rows);
+ uint64_t buf_size = num_rows * 128;
+ const char *row;
+ char *row_r;
+
+ char *pattern_copy = toku_xstrdup(pattern);
+ int num_patterns = 1;
+ for (char *p = pattern_copy; *p != '\0'; p++) {
+ if (*p == '|') {
+ *p = '\0';
+ num_patterns++;
+ }
+ }
+
+ char *XMALLOC_N(buf_size, buf);
+ int r = env->get_engine_status_text(env, buf, buf_size);
+ invariant_zero(r);
+
+ for (row = strtok_r(buf, "\n", &row_r); row != nullptr; row = strtok_r(nullptr, "\n", &row_r)) {
+ const char *p = pattern_copy;
+ for (int i = 0; i < num_patterns; i++, p += strlen(p) + 1) {
+ if (strstr(row, p) != nullptr) {
+ fprintf(stderr, "%s\n", row);
+ }
+ }
+ }
+
+ toku_free(pattern_copy);
+ toku_free(buf);
+ fflush(stderr);
+}
+
+static volatile int killed = 0;
+
+// in a big transaction, insert a bunch of rows.
+static void big_test(DB_ENV *env, DB *db, uint64_t max_i) {
+ if (verbose)
+ fprintf(stderr, "%u %s\n", toku_os_gettid(), __FUNCTION__);
+ int r;
+
+ DB_TXN *txn = NULL;
+ r = env->txn_begin(env, NULL, &txn, 0);
+ assert(r == 0);
+
+ for (uint64_t i = 0; !killed && i < max_i; i++) {
+ uint64_t k = htonl(i);
+ DBT key = { .data = &k, .size = sizeof k };
+ DBT val = { .data = &i, .size = sizeof i };
+ uint64_t t_start = toku_current_time_microsec();
+ r = db->put(db, txn, &key, &val, 0);
+ assert(r == 0);
+ uint64_t t_end = toku_current_time_microsec();
+ uint64_t t_delta = t_end - t_start;
+ if (t_delta >= 1000000) {
+ fprintf(stderr, "%u %s i=%" PRIu64 " %" PRIu64 "\n", toku_os_gettid(), __FUNCTION__, i, t_delta);
+ if (verbose)
+ print_matching_engine_status_rows(env, "locktree");
+ }
+
+ toku_pthread_yield();
+ }
+
+ r = txn->commit(txn, 0);
+ assert(r == 0);
+}
+
+// insert a row in a single transaction.
+static void small_test(DB_ENV *env, DB *db, uint64_t max_i) {
+ if (verbose)
+ fprintf(stderr, "%u %s\n", toku_os_gettid(), __FUNCTION__);
+ int r;
+ uint64_t k = toku_os_gettid(); // get a unique number
+ for (uint64_t i = 0; !killed && i < max_i; i++) {
+ DB_TXN *txn = NULL;
+ r = env->txn_begin(env, NULL, &txn, 0);
+ assert(r == 0);
+
+ DBT key = { .data = &k, .size = sizeof k };
+ DBT val = { .data = &i, .size = sizeof i };
+ uint64_t t_start = toku_current_time_microsec();
+ r = db->put(db, txn, &key, &val, 0);
+ assert(r == 0);
+ uint64_t t_end = toku_current_time_microsec();
+ uint64_t t_delta = t_end - t_start;
+ if (t_delta >= 1000000) {
+ fprintf(stderr, "%u %s %" PRIu64 "\n", toku_os_gettid(), __FUNCTION__, t_delta);
+ assert(0);
+ }
+
+ r = txn->commit(txn, 0);
+ assert(r == 0);
+
+ toku_pthread_yield();
+ }
+}
+
+struct test_args {
+ DB_ENV *env;
+ DB *db;
+ uint64_t max_i;
+ void (*test_f)(DB_ENV *env, DB *db, uint64_t max_i);
+};
+
+static void *test_f(void *args) {
+ struct test_args *test_args = (struct test_args *) args;
+ test_args->test_f(test_args->env, test_args->db, test_args->max_i);
+ return args;
+}
+
+static void run_test(uint64_t max_i, int n_small) {
+ int r;
+
+ DB_ENV *env = NULL;
+ r = db_env_create(&env, 0);
+ assert(r == 0);
+ env->set_errfile(env, stderr);
+ r = env->set_cachesize(env, 8, 0, 1);
+ assert(r == 0);
+ r = env->set_lk_max_memory(env, 1000000000);
+ assert(r == 0);
+ r = env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK+DB_INIT_MPOOL+DB_INIT_TXN+DB_INIT_LOG + DB_CREATE + DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ assert(r == 0);
+
+ DB *big_db = NULL;
+ r = db_create(&big_db, env, 0);
+ assert(r == 0);
+
+ r = big_db->open(big_db, NULL, "big", NULL, DB_BTREE, DB_AUTO_COMMIT+DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ assert(r == 0);
+
+ DB *small_db = NULL;
+ r = db_create(&small_db, env, 0);
+ assert(r == 0);
+
+ r = small_db->open(small_db, NULL, "small", NULL, DB_BTREE, DB_AUTO_COMMIT+DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
+ assert(r == 0);
+
+ struct test_args big_test_args = {
+ env, big_db, max_i, big_test,
+ };
+ toku_pthread_t big_id;
+ r = toku_pthread_create(&big_id, NULL, test_f, &big_test_args);
+ assert(r == 0);
+
+ struct test_args small_test_args[n_small];
+ toku_pthread_t small_id[n_small];
+ for (int i = 0; i < n_small; i++) {
+ small_test_args[i] = { env, small_db, max_i, small_test };
+ r = toku_pthread_create(&small_id[i], NULL, test_f, &small_test_args[i]);
+ assert(r == 0);
+ }
+
+ void *big_ret;
+ r = toku_pthread_join(big_id, &big_ret);
+ assert(r == 0);
+
+ killed = 1;
+
+ for (int i = 0; i < n_small; i++) {
+ void *small_ret;
+ r = toku_pthread_join(small_id[i], &small_ret);
+ assert(r == 0);
+ }
+
+ r = small_db->close(small_db, 0);
+ assert(r == 0);
+
+ r = big_db->close(big_db, 0);
+ assert(r == 0);
+
+ r = env->close(env, 0);
+ assert(r == 0);
+}
+
+int test_main (int argc, char * const argv[]) {
+ int r;
+ uint64_t max_i = 10000;
+ int n_small = 1;
+
+ // 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) {
+ if (verbose > 0) verbose--;
+ continue;
+ }
+ if (strcmp(argv[i], "--max_i") == 0 && i+1 < argc) {
+ max_i = atoll(argv[++i]);
+ continue;
+ }
+ if (strcmp(argv[i], "--n_small") == 0 && i+1 < argc) {
+ n_small = atoi(argv[++i]);
+ continue;
+ }
+ }
+
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
+ assert(r == 0);
+
+ run_test(max_i, n_small);
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/recover-child-rollback.cc b/storage/tokudb/ft-index/src/tests/recover-child-rollback.cc
new file mode 100644
index 00000000000..00f036cc174
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/recover-child-rollback.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:
+/*
+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 "$Id$"
+#include "test.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <toku_pthread.h>
+#include <unistd.h>
+#include <memory.h>
+#include <sys/stat.h>
+#include <db.h>
+
+#include "threaded_stress_test_helpers.h"
+
+//
+// This test is a form of stress that does operations on a single dictionary:
+// We create a dictionary bigger than the cachetable (around 4x greater).
+// Then, we spawn a bunch of pthreads that do the following:
+// - scan dictionary forward with bulk fetch
+// - scan dictionary forward slowly
+// - scan dictionary backward with bulk fetch
+// - scan dictionary backward slowly
+// - Grow the dictionary with insertions
+// - do random point queries into the dictionary
+// With the small cachetable, this should produce quite a bit of churn in reading in and evicting nodes.
+// If the test runs to completion without crashing, we consider it a success. It also tests that snapshots
+// work correctly by verifying that table scans sum their vals to 0.
+//
+// This does NOT test:
+// - splits and merges
+// - multiple DBs
+//
+// Variables that are interesting to tweak and run:
+// - small cachetable
+// - number of elements
+//
+
+static void
+stress_table(DB_ENV *env, DB **dbp, struct cli_args *cli_args) {
+ //
+ // the threads that we want:
+ // - one (or more) thread(s) constantly updating random values, wrapped in a persistent parent transaction.
+
+ if (verbose) printf("starting creation of pthreads\n");
+ const int num_threads = cli_args->num_update_threads;
+ struct arg myargs[num_threads];
+ for (int i = 0; i < num_threads; i++) {
+ arg_init(&myargs[i], dbp, env, cli_args);
+ }
+
+ struct update_op_args uoe = get_update_op_args(cli_args, NULL);
+ // make the guy that updates the db
+ for (int i = 0; i < cli_args->num_update_threads; ++i) {
+ myargs[i].operation_extra = &uoe;
+ myargs[i].operation = update_op;
+ myargs[i].do_prepare = true;
+ myargs[i].wrap_in_parent = true;
+ }
+
+ run_workers(myargs, num_threads, cli_args->num_seconds, true, cli_args);
+}
+
+int
+test_main(int argc, char *const argv[]) {
+ struct cli_args args = get_default_args();
+ args.num_seconds = 5;
+ //args.txn_size = 64; // 100 * 256 is more than enough to spill (4096) byte rollback nodes for parent and child.
+ //args.val_size = 512; // Large values to overflow a rollback log node fast.
+ //args.env_args.node_size = 4*1024*1024; // Large nodes to prevent spending much time
+ //args.env_args.basement_node_size = 128*1024; // Large nodes to prevent spending much time
+ args.env_args.checkpointing_period = 1;
+ parse_stress_test_args(argc, argv, &args);
+ if (args.do_test_and_crash) {
+ stress_test_main(&args);
+ }
+ if (args.do_recover) {
+ stress_recover(&args);
+ }
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/test_4368.cc b/storage/tokudb/ft-index/src/tests/test_4368.cc
index 2f578d03bcb..f000efa7813 100644
--- a/storage/tokudb/ft-index/src/tests/test_4368.cc
+++ b/storage/tokudb/ft-index/src/tests/test_4368.cc
@@ -113,7 +113,8 @@ test_main (int UU(argc), char UU(*const argv[])) {
r = db->open(db, NULL, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0);
// call hot_optimize on an empty db. The empty db should have only a root node, which should invoke the bug
- r = db->hot_optimize(db, NULL, NULL, NULL, NULL); assert_zero(r);
+ uint64_t loops_run;
+ r = db->hot_optimize(db, NULL, NULL, NULL, NULL, &loops_run); assert_zero(r);
r=db->close(db, 0); assert(r==0);
r=env->close(env, 0); assert(r==0);
diff --git a/storage/tokudb/ft-index/src/tests/test_bad_implicit_promotion.cc b/storage/tokudb/ft-index/src/tests/test_bad_implicit_promotion.cc
new file mode 100644
index 00000000000..8fcff7c6132
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/test_bad_implicit_promotion.cc
@@ -0,0 +1,190 @@
+/* -*- 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) 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"
+
+// Test the following scenario:
+// Begin A
+// A deletes key K
+// A aborts
+// Begin B
+// B deletes key K-1
+// B deletes key K
+// B deletes key K+1
+// B commits
+// Begin C
+// C queries K, should read K (not the delete!).
+//
+// An incorrect mvcc implementation would 'implicitly' promote
+// A's delete to committed, based on the fact that the oldest
+// referenced xid at the time of injection for key k-1 and k+1
+// is greater than A's xid.
+
+static void test_insert_bad_implicit_promotion(void) {
+ int r;
+
+ DB_ENV *env;
+ r = db_env_create(&env, 0); CKERR(r);
+ r = env->set_cachesize(env, 1, 0, 1); CKERR(r); // 1gb cache so this test fits in memory
+ 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->set_pagesize(db, 4096); CKERR(r);
+ r = db->open(db, NULL, "db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(r);
+
+ const int val_size = 512;
+
+ DBT key;
+ DBT val;
+ char *XMALLOC_N(val_size, val_buf);
+ memset(val_buf, 'x', val_size);
+ dbt_init(&val, val_buf, val_size);
+
+ // Insert rows [0, N]
+ const int N = 1000;
+ for (int i = 0; i < N; i++) {
+ int k = toku_htonl(i);
+ dbt_init(&key, &k, sizeof(k));
+ r = db->put(db, NULL, &key, &val, 0); CKERR(r);
+ }
+
+ int key_500 = toku_htonl(500);
+ int key_499 = toku_htonl(499);
+ int key_501 = toku_htonl(501);
+ // sanity check our keys
+ r = db->get(db, NULL, dbt_init(&key, &key_500, sizeof(key_500)), &val, 0); CKERR(r);
+ r = db->get(db, NULL, dbt_init(&key, &key_500, sizeof(key_499)), &val, 0); CKERR(r);
+ r = db->get(db, NULL, dbt_init(&key, &key_500, sizeof(key_501)), &val, 0); CKERR(r);
+
+ // Abort a delete for key 500
+ DB_TXN *txn_A;
+ r = env->txn_begin(env, NULL, &txn_A, DB_SERIALIZABLE); CKERR(r);
+ dbt_init(&key, &key_500, sizeof(key_500));
+ r = db->del(db, txn_A, &key, DB_DELETE_ANY); CKERR(r);
+ r = txn_A->abort(txn_A); CKERR(r);
+
+ // Commit two deletes on keys 499 and 501. This should inject
+ // at least one message in the same buffer that has the delete/abort
+ // messages for key 500.
+ DB_TXN *txn_B;
+ r = env->txn_begin(env, NULL, &txn_B, DB_SERIALIZABLE); CKERR(r);
+ dbt_init(&key, &key_499, sizeof(key_499));
+ r = db->del(db, txn_B, &key, DB_DELETE_ANY); CKERR(r);
+ dbt_init(&key, &key_501, sizeof(key_501));
+ r = db->del(db, txn_B, &key, DB_DELETE_ANY); CKERR(r);
+ r = txn_B->commit(txn_B, 0); CKERR(r);
+
+ // No transactions are live - so when we create txn C, the oldest
+ // referenced xid will be txn C. If our implicit promotion logic is
+ // wrong, we will use txn C's xid to promote the delete on key 500
+ // before the abort message hits it, and C's query will return nothing.
+ DB_TXN *txn_C;
+ dbt_init(&key, &key_500, sizeof(key_500));
+ r = env->txn_begin(env, NULL, &txn_C, DB_TXN_SNAPSHOT); CKERR(r);
+ r = db->get(db, txn_C, &key, &val, 0); CKERR(r);
+ r = txn_C->commit(txn_C, 0); CKERR(r);
+
+ toku_free(val_buf);
+ 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);
+
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
+
+ test_insert_bad_implicit_promotion();
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/test_cursor_interrupt.cc b/storage/tokudb/ft-index/src/tests/test_cursor_interrupt.cc
new file mode 100644
index 00000000000..d82fc5131da
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/test_cursor_interrupt.cc
@@ -0,0 +1,202 @@
+/* -*- 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."
+#include "test.h"
+
+
+#include <stdio.h>
+
+#include <db.h>
+
+
+int num_interrupts_called;
+static bool interrupt(void* extra UU()) {
+ num_interrupts_called++;
+ return false;
+}
+
+static bool interrupt_true(void* extra UU()) {
+ num_interrupts_called++;
+ return true;
+}
+
+
+int
+test_main(int argc, char *const argv[]) {
+ parse_args(argc, argv);
+ DB_ENV *env;
+ DB *db;
+ int r;
+
+ 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);
+ r=env->open(env, TOKU_TEST_FILENAME, DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_CREATE | DB_PRIVATE | DB_INIT_LOG, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0);
+
+ r = db_create(&db, env, 0);
+ CKERR(r);
+ r = db->set_readpagesize(db, 1024);
+ CKERR(r);
+ r = db->set_pagesize(db, 1024*10);
+ CKERR(r);
+
+ const char * const fname = "test.change_pagesize";
+ r = db->open(db, NULL, fname, "main", DB_BTREE, DB_CREATE, 0666);
+ CKERR(r);
+ DB_TXN* txn;
+ r = env->txn_begin(env, 0, &txn, 0);
+ CKERR(r);
+ for (uint64_t i = 0; i < 10000; i++) {
+ DBT key, val;
+ uint64_t k = i;
+ uint64_t v = i;
+ dbt_init(&key, &k, sizeof k);
+ dbt_init(&val, &v, sizeof v);
+ db->put(db, txn, &key, &val, DB_PRELOCKED_WRITE); // adding DB_PRELOCKED_WRITE just to make the test go faster
+ }
+ r = txn->commit(txn, 0);
+ CKERR(r);
+
+ // create a snapshot txn so that when we delete the elements
+ // we just inserted, that they do not get garbage collected away
+ DB_TXN* snapshot_txn;
+ r = env->txn_begin(env, 0, &snapshot_txn, DB_TXN_SNAPSHOT);
+ CKERR(r);
+
+ DB_TXN* delete_txn;
+ r = env->txn_begin(env, 0, &delete_txn, DB_TXN_SNAPSHOT);
+ CKERR(r);
+
+ for (uint64_t i = 0; i < 10000; i++) {
+ DBT key;
+ uint64_t k = i;
+ dbt_init(&key, &k, sizeof k);
+ db->del(db, delete_txn, &key, DB_PRELOCKED_WRITE | DB_DELETE_ANY); // adding DB_PRELOCKED_WRITE just to make the test go faster
+ }
+ r = delete_txn->commit(delete_txn, 0);
+ CKERR(r);
+
+ // to make more than one basement node in the dictionary's leaf nodes
+ r = env->txn_checkpoint(env, 0, 0, 0);
+ CKERR(r);
+
+ // create a txn that should see an empty dictionary
+ DB_TXN* test_txn;
+ r = env->txn_begin(env, 0, &test_txn, DB_TXN_SNAPSHOT);
+ CKERR(r);
+ DBC* cursor = NULL;
+ r = db->cursor(db, test_txn, &cursor, 0);
+ cursor->c_set_check_interrupt_callback(cursor, interrupt, NULL);
+ DBT key, val;
+ r = cursor->c_get(cursor, &key, &val, DB_NEXT);
+ CKERR2(r, DB_NOTFOUND);
+ assert(num_interrupts_called > 1);
+ num_interrupts_called = 0;
+ cursor->c_set_check_interrupt_callback(cursor, interrupt_true, NULL);
+ r = cursor->c_get(cursor, &key, &val, DB_NEXT);
+ CKERR2(r, TOKUDB_INTERRUPTED);
+ assert(num_interrupts_called == 1);
+
+ r = cursor->c_close(cursor);
+ CKERR(r);
+ r = test_txn->commit(test_txn, 0);
+ CKERR(r);
+
+
+ r = snapshot_txn->commit(snapshot_txn, 0);
+ CKERR(r);
+
+
+ r = db->close(db, 0);
+ CKERR(r);
+
+ r = env->close(env, 0);
+ assert(r == 0);
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/test_insert_many_gc.cc b/storage/tokudb/ft-index/src/tests/test_insert_many_gc.cc
new file mode 100644
index 00000000000..a1884d22c0c
--- /dev/null
+++ b/storage/tokudb/ft-index/src/tests/test_insert_many_gc.cc
@@ -0,0 +1,157 @@
+/* -*- 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) 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"
+
+
+static void test_insert_many_gc(void) {
+ int r;
+
+ DB_ENV *env;
+ r = db_env_create(&env, 0); CKERR(r);
+ r = env->set_cachesize(env, 1, 0, 1); CKERR(r); // 1gb cache so this test fits in memory
+ 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);
+
+ const int val_size = 1 * 1024 * 1024;
+
+ // Begin a snapshot transaction, which should prevent simple garbage collection
+ // from being effective. Only full garbage collection can prevent many inserts
+ // into a single leaf node from growing out of control.
+ DB_TXN *snapshot_txn;
+ r = env->txn_begin(env, NULL, &snapshot_txn, DB_TXN_SNAPSHOT); CKERR(r);
+
+ DBT key;
+ int k = 0;
+ dbt_init(&key, &k, sizeof(k));
+
+ DBT val;
+ char *XMALLOC_N(val_size, val_buf);
+ memset(val_buf, 0, val_size);
+ dbt_init(&val, val_buf, val_size);
+
+ // Keep overwriting the same row over and over.
+ const int N = 75;
+ for (int i = 0; i < N; i++) {
+ r = db->put(db, NULL, &key, &val, 0); CKERR(r);
+ }
+
+ // Full garbage collection should have prevented the leaf node
+ // from having an MVCC stack of size 'N'. At the time of this
+ // writing, we run full GC on leaf-inject when the leaf is
+ // 32mb or larger. A good invariant is that the max LE size
+ // never grew larger than 35mb and that the max commited xr stack
+ // length never exceeded 35
+ const uint64_t le_max_memsize = get_engine_status_val(env, "LE_MAX_MEMSIZE");
+ const uint64_t le_max_committed_xr = get_engine_status_val(env, "LE_MAX_COMMITTED_XR");
+ invariant(le_max_memsize <= 35 * 1024 * 1024);
+ invariant(le_max_committed_xr <= 35);
+
+ r = snapshot_txn->commit(snapshot_txn, 0); CKERR(r);
+
+ toku_free(val_buf);
+ 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);
+
+ toku_os_recursive_delete(TOKU_TEST_FILENAME);
+ int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
+
+ test_insert_many_gc();
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/src/tests/test_iterate_pending_lock_requests.cc b/storage/tokudb/ft-index/src/tests/test_iterate_pending_lock_requests.cc
index fe0667d2b0a..248c346c305 100644
--- a/storage/tokudb/ft-index/src/tests/test_iterate_pending_lock_requests.cc
+++ b/storage/tokudb/ft-index/src/tests/test_iterate_pending_lock_requests.cc
@@ -148,7 +148,7 @@ int test_main(int UU(argc), char *const UU(argv[])) {
r = db_env_create(&env, 0); CKERR(r);
r = env->open(env, TOKU_TEST_FILENAME, env_flags, 0755); CKERR(r);
- r = env->set_lock_timeout(env, 4000);
+ r = env->set_lock_timeout(env, 4000, nullptr);
r = db_create(&db, env, 0); CKERR(r);
r = db->open(db, NULL, dname, NULL, DB_BTREE, DB_CREATE, 0777); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_kv_gen.h b/storage/tokudb/ft-index/src/tests/test_kv_gen.h
index e22bb165e72..f17b6c18641 100644
--- a/storage/tokudb/ft-index/src/tests/test_kv_gen.h
+++ b/storage/tokudb/ft-index/src/tests/test_kv_gen.h
@@ -180,7 +180,8 @@ static void __attribute__((unused))
do_hot_optimize_on_dbs(DB_ENV *UU(env), DB **dbs, int num_dbs)
{
for (int i = 0; i < num_dbs; ++i) {
- int r = dbs[i]->hot_optimize(dbs[i], NULL, NULL, dummy_progress, NULL);
+ uint64_t loops_run;
+ int r = dbs[i]->hot_optimize(dbs[i], NULL, NULL, dummy_progress, NULL, &loops_run);
CKERR(r);
}
}
diff --git a/storage/tokudb/ft-index/src/tests/test_lock_timeout_callback.cc b/storage/tokudb/ft-index/src/tests/test_lock_timeout_callback.cc
index c56d7968ec5..d4aae0f95d4 100644
--- a/storage/tokudb/ft-index/src/tests/test_lock_timeout_callback.cc
+++ b/storage/tokudb/ft-index/src/tests/test_lock_timeout_callback.cc
@@ -149,7 +149,7 @@ int test_main(int UU(argc), char *const UU(argv[])) {
r = db_env_create(&env, 0); CKERR(r);
r = env->open(env, TOKU_TEST_FILENAME, env_flags, 0755); CKERR(r);
- r = env->set_lock_timeout(env, 1000);
+ r = env->set_lock_timeout(env, 1000, nullptr);
r = env->set_lock_timeout_callback(env, lock_not_granted);
r = db_create(&db, env, 0); CKERR(r);
diff --git a/storage/tokudb/ft-index/src/tests/test_stress5.cc b/storage/tokudb/ft-index/src/tests/test_stress5.cc
index dc2a26940e1..053da44d66c 100644
--- a/storage/tokudb/ft-index/src/tests/test_stress5.cc
+++ b/storage/tokudb/ft-index/src/tests/test_stress5.cc
@@ -108,7 +108,7 @@ stress_table(DB_ENV *env, DB **dbp, struct cli_args *cli_args) {
//
if (verbose) printf("starting creation of pthreads\n");
- const int num_threads = 4 + cli_args->num_update_threads + cli_args->num_ptquery_threads;
+ const int num_threads = 5 + cli_args->num_update_threads + cli_args->num_ptquery_threads;
struct arg myargs[num_threads];
for (int i = 0; i < num_threads; i++) {
arg_init(&myargs[i], dbp, env, cli_args);
diff --git a/storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h b/storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h
index 46427485129..c173d2d2d63 100644
--- a/storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h
+++ b/storage/tokudb/ft-index/src/tests/threaded_stress_test_helpers.h
@@ -232,6 +232,7 @@ struct arg {
bool do_prepare;
bool prelock_updates;
bool track_thread_performance;
+ bool wrap_in_parent;
};
static void arg_init(struct arg *arg, DB **dbp, DB_ENV *env, struct cli_args *cli_args) {
@@ -246,6 +247,7 @@ static void arg_init(struct arg *arg, DB **dbp, DB_ENV *env, struct cli_args *cl
arg->do_prepare = false;
arg->prelock_updates = false;
arg->track_thread_performance = true;
+ arg->wrap_in_parent = false;
}
enum operation_type {
@@ -568,6 +570,7 @@ static void *worker(void *arg_v) {
arg->random_data = &random_data;
DB_ENV *env = arg->env;
DB_TXN *txn = nullptr;
+ DB_TXN *ptxn = nullptr;
if (verbose) {
toku_pthread_t self = toku_pthread_self();
uintptr_t intself = (uintptr_t) self;
@@ -575,11 +578,13 @@ static void *worker(void *arg_v) {
}
if (arg->cli->single_txn) {
r = env->txn_begin(env, 0, &txn, arg->txn_flags); CKERR(r);
+ } else if (arg->wrap_in_parent) {
+ r = env->txn_begin(env, 0, &ptxn, arg->txn_flags); CKERR(r);
}
while (run_test) {
lock_worker_op(we);
if (!arg->cli->single_txn) {
- r = env->txn_begin(env, 0, &txn, arg->txn_flags); CKERR(r);
+ r = env->txn_begin(env, ptxn, &txn, arg->txn_flags); CKERR(r);
}
r = arg->operation(txn, arg, arg->operation_extra, we->counters);
if (r==0 && !arg->cli->single_txn && arg->do_prepare) {
@@ -616,6 +621,9 @@ static void *worker(void *arg_v) {
if (arg->cli->single_txn) {
int flags = get_commit_flags(arg->cli);
int chk_r = txn->commit(txn, flags); CKERR(chk_r);
+ } else if (arg->wrap_in_parent) {
+ int flags = get_commit_flags(arg->cli);
+ int chk_r = ptxn->commit(ptxn, flags); CKERR(chk_r);
}
if (verbose) {
toku_pthread_t self = toku_pthread_self();
@@ -1150,7 +1158,9 @@ static void scan_op_worker(void *arg) {
static int UU() scan_op_no_check_parallel(DB_TXN *txn, ARG arg, void* operation_extra, void *UU(stats_extra)) {
const int num_cores = toku_os_get_number_processors();
const int num_workers = arg->cli->num_DBs < num_cores ? arg->cli->num_DBs : num_cores;
- KIBBUTZ kibbutz = toku_kibbutz_create(num_workers);
+ KIBBUTZ kibbutz = NULL;
+ int r = toku_kibbutz_create(num_workers, &kibbutz);
+ assert(r == 0);
for (int i = 0; run_test && i < arg->cli->num_DBs; i++) {
struct scan_op_worker_info *XCALLOC(info);
info->db = arg->dbp[i];
@@ -1621,7 +1631,8 @@ static int UU() hot_op(DB_TXN *UU(txn), ARG UU(arg), void* UU(operation_extra),
int r;
for (int i = 0; run_test && i < arg->cli->num_DBs; i++) {
DB* db = arg->dbp[i];
- r = db->hot_optimize(db, NULL, NULL, hot_progress_callback, nullptr);
+ uint64_t loops_run;
+ r = db->hot_optimize(db, NULL, NULL, hot_progress_callback, nullptr, &loops_run);
if (run_test) {
CKERR(r);
}
@@ -2102,7 +2113,9 @@ static int fill_tables_default(DB_ENV *env, DB **dbs, struct cli_args *args, boo
// be used for internal engine work (ie: flushes, loader threads, etc).
const int max_num_workers = (num_cores + 1) / 2;
const int num_workers = args->num_DBs < max_num_workers ? args->num_DBs : max_num_workers;
- KIBBUTZ kibbutz = toku_kibbutz_create(num_workers);
+ KIBBUTZ kibbutz = NULL;
+ int r = toku_kibbutz_create(num_workers, &kibbutz);
+ assert(r == 0);
for (int i = 0; i < args->num_DBs; i++) {
struct fill_table_worker_info *XCALLOC(info);
info->env = env;
diff --git a/storage/tokudb/ft-index/src/tests/update-multiple-with-indexer-array.cc b/storage/tokudb/ft-index/src/tests/update-multiple-with-indexer-array.cc
index d4cd4838ce0..684925f9872 100644
--- a/storage/tokudb/ft-index/src/tests/update-multiple-with-indexer-array.cc
+++ b/storage/tokudb/ft-index/src/tests/update-multiple-with-indexer-array.cc
@@ -92,102 +92,102 @@ PATENT RIGHTS GRANT:
// verify that update_multiple where we change the data in row[i] col[j] from x to x+1
+static const int MAX_KEYS = 3;
+
+static int
+array_size(int ndbs) {
+ return +
+ 1 + // 0 for old 1 for new
+ 1 + // ndbs
+ 2 * MAX_KEYS * (ndbs-1);
+}
static int
get_num_new_keys(int i, int dbnum) {
if (dbnum == 0) return 1;
if (i & (1<<4)) {
dbnum++; // Shift every once in a while.
}
- return (i + dbnum) % 3; // 0, 1, or 2
+ return (i + dbnum) % MAX_KEYS; // 0, 1, or 2
}
static int
-get_num_keys(int i, int dbnum) {
+get_old_num_keys(int i, int dbnum) {
if (dbnum == 0) return 1;
- return (i + dbnum) % 3; // 0, 1, or 2
+ return (i + dbnum) % MAX_KEYS; // 0, 1, or 2
}
static int
get_total_secondary_rows(int num_primary) {
- assert(num_primary % 3 == 0);
- return num_primary / 3 * (0 + 1 + 2);
-}
-
-static int
-get_total_num_keys(int i, int num_dbs) {
- int sum = 0;
- for (int db = 1; db < num_dbs; ++db) {
- sum += get_num_keys(i, db);
- }
- return sum;
-}
-
-static int
-get_total_num_new_keys(int i, int num_dbs) {
- int sum = 0;
- for (int db = 1; db < num_dbs; ++db) {
- sum += get_num_new_keys(i, db);
- }
- return sum;
+ assert(num_primary % MAX_KEYS == 0);
+ return num_primary / MAX_KEYS * (0 + 1 + 2);
}
static int
-get_key(int i, int dbnum, int which) {
+get_old_key(int i, int dbnum, int which) {
assert(i < INT16_MAX / 2);
assert(which >= 0);
- assert(which < get_num_keys(i, dbnum));
assert(which < 4);
assert(dbnum < 16);
if (dbnum == 0) {
assert(which == 0);
- return htonl((2*i) << 16);
- } else {
- return htonl(((2*i+0) << 16) + (dbnum<<8) + (which<<1));
+ return htonl(2*i);
+ }
+ if (which >= get_old_num_keys(i, dbnum)) {
+ return htonl(-1);
}
+ return htonl(((2*i+0) << 16) + (dbnum<<8) + (which<<1));
}
static int
get_new_key(int i, int dbnum, int which) {
assert(which >= 0);
- assert(which < get_num_new_keys(i, dbnum));
assert(which < 4);
assert(dbnum < 16);
if (dbnum == 0) {
assert(which == 0);
- return htonl((2*i+1) << 16);
- } else if ((i+dbnum+which) & (1<<5)) {
+ return htonl(2*i);
+ }
+ if (which >= get_num_new_keys(i, dbnum)) {
+ return htonl(-1);
+ }
+ if ((i+dbnum+which) & (1<<5)) {
return htonl(((2*i+0) << 16) + (dbnum<<8) + (which<<1)); // no change from original
- } else {
- return htonl(((2*i+0) << 16) + (dbnum<<8) + (which<<1) + 1);
}
+ return htonl(((2*i+0) << 16) + (dbnum<<8) + (which<<1) + 1);
}
static void
-get_data(int *v, int i, int ndbs) {
- int index = 0;
+fill_data_2_and_later(int *v, int i, int ndbs) {
+ int index = 2;
for (int dbnum = 1; dbnum < ndbs; dbnum++) {
- for (int which = 0; which < get_num_keys(i, dbnum); ++which) {
- v[index++] = get_key(i, dbnum, which);
+ for (int which = 0; which < MAX_KEYS; ++which) {
+ v[index++] = get_old_key(i, dbnum, which);
}
}
-}
-
-static void
-get_new_data(int *v, int i, int ndbs) {
- int index = 0;
for (int dbnum = 1; dbnum < ndbs; dbnum++) {
- for (int which = 0; which < get_num_new_keys(i, dbnum); ++which) {
+ for (int which = 0; which < MAX_KEYS; ++which) {
v[index++] = get_new_key(i, dbnum, which);
- if (which > 0) {
- assert(index >= 2);
- assert(memcmp(&v[index-2], &v[index-1], sizeof(v[0])) < 0);
- }
}
}
}
+static void
+fill_old_data(int *v, int i, int ndbs) {
+ v[0] = 0;
+ v[1] = ndbs;
+ fill_data_2_and_later(v, i, ndbs);
+}
+
+static void
+fill_new_data(int *v, int i, int ndbs) {
+ v[0] = 1;
+ v[1] = ndbs;
+ fill_data_2_and_later(v, i, ndbs);
+}
+
+
static int
put_callback(DB *dest_db, DB *src_db, DBT_ARRAY *dest_key_arrays, DBT_ARRAY *dest_val_arrays, const DBT *src_key, const DBT *src_val) {
(void)src_val;
@@ -201,10 +201,10 @@ put_callback(DB *dest_db, DB *src_db, DBT_ARRAY *dest_key_arrays, DBT_ARRAY *des
int pri_key = *(int *) src_key->data;
int* pri_val = (int*) src_val->data;
- bool is_new = (ntohl(pri_key) >> 16) % 2 == 1;
- int i = (ntohl(pri_key) >> 16) / 2;
+ bool is_new = pri_val[0] == 1;
+ int i = (ntohl(pri_key)) / 2;
- int num_keys = is_new ? get_num_new_keys(i, dbnum) : get_num_keys(i, dbnum);
+ int num_keys = is_new ? get_num_new_keys(i, dbnum) : get_old_num_keys(i, dbnum);
toku_dbt_array_resize(dest_key_arrays, num_keys);
@@ -212,14 +212,16 @@ put_callback(DB *dest_db, DB *src_db, DBT_ARRAY *dest_key_arrays, DBT_ARRAY *des
toku_dbt_array_resize(dest_val_arrays, num_keys);
}
- int index = 0;
-
- for (int idb = 1; idb < dbnum; idb++) {
- index += is_new ? get_num_new_keys(i, idb) : get_num_keys(i, idb);
+ int ndbs = pri_val[1];
+ int index = 2 + (dbnum-1)*MAX_KEYS;
+ if (is_new) {
+ index += MAX_KEYS*(ndbs-1);
}
+
assert(src_val->size % sizeof(int) == 0);
assert((int)src_val->size / 4 >= index + num_keys);
+
for (int which = 0; which < num_keys; which++) {
DBT *dest_key = &dest_key_arrays->dbts[which];
DBT *dest_val = NULL;
@@ -235,7 +237,7 @@ put_callback(DB *dest_db, DB *src_db, DBT_ARRAY *dest_key_arrays, DBT_ARRAY *des
assert(dest_val->flags == DB_DBT_REALLOC);
dest_val->size = 0;
}
- int new_key = is_new ? get_new_key(i, dbnum, which) : get_key(i, dbnum, which);
+ int new_key = is_new ? get_new_key(i, dbnum, which) : get_old_key(i, dbnum, which);
assert(new_key == pri_val[index + which]);
*(int*)dest_key->data = new_key;
}
@@ -265,19 +267,17 @@ do_updates(DB_ENV *env, DB *db[], int ndbs, int nrows) {
// update the data i % ndbs col from x to x+1
- int old_k = get_key(i, 0, 0);
+ int old_k = get_old_key(i, 0, 0);
DBT old_key; dbt_init(&old_key, &old_k, sizeof old_k);
int new_k = get_new_key(i, 0, 0);
DBT new_key; dbt_init(&new_key, &new_k, sizeof new_k);
- int num_old_keys = get_total_num_keys(i, ndbs);
- int v[num_old_keys]; get_data(v, i, ndbs);
+ int v[array_size(ndbs)]; fill_old_data(v, i, ndbs);
DBT old_data; dbt_init(&old_data, &v[0], sizeof v);
-
- int num_new_keys = get_total_num_new_keys(i, ndbs);
- int newv[num_new_keys]; get_new_data(newv, i, ndbs);
+
+ int newv[array_size(ndbs)]; fill_new_data(newv, i, ndbs);
DBT new_data; dbt_init(&new_data, &newv[0], sizeof newv);
-
+
uint32_t flags_array[ndbs]; memset(flags_array, 0, sizeof(flags_array));
r = env->update_multiple(env, db[0], txn, &old_key, &old_data, &new_key, &new_data, ndbs, db, flags_array, narrays, keys, narrays, vals);
@@ -298,9 +298,9 @@ populate_primary(DB_ENV *env, DB *db, int ndbs, int nrows) {
// populate
for (int i = 0; i < nrows; i++) {
- int k = get_key(i, 0, 0);
- int secondary_keys = get_total_num_keys(i, ndbs);
- int v[secondary_keys]; get_data(v, i, ndbs);
+ int k = get_old_key(i, 0, 0);
+ int v[array_size(ndbs)];
+ fill_old_data(v, i, ndbs);
DBT key; dbt_init(&key, &k, sizeof k);
DBT val; dbt_init(&val, &v[0], sizeof v);
r = db->put(db, txn, &key, &val, 0); assert_zero(r);
@@ -317,11 +317,13 @@ populate_secondary(DB_ENV *env, DB *db, int dbnum, int nrows) {
// populate
for (int i = 0; i < nrows; i++) {
- for (int which = 0; which < get_num_keys(i, dbnum); which++) {
- int k = get_key(i, dbnum, which);
- DBT key; dbt_init(&key, &k, sizeof k);
- DBT val; dbt_init(&val, NULL, 0);
- r = db->put(db, txn, &key, &val, 0); assert_zero(r);
+ for (int which = 0; which < MAX_KEYS; which++) {
+ int k = get_old_key(i, dbnum, which);
+ if (k >= 0) {
+ DBT key; dbt_init(&key, &k, sizeof k);
+ DBT val; dbt_init(&val, NULL, 0);
+ r = db->put(db, txn, &key, &val, 0); assert_zero(r);
+ }
}
}
@@ -346,14 +348,14 @@ verify_pri_seq(DB_ENV *env, DB *db, int ndbs, int nrows) {
break;
int k;
int expectk = get_new_key(i, dbnum, 0);
-
+
assert(key.size == sizeof k);
memcpy(&k, key.data, key.size);
assert(k == expectk);
- int num_keys = get_total_num_new_keys(i, ndbs);
+ int num_keys = array_size(ndbs);
assert(val.size == num_keys*sizeof(int));
- int v[num_keys]; get_new_data(v, i, ndbs);
+ int v[num_keys]; fill_new_data(v, i, ndbs);
assert(memcmp(val.data, v, val.size) == 0);
}
assert(i == nrows); // if (i != nrows) printf("%s:%d %d %d\n", __FUNCTION__, __LINE__, i, nrows); // assert(i == nrows);
@@ -398,7 +400,7 @@ verify_sec_seq(DB_ENV *env, DB *db, int dbnum, int nrows) {
assert(k == expectk);
}
- if (k != expectk && which < get_num_keys(i, dbnum) && k == get_key(i, dbnum, which)) {
+ if (k != expectk && which < get_old_num_keys(i, dbnum) && k == get_old_key(i, dbnum, which)) {
// Will fail, never got updated.
assert(k == expectk);
}
@@ -457,9 +459,9 @@ run_test(int ndbs, int nrows) {
r = indexer_txn->commit(indexer_txn, 0); assert_zero(r);
verify_pri_seq(env, db[0], ndbs, nrows);
- for (int dbnum = 1; dbnum < ndbs; dbnum++)
+ for (int dbnum = 1; dbnum < ndbs; dbnum++)
verify_sec_seq(env, db[dbnum], dbnum, nrows);
- for (int dbnum = 0; dbnum < ndbs; dbnum++)
+ for (int dbnum = 0; dbnum < ndbs; dbnum++)
r = db[dbnum]->close(db[dbnum], 0); assert_zero(r);
r = env->close(env, 0); assert_zero(r);
@@ -469,7 +471,7 @@ int
test_main(int argc, char * const argv[]) {
int r;
int ndbs = 10;
- int nrows = 3*(1<<5)*4;
+ int nrows = MAX_KEYS*(1<<5)*4;
// parse_args(argc, argv);
for (int i = 1; i < argc; i++) {
@@ -491,7 +493,7 @@ test_main(int argc, char * const argv[]) {
continue;
}
}
- while (nrows % (3*(1<<5)) != 0) {
+ while (nrows % (MAX_KEYS*(1<<5)) != 0) {
nrows++;
}
//Need at least one to update, and one to index
diff --git a/storage/tokudb/ft-index/src/ydb-internal.h b/storage/tokudb/ft-index/src/ydb-internal.h
index fe1113d2c0d..f8c10975d5a 100644
--- a/storage/tokudb/ft-index/src/ydb-internal.h
+++ b/storage/tokudb/ft-index/src/ydb-internal.h
@@ -182,7 +182,12 @@ struct __toku_db_env_internal {
int datadir_lockfd;
int logdir_lockfd;
int tmpdir_lockfd;
- uint64_t loader_memory_size;
+ uint64_t (*get_loader_memory_size_callback)(void);
+ uint64_t default_lock_timeout_msec;
+ uint64_t (*get_lock_timeout_callback)(uint64_t default_lock_timeout_msec);
+ uint64_t default_killed_time_msec;
+ uint64_t (*get_killed_time_callback)(uint64_t default_killed_time_msec);
+ int (*killed_callback)(void);
};
// test-only environment function for running lock escalation
diff --git a/storage/tokudb/ft-index/src/ydb.cc b/storage/tokudb/ft-index/src/ydb.cc
index 6a08b89c81a..d1c09f8cc10 100644
--- a/storage/tokudb/ft-index/src/ydb.cc
+++ b/storage/tokudb/ft-index/src/ydb.cc
@@ -111,6 +111,7 @@ const char *toku_copyright_string = "Copyright (c) 2007-2013 Tokutek Inc. All r
#include <sys/types.h>
#include <util/status.h>
+#include <util/context.h>
#include <ft/ft-flusher.h>
#include <ft/cachetable.h>
@@ -365,8 +366,8 @@ env_fs_init(DB_ENV *env) {
static int
env_fs_init_minicron(DB_ENV *env) {
int r = toku_minicron_setup(&env->i->fs_poller, env->i->fs_poll_time*1000, env_fs_poller, env);
- assert(r == 0);
- env->i->fs_poller_is_init = true;
+ if (r == 0)
+ env->i->fs_poller_is_init = true;
return r;
}
@@ -402,11 +403,12 @@ env_change_fsync_log_period(DB_ENV* env, uint32_t period_ms) {
}
}
-static void
+static int
env_fsync_log_cron_init(DB_ENV *env) {
int r = toku_minicron_setup(&env->i->fsync_log_cron, env->i->fsync_log_period_ms, env_fsync_log_on_minicron, env);
- assert(r == 0);
- env->i->fsync_log_cron_is_init = true;
+ if (r == 0)
+ env->i->fsync_log_cron_is_init = true;
+ return r;
}
static void
@@ -994,7 +996,11 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
if (env->i->cachetable==NULL) {
// If we ran recovery then the cachetable should be set here.
- toku_cachetable_create(&env->i->cachetable, env->i->cachetable_size, ZERO_LSN, env->i->logger);
+ r = toku_cachetable_create(&env->i->cachetable, env->i->cachetable_size, ZERO_LSN, env->i->logger);
+ if (r != 0) {
+ r = toku_ydb_do_error(env, r, "Cant create a cachetable\n");
+ goto cleanup;
+ }
}
toku_cachetable_set_env_dir(env->i->cachetable, env->i->dir);
@@ -1009,7 +1015,7 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
bool create_new_rollback_file = newenv | upgrade_in_progress;
r = toku_logger_open_rollback(env->i->logger, env->i->cachetable, create_new_rollback_file);
if (r != 0) {
- r = toku_ydb_do_error(env, r, "cant open rollback");
+ r = toku_ydb_do_error(env, r, "Cant open rollback\n");
goto cleanup;
}
}
@@ -1027,7 +1033,7 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
assert_zero(r);
r = toku_db_open_iname(env->i->persistent_environment, txn, toku_product_name_strings.environmentdictionary, DB_CREATE, mode);
if (r != 0) {
- r = toku_ydb_do_error(env, r, "cant open persistent env");
+ r = toku_ydb_do_error(env, r, "Cant open persistent env\n");
goto cleanup;
}
if (newenv) {
@@ -1065,20 +1071,29 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
assert_zero(r);
r = toku_db_open_iname(env->i->directory, txn, toku_product_name_strings.fileopsdirectory, DB_CREATE, mode);
if (r != 0) {
- r = toku_ydb_do_error(env, r, "cant open %s", toku_product_name_strings.fileopsdirectory);
+ r = toku_ydb_do_error(env, r, "Cant open %s\n", toku_product_name_strings.fileopsdirectory);
goto cleanup;
}
}
if (using_txns) {
r = locked_txn_commit(txn, 0);
assert_zero(r);
+ txn = NULL;
}
cp = toku_cachetable_get_checkpointer(env->i->cachetable);
r = toku_checkpoint(cp, env->i->logger, NULL, NULL, NULL, NULL, STARTUP_CHECKPOINT);
assert_zero(r);
env_fs_poller(env); // get the file system state at startup
- env_fs_init_minicron(env);
- env_fsync_log_cron_init(env);
+ r = env_fs_init_minicron(env);
+ if (r != 0) {
+ r = toku_ydb_do_error(env, r, "Cant create fs minicron\n");
+ goto cleanup;
+ }
+ r = env_fsync_log_cron_init(env);
+ if (r != 0) {
+ r = toku_ydb_do_error(env, r, "Cant create fsync log minicron\n");
+ goto cleanup;
+ }
cleanup:
if (r!=0) {
if (txn) {
@@ -1708,15 +1723,17 @@ env_set_redzone(DB_ENV *env, int redzone) {
return r;
}
-static int
-env_get_lock_timeout(DB_ENV *env, uint64_t *lock_timeout_msec) {
- *lock_timeout_msec = env->i->ltm.get_lock_wait_time();
+static int env_get_lock_timeout(DB_ENV *env, uint64_t *lock_timeout_msec) {
+ uint64_t t = env->i->default_lock_timeout_msec;
+ if (env->i->get_lock_timeout_callback)
+ t = env->i->get_lock_timeout_callback(t);
+ *lock_timeout_msec = t;
return 0;
}
-static int
-env_set_lock_timeout(DB_ENV *env, uint64_t lock_timeout_msec) {
- env->i->ltm.set_lock_wait_time(lock_timeout_msec);
+static int env_set_lock_timeout(DB_ENV *env, uint64_t default_lock_timeout_msec, uint64_t (*get_lock_timeout_callback)(uint64_t default_lock_timeout_msec)) {
+ env->i->default_lock_timeout_msec = default_lock_timeout_msec;
+ env->i->get_lock_timeout_callback = get_lock_timeout_callback;
return 0;
}
@@ -1900,6 +1917,7 @@ env_get_engine_status_num_rows (DB_ENV * UU(env), uint64_t * num_rowsp) {
num_rows += FS_STATUS_NUM_ROWS;
num_rows += INDEXER_STATUS_NUM_ROWS;
num_rows += LOADER_STATUS_NUM_ROWS;
+ num_rows += CTX_STATUS_NUM_ROWS;
#if 0
// enable when upgrade is supported
num_rows += FT_UPGRADE_STATUS_NUM_ROWS;
@@ -2086,6 +2104,15 @@ env_get_engine_status (DB_ENV * env, TOKU_ENGINE_STATUS_ROW engstat, uint64_t ma
}
}
}
+ {
+ struct context_status ctxstatus;
+ toku_context_get_status(&ctxstatus);
+ for (int i = 0; i < CTX_STATUS_NUM_ROWS && row < maxrows; i++) {
+ if (ctxstatus.status[i].include & include_flags) {
+ engstat[row++] = ctxstatus.status[i];
+ }
+ }
+ }
#if 0
// enable when upgrade is supported
{
@@ -2416,12 +2443,21 @@ env_iterate_live_transactions(DB_ENV *env,
return toku_txn_manager_iter_over_live_root_txns(txn_manager, iter_txns_callback, &e);
}
-static void env_set_loader_memory_size(DB_ENV *env, uint64_t loader_memory_size) {
- env->i->loader_memory_size = loader_memory_size;
+static void env_set_loader_memory_size(DB_ENV *env, uint64_t (*get_loader_memory_size_callback)(void)) {
+ env->i->get_loader_memory_size_callback = get_loader_memory_size_callback;
}
static uint64_t env_get_loader_memory_size(DB_ENV *env) {
- return env->i->loader_memory_size;
+ uint64_t memory_size = 0;
+ if (env->i->get_loader_memory_size_callback)
+ memory_size = env->i->get_loader_memory_size_callback();
+ return memory_size;
+}
+
+static void env_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)) {
+ env->i->default_killed_time_msec = default_killed_time_msec;
+ env->i->get_killed_time_callback = get_killed_time_callback;
+ env->i->killed_callback = killed_callback;
}
static int
@@ -2499,6 +2535,7 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) {
USENV(change_fsync_log_period);
USENV(set_loader_memory_size);
USENV(get_loader_memory_size);
+ USENV(set_killed_callback);
#undef USENV
// unlocked methods
diff --git a/storage/tokudb/ft-index/src/ydb_cursor.cc b/storage/tokudb/ft-index/src/ydb_cursor.cc
index cf7fb1d958b..ae3b6e08820 100644
--- a/storage/tokudb/ft-index/src/ydb_cursor.cc
+++ b/storage/tokudb/ft-index/src/ydb_cursor.cc
@@ -212,8 +212,7 @@ query_context_base_init(QUERY_CONTEXT_BASE context, DBC *c, uint32_t flag, bool
}
context->do_locking = (context->db->i->lt != nullptr && !(lock_flags & (DB_PRELOCKED | DB_PRELOCKED_WRITE)));
context->r_user_callback = 0;
- uint64_t lock_wait_time = context->txn ? context->txn->mgrp->i->ltm.get_lock_wait_time() : 0;
- context->request.create(lock_wait_time);
+ context->request.create();
}
static toku::lock_request::type
@@ -740,6 +739,11 @@ c_remove_restriction(DBC *dbc) {
toku_ft_cursor_remove_restriction(dbc_struct_i(dbc)->c);
}
+static void
+c_set_check_interrupt_callback(DBC* dbc, bool (*interrupt_callback)(void*), void *extra) {
+ toku_ft_cursor_set_check_interrupt_cb(dbc_struct_i(dbc)->c, interrupt_callback, extra);
+}
+
int
toku_c_get(DBC* c, DBT* key, DBT* val, uint32_t flag) {
//This function exists for legacy (test compatibility) purposes/parity with bdb.
@@ -833,6 +837,7 @@ toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC ** c, uint32_t flags, int is_
SCRS(c_getf_set_range_reverse);
SCRS(c_set_bounds);
SCRS(c_remove_restriction);
+ SCRS(c_set_check_interrupt_callback);
#undef SCRS
result->c_get = toku_c_get;
diff --git a/storage/tokudb/ft-index/src/ydb_db.cc b/storage/tokudb/ft-index/src/ydb_db.cc
index f0159c44d1f..c9fa99d54de 100644
--- a/storage/tokudb/ft-index/src/ydb_db.cc
+++ b/storage/tokudb/ft-index/src/ydb_db.cc
@@ -107,6 +107,7 @@ PATENT RIGHTS GRANT:
#include "indexer.h"
#include <portability/toku_atomic.h>
#include <util/status.h>
+#include <ft/le-cursor.h>
static YDB_DB_LAYER_STATUS_S ydb_db_layer_status;
#ifdef STATUS_VALUE
@@ -688,6 +689,29 @@ toku_db_get_compression_method(DB *db, enum toku_compression_method *compression
return 0;
}
+static int
+toku_db_change_fanout(DB *db, unsigned int fanout) {
+ HANDLE_PANICKED_DB(db);
+ if (!db_opened(db)) return EINVAL;
+ toku_ft_handle_set_fanout(db->i->ft_handle, fanout);
+ return 0;
+}
+
+static int
+toku_db_set_fanout(DB *db, unsigned int fanout) {
+ HANDLE_PANICKED_DB(db);
+ if (db_opened(db)) return EINVAL;
+ toku_ft_handle_set_fanout(db->i->ft_handle, fanout);
+ return 0;
+}
+
+static int
+toku_db_get_fanout(DB *db, unsigned int *fanout) {
+ HANDLE_PANICKED_DB(db);
+ toku_ft_handle_get_fanout(db->i->ft_handle, fanout);
+ return 0;
+}
+
static int
toku_db_get_fractal_tree_info64(DB *db, uint64_t *num_blocks_allocated, uint64_t *num_blocks_in_use, uint64_t *size_allocated, uint64_t *size_in_use) {
HANDLE_PANICKED_DB(db);
@@ -898,13 +922,13 @@ toku_db_optimize(DB *db) {
static int
toku_db_hot_optimize(DB *db, DBT* left, DBT* right,
int (*progress_callback)(void *extra, float progress),
- void *progress_extra)
+ void *progress_extra, uint64_t* loops_run)
{
HANDLE_PANICKED_DB(db);
int r = 0;
r = toku_ft_hot_optimize(db->i->ft_handle, left, right,
progress_callback,
- progress_extra);
+ progress_extra, loops_run);
return r;
}
@@ -919,6 +943,55 @@ locked_db_optimize(DB *db) {
return r;
}
+
+struct last_key_extra {
+ YDB_CALLBACK_FUNCTION func;
+ void* extra;
+};
+
+static int
+db_get_last_key_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen UU(), bytevec val UU(), void *extra, bool lock_only) {
+ if (!lock_only) {
+ DBT keydbt;
+ toku_fill_dbt(&keydbt, key, keylen);
+ struct last_key_extra * CAST_FROM_VOIDP(info, extra);
+ info->func(&keydbt, NULL, info->extra);
+ }
+ return 0;
+}
+
+static int
+toku_db_get_last_key(DB * db, DB_TXN *txn, YDB_CALLBACK_FUNCTION func, void* extra) {
+ int r;
+ LE_CURSOR cursor = nullptr;
+ struct last_key_extra last_extra = { .func = func, .extra = extra };
+
+ r = toku_le_cursor_create(&cursor, db->i->ft_handle, db_txn_struct_i(txn)->tokutxn);
+ if (r != 0) { goto cleanup; }
+
+ // Goes in reverse order. First key returned is last in dictionary.
+ r = toku_le_cursor_next(cursor, db_get_last_key_callback, &last_extra);
+ if (r != 0) { goto cleanup; }
+
+cleanup:
+ if (cursor) {
+ toku_le_cursor_close(cursor);
+ }
+ return r;
+}
+
+static int
+autotxn_db_get_last_key(DB* db, YDB_CALLBACK_FUNCTION func, void* extra) {
+ bool changed; int r;
+ DB_TXN *txn = nullptr;
+ // Cursors inside require transactions, but this is _not_ a transactional function.
+ // Create transaction in a wrapper and then later close it.
+ r = toku_db_construct_autotxn(db, &txn, &changed, false);
+ if (r!=0) return r;
+ r = toku_db_get_last_key(db, txn, func, extra);
+ return toku_db_destruct_autotxn(txn, r, changed);
+}
+
static int
toku_db_get_fragmentation(DB * db, TOKU_DB_FRAGMENTATION report) {
HANDLE_PANICKED_DB(db);
@@ -1034,6 +1107,9 @@ toku_db_create(DB ** db, DB_ENV * env, uint32_t flags) {
USDB(set_compression_method);
USDB(get_compression_method);
USDB(change_compression_method);
+ USDB(set_fanout);
+ USDB(get_fanout);
+ USDB(change_fanout);
USDB(set_flags);
USDB(get_flags);
USDB(fd);
@@ -1061,6 +1137,7 @@ toku_db_create(DB ** db, DB_ENV * env, uint32_t flags) {
result->update = autotxn_db_update;
result->update_broadcast = autotxn_db_update_broadcast;
result->change_descriptor = autotxn_db_change_descriptor;
+ result->get_last_key = autotxn_db_get_last_key;
// unlocked methods
result->get = autotxn_db_get;
diff --git a/storage/tokudb/ft-index/src/ydb_env_func.cc b/storage/tokudb/ft-index/src/ydb_env_func.cc
index febdb5eb309..5247e699a23 100644
--- a/storage/tokudb/ft-index/src/ydb_env_func.cc
+++ b/storage/tokudb/ft-index/src/ydb_env_func.cc
@@ -117,6 +117,10 @@ void db_env_set_direct_io (bool direct_io_on) {
toku_ft_set_direct_io(direct_io_on);
}
+void db_env_set_compress_buffers_before_eviction (bool compress_buffers) {
+ toku_ft_set_compress_buffers_before_eviction(compress_buffers);
+}
+
void db_env_set_func_fsync (int (*fsync_function)(int)) {
toku_set_func_fsync(fsync_function);
}
diff --git a/storage/tokudb/ft-index/src/ydb_row_lock.cc b/storage/tokudb/ft-index/src/ydb_row_lock.cc
index c355cf1d39e..f7cdcbb563c 100644
--- a/storage/tokudb/ft-index/src/ydb_row_lock.cc
+++ b/storage/tokudb/ft-index/src/ydb_row_lock.cc
@@ -231,10 +231,8 @@ void toku_db_txn_escalate_callback(TXNID txnid, const toku::locktree *lt, const
// Return when the range lock is acquired or the default lock tree timeout has expired.
int toku_db_get_range_lock(DB *db, DB_TXN *txn, const DBT *left_key, const DBT *right_key,
toku::lock_request::type lock_type) {
- uint64_t wait_time = txn->mgrp->i->ltm.get_lock_wait_time();
toku::lock_request request;
- request.create(wait_time);
-
+ request.create();
int r = toku_db_start_range_lock(db, txn, left_key, right_key, lock_type, &request);
if (r == DB_LOCK_NOTGRANTED) {
r = toku_db_wait_range_lock(db, txn, &request);
@@ -249,7 +247,7 @@ int toku_db_start_range_lock(DB *db, DB_TXN *txn, const DBT *left_key, const DBT
toku::lock_request::type lock_type, toku::lock_request *request) {
DB_TXN *txn_anc = txn_oldest_ancester(txn);
TXNID txn_anc_id = txn_anc->id64(txn_anc);
- request->set(db->i->lt, txn_anc_id, left_key, right_key, lock_type);
+ request->set(db->i->lt, txn_anc_id, left_key, right_key, lock_type, toku_is_big_txn(txn_anc));
const int r = request->start();
if (r == 0) {
@@ -270,8 +268,14 @@ int toku_db_wait_range_lock(DB *db, DB_TXN *txn, toku::lock_request *request) {
DB_TXN *txn_anc = txn_oldest_ancester(txn);
const DBT *left_key = request->get_left_key();
const DBT *right_key = request->get_right_key();
-
- const int r = request->wait();
+ DB_ENV *env = db->dbenv;
+ uint64_t wait_time_msec = env->i->default_lock_timeout_msec;
+ if (env->i->get_lock_timeout_callback)
+ wait_time_msec = env->i->get_lock_timeout_callback(wait_time_msec);
+ uint64_t killed_time_msec = env->i->default_killed_time_msec;
+ if (env->i->get_killed_time_callback)
+ killed_time_msec = env->i->get_killed_time_callback(killed_time_msec);
+ const int r = request->wait(wait_time_msec, killed_time_msec, env->i->killed_callback);
if (r == 0) {
db_txn_note_row_lock(db, txn_anc, left_key, right_key);
} else if (r == DB_LOCK_NOTGRANTED) {
@@ -296,11 +300,9 @@ void toku_db_grab_write_lock (DB *db, DBT *key, TOKUTXN tokutxn) {
TXNID txn_anc_id = txn_anc->id64(txn_anc);
// This lock request must succeed, so we do not want to wait
- const uint64_t lock_wait_time = 0;
toku::lock_request request;
-
- request.create(lock_wait_time);
- request.set(db->i->lt, txn_anc_id, key, key, toku::lock_request::type::WRITE);
+ request.create();
+ request.set(db->i->lt, txn_anc_id, key, key, toku::lock_request::type::WRITE, toku_is_big_txn(txn_anc));
int r = request.start();
invariant_zero(r);
db_txn_note_row_lock(db, txn_anc, key, key);
diff --git a/storage/tokudb/ft-index/src/ydb_txn.cc b/storage/tokudb/ft-index/src/ydb_txn.cc
index f8453753717..6f1105412d7 100644
--- a/storage/tokudb/ft-index/src/ydb_txn.cc
+++ b/storage/tokudb/ft-index/src/ydb_txn.cc
@@ -323,7 +323,7 @@ static int locked_txn_commit_with_progress(DB_TXN *txn, uint32_t flags,
if (!toku_txn_is_read_only(tokutxn)) {
// A readonly transaction does no logging, and therefore does not need the MO lock.
holds_mo_lock = true;
- if (toku_txn_has_spilled_rollback(tokutxn)) {
+ if (toku_is_big_tokutxn(tokutxn)) {
low_priority = true;
toku_low_priority_multi_operation_client_lock();
} else {
@@ -351,7 +351,7 @@ static int locked_txn_abort_with_progress(DB_TXN *txn,
if (!toku_txn_is_read_only(tokutxn)) {
// A readonly transaction does no logging, and therefore does not need the MO lock.
holds_mo_lock = true;
- if (toku_txn_has_spilled_rollback(tokutxn)) {
+ if (toku_is_big_tokutxn(tokutxn)) {
low_priority = true;
toku_low_priority_multi_operation_client_lock();
} else {
@@ -602,3 +602,11 @@ void toku_keep_prepared_txn_callback (DB_ENV *env, TOKUTXN tokutxn) {
void toku_increase_last_xid(DB_ENV *env, uint64_t increment) {
toku_txn_manager_increase_last_xid(toku_logger_get_txn_manager(env->i->logger), increment);
}
+
+bool toku_is_big_txn(DB_TXN *txn) {
+ return toku_is_big_tokutxn(db_txn_struct_i(txn)->tokutxn);
+}
+
+bool toku_is_big_tokutxn(TOKUTXN tokutxn) {
+ return toku_txn_has_spilled_rollback(tokutxn);
+}
diff --git a/storage/tokudb/ft-index/src/ydb_txn.h b/storage/tokudb/ft-index/src/ydb_txn.h
index 9992d267737..454b6578e9f 100644
--- a/storage/tokudb/ft-index/src/ydb_txn.h
+++ b/storage/tokudb/ft-index/src/ydb_txn.h
@@ -107,6 +107,9 @@ int locked_txn_abort(DB_TXN *txn);
void toku_keep_prepared_txn_callback(DB_ENV *env, TOKUTXN tokutxn);
+bool toku_is_big_txn(DB_TXN *txn);
+bool toku_is_big_tokutxn(TOKUTXN tokutxn);
+
// Test-only function
extern "C" void toku_increase_last_xid(DB_ENV *env, uint64_t increment) __attribute__((__visibility__("default")));
diff --git a/storage/tokudb/ft-index/toku_include/CMakeLists.txt b/storage/tokudb/ft-index/toku_include/CMakeLists.txt
index 6ae304f8df3..44291012538 100644
--- a/storage/tokudb/ft-index/toku_include/CMakeLists.txt
+++ b/storage/tokudb/ft-index/toku_include/CMakeLists.txt
@@ -7,9 +7,11 @@ 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/util/CMakeLists.txt b/storage/tokudb/ft-index/util/CMakeLists.txt
index abfc88cc711..08822c4a73c 100644
--- a/storage/tokudb/ft-index/util/CMakeLists.txt
+++ b/storage/tokudb/ft-index/util/CMakeLists.txt
@@ -1,8 +1,11 @@
set(util_srcs
+ context
+ frwlock
kibbutz
mempool
partitioned_counter
threadpool
+ scoped_malloc
)
add_library(util SHARED ${util_srcs})
@@ -19,6 +22,7 @@ if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING)
install(
FILES partitioned_counter.h
DESTINATION include
+ COMPONENT tokukv_headers
)
endif ()
diff --git a/storage/tokudb/ft-index/util/context.cc b/storage/tokudb/ft-index/util/context.cc
new file mode 100644
index 00000000000..350cac07960
--- /dev/null
+++ b/storage/tokudb/ft-index/util/context.cc
@@ -0,0 +1,242 @@
+/* -*- 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) 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 <string.h>
+
+#include <util/context.h>
+
+namespace toku {
+
+ static const context default_context(CTX_DEFAULT);
+ static __thread const context *tl_current_context = &default_context;
+
+ // save the old context, set the current context
+ context::context(const context_id id) :
+ m_old_ctx(tl_current_context),
+ m_id(id) {
+ tl_current_context = this;
+ }
+
+ // restore the old context
+ context::~context() {
+ tl_current_context = m_old_ctx;
+ }
+
+} // namespace toku
+
+// thread local context
+
+const toku::context *toku_thread_get_context() {
+ return toku::tl_current_context;
+}
+
+// engine status
+
+static struct context_status context_status;
+#define CONTEXT_STATUS_INIT(key, legend) TOKUDB_STATUS_INIT(context_status, key, nullptr, PARCOUNT, "context: " legend, TOKU_ENGINE_STATUS)
+
+static void
+context_status_init(void) {
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_FULL_FETCH, "tree traversals blocked by a full fetch");
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_PARTIAL_FETCH, "tree traversals blocked by a partial fetch");
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_FULL_EVICTION, "tree traversals blocked by a full eviction");
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_PARTIAL_EVICTION, "tree traversals blocked by a partial eviction");
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_MESSAGE_INJECTION, "tree traversals blocked by a message injection");
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_MESSAGE_APPLICATION, "tree traversals blocked by a message application");
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_FLUSH, "tree traversals blocked by a flush");
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_BY_CLEANER, "tree traversals blocked by a the cleaner thread");
+ CONTEXT_STATUS_INIT(CTX_SEARCH_BLOCKED_OTHER, "tree traversals blocked by something uninstrumented");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_FULL_FETCH, "promotion blocked by a full fetch (should never happen)");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_PARTIAL_FETCH, "promotion blocked by a partial fetch (should never happen)");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_FULL_EVICTION, "promotion blocked by a full eviction (should never happen)");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_PARTIAL_EVICTION, "promotion blocked by a partial eviction (should never happen)");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_MESSAGE_INJECTION, "promotion blocked by a message injection");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_MESSAGE_APPLICATION, "promotion blocked by a message application");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_FLUSH, "promotion blocked by a flush");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_BY_CLEANER, "promotion blocked by the cleaner thread");
+ CONTEXT_STATUS_INIT(CTX_PROMO_BLOCKED_OTHER, "promotion blocked by something uninstrumented");
+ CONTEXT_STATUS_INIT(CTX_BLOCKED_OTHER, "something uninstrumented blocked by something uninstrumented");
+ context_status.initialized = true;
+}
+#undef FS_STATUS_INIT
+
+void toku_context_get_status(struct context_status *status) {
+ if (!context_status.initialized) {
+ context_status_init();
+ }
+ *status = context_status;
+}
+
+#define STATUS_INC(x, d) increment_partitioned_counter(context_status.status[x].value.parcount, d);
+
+void toku_context_note_frwlock_contention(const context_id blocked, const context_id blocking) {
+ if (!context_status.initialized) {
+ context_status_init();
+ }
+ if (blocked != CTX_SEARCH && blocked != CTX_PROMO) {
+ // Return early if this event is "unknown"
+ STATUS_INC(CTX_BLOCKED_OTHER, 1);
+ return;
+ }
+ switch (blocking) {
+ case CTX_FULL_FETCH:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_BY_FULL_FETCH, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_BY_FULL_FETCH, 1);
+ }
+ break;
+ case CTX_PARTIAL_FETCH:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_BY_PARTIAL_FETCH, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_BY_PARTIAL_FETCH, 1);
+ }
+ break;
+ case CTX_FULL_EVICTION:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_BY_FULL_EVICTION, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_BY_FULL_EVICTION, 1);
+ }
+ break;
+ case CTX_PARTIAL_EVICTION:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_BY_PARTIAL_EVICTION, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_BY_PARTIAL_EVICTION, 1);
+ }
+ break;
+ case CTX_MESSAGE_INJECTION:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_BY_MESSAGE_INJECTION, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_BY_MESSAGE_INJECTION, 1);
+ }
+ break;
+ case CTX_MESSAGE_APPLICATION:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_BY_MESSAGE_APPLICATION, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_BY_MESSAGE_APPLICATION, 1);
+ }
+ break;
+ case CTX_FLUSH:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_BY_FLUSH, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_BY_FLUSH, 1);
+ }
+ break;
+ case CTX_CLEANER:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_BY_CLEANER, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_BY_CLEANER, 1);
+ }
+ break;
+ default:
+ if (blocked == CTX_SEARCH) {
+ STATUS_INC(CTX_SEARCH_BLOCKED_OTHER, 1);
+ } else if (blocked == CTX_PROMO) {
+ STATUS_INC(CTX_PROMO_BLOCKED_OTHER, 1);
+ }
+ break;
+ }
+}
+
+void toku_context_status_destroy(void) {
+ for (int i = 0; i < CTX_STATUS_NUM_ROWS; ++i) {
+ if (context_status.status[i].type == PARCOUNT) {
+ destroy_partitioned_counter(context_status.status[i].value.parcount);
+ }
+ }
+}
diff --git a/storage/tokudb/ft-index/util/context.h b/storage/tokudb/ft-index/util/context.h
new file mode 100644
index 00000000000..3d424ff597d
--- /dev/null
+++ b/storage/tokudb/ft-index/util/context.h
@@ -0,0 +1,204 @@
+/* -*- 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.
+*/
+
+#pragma once
+
+#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 <toku_include/toku_portability.h>
+
+#include <db.h>
+
+#include <util/status.h>
+
+enum context_id {
+ CTX_INVALID = -1,
+ CTX_DEFAULT = 0, // default context for when no context is set
+ CTX_SEARCH, // searching for a key at the bottom of the tree
+ CTX_PROMO, // promoting a message down the tree
+ CTX_FULL_FETCH, // performing full fetch (pivots + some partial fetch)
+ CTX_PARTIAL_FETCH, // performing partial fetch
+ CTX_FULL_EVICTION, // running partial eviction
+ CTX_PARTIAL_EVICTION, // running partial eviction
+ CTX_MESSAGE_INJECTION, // injecting a message into a buffer
+ CTX_MESSAGE_APPLICATION, // applying ancestor's messages to a basement node
+ CTX_FLUSH, // flushing a buffer
+ CTX_CLEANER // doing work as the cleaner thread
+};
+
+// Note a contention event in engine status
+void toku_context_note_frwlock_contention(const context_id blocking, const context_id blocked);
+
+namespace toku {
+
+ // class for tracking what a thread is doing
+ //
+ // usage:
+ //
+ // // automatically tag and document what you're doing
+ // void my_interesting_function(void) {
+ // toku::context ctx("doing something interesting", INTERESTING_FN_1);
+ // ...
+ // {
+ // toku::context inner_ctx("doing something expensive", EXPENSIVE_FN_1);
+ // my_rwlock.wrlock();
+ // expensive();
+ // my_rwlock.wrunlock();
+ // }
+ // ...
+ // }
+ //
+ // // ... so later you can write code like this.
+ // // here, we save some info to help determine why a lock could not be acquired
+ // void my_rwlock::wrlock() {
+ // r = try_acquire_write_lock();
+ // if (r == 0) {
+ // m_write_locked_context_id = get_thread_local_context()->get_id();
+ // ...
+ // } else {
+ // if (m_write_locked_context_id == EXPENSIVE_FN_1) {
+ // status.blocked_because_of_expensive_fn_1++;
+ // } else if (...) {
+ // ...
+ // }
+ // ...
+ // }
+ // }
+ class context {
+ public:
+ context(const context_id id);
+
+ ~context();
+
+ context_id get_id() const {
+ return m_id;
+ }
+
+ private:
+ // each thread has a stack of contexts, rooted at the trivial "root context"
+ const context *m_old_ctx;
+ const context_id m_id;
+ };
+
+} // namespace toku
+
+// Get the current context of this thread
+const toku::context *toku_thread_get_context();
+
+enum context_status_entry {
+ CTX_SEARCH_BLOCKED_BY_FULL_FETCH = 0,
+ CTX_SEARCH_BLOCKED_BY_PARTIAL_FETCH,
+ CTX_SEARCH_BLOCKED_BY_FULL_EVICTION,
+ CTX_SEARCH_BLOCKED_BY_PARTIAL_EVICTION,
+ CTX_SEARCH_BLOCKED_BY_MESSAGE_INJECTION,
+ CTX_SEARCH_BLOCKED_BY_MESSAGE_APPLICATION,
+ CTX_SEARCH_BLOCKED_BY_FLUSH,
+ CTX_SEARCH_BLOCKED_BY_CLEANER,
+ CTX_SEARCH_BLOCKED_OTHER,
+ CTX_PROMO_BLOCKED_BY_FULL_FETCH,
+ CTX_PROMO_BLOCKED_BY_PARTIAL_FETCH,
+ CTX_PROMO_BLOCKED_BY_FULL_EVICTION,
+ CTX_PROMO_BLOCKED_BY_PARTIAL_EVICTION,
+ CTX_PROMO_BLOCKED_BY_MESSAGE_INJECTION,
+ CTX_PROMO_BLOCKED_BY_MESSAGE_APPLICATION,
+ CTX_PROMO_BLOCKED_BY_FLUSH,
+ CTX_PROMO_BLOCKED_BY_CLEANER,
+ CTX_PROMO_BLOCKED_OTHER,
+ CTX_BLOCKED_OTHER,
+ CTX_STATUS_NUM_ROWS
+};
+
+struct context_status {
+ bool initialized;
+ TOKU_ENGINE_STATUS_ROW_S status[CTX_STATUS_NUM_ROWS];
+};
+
+void toku_context_get_status(struct context_status *status);
+
+void toku_context_status_destroy(void);
diff --git a/storage/tokudb/ft-index/util/frwlock.cc b/storage/tokudb/ft-index/util/frwlock.cc
index 7400f3c4abc..7259c776f83 100644
--- a/storage/tokudb/ft-index/util/frwlock.cc
+++ b/storage/tokudb/ft-index/util/frwlock.cc
@@ -91,8 +91,19 @@ PATENT RIGHTS GRANT:
#include <toku_assert.h>
+#include <util/context.h>
+#include <util/frwlock.h>
+
namespace toku {
+static __thread int thread_local_tid = -1;
+static int get_local_tid() {
+ if (thread_local_tid == -1) {
+ thread_local_tid = toku_os_gettid();
+ }
+ return thread_local_tid;
+}
+
void frwlock::init(toku_mutex_t *const mutex) {
m_mutex = mutex;
@@ -109,6 +120,8 @@ void frwlock::init(toku_mutex_t *const mutex) {
m_wait_read_is_in_queue = false;
m_current_writer_expensive = false;
m_read_wait_expensive = false;
+ m_current_writer_tid = -1;
+ m_blocking_writer_context_id = CTX_INVALID;
m_wait_head = nullptr;
m_wait_tail = nullptr;
@@ -118,11 +131,11 @@ void frwlock::deinit(void) {
toku_cond_destroy(&m_wait_read);
}
-inline bool frwlock::queue_is_empty(void) const {
+bool frwlock::queue_is_empty(void) const {
return m_wait_head == nullptr;
}
-inline void frwlock::enq_item(queue_item *const item) {
+void frwlock::enq_item(queue_item *const item) {
paranoid_invariant_null(item->next);
if (m_wait_tail != nullptr) {
m_wait_tail->next = item;
@@ -133,7 +146,7 @@ inline void frwlock::enq_item(queue_item *const item) {
m_wait_tail = item;
}
-inline toku_cond_t *frwlock::deq_item(void) {
+toku_cond_t *frwlock::deq_item(void) {
paranoid_invariant_notnull(m_wait_head);
paranoid_invariant_notnull(m_wait_tail);
queue_item *item = m_wait_head;
@@ -145,7 +158,7 @@ inline toku_cond_t *frwlock::deq_item(void) {
}
// Prerequisite: Holds m_mutex.
-inline void frwlock::write_lock(bool expensive) {
+void frwlock::write_lock(bool expensive) {
toku_mutex_assert_locked(m_mutex);
if (this->try_write_lock(expensive)) {
return;
@@ -160,6 +173,13 @@ inline void frwlock::write_lock(bool expensive) {
if (expensive) {
++m_num_expensive_want_write;
}
+ if (m_num_writers == 0 && m_num_want_write == 1) {
+ // We are the first to want a write lock. No new readers can get the lock.
+ // Set our thread id and context for proper instrumentation.
+ // see: toku_context_note_frwlock_contention()
+ m_current_writer_tid = get_local_tid();
+ m_blocking_writer_context_id = toku_thread_get_context()->get_id();
+ }
toku_cond_wait(&cond, m_mutex);
toku_cond_destroy(&cond);
@@ -176,9 +196,11 @@ inline void frwlock::write_lock(bool expensive) {
}
m_num_writers = 1;
m_current_writer_expensive = expensive;
+ m_current_writer_tid = get_local_tid();
+ m_blocking_writer_context_id = toku_thread_get_context()->get_id();
}
-inline bool frwlock::try_write_lock(bool expensive) {
+bool frwlock::try_write_lock(bool expensive) {
toku_mutex_assert_locked(m_mutex);
if (m_num_readers > 0 || m_num_writers > 0 || m_num_signaled_readers > 0 || m_num_want_write > 0) {
return false;
@@ -188,10 +210,12 @@ inline bool frwlock::try_write_lock(bool expensive) {
paranoid_invariant_zero(m_num_want_read);
m_num_writers = 1;
m_current_writer_expensive = expensive;
+ m_current_writer_tid = get_local_tid();
+ m_blocking_writer_context_id = toku_thread_get_context()->get_id();
return true;
}
-inline void frwlock::read_lock(void) {
+void frwlock::read_lock(void) {
toku_mutex_assert_locked(m_mutex);
if (m_num_writers > 0 || m_num_want_write > 0) {
if (!m_wait_read_is_in_queue) {
@@ -207,6 +231,12 @@ inline void frwlock::read_lock(void) {
);
}
+ // Note this contention event in engine status.
+ toku_context_note_frwlock_contention(
+ toku_thread_get_context()->get_id(),
+ m_blocking_writer_context_id
+ );
+
// Wait for our turn.
++m_num_want_read;
toku_cond_wait(&m_wait_read, m_mutex);
@@ -223,7 +253,7 @@ inline void frwlock::read_lock(void) {
++m_num_readers;
}
-inline bool frwlock::try_read_lock(void) {
+bool frwlock::try_read_lock(void) {
toku_mutex_assert_locked(m_mutex);
if (m_num_writers > 0 || m_num_want_write > 0) {
return false;
@@ -235,7 +265,7 @@ inline bool frwlock::try_read_lock(void) {
return true;
}
-inline void frwlock::maybe_signal_next_writer(void) {
+void frwlock::maybe_signal_next_writer(void) {
if (m_num_want_write > 0 && m_num_signaled_readers == 0 && m_num_readers == 0) {
toku_cond_t *cond = this->deq_item();
paranoid_invariant(cond != &m_wait_read);
@@ -245,7 +275,7 @@ inline void frwlock::maybe_signal_next_writer(void) {
}
}
-inline void frwlock::read_unlock(void) {
+void frwlock::read_unlock(void) {
toku_mutex_assert_locked(m_mutex);
paranoid_invariant(m_num_writers == 0);
paranoid_invariant(m_num_readers > 0);
@@ -253,7 +283,7 @@ inline void frwlock::read_unlock(void) {
this->maybe_signal_next_writer();
}
-inline bool frwlock::read_lock_is_expensive(void) {
+bool frwlock::read_lock_is_expensive(void) {
toku_mutex_assert_locked(m_mutex);
if (m_wait_read_is_in_queue) {
return m_read_wait_expensive;
@@ -264,7 +294,7 @@ inline bool frwlock::read_lock_is_expensive(void) {
}
-inline void frwlock::maybe_signal_or_broadcast_next(void) {
+void frwlock::maybe_signal_or_broadcast_next(void) {
paranoid_invariant(m_num_signaled_readers == 0);
if (this->queue_is_empty()) {
@@ -289,42 +319,44 @@ inline void frwlock::maybe_signal_or_broadcast_next(void) {
}
}
-inline void frwlock::write_unlock(void) {
+void frwlock::write_unlock(void) {
toku_mutex_assert_locked(m_mutex);
paranoid_invariant(m_num_writers == 1);
m_num_writers = 0;
m_current_writer_expensive = false;
+ m_current_writer_tid = -1;
+ m_blocking_writer_context_id = CTX_INVALID;
this->maybe_signal_or_broadcast_next();
}
-inline bool frwlock::write_lock_is_expensive(void) {
+bool frwlock::write_lock_is_expensive(void) {
toku_mutex_assert_locked(m_mutex);
return (m_num_expensive_want_write > 0) || (m_current_writer_expensive);
}
-inline uint32_t frwlock::users(void) const {
+uint32_t frwlock::users(void) const {
toku_mutex_assert_locked(m_mutex);
return m_num_readers + m_num_writers + m_num_want_read + m_num_want_write;
}
-inline uint32_t frwlock::blocked_users(void) const {
+uint32_t frwlock::blocked_users(void) const {
toku_mutex_assert_locked(m_mutex);
return m_num_want_read + m_num_want_write;
}
-inline uint32_t frwlock::writers(void) const {
+uint32_t frwlock::writers(void) const {
// this is sometimes called as "assert(lock->writers())" when we
// assume we have the write lock. if that's the assumption, we may
// not own the mutex, so we don't assert_locked here
return m_num_writers;
}
-inline uint32_t frwlock::blocked_writers(void) const {
+uint32_t frwlock::blocked_writers(void) const {
toku_mutex_assert_locked(m_mutex);
return m_num_want_write;
}
-inline uint32_t frwlock::readers(void) const {
+uint32_t frwlock::readers(void) const {
toku_mutex_assert_locked(m_mutex);
return m_num_readers;
}
-inline uint32_t frwlock::blocked_readers(void) const {
+uint32_t frwlock::blocked_readers(void) const {
toku_mutex_assert_locked(m_mutex);
return m_num_want_read;
}
diff --git a/storage/tokudb/ft-index/util/frwlock.h b/storage/tokudb/ft-index/util/frwlock.h
index 9ad2b6f7a9d..7811e0d2427 100644
--- a/storage/tokudb/ft-index/util/frwlock.h
+++ b/storage/tokudb/ft-index/util/frwlock.h
@@ -95,6 +95,7 @@ PATENT RIGHTS GRANT:
#include <toku_pthread.h>
#include <stdbool.h>
#include <stdint.h>
+#include <util/context.h>
//TODO: update comment, this is from rwlock.h
@@ -106,24 +107,24 @@ public:
void init(toku_mutex_t *const mutex);
void deinit(void);
- inline void write_lock(bool expensive);
- inline bool try_write_lock(bool expensive);
- inline void write_unlock(void);
+ void write_lock(bool expensive);
+ bool try_write_lock(bool expensive);
+ void write_unlock(void);
// returns true if acquiring a write lock will be expensive
- inline bool write_lock_is_expensive(void);
+ bool write_lock_is_expensive(void);
- inline void read_lock(void);
- inline bool try_read_lock(void);
- inline void read_unlock(void);
+ void read_lock(void);
+ bool try_read_lock(void);
+ void read_unlock(void);
// returns true if acquiring a read lock will be expensive
- inline bool read_lock_is_expensive(void);
+ bool read_lock_is_expensive(void);
- inline uint32_t users(void) const;
- inline uint32_t blocked_users(void) const;
- inline uint32_t writers(void) const;
- inline uint32_t blocked_writers(void) const;
- inline uint32_t readers(void) const;
- inline uint32_t blocked_readers(void) const;
+ uint32_t users(void) const;
+ uint32_t blocked_users(void) const;
+ uint32_t writers(void) const;
+ uint32_t blocked_writers(void) const;
+ uint32_t readers(void) const;
+ uint32_t blocked_readers(void) const;
private:
struct queue_item {
@@ -131,11 +132,11 @@ private:
struct queue_item *next;
};
- inline bool queue_is_empty(void) const;
- inline void enq_item(queue_item *const item);
- inline toku_cond_t *deq_item(void);
- inline void maybe_signal_or_broadcast_next(void);
- inline void maybe_signal_next_writer(void);
+ bool queue_is_empty(void) const;
+ void enq_item(queue_item *const item);
+ toku_cond_t *deq_item(void);
+ void maybe_signal_or_broadcast_next(void);
+ void maybe_signal_next_writer(void);
toku_mutex_t *m_mutex;
@@ -154,6 +155,12 @@ private:
// is expensive
// if there are currently no waiting readers, then set to false
bool m_read_wait_expensive;
+ // thread-id of the current writer
+ int m_current_writer_tid;
+ // context id describing the context of the current writer blocking
+ // new readers (either because this writer holds the write lock or
+ // is the first to want the write lock).
+ context_id m_blocking_writer_context_id;
toku_cond_t m_wait_read;
queue_item m_queue_item_read;
@@ -168,6 +175,6 @@ ENSURE_POD(frwlock);
} // namespace toku
// include the implementation here
-#include "frwlock.cc"
+// #include "frwlock.cc"
#endif // UTIL_FRWLOCK_H
diff --git a/storage/tokudb/ft-index/util/kibbutz.cc b/storage/tokudb/ft-index/util/kibbutz.cc
index e9057de7915..a84a6f4827f 100644
--- a/storage/tokudb/ft-index/util/kibbutz.cc
+++ b/storage/tokudb/ft-index/util/kibbutz.cc
@@ -118,7 +118,9 @@ struct kibbutz {
static void *work_on_kibbutz (void *);
-KIBBUTZ toku_kibbutz_create (int n_workers) {
+int toku_kibbutz_create (int n_workers, KIBBUTZ *kb_ret) {
+ int r = 0;
+ *kb_ret = NULL;
KIBBUTZ XCALLOC(k);
toku_mutex_init(&k->mutex, NULL);
toku_cond_init(&k->cond, NULL);
@@ -128,12 +130,19 @@ KIBBUTZ toku_kibbutz_create (int n_workers) {
k->n_workers = n_workers;
XMALLOC_N(n_workers, k->workers);
XMALLOC_N(n_workers, k->ids);
- for (int i=0; i<n_workers; i++) {
+ for (int i = 0; i < n_workers; i++) {
k->ids[i].k = k;
- int r = toku_pthread_create(&k->workers[i], NULL, work_on_kibbutz, &k->ids[i]);
- assert(r==0);
+ r = toku_pthread_create(&k->workers[i], NULL, work_on_kibbutz, &k->ids[i]);
+ if (r != 0) {
+ k->n_workers = i;
+ toku_kibbutz_destroy(k);
+ break;
+ }
+ }
+ if (r == 0) {
+ *kb_ret = k;
}
- return k;
+ return r;
}
static void klock (KIBBUTZ k) {
diff --git a/storage/tokudb/ft-index/util/kibbutz.h b/storage/tokudb/ft-index/util/kibbutz.h
index 06fa624b211..83e981b916c 100644
--- a/storage/tokudb/ft-index/util/kibbutz.h
+++ b/storage/tokudb/ft-index/util/kibbutz.h
@@ -100,7 +100,7 @@ typedef struct kibbutz *KIBBUTZ;
//
// create a kibbutz where n_workers is the number of threads in the threadpool
//
-KIBBUTZ toku_kibbutz_create (int n_workers);
+int toku_kibbutz_create (int n_workers, KIBBUTZ *kb);
//
// enqueue a workitem in the kibbutz. When the kibbutz is to work on this workitem,
// it calls f(extra).
diff --git a/storage/tokudb/ft-index/util/mempool.cc b/storage/tokudb/ft-index/util/mempool.cc
index 312848e6194..8a37fd41b44 100644
--- a/storage/tokudb/ft-index/util/mempool.cc
+++ b/storage/tokudb/ft-index/util/mempool.cc
@@ -114,23 +114,6 @@ void toku_mempool_zero(struct mempool *mp) {
memset(mp, 0, sizeof(*mp));
}
-/* Copy constructor. Any time a new mempool is needed, allocate 1/4 more space
- * than is currently needed.
- */
-void toku_mempool_copy_construct(struct mempool *mp, const void * const data_source, const size_t data_size) {
- // printf("mempool_copy %p %p %lu\n", mp, data_source, data_size);
- if (data_size) {
- paranoid_invariant(data_source);
- toku_mempool_construct(mp, data_size);
- memcpy(mp->base, data_source, data_size);
- mp->free_offset = data_size; // address of first available memory for new data
- }
- else {
- toku_mempool_zero(mp);
- // fprintf(stderr, "Empty mempool created (copy constructor)\n");
- }
-}
-
// TODO 4050 this is dirty, try to replace all uses of this
void toku_mempool_init(struct mempool *mp, void *base, size_t free_offset, size_t size) {
// printf("mempool_init %p %p %lu\n", mp, base, size);
diff --git a/storage/tokudb/ft-index/util/mempool.h b/storage/tokudb/ft-index/util/mempool.h
index f6a2bc6dde3..fa59d7a63ac 100644
--- a/storage/tokudb/ft-index/util/mempool.h
+++ b/storage/tokudb/ft-index/util/mempool.h
@@ -115,13 +115,6 @@ struct mempool {
*/
void toku_mempool_zero(struct mempool *mp);
-/* Copy constructor. Fill in empty mempool struct with new values, allocating
- * a new buffer and filling the buffer with data from from data_source.
- * Any time a new mempool is needed, allocate 1/4 more space
- * than is currently needed.
- */
-void toku_mempool_copy_construct(struct mempool *mp, const void * const data_source, const size_t data_size);
-
/* initialize the memory pool with the base address and size of a
contiguous chunk of memory */
void toku_mempool_init(struct mempool *mp, void *base, size_t free_offset, size_t size);
diff --git a/storage/tokudb/ft-index/util/scoped_malloc.cc b/storage/tokudb/ft-index/util/scoped_malloc.cc
new file mode 100644
index 00000000000..7fc847c3af6
--- /dev/null
+++ b/storage/tokudb/ft-index/util/scoped_malloc.cc
@@ -0,0 +1,265 @@
+/* -*- 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."
+
+#include <toku_include/memory.h>
+
+#include <util/scoped_malloc.h>
+
+// The __thread storage class modifier isn't well supported on osx, but we
+// aren't worried about the performance on osx, so we provide a
+// pass-through implementation of scoped mallocs.
+#ifdef __APPLE__
+
+namespace toku {
+
+ scoped_malloc::scoped_malloc(const size_t size)
+ : m_size(size),
+ m_local(false),
+ m_buf(toku_xmalloc(size)) {}
+
+ scoped_malloc::~scoped_malloc() {
+ toku_free(m_buf);
+ }
+
+} // namespace toku
+
+void toku_scoped_malloc_init(void) {}
+void toku_scoped_malloc_destroy(void) {}
+
+#else // __APPLE__
+
+#include <set>
+#include <pthread.h>
+
+#include <portability/toku_pthread.h>
+
+namespace toku {
+
+ // see pthread_key handling at the bottom
+ //
+ // when we use gcc 4.8, we can use the 'thread_local' keyword and proper c++
+ // constructors/destructors instead of this pthread / global set wizardy.
+ static pthread_key_t tl_stack_destroy_pthread_key;
+ class tl_stack;
+ std::set<tl_stack *> *global_stack_set;
+ toku_mutex_t global_stack_set_mutex = TOKU_MUTEX_INITIALIZER;
+
+ class tl_stack {
+ // 1MB
+ static const size_t STACK_SIZE = 1 * 1024 * 1024;
+
+ public:
+ void init() {
+ m_stack = reinterpret_cast<char *>(toku_xmalloc(STACK_SIZE));
+ m_current_offset = 0;
+ int r = pthread_setspecific(tl_stack_destroy_pthread_key, this);
+ invariant_zero(r);
+ }
+
+ void destroy() {
+ if (m_stack != NULL) {
+ toku_free(m_stack);
+ m_stack = NULL;
+ }
+ }
+
+ // initialize a tl_stack and insert it into the global map
+ static void init_and_register(tl_stack *st) {
+ st->init();
+ invariant_notnull(global_stack_set);
+
+ toku_mutex_lock(&global_stack_set_mutex);
+ std::pair<std::set<tl_stack *>::iterator, bool> p = global_stack_set->insert(st);
+ invariant(p.second);
+ toku_mutex_unlock(&global_stack_set_mutex);
+ }
+
+ // destruct a tl_stack and remove it from the global map
+ // passed in as void * to match the generic pthread destructor API
+ static void destroy_and_deregister(void *key) {
+ invariant_notnull(key);
+ tl_stack *st = reinterpret_cast<tl_stack *>(key);
+ st->destroy();
+
+ toku_mutex_lock(&global_stack_set_mutex);
+ invariant_notnull(global_stack_set);
+ size_t n = global_stack_set->erase(st);
+ invariant(n == 1);
+ toku_mutex_unlock(&global_stack_set_mutex);
+ }
+
+ // Allocate 'size' bytes and return a pointer to the first byte
+ void *alloc(const size_t size) {
+ if (m_stack == NULL) {
+ init_and_register(this);
+ }
+ invariant(m_current_offset + size <= STACK_SIZE);
+ void *mem = &m_stack[m_current_offset];
+ m_current_offset += size;
+ return mem;
+ }
+
+ // Give back a previously allocated region of 'size' bytes.
+ void dealloc(const size_t size) {
+ invariant(m_current_offset >= size);
+ m_current_offset -= size;
+ }
+
+ // Get the current size of free-space in bytes.
+ size_t get_free_space() const {
+ invariant(m_current_offset <= STACK_SIZE);
+ return STACK_SIZE - m_current_offset;
+ }
+
+ private:
+ // Offset of the free region in the stack
+ size_t m_current_offset;
+ char *m_stack;
+ };
+
+ // Each thread has its own local stack.
+ static __thread tl_stack local_stack;
+
+ // Memory is allocated from thread-local storage if available, otherwise from malloc(1).
+ scoped_malloc::scoped_malloc(const size_t size) :
+ m_size(size),
+ m_local(local_stack.get_free_space() >= m_size),
+ m_buf(m_local ? local_stack.alloc(m_size) : toku_xmalloc(m_size)) {
+ }
+
+ scoped_malloc::~scoped_malloc() {
+ if (m_local) {
+ local_stack.dealloc(m_size);
+ } else {
+ toku_free(m_buf);
+ }
+ }
+
+} // namespace toku
+
+// pthread key handling:
+// - there is a process-wide pthread key that is associated with the destructor for a tl_stack
+// - on process construction, we initialize the key; on destruction, we clean it up.
+// - when a thread first uses its tl_stack, it calls pthread_setspecific(&destroy_key, "some key"),
+// associating the destroy key with the tl_stack_destroy_and_deregister destructor
+// - when a thread terminates, it calls the associated destructor; tl_stack_destroy_and_deregister.
+
+void toku_scoped_malloc_init(void) {
+ toku_mutex_lock(&toku::global_stack_set_mutex);
+ invariant_null(toku::global_stack_set);
+ toku::global_stack_set = new std::set<toku::tl_stack *>();
+ toku_mutex_unlock(&toku::global_stack_set_mutex);
+
+ int r = pthread_key_create(&toku::tl_stack_destroy_pthread_key,
+ toku::tl_stack::destroy_and_deregister);
+ invariant_zero(r);
+}
+
+void toku_scoped_malloc_destroy(void) {
+ toku_mutex_lock(&toku::global_stack_set_mutex);
+ invariant_notnull(toku::global_stack_set);
+ // Destroy any tl_stacks that were registered as thread locals but did not
+ // get a chance to clean up using the pthread key destructor (because this code
+ // is now running before those threads fully shutdown)
+ for (std::set<toku::tl_stack *>::iterator i = toku::global_stack_set->begin();
+ i != toku::global_stack_set->end(); i++) {
+ (*i)->destroy();
+ }
+ delete toku::global_stack_set;
+ toku_mutex_unlock(&toku::global_stack_set_mutex);
+
+ // We're deregistering the destructor key here. When this thread exits,
+ // the tl_stack destructor won't get called, so we need to do that first.
+ int r = pthread_key_delete(toku::tl_stack_destroy_pthread_key);
+ invariant_zero(r);
+}
+
+#endif // !__APPLE__
diff --git a/storage/tokudb/ft-index/util/scoped_malloc.h b/storage/tokudb/ft-index/util/scoped_malloc.h
new file mode 100644
index 00000000000..ae8847731f3
--- /dev/null
+++ b/storage/tokudb/ft-index/util/scoped_malloc.h
@@ -0,0 +1,153 @@
+/* -*- 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.
+*/
+
+#pragma once
+
+#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>
+
+namespace toku {
+
+ class scoped_malloc {
+ public:
+ // Memory is allocated from thread-local storage if available, otherwise from malloc(3).
+ scoped_malloc(const size_t size);
+
+ ~scoped_malloc();
+
+ void *get() const {
+ return m_buf;
+ }
+
+ private:
+ // Non-copyable
+ scoped_malloc();
+
+ const size_t m_size;
+ const bool m_local;
+ void *const m_buf;
+ };
+
+ class scoped_calloc : public scoped_malloc {
+ public:
+ // A scoped malloc whose bytes are initialized to zero, as in calloc(3)
+ scoped_calloc(const size_t size) :
+ scoped_malloc(size) {
+ memset(scoped_malloc::get(), 0, size);
+ }
+ };
+
+ class scoped_malloc_aligned : public scoped_malloc {
+ public:
+ scoped_malloc_aligned(const size_t size, const size_t alignment) :
+ scoped_malloc(size + alignment) {
+ invariant(size >= alignment);
+ invariant(alignment > 0);
+ const uintptr_t addr = reinterpret_cast<uintptr_t>(scoped_malloc::get());
+ const uintptr_t aligned_addr = (addr + alignment) - (addr % alignment);
+ invariant(aligned_addr < addr + size + alignment);
+ m_aligned_buf = reinterpret_cast<char *>(aligned_addr);
+ }
+
+ void *get() const {
+ return m_aligned_buf;
+ }
+
+ private:
+ void *m_aligned_buf;
+ };
+
+} // namespace toku
+
+void toku_scoped_malloc_init(void);
+
+void toku_scoped_malloc_destroy(void);
+
diff --git a/storage/tokudb/ft-index/util/tests/test-frwlock-fair-writers.cc b/storage/tokudb/ft-index/util/tests/test-frwlock-fair-writers.cc
new file mode 100644
index 00000000000..653be1c2fbc
--- /dev/null
+++ b/storage/tokudb/ft-index/util/tests/test-frwlock-fair-writers.cc
@@ -0,0 +1,52 @@
+// check if write locks are fair
+
+#include <stdio.h>
+#include <toku_assert.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <util/frwlock.h>
+
+toku_mutex_t rwlock_mutex;
+toku::frwlock rwlock;
+volatile int killed = 0;
+
+static void *t1_func(void *arg) {
+ int i;
+ for (i = 0; !killed; i++) {
+ toku_mutex_lock(&rwlock_mutex);
+ rwlock.write_lock(false);
+ toku_mutex_unlock(&rwlock_mutex);
+ usleep(10000);
+ toku_mutex_lock(&rwlock_mutex);
+ rwlock.write_unlock();
+ toku_mutex_unlock(&rwlock_mutex);
+ }
+ printf("%lu %d\n", (unsigned long) pthread_self(), i);
+ return arg;
+}
+
+int main(void) {
+ int r;
+
+ toku_mutex_init(&rwlock_mutex, NULL);
+ rwlock.init(&rwlock_mutex);
+
+ const int nthreads = 2;
+ pthread_t tids[nthreads];
+ for (int i = 0; i < nthreads; i++) {
+ r = pthread_create(&tids[i], NULL, t1_func, NULL);
+ assert(r == 0);
+ }
+ sleep(10);
+ killed = 1;
+ for (int i = 0; i < nthreads; i++) {
+ void *ret;
+ r = pthread_join(tids[i], &ret);
+ assert(r == 0);
+ }
+
+ rwlock.deinit();
+ toku_mutex_destroy(&rwlock_mutex);
+
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/util/tests/test-kibbutz.cc b/storage/tokudb/ft-index/util/tests/test-kibbutz.cc
index 4e0b6076f2d..1f73037892c 100644
--- a/storage/tokudb/ft-index/util/tests/test-kibbutz.cc
+++ b/storage/tokudb/ft-index/util/tests/test-kibbutz.cc
@@ -111,7 +111,9 @@ static void dowork (void *idv) {
}
static void kibbutz_test (bool parent_finishes_first) {
- KIBBUTZ k = toku_kibbutz_create(NT);
+ KIBBUTZ k = NULL;
+ int r = toku_kibbutz_create(NT, &k);
+ assert(r == 0);
if (verbose) printf("create\n");
int ids[ND];
for (int i=0; i<ND; i++) {
diff --git a/storage/tokudb/ft-index/util/tests/test-kibbutz2.cc b/storage/tokudb/ft-index/util/tests/test-kibbutz2.cc
index 3afc7d5f005..ce797c068d8 100644
--- a/storage/tokudb/ft-index/util/tests/test-kibbutz2.cc
+++ b/storage/tokudb/ft-index/util/tests/test-kibbutz2.cc
@@ -113,7 +113,9 @@ static void dowork (void *idv) {
}
static void kibbutz_test (void) {
- KIBBUTZ k = toku_kibbutz_create(1);
+ KIBBUTZ k = NULL;
+ int r = toku_kibbutz_create(1, &k);
+ assert(r == 0);
if (verbose) printf("create\n");
int ids[ND];
for (int i=0; i<ND; i++) {
diff --git a/storage/tokudb/ft-index/util/tests/test-rwlock-cheapness.cc b/storage/tokudb/ft-index/util/tests/test-rwlock-cheapness.cc
index b787d1983bc..de54c21efd2 100644
--- a/storage/tokudb/ft-index/util/tests/test-rwlock-cheapness.cc
+++ b/storage/tokudb/ft-index/util/tests/test-rwlock-cheapness.cc
@@ -96,13 +96,16 @@ PATENT RIGHTS GRANT:
#include <toku_portability.h>
#include <toku_assert.h>
-#include <portability/toku_fair_rwlock.h>
#include <portability/toku_pthread.h>
#include <portability/toku_time.h>
#include <util/frwlock.h>
#include <util/rwlock.h>
#include "rwlock_condvar.h"
+// We need to manually intialize partitioned counters so that the
+// ones automatically incremented by the frwlock get handled properly.
+#include <util/partitioned_counter.h>
+
toku_mutex_t mutex;
toku::frwlock w;
@@ -288,6 +291,12 @@ static void test_write_cheapness(void) {
}
int main (int UU(argc), const char* UU(argv[])) {
+ // Ultra ugly. We manually init/destroy partitioned counters
+ // and context because normally toku_ft_layer_init() does that
+ // for us, but we don't want to initialize everything.
+ partitioned_counters_init();
test_write_cheapness();
+ toku_context_status_destroy();
+ partitioned_counters_destroy();
return 0;
}
diff --git a/storage/tokudb/ft-index/util/tests/test-rwlock-unfair-writers.cc b/storage/tokudb/ft-index/util/tests/test-rwlock-unfair-writers.cc
new file mode 100644
index 00000000000..fe569e3ec85
--- /dev/null
+++ b/storage/tokudb/ft-index/util/tests/test-rwlock-unfair-writers.cc
@@ -0,0 +1,60 @@
+// check if write locks are fair
+
+#include <stdio.h>
+#include <assert.h>
+#include <unistd.h>
+#include <pthread.h>
+
+pthread_rwlock_t rwlock;
+volatile int killed = 0;
+
+static void *t1_func(void *arg) {
+ int i;
+ for (i = 0; !killed; i++) {
+ int r;
+ r = pthread_rwlock_wrlock(&rwlock);
+ assert(r == 0);
+ usleep(10000);
+ r = pthread_rwlock_unlock(&rwlock);
+ assert(r == 0);
+ }
+ printf("%lu %d\n", (unsigned long) pthread_self(), i);
+ return arg;
+}
+
+int main(void) {
+ int r;
+#if 0
+ rwlock = PTHREAD_RWLOCK_INITIALIZER;
+#endif
+#if 0
+ pthread_rwlockattr_t attr;
+ pthread_rwlockattr_init(&attr);
+ pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+ r = pthread_rwlock_init(&rwlock, &attr);
+#endif
+#if 0
+ pthread_rwlockattr_t attr;
+ pthread_rwlockattr_init(&attr);
+ r = pthread_rwlock_init(&rwlock, &attr);
+#endif
+#if 1
+ r = pthread_rwlock_init(&rwlock, NULL);
+ assert(r == 0);
+#endif
+
+ const int nthreads = 2;
+ pthread_t tids[nthreads];
+ for (int i = 0; i < nthreads; i++) {
+ r = pthread_create(&tids[i], NULL, t1_func, NULL);
+ assert(r == 0);
+ }
+ sleep(10);
+ killed = 1;
+ for (int i = 0; i < nthreads; i++) {
+ void *ret;
+ r = pthread_join(tids[i], &ret);
+ assert(r == 0);
+ }
+ return 0;
+}
diff --git a/storage/tokudb/ft-index/util/tests/test-rwlock.cc b/storage/tokudb/ft-index/util/tests/test-rwlock.cc
index a560ef532eb..42ceb00ad19 100644
--- a/storage/tokudb/ft-index/util/tests/test-rwlock.cc
+++ b/storage/tokudb/ft-index/util/tests/test-rwlock.cc
@@ -96,7 +96,7 @@ PATENT RIGHTS GRANT:
// Best cas time= 8.595600ns
// Best mutex time= 19.340201ns
// Best rwlock time= 34.024799ns
-// Best newbrt rwlock time= 38.680500ns
+// Best util rwlock time= 38.680500ns
// Best prelocked time= 2.148700ns
// Best fair rwlock time= 45.127600ns
// On laptop
@@ -104,7 +104,7 @@ PATENT RIGHTS GRANT:
// Best cas time= 15.362500ns
// Best mutex time= 51.951498ns
// Best rwlock time= 97.721201ns
-// Best newbrt rwlock time=110.456800ns
+// Best util rwlock time=110.456800ns
// Best prelocked time= 4.240100ns
// Best fair rwlock time=113.119102ns
//
@@ -123,7 +123,6 @@ PATENT RIGHTS GRANT:
#include <toku_portability.h>
#include <toku_assert.h>
#include <portability/toku_atomic.h>
-#include <portability/toku_fair_rwlock.h>
#include <portability/toku_pthread.h>
#include <portability/toku_time.h>
#include <util/frwlock.h>
@@ -159,10 +158,8 @@ static double best_fcall_time=1e12;
static double best_cas_time=1e12;
static double best_mutex_time=1e12;
static double best_rwlock_time=1e12;
-static double best_newbrt_time=1e12;
+static double best_util_time=1e12;
static double best_prelocked_time=1e12;
-static double best_cv_fair_rwlock_time=1e12; // fair from condition variables
-static double best_fair_rwlock_time=1e12;
static double best_frwlock_time=1e12;
static double best_frwlock_prelocked_time=1e12;
static double mind(double a, double b) { if (a<b) return a; else return b; }
@@ -287,48 +284,48 @@ void time_pthread_rwlock (void) {
{ int r = pthread_rwlock_destroy(&mutex); assert(r==0); }
}
-static void newbrt_rwlock_lock (RWLOCK rwlock, toku_mutex_t *mutex) {
+static void util_rwlock_lock (RWLOCK rwlock, toku_mutex_t *mutex) {
toku_mutex_lock(mutex);
rwlock_read_lock(rwlock, mutex);
toku_mutex_unlock(mutex);
}
-static void newbrt_rwlock_unlock (RWLOCK rwlock, toku_mutex_t *mutex) {
+static void util_rwlock_unlock (RWLOCK rwlock, toku_mutex_t *mutex) {
toku_mutex_lock(mutex);
rwlock_read_unlock(rwlock);
toku_mutex_unlock(mutex);
}
-// Time the read lock that's in newbrt/rwlock.h
-void time_newbrt_rwlock (void) __attribute((__noinline__));
-void time_newbrt_rwlock (void) {
+// Time the read lock that's in util/rwlock.h
+void time_util_rwlock (void) __attribute((__noinline__));
+void time_util_rwlock (void) {
struct rwlock rwlock;
toku_mutex_t external_mutex;
toku_mutex_init(&external_mutex, NULL);
rwlock_init(&rwlock);
struct timeval start,end;
- newbrt_rwlock_lock(&rwlock, &external_mutex);
- newbrt_rwlock_unlock(&rwlock, &external_mutex);
+ util_rwlock_lock(&rwlock, &external_mutex);
+ util_rwlock_unlock(&rwlock, &external_mutex);
for (int t=0; t<T; t++) {
gettimeofday(&start, NULL);
for (int i=0; i<N; i++) {
- newbrt_rwlock_lock(&rwlock, &external_mutex);
- newbrt_rwlock_unlock(&rwlock, &external_mutex);
+ util_rwlock_lock(&rwlock, &external_mutex);
+ util_rwlock_unlock(&rwlock, &external_mutex);
}
gettimeofday(&end, NULL);
double diff = 1e9*toku_tdiff(&end, &start)/N;
if (verbose>1)
- fprintf(stderr, "newbrt_rwlock(r) = %.6fns/(lock+unlock)\n", diff);
- best_newbrt_time=mind(best_newbrt_time,diff);
+ fprintf(stderr, "util_rwlock(r) = %.6fns/(lock+unlock)\n", diff);
+ best_util_time=mind(best_util_time,diff);
}
rwlock_destroy(&rwlock);
toku_mutex_destroy(&external_mutex);
}
-// Time the read lock that's in newbrt/rwlock.h, assuming the mutex is already held.
-void time_newbrt_prelocked_rwlock (void) __attribute__((__noinline__));
-void time_newbrt_prelocked_rwlock (void) {
+// Time the read lock that's in util/rwlock.h, assuming the mutex is already held.
+void time_util_prelocked_rwlock (void) __attribute__((__noinline__));
+void time_util_prelocked_rwlock (void) {
struct rwlock rwlock;
toku_mutex_t external_mutex;
toku_mutex_init(&external_mutex, NULL);
@@ -347,7 +344,7 @@ void time_newbrt_prelocked_rwlock (void) {
gettimeofday(&end, NULL);
double diff = 1e9*toku_tdiff(&end, &start)/N;
if (verbose>1)
- fprintf(stderr, "pre_newbrt_rwlock(r) = %.6fns/(lock+unlock)\n", diff);
+ fprintf(stderr, "pre_util_rwlock(r) = %.6fns/(lock+unlock)\n", diff);
best_prelocked_time=mind(best_prelocked_time,diff);
}
rwlock_destroy(&rwlock);
@@ -355,51 +352,6 @@ void time_newbrt_prelocked_rwlock (void) {
toku_mutex_destroy(&external_mutex);
}
-void time_toku_fair_rwlock (void) __attribute__((__noinline__));
-void time_toku_fair_rwlock (void) {
- toku_fair_rwlock_t mutex;
- toku_fair_rwlock_init(&mutex);
- struct timeval start,end;
- toku_fair_rwlock_rdlock(&mutex);
- toku_fair_rwlock_unlock(&mutex);
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- toku_fair_rwlock_rdlock(&mutex);
- toku_fair_rwlock_unlock(&mutex);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "pthread_fair(r) = %.6fns/(lock+unlock)\n", diff);
- best_fair_rwlock_time=mind(best_fair_rwlock_time,diff);
- }
- toku_fair_rwlock_destroy(&mutex);
-}
-
-/* not static*/
-void time_toku_cv_fair_rwlock(void) __attribute__((__noinline__));
-void time_toku_cv_fair_rwlock(void) {
- toku_cv_fair_rwlock_t mutex;
- toku_cv_fair_rwlock_init(&mutex);
- struct timeval start,end;
- toku_cv_fair_rwlock_rdlock(&mutex);
- toku_cv_fair_rwlock_unlock(&mutex);
- for (int t=0; t<T; t++) {
- gettimeofday(&start, NULL);
- for (int i=0; i<N; i++) {
- toku_cv_fair_rwlock_rdlock(&mutex);
- toku_cv_fair_rwlock_unlock(&mutex);
- }
- gettimeofday(&end, NULL);
- double diff = 1e9*toku_tdiff(&end, &start)/N;
- if (verbose>1)
- fprintf(stderr, "pthread_cvfair(r) = %.6fns/(lock+unlock)\n", diff);
- best_cv_fair_rwlock_time=mind(best_cv_fair_rwlock_time,diff);
- }
- toku_cv_fair_rwlock_destroy(&mutex);
-}
-
void time_frwlock_prelocked(void) __attribute__((__noinline__));
void time_frwlock_prelocked(void) {
toku_mutex_t external_mutex;
@@ -469,208 +421,6 @@ void time_frwlock(void) {
toku_mutex_destroy(&external_mutex);
}
-
-#define N 6
-#define T 150000
-#define L 5
-#define N_LOG_ENTRIES (L*N*4)
-
-static toku_fair_rwlock_t rwlock;
-
-static struct log_s {
- int threadid, loopid;
- char action;
-} actionlog[N_LOG_ENTRIES];
-static int log_counter=0;
-
-static void logit (int threadid, int loopid, char action) {
- //printf("%d %d %c\n", threadid, loopid, action);
- int my_log_counter = toku_sync_fetch_and_add(&log_counter, 1);
- assert(my_log_counter<N_LOG_ENTRIES);
- actionlog[my_log_counter].threadid = threadid;
- actionlog[my_log_counter].loopid = loopid;
- actionlog[my_log_counter].action = action;
-}
-
-// The action should look like this:
-// Threads 0-2 are reader threads.
-// Threads 3-6 are writer threads.
-// The threads all repeatedly grab the lock, wait T steps, and release.
-// If the readers can starve the writers, then most of the writers will be at the end.
-// If the writers can starve the readers, then most of the readers will be at the end.
-// The reader threads all grab the lock, wait T*2 steps, and release the lock.
-// The writer threads
-// First the writer threads wait time T while the reader threads all go for the lock.
-// Before the first one lets go, the writer threads wake up and try to grab the lock. But the readers are still
-
-// 3 threads (0-2) try to grab the lock all at once. They'll get it. They each sleep for time T*2
-// 3 threads (3-6) try to grab the write lock. They'll get it one after another.
-
-
-extern __thread int mytid;
-
-static void grab_rdlock (int threadid, int iteration) {
- logit(threadid, iteration, 't');
- { int r = toku_fair_rwlock_rdlock(&rwlock); assert(r==0); }
- logit(threadid, iteration, 'R');
-}
-
-static void release_rdlock (int threadid, int iteration) {
- logit(threadid, iteration, 'u');
- { int r = toku_fair_rwlock_unlock(&rwlock); assert(r==0); }
-}
-
-static void grab_wrlock (int threadid, int iteration) {
- logit(threadid, iteration, 'T');
- { int r = toku_fair_rwlock_wrlock(&rwlock); assert(r==0); }
- logit(threadid, iteration, 'W');
-}
-
-static void release_wrlock (int threadid, int iteration) {
- logit(threadid, iteration, 'U');
- { int r = toku_fair_rwlock_unlock(&rwlock); assert(r==0);}
-}
-
-static void *start_thread (void *vv) {
- int *vp=(int*)vv;
- int v=*vp;
-
- //printf("T%d=%ld\n", v, pthread_self());
- switch(v) {
- case 0:
- case 1:
- case 2:
- for (int i=0; i<L; i++) {
- grab_rdlock(v, i);
- usleep(T);
- release_rdlock(v, i);
- }
- break;
- case 3:
- case 4:
- case 5:
- for (int i=0; i<L; i++) {
- grab_wrlock(v, i);
- usleep(T);
- release_wrlock(v, i);
- }
- }
- return NULL;
-}
-
-static void *start_thread_random (void *vv) {
- int *vp=(int*)vv;
- int v=*vp;
-
- for (int i=0; i<L; i++) {
- if (random()%2==0) {
- grab_rdlock(v, i);
- for (int j=0; j<random()%20; j++) sched_yield();
- release_rdlock(v, i);
- for (int j=0; j<random()%20; j++) sched_yield();
- } else {
- grab_wrlock(v, i);
- for (int j=0; j<random()%20; j++) sched_yield();
- release_wrlock(v, i);
- for (int j=0; j<random()%20; j++) sched_yield();
- }
- }
- return NULL;
-}
-
-static void check_actionlog (int expected_writer_max_count,
- int expected_reader_parallelism_min,
- int expected_reader_parallelism_max)
-// Effect:
-// Make sure that writers are exclusive.
-// Make sure that anyone who asks for a lock doesn't have one.
-// Make sure that anyone granted a lock actually asked for a lock.
-// Make sure that anyone who releases a lock has it.
-// Make sure that readers don't starve writers, and writers don't starve readers. (Not sure how to code this up...)
-{
- int reader_max=0;
- int writer_max=0;
- int state=0;
- char tstate[N];
- for (int i=0; i<N; i++) tstate[i]=0;
- for (int i=0; i<log_counter; i++) {
- switch (actionlog[i].action) {
- case 't': // fall through to 'T'
- case 'T':
- assert(tstate[actionlog[i].threadid]==0);
- tstate[actionlog[i].threadid]=actionlog[i].action;
- break;
- case 'W':
- assert(tstate[actionlog[i].threadid]=='T');
- tstate[actionlog[i].threadid]=actionlog[i].action;
- assert(state==0);
- state=-1;
- writer_max = 1;
- break;
- case 'U':
- assert(tstate[actionlog[i].threadid]=='W');
- tstate[actionlog[i].threadid]=0;
- assert(state==-1);
- state=0;
- break;
- case 'R':
- assert(tstate[actionlog[i].threadid]=='t');
- tstate[actionlog[i].threadid]=actionlog[i].action;
- if (state<0) { printf("On step %d\n", i); }
- assert(state>=0);
- state++;
- if (state>reader_max) reader_max=state;
- break;
- case 'u':
- assert(tstate[actionlog[i].threadid]=='R');
- tstate[actionlog[i].threadid]=0;
- assert(state>=0);
- state--;
- break;
- default:
- abort();
- }
- }
- assert(reader_max>=expected_reader_parallelism_min);
- assert(reader_max<=expected_reader_parallelism_max);
- assert(writer_max==expected_writer_max_count);
-}
-
-
-static void test_rwlock_internal (void *(*start_th)(void*), int max_wr, int min_rd, int max_rd) {
- if (verbose>=2) printf("Running threads:\n");
- log_counter=0;
- pthread_t threads[N];
- int v[N];
- toku_fair_rwlock_init(&rwlock);
- for (int i=0; i<N; i++) {
- v[i]=i;
- int r = pthread_create(&threads[i], NULL, start_th, &v[i]);
- assert(r==0);
- }
- for (int i=0; i<N; i++) {
- void *rv;
- int r = pthread_join(threads[i], &rv);
- assert(rv==NULL);
- assert(r==0);
- }
- if (verbose>1) {
- for (int i=0; i<log_counter; i++) {
- printf("%d: %*s%c%d\n", i, actionlog[i].threadid*4, "", actionlog[i].action, actionlog[i].loopid);
- }
- }
- check_actionlog(max_wr, min_rd, max_rd);
- toku_fair_rwlock_destroy(&rwlock);
- if (verbose>2) printf("OK\n");
-}
-
-static void test_rwlock (void) {
- test_rwlock_internal(start_thread, 1, 2, 3);
- for (int i=0; i<10; i++) {
- test_rwlock_internal(start_thread_random, 1, 0, N);
- }
-}
-
int main (int argc, const char *argv[]) {
parse_args(argc, argv);
if (timing_only) {
@@ -680,10 +430,8 @@ int main (int argc, const char *argv[]) {
time_cas();
time_pthread_mutex();
time_pthread_rwlock();
- time_newbrt_rwlock();
- time_newbrt_prelocked_rwlock();
- time_toku_cv_fair_rwlock();
- time_toku_fair_rwlock();
+ time_util_rwlock();
+ time_util_prelocked_rwlock();
}
time_frwlock();
time_frwlock_prelocked();
@@ -694,16 +442,12 @@ int main (int argc, const char *argv[]) {
printf("// Best cas time=%10.6fns\n", best_cas_time);
printf("// Best mutex time=%10.6fns\n", best_mutex_time);
printf("// Best rwlock time=%10.6fns\n", best_rwlock_time);
- printf("// Best newbrt rwlock time=%10.6fns\n", best_newbrt_time);
+ printf("// Best util rwlock time=%10.6fns\n", best_util_time);
printf("// Best prelocked time=%10.6fns\n", best_prelocked_time);
- printf("// Best fair cv rwlock time=%10.6fns\n", best_cv_fair_rwlock_time);
- printf("// Best fair fast rwlock time=%10.6fns\n", best_fair_rwlock_time);
}
printf("// Best frwlock time=%10.6fns\n", best_frwlock_time);
printf("// Best frwlock_pre time=%10.6fns\n", best_frwlock_prelocked_time);
}
- } else {
- test_rwlock();
}
return 0;
}