From f6716cef7eb267db958ce72c597d765bb8b7923e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 23 Jan 2018 19:20:10 +0200 Subject: 5.6.38-83.0 --- storage/tokudb/CMakeLists.txt | 2 +- storage/tokudb/PerconaFT/CMakeLists.txt | 7 +- storage/tokudb/PerconaFT/buildheader/make_tdb.cc | 13 +- .../cmake_modules/TokuSetupCompiler.cmake | 10 +- .../ft/cachetable/background_job_manager.cc | 9 +- .../tokudb/PerconaFT/ft/cachetable/cachetable.cc | 82 +++- .../tokudb/PerconaFT/ft/cachetable/checkpoint.cc | 36 +- storage/tokudb/PerconaFT/ft/ft-ops.cc | 304 +++++++++++- storage/tokudb/PerconaFT/ft/ft.cc | 17 +- storage/tokudb/PerconaFT/ft/loader/callbacks.cc | 6 +- storage/tokudb/PerconaFT/ft/loader/dbufio.cc | 163 ++++--- .../tokudb/PerconaFT/ft/loader/loader-internal.h | 37 +- storage/tokudb/PerconaFT/ft/loader/loader.cc | 365 ++++++++------- storage/tokudb/PerconaFT/ft/loader/loader.h | 5 +- storage/tokudb/PerconaFT/ft/logger/log-internal.h | 8 +- storage/tokudb/PerconaFT/ft/logger/logcursor.cc | 8 +- storage/tokudb/PerconaFT/ft/logger/logger.cc | 79 +++- storage/tokudb/PerconaFT/ft/logger/recover.cc | 14 +- .../PerconaFT/ft/serialize/block_allocator.cc | 1 + .../tokudb/PerconaFT/ft/serialize/block_table.cc | 13 +- .../tokudb/PerconaFT/ft/serialize/ft-serialize.cc | 10 +- storage/tokudb/PerconaFT/ft/serialize/sub_block.cc | 3 + storage/tokudb/PerconaFT/ft/serialize/workset.h | 14 +- .../tokudb/PerconaFT/ft/tests/cachetable-4357.cc | 31 +- .../tokudb/PerconaFT/ft/tests/cachetable-4365.cc | 42 +- .../tokudb/PerconaFT/ft/tests/cachetable-5097.cc | 11 +- .../tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc | 20 +- .../tokudb/PerconaFT/ft/tests/cachetable-5978.cc | 6 +- .../ft/tests/cachetable-checkpoint-pending.cc | 24 +- .../cachetable-cleaner-thread-attrs-accumulate.cc | 2 +- .../ft/tests/cachetable-clone-checkpoint.cc | 11 +- .../ft/tests/cachetable-pin-checkpoint.cc | 21 +- .../ft/tests/cachetable-put-checkpoint.cc | 21 +- .../PerconaFT/ft/tests/cachetable-rwlock-test.cc | 47 +- .../cachetable-simple-read-pin-nonblocking.cc | 30 +- .../ft/tests/cachetable-simple-read-pin.cc | 30 +- .../tokudb/PerconaFT/ft/tests/cachetable-test.cc | 8 +- .../cachetable-unpin-remove-and-checkpoint.cc | 17 +- .../ft/tests/ftloader-test-extractor-errors.cc | 4 +- .../ft/tests/ftloader-test-merge-files-dbufio.cc | 12 +- .../ft/tests/ftloader-test-writer-errors.cc | 4 +- storage/tokudb/PerconaFT/ft/tests/log-test4.cc | 13 +- storage/tokudb/PerconaFT/ft/tests/log-test5.cc | 16 +- storage/tokudb/PerconaFT/ft/tests/log-test6.cc | 13 +- .../PerconaFT/ft/tests/recovery-bad-last-entry.cc | 15 +- storage/tokudb/PerconaFT/ft/tests/test-bjm.cc | 14 +- .../ft/tests/test-checkpoint-during-flush.cc | 8 +- .../ft/tests/test-checkpoint-during-merge.cc | 8 +- .../ft/tests/test-checkpoint-during-rebalance.cc | 8 +- .../ft/tests/test-checkpoint-during-split.cc | 8 +- storage/tokudb/PerconaFT/ft/tests/test3681.cc | 34 +- storage/tokudb/PerconaFT/ft/txn/roll.cc | 6 +- .../PerconaFT/ft/txn/rollback_log_node_cache.cc | 6 +- storage/tokudb/PerconaFT/ft/txn/txn.cc | 119 ++--- .../tokudb/PerconaFT/ft/txn/txn_child_manager.cc | 4 +- storage/tokudb/PerconaFT/ft/txn/txn_manager.cc | 10 +- storage/tokudb/PerconaFT/locktree/lock_request.cc | 2 +- storage/tokudb/PerconaFT/locktree/locktree.cc | 8 +- storage/tokudb/PerconaFT/locktree/manager.cc | 10 +- .../tests/locktree_escalation_1big7lt_1small.cc | 10 +- .../locktree/tests/locktree_escalation_2big_1lt.cc | 6 +- .../locktree/tests/locktree_escalation_2big_2lt.cc | 6 +- .../locktree/tests/locktree_escalation_stalls.cc | 13 +- .../tests/manager_parallel_locktree_get_release.cc | 3 +- storage/tokudb/PerconaFT/locktree/treenode.cc | 8 +- .../tokudb/PerconaFT/portability/CMakeLists.txt | 5 + storage/tokudb/PerconaFT/portability/file.cc | 498 ++++++++++++++++---- .../tokudb/PerconaFT/portability/portability.cc | 60 ++- .../PerconaFT/portability/tests/rwlock_condvar.h | 4 +- .../tests/test-pthread-rwlock-rdlock.cc | 2 +- .../portability/tests/test-pthread-rwlock-rwr.cc | 14 +- .../PerconaFT/portability/tests/test-stat.cc | 9 +- .../portability/tests/test-toku-malloc.cc | 8 +- storage/tokudb/PerconaFT/portability/toku_assert.h | 14 +- .../PerconaFT/portability/toku_instr_mysql.cc | 365 +++++++++++++++ .../PerconaFT/portability/toku_instr_mysql.h | 249 ++++++++++ .../PerconaFT/portability/toku_instrumentation.h | 339 ++++++++++++++ storage/tokudb/PerconaFT/portability/toku_os.h | 10 +- .../PerconaFT/portability/toku_portability.h | 328 +++++++++++-- .../tokudb/PerconaFT/portability/toku_pthread.h | 450 ++++++++++++------ storage/tokudb/PerconaFT/src/indexer-undo-do.cc | 2 + storage/tokudb/PerconaFT/src/indexer.cc | 19 +- .../PerconaFT/src/tests/blocking-first-empty.cc | 10 +- .../tokudb/PerconaFT/src/tests/blocking-first.cc | 10 +- .../tokudb/PerconaFT/src/tests/blocking-last.cc | 10 +- .../src/tests/blocking-next-prev-deadlock.cc | 10 +- .../PerconaFT/src/tests/blocking-next-prev.cc | 10 +- .../PerconaFT/src/tests/blocking-prelock-range.cc | 13 +- .../PerconaFT/src/tests/blocking-put-timeout.cc | 17 +- .../PerconaFT/src/tests/blocking-put-wakeup.cc | 17 +- storage/tokudb/PerconaFT/src/tests/blocking-put.cc | 10 +- .../PerconaFT/src/tests/blocking-set-range-0.cc | 11 +- .../PerconaFT/src/tests/blocking-set-range-n.cc | 11 +- .../src/tests/blocking-set-range-reverse-0.cc | 11 +- storage/tokudb/PerconaFT/src/tests/blocking-set.cc | 10 +- .../PerconaFT/src/tests/blocking-table-lock.cc | 13 +- .../PerconaFT/src/tests/checkpoint_fairness.cc | 12 +- .../PerconaFT/src/tests/checkpoint_stress.cc | 37 +- .../src/tests/db-put-simple-deadlock-threads.cc | 9 +- .../PerconaFT/src/tests/db-put-simple-lockwait.cc | 7 +- .../PerconaFT/src/tests/db-put-update-deadlock.cc | 15 +- storage/tokudb/PerconaFT/src/tests/filesize.cc | 6 +- .../tokudb/PerconaFT/src/tests/hotindexer-bw.cc | 26 +- .../PerconaFT/src/tests/hotindexer-multiclient.cc | 22 +- .../PerconaFT/src/tests/hotindexer-put-abort.cc | 9 +- .../PerconaFT/src/tests/hotindexer-put-commit.cc | 14 +- .../PerconaFT/src/tests/hotindexer-with-queries.cc | 13 +- .../src/tests/locktree_escalation_stalls.cc | 13 +- .../tests/recover-test_crash_in_flusher_thread.h | 19 +- .../tokudb/PerconaFT/src/tests/recovery_stress.cc | 15 +- .../tokudb/PerconaFT/src/tests/stress_openclose.h | 11 +- storage/tokudb/PerconaFT/src/tests/test3039.cc | 44 +- storage/tokudb/PerconaFT/src/tests/test_1672532.cc | 210 +++++++++ storage/tokudb/PerconaFT/src/tests/test_3645.cc | 46 +- storage/tokudb/PerconaFT/src/tests/test_4015.cc | 14 +- storage/tokudb/PerconaFT/src/tests/test_abort1.cc | 20 +- storage/tokudb/PerconaFT/src/tests/test_abort4.cc | 10 +- storage/tokudb/PerconaFT/src/tests/test_abort5.cc | 10 +- .../tokudb/PerconaFT/src/tests/test_forkjoin.cc | 9 +- .../PerconaFT/src/tests/test_groupcommit_count.cc | 14 +- .../PerconaFT/src/tests/test_groupcommit_perf.cc | 14 +- .../tests/test_iterate_pending_lock_requests.cc | 11 +- .../src/tests/test_lock_timeout_callback.cc | 3 +- storage/tokudb/PerconaFT/src/tests/test_log1.cc | 10 +- .../tokudb/PerconaFT/src/tests/test_log1_abort.cc | 12 +- storage/tokudb/PerconaFT/src/tests/test_logmax.cc | 21 +- .../test_multiple_checkpoints_block_commit.cc | 15 +- .../src/tests/test_stress_hot_indexing.cc | 7 +- .../PerconaFT/src/tests/test_thread_insert.cc | 9 +- .../tokudb/PerconaFT/src/tests/test_txn_abort7.cc | 21 +- .../src/tests/threaded_stress_test_helpers.h | 49 +- .../tests/txn_manager_handle_snapshot_atomicity.cc | 4 +- storage/tokudb/PerconaFT/src/ydb.cc | 31 +- storage/tokudb/PerconaFT/src/ydb_db.cc | 105 ++--- storage/tokudb/PerconaFT/src/ydb_db.h | 3 +- storage/tokudb/PerconaFT/src/ydb_env_func.cc | 2 +- storage/tokudb/PerconaFT/src/ydb_txn.cc | 10 +- storage/tokudb/PerconaFT/tools/CMakeLists.txt | 1 + storage/tokudb/PerconaFT/util/dbt.cc | 3 +- storage/tokudb/PerconaFT/util/fmutex.h | 6 +- storage/tokudb/PerconaFT/util/frwlock.cc | 510 +++++++++++---------- storage/tokudb/PerconaFT/util/frwlock.h | 142 +++--- storage/tokudb/PerconaFT/util/kibbutz.cc | 28 +- storage/tokudb/PerconaFT/util/minicron.cc | 31 +- storage/tokudb/PerconaFT/util/nb_mutex.h | 52 ++- storage/tokudb/PerconaFT/util/queue.cc | 13 +- storage/tokudb/PerconaFT/util/rwlock.h | 88 +++- .../tokudb/PerconaFT/util/tests/marked-omt-test.cc | 18 +- .../tokudb/PerconaFT/util/tests/minicron-test.cc | 9 +- storage/tokudb/PerconaFT/util/tests/queue-test.cc | 6 +- .../tokudb/PerconaFT/util/tests/rwlock_condvar.h | 6 +- storage/tokudb/PerconaFT/util/tests/sm-basic.cc | 3 +- .../PerconaFT/util/tests/sm-crash-double-free.cc | 6 +- .../util/tests/test-frwlock-fair-writers.cc | 4 +- .../PerconaFT/util/tests/test-rwlock-cheapness.cc | 11 +- storage/tokudb/PerconaFT/util/tests/test-rwlock.cc | 39 +- .../tokudb/PerconaFT/util/tests/threadpool-test.cc | 7 +- storage/tokudb/PerconaFT/util/threadpool.cc | 31 +- storage/tokudb/ha_tokudb.cc | 139 +++--- storage/tokudb/ha_tokudb.h | 16 +- storage/tokudb/ha_tokudb_update.cc | 4 +- storage/tokudb/hatoku_cmp.cc | 1 + storage/tokudb/hatoku_defines.h | 20 +- storage/tokudb/hatoku_hton.cc | 50 +- storage/tokudb/hatoku_hton.h | 5 +- .../mysql-test/tokudb/r/card_scale_percent.result | 11 +- .../tokudb/r/locking-read-repeatable-read-1.result | 13 + .../tokudb/r/locking-read-repeatable-read-2.result | 17 + .../tokudb/r/nonflushing_analyze_debug.result | 19 + .../tokudb/mysql-test/tokudb/r/row_format.result | 39 ++ .../mysql-test/tokudb/t/card_scale_percent.test | 6 +- .../tokudb/t/locking-read-repeatable-read-1.test | 23 + .../tokudb/t/locking-read-repeatable-read-2.test | 29 ++ .../tokudb/t/nonflushing_analyze_debug.test | 10 + storage/tokudb/mysql-test/tokudb/t/row_format.test | 21 + .../tokudb_alter_table/r/null_bytes_add_key.result | 2 + .../r/null_bytes_col_rename.result | 2 + .../r/null_bytes_drop_default.result | 2 + .../r/null_bytes_drop_key.result | 2 + .../r/db756_card_part_hash_1_pick.result | 2 +- .../r/nonflushing_analyze_debug.result | 50 ++ .../tokudb_parts/t/nonflushing_analyze_debug.test | 29 ++ .../tokudb_perfschema/r/crash_tokudb.result | 30 ++ .../tokudb_perfschema/r/start_server_tokudb.result | 114 +++++ .../tokudb_perfschema/t/crash_tokudb.test | 36 ++ .../tokudb_perfschema/t/start_server_tokudb.test | 10 + .../mysql-test/tokudb_perfschema/t/suite.opt | 1 + storage/tokudb/tokudb_background.cc | 30 +- storage/tokudb/tokudb_background.h | 4 +- storage/tokudb/tokudb_information_schema.cc | 14 +- storage/tokudb/tokudb_thread.cc | 1 + storage/tokudb/tokudb_thread.h | 298 ++++++------ 192 files changed, 5432 insertions(+), 1998 deletions(-) create mode 100644 storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc create mode 100644 storage/tokudb/PerconaFT/portability/toku_instr_mysql.h create mode 100644 storage/tokudb/PerconaFT/portability/toku_instrumentation.h create mode 100644 storage/tokudb/PerconaFT/src/tests/test_1672532.cc create mode 100644 storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-1.result create mode 100644 storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-2.result create mode 100644 storage/tokudb/mysql-test/tokudb/r/nonflushing_analyze_debug.result create mode 100644 storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-1.test create mode 100644 storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-2.test create mode 100644 storage/tokudb/mysql-test/tokudb/t/nonflushing_analyze_debug.test create mode 100644 storage/tokudb/mysql-test/tokudb_parts/r/nonflushing_analyze_debug.result create mode 100644 storage/tokudb/mysql-test/tokudb_parts/t/nonflushing_analyze_debug.test create mode 100644 storage/tokudb/mysql-test/tokudb_perfschema/r/crash_tokudb.result create mode 100644 storage/tokudb/mysql-test/tokudb_perfschema/r/start_server_tokudb.result create mode 100644 storage/tokudb/mysql-test/tokudb_perfschema/t/crash_tokudb.test create mode 100644 storage/tokudb/mysql-test/tokudb_perfschema/t/start_server_tokudb.test create mode 100644 storage/tokudb/mysql-test/tokudb_perfschema/t/suite.opt (limited to 'storage/tokudb') diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index df22ef3530e..87c49deb91d 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(TOKUDB_VERSION 5.6.37-82.2) +SET(TOKUDB_VERSION 5.6.38-83.0) # PerconaFT only supports x86-64 and cmake-2.8.9+ IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT CMAKE_VERSION VERSION_LESS "2.8.9") diff --git a/storage/tokudb/PerconaFT/CMakeLists.txt b/storage/tokudb/PerconaFT/CMakeLists.txt index a850400e726..487ba8b734a 100644 --- a/storage/tokudb/PerconaFT/CMakeLists.txt +++ b/storage/tokudb/PerconaFT/CMakeLists.txt @@ -12,9 +12,14 @@ set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # detect when we are being built as a subproject if (DEFINED MYSQL_PROJECT_NAME_DOCSTRING) add_definitions( -DMYSQL_TOKUDB_ENGINE=1) + # Extended PFS instrumentation: + # -DTOKU_PFS_MUTEX_EXTENDED_CACHETABLEMMUTEX=1 + if (WITH_PERFSCHEMA_STORAGE_ENGINE) + add_definitions(-DTOKU_MYSQL_WITH_PFS) + endif () + include_directories(${CMAKE_SOURCE_DIR}/include) if ((CMAKE_BUILD_TYPE MATCHES "Debug") AND (CMAKE_CXX_FLAGS_DEBUG MATCHES " -DENABLED_DEBUG_SYNC")) - include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_SOURCE_DIR}/sql) endif () endif () diff --git a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc index 5fe55c886cd..8102798001f 100644 --- a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc +++ b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc @@ -444,14 +444,15 @@ static void print_db_key_range_struct (void) { sort_and_dump_fields("db_key_range", false, NULL); } -static void print_db_lsn_struct (void) { - field_counter=0; - /* A dummy field to make sizeof(DB_LSN) equal in C and C++ */ - const char *extra[] = { "char dummy", NULL }; - sort_and_dump_fields("db_lsn", false, extra); +static void print_db_lsn_struct(void) { + field_counter = 0; + // FT-692 + STRUCT_SETUP(DB_LSN, file, "uint32_t %s"); + STRUCT_SETUP(DB_LSN, offset, "uint32_t %s"); + sort_and_dump_fields("db_lsn", false, NULL); } -static void print_dbt_struct (void) { +static void print_dbt_struct(void) { field_counter=0; #if 0 && DB_VERSION_MAJOR==4 && DB_VERSION_MINOR==1 STRUCT_SETUP(DBT, app_private, "void*%s"); diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake index ea5c7e22209..1d59ab0f8fc 100644 --- a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake +++ b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake @@ -83,7 +83,13 @@ macro(set_ldflags_if_supported) endforeach(flag) endmacro(set_ldflags_if_supported) +if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING) + set (OPTIONAL_CFLAGS "${OPTIONAL_CFLAGS} -Wmissing-format-attribute") +endif() + ## disable some warnings +## missing-format-attribute causes warnings in some MySQL include files +## if the library is built as a part of TokuDB MySQL storage engine set_cflags_if_supported( -Wno-missing-field-initializers -Wstrict-null-sentinel @@ -91,7 +97,7 @@ set_cflags_if_supported( -Wswitch -Wtrampolines -Wlogical-op - -Wmissing-format-attribute + ${OPTIONAL_CFLAGS} -Wno-error=missing-format-attribute -Wno-error=address-of-array-temporary -Wno-error=tautological-constant-out-of-range-compare @@ -178,8 +184,8 @@ set_cflags_if_supported( -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith - -Wmissing-format-attribute -Wshadow + ${OPTIONAL_CFLAGS} ## other flags to try: #-Wunsafe-loop-optimizations #-Wpointer-arith diff --git a/storage/tokudb/PerconaFT/ft/cachetable/background_job_manager.cc b/storage/tokudb/PerconaFT/ft/cachetable/background_job_manager.cc index 9119a49b081..c109185f973 100644 --- a/storage/tokudb/PerconaFT/ft/cachetable/background_job_manager.cc +++ b/storage/tokudb/PerconaFT/ft/cachetable/background_job_manager.cc @@ -42,6 +42,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "cachetable/background_job_manager.h" +toku_instr_key *bjm_jobs_lock_mutex_key; +toku_instr_key *bjm_jobs_wait_key; + struct background_job_manager_struct { bool accepting_jobs; uint32_t num_jobs; @@ -49,10 +52,10 @@ struct background_job_manager_struct { toku_mutex_t jobs_lock; }; -void bjm_init(BACKGROUND_JOB_MANAGER* pbjm) { +void bjm_init(BACKGROUND_JOB_MANAGER *pbjm) { BACKGROUND_JOB_MANAGER XCALLOC(bjm); - toku_mutex_init(&bjm->jobs_lock, 0); - toku_cond_init(&bjm->jobs_wait, NULL); + toku_mutex_init(*bjm_jobs_lock_mutex_key, &bjm->jobs_lock, nullptr); + toku_cond_init(*bjm_jobs_wait_key, &bjm->jobs_wait, nullptr); bjm->accepting_jobs = true; bjm->num_jobs = 0; *pbjm = bjm; diff --git a/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc b/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc index 31aab932fd6..ae2bb2846e8 100644 --- a/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc +++ b/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc @@ -57,6 +57,25 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/status.h" #include "util/context.h" +toku_instr_key *cachetable_m_mutex_key; +toku_instr_key *cachetable_ev_thread_lock_mutex_key; + +toku_instr_key *cachetable_m_list_lock_key; +toku_instr_key *cachetable_m_pending_lock_expensive_key; +toku_instr_key *cachetable_m_pending_lock_cheap_key; +toku_instr_key *cachetable_m_lock_key; + +toku_instr_key *cachetable_value_key; +toku_instr_key *cachetable_disk_nb_rwlock_key; + +toku_instr_key *cachetable_p_refcount_wait_key; +toku_instr_key *cachetable_m_flow_control_cond_key; +toku_instr_key *cachetable_m_ev_thread_cond_key; + +toku_instr_key *cachetable_disk_nb_mutex_key; +toku_instr_key *log_internal_lock_mutex_key; +toku_instr_key *eviction_thread_key; + /////////////////////////////////////////////////////////////////////////////////// // Engine status // @@ -779,18 +798,25 @@ void pair_init(PAIR p, p->checkpoint_complete_callback = write_callback.checkpoint_complete_callback; p->write_extraargs = write_callback.write_extraargs; - p->count = 0; // Is zero the correct init value? + p->count = 0; // Is zero the correct init value? p->refcount = 0; p->num_waiting_on_refs = 0; - toku_cond_init(&p->refcount_wait, NULL); + toku_cond_init(*cachetable_p_refcount_wait_key, &p->refcount_wait, nullptr); p->checkpoint_pending = false; p->mutex = list->get_mutex_for_pair(fullhash); assert(p->mutex); - p->value_rwlock.init(p->mutex); - nb_mutex_init(&p->disk_nb_mutex); + p->value_rwlock.init(p->mutex +#ifdef TOKU_MYSQL_WITH_PFS + , + *cachetable_value_key +#endif + ); + nb_mutex_init(*cachetable_disk_nb_mutex_key, + *cachetable_disk_nb_rwlock_key, + &p->disk_nb_mutex); - p->size_evicting_estimate = 0; // Is zero the correct init value? + p->size_evicting_estimate = 0; // Is zero the correct init value? p->ev = ev; p->list = list; @@ -3229,16 +3255,26 @@ void pair_list::init() { #if defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); #else - // TODO: need to figure out how to make writer-preferential rwlocks - // happen on osx +// TODO: need to figure out how to make writer-preferential rwlocks +// happen on osx #endif - toku_pthread_rwlock_init(&m_list_lock, &attr); - toku_pthread_rwlock_init(&m_pending_lock_expensive, &attr); - toku_pthread_rwlock_init(&m_pending_lock_cheap, &attr); + toku_pthread_rwlock_init(*cachetable_m_list_lock_key, &m_list_lock, &attr); + toku_pthread_rwlock_init(*cachetable_m_pending_lock_expensive_key, + &m_pending_lock_expensive, + &attr); + toku_pthread_rwlock_init( + *cachetable_m_pending_lock_cheap_key, &m_pending_lock_cheap, &attr); XCALLOC_N(m_table_size, m_table); XCALLOC_N(m_num_locks, m_mutexes); for (uint64_t i = 0; i < m_num_locks; i++) { - toku_mutex_init(&m_mutexes[i].aligned_mutex, NULL); + toku_mutex_init( +#ifdef TOKU_PFS_MUTEX_EXTENDED_CACHETABLEMMUTEX + *cachetable_m_mutex_key, +#else + toku_uninstrumented, +#endif + &m_mutexes[i].aligned_mutex, + nullptr); } } @@ -3578,9 +3614,9 @@ ENSURE_POD(evictor); // This is the function that runs eviction on its own thread. // static void *eviction_thread(void *evictor_v) { - evictor* CAST_FROM_VOIDP(evictor, evictor_v); + evictor *CAST_FROM_VOIDP(evictor, evictor_v); evictor->run_eviction_thread(); - return evictor_v; + return toku_pthread_done(evictor_v); } // @@ -3629,11 +3665,14 @@ int evictor::init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KI m_pl = _pl; m_cf_list = _cf_list; - m_kibbutz = _kibbutz; - toku_mutex_init(&m_ev_thread_lock, NULL); - toku_cond_init(&m_flow_control_cond, NULL); - toku_cond_init(&m_ev_thread_cond, NULL); - m_num_sleepers = 0; + m_kibbutz = _kibbutz; + toku_mutex_init( + *cachetable_ev_thread_lock_mutex_key, &m_ev_thread_lock, nullptr); + toku_cond_init( + *cachetable_m_flow_control_cond_key, &m_flow_control_cond, nullptr); + toku_cond_init( + *cachetable_m_ev_thread_cond_key, &m_ev_thread_cond, nullptr); + m_num_sleepers = 0; m_ev_thread_is_running = false; m_period_in_seconds = eviction_period; @@ -3641,11 +3680,12 @@ int evictor::init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KI int r = myinitstate_r(seed, m_random_statebuf, sizeof m_random_statebuf, &m_random_data); assert_zero(r); - // start the background thread + // 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); + r = toku_pthread_create( + *eviction_thread_key, &m_ev_thread, nullptr, eviction_thread, this); if (r == 0) { m_ev_thread_init = true; } @@ -4702,7 +4742,7 @@ static_assert(std::is_pod::value, "cachefile_list isn't POD"); void cachefile_list::init() { m_next_filenum_to_use.fileid = 0; m_next_hash_id_to_use = 0; - toku_pthread_rwlock_init(&m_lock, NULL); + toku_pthread_rwlock_init(*cachetable_m_lock_key, &m_lock, nullptr); m_active_filenum.create(); m_active_fileid.create(); m_stale_fileid.create(); diff --git a/storage/tokudb/PerconaFT/ft/cachetable/checkpoint.cc b/storage/tokudb/PerconaFT/ft/cachetable/checkpoint.cc index 3223ab0a4ce..13ff5eff5af 100644 --- a/storage/tokudb/PerconaFT/ft/cachetable/checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/cachetable/checkpoint.cc @@ -86,8 +86,16 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/frwlock.h" #include "util/status.h" -void -toku_checkpoint_get_status(CACHETABLE ct, CHECKPOINT_STATUS statp) { +toku_instr_key *checkpoint_safe_mutex_key; +toku_instr_key *checkpoint_safe_rwlock_key; +toku_instr_key *multi_operation_lock_key; +toku_instr_key *low_priority_multi_operation_lock_key; + +toku_instr_key *rwlock_cond_key; +toku_instr_key *rwlock_wait_read_key; +toku_instr_key *rwlock_wait_write_key; + +void toku_checkpoint_get_status(CACHETABLE ct, CHECKPOINT_STATUS statp) { cp_status.init(); CP_STATUS_VAL(CP_PERIOD) = toku_get_checkpoint_period_unlocked(ct); *statp = cp_status; @@ -116,11 +124,14 @@ multi_operation_lock_init(void) { #if defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); #else - // TODO: need to figure out how to make writer-preferential rwlocks - // happen on osx +// TODO: need to figure out how to make writer-preferential rwlocks +// happen on osx #endif - toku_pthread_rwlock_init(&multi_operation_lock, &attr); - toku_pthread_rwlock_init(&low_priority_multi_operation_lock, &attr); + toku_pthread_rwlock_init( + *multi_operation_lock_key, &multi_operation_lock, &attr); + toku_pthread_rwlock_init(*low_priority_multi_operation_lock_key, + &low_priority_multi_operation_lock, + &attr); pthread_rwlockattr_destroy(&attr); locked_mo = false; } @@ -145,10 +156,15 @@ multi_operation_checkpoint_unlock(void) { toku_pthread_rwlock_wrunlock(&low_priority_multi_operation_lock); } -static void -checkpoint_safe_lock_init(void) { - toku_mutex_init(&checkpoint_safe_mutex, NULL); - checkpoint_safe_lock.init(&checkpoint_safe_mutex); +static void checkpoint_safe_lock_init(void) { + toku_mutex_init( + *checkpoint_safe_mutex_key, &checkpoint_safe_mutex, nullptr); + checkpoint_safe_lock.init(&checkpoint_safe_mutex +#ifdef TOKU_MYSQL_WITH_PFS + , + *checkpoint_safe_rwlock_key +#endif + ); locked_cs = false; } diff --git a/storage/tokudb/PerconaFT/ft/ft-ops.cc b/storage/tokudb/PerconaFT/ft/ft-ops.cc index 07e244947e4..60885ed9f33 100644 --- a/storage/tokudb/PerconaFT/ft/ft-ops.cc +++ b/storage/tokudb/PerconaFT/ft/ft-ops.cc @@ -186,9 +186,35 @@ basement nodes, bulk fetch, and partial fetch: */ static toku_mutex_t ft_open_close_lock; - -void -toku_ft_get_status(FT_STATUS s) { +static toku_instr_key *ft_open_close_lock_mutex_key; +// FIXME: the instrumentation keys below are defined here even though they +// belong to other modules, because they are registered here. If desired, they +// can be moved to their proper modules and registration done there in a +// one-time init function +// locktree +toku_instr_key *treenode_mutex_key; +toku_instr_key *manager_mutex_key; +toku_instr_key *manager_escalation_mutex_key; +toku_instr_key *manager_escalator_mutex_key; +// src +toku_instr_key *db_txn_struct_i_txn_mutex_key; +toku_instr_key *indexer_i_indexer_lock_mutex_key; +toku_instr_key *indexer_i_indexer_estimate_lock_mutex_key; +toku_instr_key *result_i_open_dbs_rwlock_key; +// locktree +toku_instr_key *lock_request_m_wait_cond_key; +toku_instr_key *manager_m_escalator_done_key; +toku_instr_key *locktree_request_info_mutex_key; +toku_instr_key *locktree_request_info_retry_mutex_key; +toku_instr_key *locktree_request_info_retry_cv_key; + +// this is a sample probe for custom instrumentation +static toku_instr_key *fti_probe_1_key; + +// This is a sample probe for custom instrumentation +toku_instr_probe *toku_instr_probe_1; + +void toku_ft_get_status(FT_STATUS s) { ft_status.init(); *s = ft_status; @@ -2643,11 +2669,14 @@ void toku_ft_set_direct_io (bool direct_io_on) { use_direct_io = direct_io_on; } -static inline int ft_open_maybe_direct(const char *filename, int oflag, int mode) { +static inline int ft_open_maybe_direct(const char *filename, + int oflag, + int mode) { if (use_direct_io) { - return toku_os_open_direct(filename, oflag, mode); + return toku_os_open_direct( + filename, oflag, mode, *tokudb_file_data_key); } else { - return toku_os_open(filename, oflag, mode); + return toku_os_open(filename, oflag, mode, *tokudb_file_data_key); } } @@ -2721,7 +2750,7 @@ bool toku_create_subdirs_if_needed(const char *path) { if (!subdir.get()) return true; - if (toku_stat(subdir.get(), &stat) == -1) { + if (toku_stat(subdir.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == get_error_errno()) subdir_exists = false; else @@ -2933,6 +2962,8 @@ ft_handle_open(FT_HANDLE ft_h, const char *fname_in_env, int is_create, int only CACHEFILE cf = NULL; FT ft = NULL; bool did_create = false; + bool was_already_open = false; + toku_ft_open_close_lock(); if (ft_h->did_set_flags) { @@ -2944,7 +2975,6 @@ ft_handle_open(FT_HANDLE ft_h, const char *fname_in_env, int is_create, int only FILENUM reserved_filenum; reserved_filenum = use_filenum; fname_in_cwd = toku_cachetable_get_fname_in_cwd(cachetable, fname_in_env); - bool was_already_open; { int fd = -1; r = ft_open_file(fname_in_cwd, &fd); @@ -4614,20 +4644,265 @@ int toku_dump_ft(FILE *f, FT_HANDLE ft_handle) { return toku_dump_ftnode(f, ft_handle, root_key, 0, 0, 0); } + +static void toku_pfs_keys_init(const char *toku_instr_group_name) { + kibbutz_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, "kibbutz_mutex"); + minicron_p_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "minicron_p_mutex"); + queue_result_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "queue_result_mutex"); + tpool_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "tpool_lock_mutex"); + workset_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "workset_lock_mutex"); + bjm_jobs_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "bjm_jobs_lock_mutex"); + log_internal_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "log_internal_lock_mutex"); + cachetable_ev_thread_lock_mutex_key = + new toku_instr_key(toku_instr_object_type::mutex, + toku_instr_group_name, + "cachetable_ev_thread_lock_mutex"); + cachetable_disk_nb_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "cachetable_disk_nb_mutex"); + safe_file_size_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "safe_file_size_lock_mutex"); + cachetable_m_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "cachetable_m_mutex_key"); + checkpoint_safe_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "checkpoint_safe_mutex"); + ft_ref_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "ft_ref_lock_mutex"); + ft_open_close_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "ft_open_close_lock_mutex"); + loader_error_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "loader_error_mutex"); + bfs_mutex_key = + new toku_instr_key(toku_instr_object_type::mutex, toku_instr_group_name, + "bfs_mutex"); + loader_bl_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "loader_bl_mutex"); + loader_fi_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "loader_fi_lock_mutex"); + loader_out_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "loader_out_mutex"); + result_output_condition_lock_mutex_key = + new toku_instr_key(toku_instr_object_type::mutex, + toku_instr_group_name, + "result_output_condition_lock_mutex"); + block_table_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "block_table_mutex"); + rollback_log_node_cache_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "rollback_log_node_cache_mutex"); + txn_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, "txn_lock_mutex"); + txn_state_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "txn_state_lock_mutex"); + txn_child_manager_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "txn_child_manager_mutex"); + txn_manager_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "txn_manager_lock_mutex"); + treenode_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, "treenode_mutex"); + locktree_request_info_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "locktree_request_info_mutex"); + locktree_request_info_retry_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "locktree_request_info_retry_mutex_key"); + manager_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, "manager_mutex"); + manager_escalation_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "manager_escalation_mutex"); + db_txn_struct_i_txn_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "db_txn_struct_i_txn_mutex"); + manager_escalator_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "manager_escalator_mutex"); + indexer_i_indexer_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "indexer_i_indexer_lock_mutex"); + indexer_i_indexer_estimate_lock_mutex_key = + new toku_instr_key(toku_instr_object_type::mutex, + toku_instr_group_name, + "indexer_i_indexer_estimate_lock_mutex"); + + tokudb_file_data_key = new toku_instr_key( + toku_instr_object_type::file, toku_instr_group_name, "tokudb_data_file"); + tokudb_file_load_key = new toku_instr_key( + toku_instr_object_type::file, toku_instr_group_name, "tokudb_load_file"); + tokudb_file_tmp_key = new toku_instr_key( + toku_instr_object_type::file, toku_instr_group_name, "tokudb_tmp_file"); + tokudb_file_log_key = new toku_instr_key( + toku_instr_object_type::file, toku_instr_group_name, "tokudb_log_file"); + + fti_probe_1_key = + new toku_instr_key(toku_instr_object_type::mutex, toku_instr_group_name, + "fti_probe_1"); + + extractor_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, + "extractor_thread"); + fractal_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, "fractal_thread"); + io_thread_key = + new toku_instr_key(toku_instr_object_type::thread, toku_instr_group_name, + "io_thread"); + eviction_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, + "eviction_thread"); + kibbutz_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, "kibbutz_thread"); + minicron_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, + "minicron_thread"); + tp_internal_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, + "tp_internal_thread"); + + result_state_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "result_state_cond"); + bjm_jobs_wait_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "bjm_jobs_wait"); + cachetable_p_refcount_wait_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "cachetable_p_refcount_wait"); + cachetable_m_flow_control_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "cachetable_m_flow_control_cond"); + cachetable_m_ev_thread_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "cachetable_m_ev_thread_cond"); + bfs_cond_key = + new toku_instr_key(toku_instr_object_type::cond, toku_instr_group_name, + "bfs_cond"); + result_output_condition_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "result_output_condition"); + manager_m_escalator_done_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "manager_m_escalator_done"); + lock_request_m_wait_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "lock_request_m_wait_cond"); + queue_result_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "queue_result_cond"); + ws_worker_wait_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "ws_worker_wait"); + rwlock_wait_read_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "rwlock_wait_read"); + rwlock_wait_write_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "rwlock_wait_write"); + rwlock_cond_key = + new toku_instr_key(toku_instr_object_type::cond, toku_instr_group_name, + "rwlock_cond"); + tp_thread_wait_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "tp_thread_wait"); + tp_pool_wait_free_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "tp_pool_wait_free"); + frwlock_m_wait_read_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "frwlock_m_wait_read"); + kibbutz_k_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "kibbutz_k_cond"); + minicron_p_condvar_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "minicron_p_condvar"); + locktree_request_info_retry_cv_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "locktree_request_info_retry_cv_key"); + + multi_operation_lock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "multi_operation_lock"); + low_priority_multi_operation_lock_key = + new toku_instr_key(toku_instr_object_type::rwlock, + toku_instr_group_name, + "low_priority_multi_operation_lock"); + cachetable_m_list_lock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "cachetable_m_list_lock"); + cachetable_m_pending_lock_expensive_key = + new toku_instr_key(toku_instr_object_type::rwlock, + toku_instr_group_name, + "cachetable_m_pending_lock_expensive"); + cachetable_m_pending_lock_cheap_key = + new toku_instr_key(toku_instr_object_type::rwlock, + toku_instr_group_name, + "cachetable_m_pending_lock_cheap"); + cachetable_m_lock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "cachetable_m_lock"); + result_i_open_dbs_rwlock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "result_i_open_dbs_rwlock"); + checkpoint_safe_rwlock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "checkpoint_safe_rwlock"); + cachetable_value_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "cachetable_value"); + safe_file_size_lock_rwlock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "safe_file_size_lock_rwlock"); + cachetable_disk_nb_rwlock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "cachetable_disk_nb_rwlock"); + + toku_instr_probe_1 = new toku_instr_probe(*fti_probe_1_key); +} + int toku_ft_layer_init(void) { int r = 0; - //Portability must be initialized first + + // Portability must be initialized first r = toku_portability_init(); - if (r) { goto exit; } + if (r) { + goto exit; + } + + toku_pfs_keys_init("fti"); + r = db_env_set_toku_product_name("tokudb"); - if (r) { goto exit; } + if (r) { + goto exit; + } partitioned_counters_init(); toku_status_init(); toku_context_status_init(); toku_checkpoint_init(); toku_ft_serialize_layer_init(); - toku_mutex_init(&ft_open_close_lock, NULL); + toku_mutex_init( + *ft_open_close_lock_mutex_key, &ft_open_close_lock, nullptr); toku_scoped_malloc_init(); exit: return r; @@ -4641,7 +4916,10 @@ void toku_ft_layer_destroy(void) { toku_status_destroy(); partitioned_counters_destroy(); toku_scoped_malloc_destroy(); - //Portability must be cleaned up last + + delete toku_instr_probe_1; + + // Portability must be cleaned up last toku_portability_destroy(); } diff --git a/storage/tokudb/PerconaFT/ft/ft.cc b/storage/tokudb/PerconaFT/ft/ft.cc index 700e532d5cf..454bf11794f 100644 --- a/storage/tokudb/PerconaFT/ft/ft.cc +++ b/storage/tokudb/PerconaFT/ft/ft.cc @@ -50,9 +50,10 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include #include -void -toku_reset_root_xid_that_created(FT ft, TXNID new_root_xid_that_created) { - // Reset the root_xid_that_created field to the given value. +toku_instr_key *ft_ref_lock_mutex_key; + +void toku_reset_root_xid_that_created(FT ft, TXNID new_root_xid_that_created) { + // Reset the root_xid_that_created field to the given value. // This redefines which xid created the dictionary. // hold lock around setting and clearing of dirty bit @@ -100,15 +101,11 @@ toku_ft_free (FT ft) { toku_free(ft); } -void -toku_ft_init_reflock(FT ft) { - toku_mutex_init(&ft->ft_ref_lock, NULL); +void toku_ft_init_reflock(FT ft) { + toku_mutex_init(*ft_ref_lock_mutex_key, &ft->ft_ref_lock, nullptr); } -void -toku_ft_destroy_reflock(FT ft) { - toku_mutex_destroy(&ft->ft_ref_lock); -} +void toku_ft_destroy_reflock(FT ft) { toku_mutex_destroy(&ft->ft_ref_lock); } void toku_ft_grab_reflock(FT ft) { diff --git a/storage/tokudb/PerconaFT/ft/loader/callbacks.cc b/storage/tokudb/PerconaFT/ft/loader/callbacks.cc index 6a520dba3a3..ac69fb7e789 100644 --- a/storage/tokudb/PerconaFT/ft/loader/callbacks.cc +++ b/storage/tokudb/PerconaFT/ft/loader/callbacks.cc @@ -45,6 +45,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "loader/loader-internal.h" #include "util/dbt.h" +toku_instr_key *loader_error_mutex_key; + static void error_callback_lock(ft_loader_error_callback loader_error) { toku_mutex_lock(&loader_error->mutex); } @@ -57,10 +59,10 @@ void ft_loader_init_error_callback(ft_loader_error_callback loader_error) { memset(loader_error, 0, sizeof *loader_error); toku_init_dbt(&loader_error->key); toku_init_dbt(&loader_error->val); - toku_mutex_init(&loader_error->mutex, NULL); + toku_mutex_init(*loader_error_mutex_key, &loader_error->mutex, nullptr); } -void ft_loader_destroy_error_callback(ft_loader_error_callback loader_error) { +void ft_loader_destroy_error_callback(ft_loader_error_callback loader_error) { toku_mutex_destroy(&loader_error->mutex); toku_destroy_dbt(&loader_error->key); toku_destroy_dbt(&loader_error->val); diff --git a/storage/tokudb/PerconaFT/ft/loader/dbufio.cc b/storage/tokudb/PerconaFT/ft/loader/dbufio.cc index 28d8d49ba9f..9ff712bcbae 100644 --- a/storage/tokudb/PerconaFT/ft/loader/dbufio.cc +++ b/storage/tokudb/PerconaFT/ft/loader/dbufio.cc @@ -48,6 +48,10 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "loader/dbufio.h" #include "loader/loader-internal.h" +toku_instr_key *bfs_mutex_key; +toku_instr_key *bfs_cond_key; +toku_instr_key *io_thread_key; + struct dbufio_file { // i/o thread owns these int fd; @@ -275,39 +279,44 @@ static void* io_thread (void *v) toku_mutex_lock(&bfs->mutex); //printf("%s:%d Locked\n", __FILE__, __LINE__); while (1) { + if (paniced(bfs)) { + toku_mutex_unlock(&bfs->mutex); // ignore any error + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); + } + // printf("n_not_done=%d\n", bfs->n_not_done); + if (bfs->n_not_done == 0) { + // all done (meaning we stored EOF (or another error) in + // error_code[0] for the file. + // printf("unlocked\n"); + toku_mutex_unlock(&bfs->mutex); + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); + } - if (paniced(bfs)) { - toku_mutex_unlock(&bfs->mutex); // ignore any error - return 0; - } - //printf("n_not_done=%d\n", bfs->n_not_done); - if (bfs->n_not_done==0) { - // all done (meaning we stored EOF (or another error) in error_code[0] for the file. - //printf("unlocked\n"); - toku_mutex_unlock(&bfs->mutex); - return 0; - } - - struct dbufio_file *dbf = bfs->head; - if (dbf==NULL) { - // No I/O needs to be done yet. - // Wait until something happens that will wake us up. - toku_cond_wait(&bfs->cond, &bfs->mutex); - if (paniced(bfs)) { - toku_mutex_unlock(&bfs->mutex); // ignore any error - return 0; - } - // Have the lock so go around. - } else { - // Some I/O needs to be done. - //printf("%s:%d Need I/O\n", __FILE__, __LINE__); - assert(dbf->second_buf_ready == false); - assert(!dbf->io_done); - bfs->head = dbf->next; - if (bfs->head==NULL) bfs->tail=NULL; - - // Unlock the mutex now that we have ownership of dbf to allow consumers to get the mutex and perform swaps. They won't swap - // this buffer because second_buf_ready is false. + struct dbufio_file *dbf = bfs->head; + if (dbf == NULL) { + // No I/O needs to be done yet. + // Wait until something happens that will wake us up. + toku_cond_wait(&bfs->cond, &bfs->mutex); + if (paniced(bfs)) { + toku_mutex_unlock(&bfs->mutex); // ignore any error + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); + } + // Have the lock so go around. + } else { + // Some I/O needs to be done. + // printf("%s:%d Need I/O\n", __FILE__, __LINE__); + assert(dbf->second_buf_ready == false); + assert(!dbf->io_done); + bfs->head = dbf->next; + if (bfs->head == NULL) + bfs->tail = NULL; + + // Unlock the mutex now that we have ownership of dbf to allow + // consumers to get the mutex and perform swaps. They won't swap + // this buffer because second_buf_ready is false. toku_mutex_unlock(&bfs->mutex); //printf("%s:%d Doing read fd=%d\n", __FILE__, __LINE__, dbf->fd); { @@ -338,14 +347,16 @@ static void* io_thread (void *v) //printf("%s:%d locking mutex again=%ld\n", __FILE__, __LINE__, readcode); { - toku_mutex_lock(&bfs->mutex); - if (paniced(bfs)) { - toku_mutex_unlock(&bfs->mutex); // ignore any error - return 0; - } - } - // Now that we have the mutex, we can decrement n_not_done (if applicable) and set second_buf_ready - if (readcode<=0) { + toku_mutex_lock(&bfs->mutex); + if (paniced(bfs)) { + toku_mutex_unlock(&bfs->mutex); // ignore any error + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); + } + } + // Now that we have the mutex, we can decrement n_not_done (if + // applicable) and set second_buf_ready + if (readcode<=0) { bfs->n_not_done--; } //printf("%s:%d n_not_done=%d\n", __FILE__, __LINE__, bfs->n_not_done); @@ -376,34 +387,36 @@ int create_dbufio_fileset (DBUFIO_FILESET *bfsp, int N, int fds[/*N*/], size_t b } } } - //printf("%s:%d here\n", __FILE__, __LINE__); - if (result==0) { - toku_mutex_init(&bfs->mutex, NULL); - mutex_inited = true; + // printf("%s:%d here\n", __FILE__, __LINE__); + if (result == 0) { + toku_mutex_init(*bfs_mutex_key, &bfs->mutex, nullptr); + mutex_inited = true; } - if (result==0) { - toku_cond_init(&bfs->cond, NULL); - cond_inited = true; + if (result == 0) { + toku_cond_init(*bfs_cond_key, &bfs->cond, nullptr); + cond_inited = true; } - if (result==0) { - bfs->N = N; - bfs->n_not_done = N; - bfs->head = bfs->tail = NULL; - for (int i=0; ifiles[i].fd = fds[i]; - bfs->files[i].offset_in_buf = 0; - bfs->files[i].offset_in_uncompressed_file = 0; - bfs->files[i].next = NULL; - bfs->files[i].second_buf_ready = false; - for (int j=0; j<2; j++) { - if (result==0) { - MALLOC_N(bufsize, bfs->files[i].buf[j]); - if (bfs->files[i].buf[j]==NULL) { result=get_error_errno(); } - } - bfs->files[i].n_in_buf[j] = 0; - bfs->files[i].error_code[j] = 0; - } - bfs->files[i].io_done = false; + if (result == 0) { + bfs->N = N; + bfs->n_not_done = N; + bfs->head = bfs->tail = NULL; + for (int i = 0; i < N; i++) { + bfs->files[i].fd = fds[i]; + bfs->files[i].offset_in_buf = 0; + bfs->files[i].offset_in_uncompressed_file = 0; + bfs->files[i].next = NULL; + bfs->files[i].second_buf_ready = false; + for (int j = 0; j < 2; j++) { + if (result == 0) { + MALLOC_N(bufsize, bfs->files[i].buf[j]); + if (bfs->files[i].buf[j] == NULL) { + result = get_error_errno(); + } + } + bfs->files[i].n_in_buf[j] = 0; + bfs->files[i].error_code[j] = 0; + } + bfs->files[i].io_done = false; ssize_t r; if (bfs->compressed) { r = dbf_read_compressed(&bfs->files[i], bfs->files[i].buf[0], bufsize); @@ -430,13 +443,21 @@ int create_dbufio_fileset (DBUFIO_FILESET *bfsp, int N, int fds[/*N*/], size_t b bfs->panic = false; bfs->panic_errno = 0; } - //printf("Creating IO thread\n"); - if (result==0) { - result = toku_pthread_create(&bfs->iothread, NULL, io_thread, (void*)bfs); + // printf("Creating IO thread\n"); + if (result == 0) { + result = toku_pthread_create(*io_thread_key, + &bfs->iothread, + nullptr, + io_thread, + static_cast(bfs)); + } + if (result == 0) { + *bfsp = bfs; + return 0; } - if (result==0) { *bfsp = bfs; return 0; } // Now undo everything. - // If we got here, there is no thread (either result was zero before the thread was created, or else the thread creation itself failed. + // If we got here, there is no thread (either result was zero before the + // thread was created, or else the thread creation itself failed. if (bfs) { if (bfs->files) { // the files were allocated, so we have to free all the bufs. diff --git a/storage/tokudb/PerconaFT/ft/loader/loader-internal.h b/storage/tokudb/PerconaFT/ft/loader/loader-internal.h index 1aa2c203831..6f7b0147b21 100644 --- a/storage/tokudb/PerconaFT/ft/loader/loader-internal.h +++ b/storage/tokudb/PerconaFT/ft/loader/loader-internal.h @@ -64,10 +64,10 @@ enum { /* These structures maintain a collection of all the open temporary files used by the loader. */ struct file_info { bool is_open; - bool is_extant; // if true, the file must be unlinked. + bool is_extant; // if true, the file must be unlinked. char *fname; - FILE *file; - uint64_t n_rows; // how many rows were written into that file + TOKU_FILE *file; + uint64_t n_rows; // how many rows were written into that file size_t buffer_size; void *buffer; }; @@ -80,11 +80,11 @@ struct file_infos { }; typedef struct fidx { int idx; } FIDX; static const FIDX FIDX_NULL __attribute__((__unused__)) = {-1}; -static int fidx_is_null (const FIDX f) __attribute__((__unused__)); -static int fidx_is_null (const FIDX f) { return f.idx==-1; } -FILE *toku_bl_fidx2file (FTLOADER bl, FIDX i); +static int fidx_is_null(const FIDX f) __attribute__((__unused__)); +static int fidx_is_null(const FIDX f) { return f.idx == -1; } +TOKU_FILE *toku_bl_fidx2file(FTLOADER bl, FIDX i); -int ft_loader_open_temp_file (FTLOADER bl, FIDX*file_idx); +int ft_loader_open_temp_file(FTLOADER bl, FIDX *file_idx); /* These data structures are used for manipulating a collection of rows in main memory. */ struct row { @@ -100,11 +100,17 @@ struct rowset { }; int init_rowset (struct rowset *rows, uint64_t memory_budget); -void destroy_rowset (struct rowset *rows); -int add_row (struct rowset *rows, DBT *key, DBT *val); - -int loader_write_row(DBT *key, DBT *val, FIDX data, FILE*, uint64_t *dataoff, struct wbuf *wb, FTLOADER bl); -int loader_read_row (FILE *f, DBT *key, DBT *val); +void destroy_rowset(struct rowset *rows); +int add_row(struct rowset *rows, DBT *key, DBT *val); + +int loader_write_row(DBT *key, + DBT *val, + FIDX data, + TOKU_FILE *, + uint64_t *dataoff, + struct wbuf *wb, + FTLOADER bl); +int loader_read_row(TOKU_FILE *f, DBT *key, DBT *val); struct merge_fileset { bool have_sorted_output; // Is there an previous key? @@ -195,12 +201,13 @@ struct ft_loader_s { bool did_reserve_memory; bool compress_intermediates; bool allow_puts; - uint64_t reserved_memory; // how much memory are we allowed to use? + uint64_t reserved_memory; // how much memory are we allowed to use? - /* To make it easier to recover from errors, we don't use FILE*, instead we use an index into the file_infos. */ + /* To make it easier to recover from errors, we don't use TOKU_FILE*, + * instead we use an index into the file_infos. */ struct file_infos file_infos; -#define PROGRESS_MAX (1<<16) +#define PROGRESS_MAX (1 << 16) int progress; // Progress runs from 0 to PROGRESS_MAX. When we call the poll function we convert to a float from 0.0 to 1.0 // We use an integer so that we can add to the progress using a fetch-and-add instruction. diff --git a/storage/tokudb/PerconaFT/ft/loader/loader.cc b/storage/tokudb/PerconaFT/ft/loader/loader.cc index 528c86a8f79..9528af95627 100644 --- a/storage/tokudb/PerconaFT/ft/loader/loader.cc +++ b/storage/tokudb/PerconaFT/ft/loader/loader.cc @@ -62,21 +62,17 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/x1764.h" -static size_t (*os_fwrite_fun)(const void *,size_t,size_t,FILE*)=NULL; -void ft_loader_set_os_fwrite (size_t (*fwrite_fun)(const void*,size_t,size_t,FILE*)) { - os_fwrite_fun=fwrite_fun; -} +toku_instr_key *loader_bl_mutex_key; +toku_instr_key *loader_fi_lock_mutex_key; +toku_instr_key *loader_out_mutex_key; -static size_t do_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream) { - if (os_fwrite_fun) { - return os_fwrite_fun(ptr, size, nmemb, stream); - } else { - return fwrite(ptr, size, nmemb, stream); - } -} +toku_instr_key *extractor_thread_key; +toku_instr_key *fractal_thread_key; +toku_instr_key *tokudb_file_tmp_key; +toku_instr_key *tokudb_file_load_key; -// 1024 is the right size_factor for production. +// 1024 is the right size_factor for production. // Different values for these sizes may be used for testing. static uint32_t size_factor = 1024; static uint32_t default_loader_nodesize = FT_DEFAULT_NODE_SIZE; @@ -98,7 +94,7 @@ toku_ft_loader_get_rowset_budget_for_testing (void) void ft_loader_lock_init(FTLOADER bl) { invariant(!bl->mutex_init); - toku_mutex_init(&bl->mutex, NULL); + toku_mutex_init(*loader_bl_mutex_key, &bl->mutex, nullptr); bl->mutex_init = true; } @@ -130,7 +126,10 @@ static int add_big_buffer(struct file_info *file) { newbuffer = true; } if (result == 0) { - int r = setvbuf(file->file, (char *) file->buffer, _IOFBF, file->buffer_size); + int r = setvbuf(file->file->file, + static_cast(file->buffer), + _IOFBF, + file->buffer_size); if (r != 0) { result = get_error_errno(); if (newbuffer) { @@ -149,9 +148,9 @@ static void cleanup_big_buffer(struct file_info *file) { } } -int ft_loader_init_file_infos (struct file_infos *fi) { +int ft_loader_init_file_infos(struct file_infos *fi) { int result = 0; - toku_mutex_init(&fi->lock, NULL); + toku_mutex_init(*loader_fi_lock_mutex_key, &fi->lock, nullptr); fi->n_files = 0; fi->n_files_limit = 1; fi->n_files_open = 0; @@ -195,11 +194,10 @@ void ft_loader_fi_destroy (struct file_infos *fi, bool is_error) fi->file_infos = NULL; } -static int open_file_add (struct file_infos *fi, - FILE *file, - char *fname, - /* out */ FIDX *idx) -{ +static int open_file_add(struct file_infos *fi, + TOKU_FILE *file, + char *fname, + /* out */ FIDX *idx) { int result = 0; toku_mutex_lock(&fi->lock); if (fi->n_files >= fi->n_files_limit) { @@ -229,11 +227,12 @@ int ft_loader_fi_reopen (struct file_infos *fi, FIDX idx, const char *mode) { int result = 0; toku_mutex_lock(&fi->lock); int i = idx.idx; - invariant(i>=0 && in_files); + invariant(i >= 0 && i < fi->n_files); invariant(!fi->file_infos[i].is_open); invariant(fi->file_infos[i].is_extant); - fi->file_infos[i].file = toku_os_fopen(fi->file_infos[i].fname, mode); - if (fi->file_infos[i].file == NULL) { + fi->file_infos[i].file = + toku_os_fopen(fi->file_infos[i].fname, mode, *tokudb_file_load_key); + if (fi->file_infos[i].file == NULL) { result = get_error_errno(); } else { fi->file_infos[i].is_open = true; @@ -306,20 +305,20 @@ int ft_loader_open_temp_file (FTLOADER bl, FIDX *file_idx) */ { int result = 0; - if (result) // debug hack + if (result) // debug hack return result; - FILE *f = NULL; + TOKU_FILE *f = NULL; int fd = -1; - char *fname = toku_strdup(bl->temp_file_template); + char *fname = toku_strdup(bl->temp_file_template); if (fname == NULL) result = get_error_errno(); else { fd = mkstemp(fname); - if (fd < 0) { + if (fd < 0) { result = get_error_errno(); } else { - f = toku_os_fdopen(fd, "r+"); - if (f == NULL) + f = toku_os_fdopen(fd, "r+", fname, *tokudb_file_tmp_key); + if (f->file == nullptr) result = get_error_errno(); else result = open_file_add(&bl->file_infos, f, fname, file_idx); @@ -338,7 +337,7 @@ int ft_loader_open_temp_file (FTLOADER bl, FIDX *file_idx) return result; } -void toku_ft_loader_internal_destroy (FTLOADER bl, bool is_error) { +void toku_ft_loader_internal_destroy(FTLOADER bl, bool is_error) { ft_loader_lock_destroy(bl); // These frees rely on the fact that if you free a NULL pointer then nothing bad happens. @@ -634,12 +633,16 @@ int toku_ft_loader_open (FTLOADER *blp, /* out */ allow_puts); if (r!=0) result = r; } - if (result==0 && allow_puts) { + if (result == 0 && allow_puts) { FTLOADER bl = *blp; - int r = toku_pthread_create(&bl->extractor_thread, NULL, extractor_thread, (void*)bl); - if (r==0) { + int r = toku_pthread_create(*extractor_thread_key, + &bl->extractor_thread, + nullptr, + extractor_thread, + static_cast(bl)); + if (r == 0) { bl->extractor_live = true; - } else { + } else { result = r; (void) toku_ft_loader_internal_destroy(bl, true); } @@ -658,17 +661,17 @@ static void ft_loader_set_panic(FTLOADER bl, int error, bool callback, int which } // One of the tests uses this. -FILE *toku_bl_fidx2file (FTLOADER bl, FIDX i) { +TOKU_FILE *toku_bl_fidx2file(FTLOADER bl, FIDX i) { toku_mutex_lock(&bl->file_infos.lock); - invariant(i.idx >=0 && i.idx < bl->file_infos.n_files); + invariant(i.idx >= 0 && i.idx < bl->file_infos.n_files); invariant(bl->file_infos.file_infos[i.idx].is_open); - FILE *result=bl->file_infos.file_infos[i.idx].file; + TOKU_FILE *result = bl->file_infos.file_infos[i.idx].file; toku_mutex_unlock(&bl->file_infos.lock); return result; } -static int bl_finish_compressed_write(FILE *stream, struct wbuf *wb) { - int r; +static int bl_finish_compressed_write(TOKU_FILE *stream, struct wbuf *wb) { + int r = 0; char *compressed_buf = NULL; const size_t data_size = wb->ndone; invariant(data_size > 0); @@ -719,31 +722,23 @@ static int bl_finish_compressed_write(FILE *stream, struct wbuf *wb) { // Mark as written wb->ndone = 0; - size_t size_to_write = total_size + 4; // Includes writing total_size + size_t size_to_write = total_size + 4; // Includes writing total_size + + r = toku_os_fwrite(compressed_buf, 1, size_to_write, stream); - { - size_t written = do_fwrite(compressed_buf, 1, size_to_write, stream); - if (written!=size_to_write) { - if (os_fwrite_fun) // if using hook to induce artificial errors (for testing) ... - r = get_maybe_error_errno(); // ... then there is no error in the stream, but there is one in errno - else - r = ferror(stream); - invariant(r!=0); - goto exit; - } - } - r = 0; -exit: if (compressed_buf) { toku_free(compressed_buf); } return r; } -static int bl_compressed_write(void *ptr, size_t nbytes, FILE *stream, struct wbuf *wb) { +static int bl_compressed_write(void *ptr, + size_t nbytes, + TOKU_FILE *stream, + struct wbuf *wb) { invariant(wb->size <= MAX_UNCOMPRESSED_BUF); size_t bytes_left = nbytes; - char *buf = (char*)ptr; + char *buf = (char *)ptr; while (bytes_left > 0) { size_t bytes_to_copy = bytes_left; @@ -766,29 +761,28 @@ static int bl_compressed_write(void *ptr, size_t nbytes, FILE *stream, struct wb return 0; } -static int bl_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream, struct wbuf *wb, FTLOADER bl) -/* Effect: this is a wrapper for fwrite that returns 0 on success, otherwise returns an error number. +static int bl_fwrite(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + struct wbuf *wb, + FTLOADER bl) +/* Effect: this is a wrapper for fwrite that returns 0 on success, otherwise + * returns an error number. * Arguments: * ptr the data to be writen. * size the amount of data to be written. * nmemb the number of units of size to be written. * stream write the data here. - * wb where to write uncompressed data (if we're compressing) or ignore if NULL - * bl passed so we can panic the ft_loader if something goes wrong (recording the error number). + * wb where to write uncompressed data (if we're compressing) or ignore if + * NULL + * bl passed so we can panic the ft_loader if something goes wrong + * (recording the error number). * Return value: 0 on success, an error number otherwise. */ { if (!bl->compress_intermediates || !wb) { - size_t r = do_fwrite(ptr, size, nmemb, stream); - if (r!=nmemb) { - int e; - if (os_fwrite_fun) // if using hook to induce artificial errors (for testing) ... - e = get_maybe_error_errno(); // ... then there is no error in the stream, but there is one in errno - else - e = ferror(stream); - invariant(e!=0); - return e; - } + return toku_os_fwrite(ptr, size, nmemb, stream); } else { size_t num_bytes = size * nmemb; int r = bl_compressed_write(ptr, num_bytes, stream, wb); @@ -799,8 +793,9 @@ static int bl_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream, struct return 0; } -static int bl_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) -/* Effect: this is a wrapper for fread that returns 0 on success, otherwise returns an error number. +static int bl_fread(void *ptr, size_t size, size_t nmemb, TOKU_FILE *stream) +/* Effect: this is a wrapper for fread that returns 0 on success, otherwise + * returns an error number. * Arguments: * ptr read data into here. * size size of data element to be read. @@ -809,24 +804,14 @@ static int bl_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) * Return value: 0 on success, an error number otherwise. */ { - size_t r = fread(ptr, size, nmemb, stream); - if (r==0) { - if (feof(stream)) return EOF; - else { - do_error: ; - int e = ferror(stream); - // r == 0 && !feof && e == 0, how does this happen? invariant(e!=0); - return e; - } - } else if (rsize; if ((r=bl_fwrite(&dlen, sizeof(dlen), 1, datafile, wb, bl))) return r; @@ -836,8 +821,7 @@ static int bl_write_dbt (DBT *dbt, FILE* datafile, uint64_t *dataoff, struct wbu return 0; } -static int bl_read_dbt (/*in*/DBT *dbt, FILE *stream) -{ +static int bl_read_dbt(/*in*/ DBT *dbt, TOKU_FILE *stream) { int len; { int r; @@ -891,13 +875,20 @@ static int bl_read_dbt_from_dbufio (/*in*/DBT *dbt, DBUFIO_FILESET bfs, int file return result; } - -int loader_write_row(DBT *key, DBT *val, FIDX data, FILE *dataf, uint64_t *dataoff, struct wbuf *wb, FTLOADER bl) -/* Effect: Given a key and a val (both DBTs), write them to a file. Increment *dataoff so that it's up to date. +int loader_write_row(DBT *key, + DBT *val, + FIDX data, + TOKU_FILE *dataf, + uint64_t *dataoff, + struct wbuf *wb, + FTLOADER bl) +/* Effect: Given a key and a val (both DBTs), write them to a file. Increment + * *dataoff so that it's up to date. * Arguments: * key, val write these. * data the file to write them to - * dataoff a pointer to a counter that keeps track of the amount of data written so far. + * dataoff a pointer to a counter that keeps track of the amount of data + * written so far. * wb a pointer (possibly NULL) to buffer uncompressed output * bl the ft_loader (passed so we can panic if needed). * Return value: 0 on success, an error number otherwise. @@ -915,8 +906,9 @@ int loader_write_row(DBT *key, DBT *val, FIDX data, FILE *dataf, uint64_t *datao return 0; } -int loader_read_row (FILE *f, DBT *key, DBT *val) -/* Effect: Read a key value pair from a file. The DBTs must have DB_DBT_REALLOC set. +int loader_read_row(TOKU_FILE *f, DBT *key, DBT *val) +/* Effect: Read a key value pair from a file. The DBTs must have DB_DBT_REALLOC + * set. * Arguments: * f where to read it from. * key, val read it into these. @@ -1086,7 +1078,7 @@ static void* extractor_thread (void *blv) { FTLOADER bl = (FTLOADER)blv; int r = 0; while (1) { - void *item; + void *item = nullptr; { int rq = toku_queue_deq(bl->primary_rowset_queue, &item, NULL, NULL); if (rq==EOF) break; @@ -1107,14 +1099,14 @@ static void* extractor_thread (void *blv) { //printf("%s:%d extractor finishing\n", __FILE__, __LINE__); if (r == 0) { r = finish_primary_rows(bl); - if (r) + if (r) ft_loader_set_panic(bl, r, false, 0, nullptr, nullptr); - } - return NULL; + toku_instr_delete_current_thread(); + return nullptr; } -static void enqueue_for_extraction (FTLOADER bl) { +static void enqueue_for_extraction(FTLOADER bl) { //printf("%s:%d enqueing %ld items\n", __FILE__, __LINE__, bl->primary_rowset.n_rows); struct rowset *XMALLOC(enqueue_me); *enqueue_me = bl->primary_rowset; @@ -1625,11 +1617,12 @@ static int write_rowset_to_file (FTLOADER bl, FIDX sfile, const struct rowset ro struct wbuf wb; wbuf_init(&wb, uncompressed_buffer, MAX_UNCOMPRESSED_BUF); - FILE *sstream = toku_bl_fidx2file(bl, sfile); - for (size_t i=0; iprogress, bl->progress+progress_allocation); + // printf(" merge_some_files progress=%d fin at %d\n", bl->progress, + // bl->progress+progress_allocation); DBT keys[n_sources]; DBT vals[n_sources]; uint64_t dataoff[n_sources]; @@ -1942,12 +1952,18 @@ static int merge_some_files (const bool to_q, FIDX dest_data, QUEUE q, int n_sou int result = 0; DBUFIO_FILESET bfs = NULL; int *MALLOC_N(n_sources, fds); - if (fds==NULL) result=get_error_errno(); - if (result==0) { - for (int i=0; ifile); // we rely on the + // fact that when + // the files are + // closed, the fd + // is also closed. + if (r == -1) { + result = get_error_errno(); break; } fds[i] = r; @@ -2177,7 +2193,7 @@ static inline void dbout_init(struct dbout *out, FT ft) { out->current_off = 0; out->n_translations = out->n_translations_limit = 0; out->translation = NULL; - toku_mutex_init(&out->mutex, NULL); + toku_mutex_init(*loader_out_mutex_key, &out->mutex, nullptr); out->ft = ft; } @@ -2417,7 +2433,7 @@ static int toku_loader_write_ft_from_q (FTLOADER bl, assert_zero(r); return result; } - FILE *pivots_stream = toku_bl_fidx2file(bl, pivots_file); + TOKU_FILE *pivots_stream = toku_bl_fidx2file(bl, pivots_file); TXNID root_xid_that_created = TXNID_NONE; if (bl->root_xids_that_created) @@ -2704,21 +2720,35 @@ int toku_loader_write_ft_from_q_in_C (FTLOADER bl, 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, fta->target_fanout); + 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; -} - -static int loader_do_i (FTLOADER bl, - int which_db, - DB *dest_db, - ft_compare_func compare, - const DESCRIPTOR descriptor, - const char *new_fname, - int progress_allocation // how much progress do I need to add into bl->progress by the end.. - ) + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); +} + +static int loader_do_i(FTLOADER bl, + int which_db, + DB *dest_db, + ft_compare_func compare, + const DESCRIPTOR descriptor, + const char *new_fname, + int progress_allocation // how much progress do I need + // to add into bl->progress by + // the end.. + ) /* Effect: Handle the file creating for one particular DB in the bulk loader. */ -/* Requires: The data is fully extracted, so we can do merges out of files and write the ft file. */ +/* Requires: The data is fully extracted, so we can do merges out of files and + write the ft file. */ { //printf("doing i use %d progress=%d fin at %d\n", progress_allocation, bl->progress, bl->progress+progress_allocation); struct merge_fileset *fs = &(bl->fs[which_db]); @@ -2729,10 +2759,14 @@ static int loader_do_i (FTLOADER bl, if (r) goto error; { - mode_t mode = S_IRUSR+S_IWUSR + S_IRGRP+S_IWGRP; - int fd = toku_os_open(new_fname, O_RDWR| O_CREAT | O_BINARY, mode); // #2621 + mode_t mode = S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP; + int fd = toku_os_open(new_fname, + O_RDWR | O_CREAT | O_BINARY, + mode, + *tokudb_file_load_key); // #2621 if (fd < 0) { - r = get_error_errno(); goto error; + r = get_error_errno(); + goto error; } uint32_t target_nodesize, target_basementnodesize, target_fanout; @@ -2752,24 +2786,27 @@ static int loader_do_i (FTLOADER bl, progress_allocation -= allocation_for_merge; // This structure must stay live until the join below. - struct fractal_thread_args fta = { - bl, - descriptor, - fd, - progress_allocation, - bl->fractal_queues[which_db], - bl->extracted_datasizes[which_db], - 0, - which_db, - target_nodesize, - target_basementnodesize, - target_compression_method, - target_fanout - }; - - r = toku_pthread_create(bl->fractal_threads+which_db, NULL, fractal_thread, (void*)&fta); + struct fractal_thread_args fta = {bl, + descriptor, + fd, + progress_allocation, + bl->fractal_queues[which_db], + bl->extracted_datasizes[which_db], + 0, + which_db, + target_nodesize, + target_basementnodesize, + target_compression_method, + target_fanout}; + + r = toku_pthread_create(*fractal_thread_key, + bl->fractal_threads + which_db, + nullptr, + fractal_thread, + static_cast(&fta)); if (r) { - int r2 __attribute__((__unused__)) = toku_queue_destroy(bl->fractal_queues[which_db]); + int r2 __attribute__((__unused__)) = + toku_queue_destroy(bl->fractal_queues[which_db]); // ignore r2, since we already have an error bl->fractal_queues[which_db] = nullptr; goto error; @@ -3106,7 +3143,7 @@ static int read_some_pivots (FIDX pivots_file, int n_to_read, FTLOADER bl, for (int i = 0; i < n_to_read; i++) pivots[i] = zero_dbt; - FILE *pivots_stream = toku_bl_fidx2file(bl, pivots_file); + TOKU_FILE *pivots_stream = toku_bl_fidx2file(bl, pivots_file); int result = 0; for (int i = 0; i < n_to_read; i++) { @@ -3158,8 +3195,9 @@ static int setup_nonleaf_block (int n_children, } if (result == 0) { - FILE *next_pivots_stream = toku_bl_fidx2file(bl, next_pivots_file); - int r = bl_write_dbt(&pivots[n_children-1], next_pivots_stream, NULL, nullptr, bl); + TOKU_FILE *next_pivots_stream = toku_bl_fidx2file(bl, next_pivots_file); + int r = bl_write_dbt( + &pivots[n_children - 1], next_pivots_stream, NULL, nullptr, bl); if (r) result = r; } @@ -3274,8 +3312,11 @@ static int write_nonleaves (FTLOADER bl, FIDX pivots_fidx, struct dbout *out, st // 2) We put the 15 pivots and 16 blocks into an non-leaf node. // 3) We put the 16th pivot into the next pivots file. { - int r = fseek(toku_bl_fidx2file(bl, pivots_fidx), 0, SEEK_SET); - if (r!=0) { return get_error_errno(); } + int r = + fseek(toku_bl_fidx2file(bl, pivots_fidx)->file, 0, SEEK_SET); + if (r != 0) { + return get_error_errno(); + } } FIDX next_pivots_file; @@ -3295,7 +3336,7 @@ static int write_nonleaves (FTLOADER bl, FIDX pivots_fidx, struct dbout *out, st while (sts->n_subtrees - n_subtrees_used >= n_per_block*2) { // grab the first N_PER_BLOCK and build a node. DBT *pivots; - int64_t blocknum_of_new_node; + int64_t blocknum_of_new_node = 0; struct subtree_info *subtree_info; int r = setup_nonleaf_block (n_per_block, sts, pivots_fidx, n_subtrees_used, diff --git a/storage/tokudb/PerconaFT/ft/loader/loader.h b/storage/tokudb/PerconaFT/ft/loader/loader.h index 9c1bdab1ee2..cea2e8dfda2 100644 --- a/storage/tokudb/PerconaFT/ft/loader/loader.h +++ b/storage/tokudb/PerconaFT/ft/loader/loader.h @@ -38,6 +38,7 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #pragma once +#include "toku_portability.h" #include "ft/txn/txn.h" #include "ft/cachetable/cachetable.h" #include "ft/comparator.h" @@ -77,8 +78,6 @@ int toku_ft_loader_abort(FTLOADER bl, bool is_error); // For test purposes only -void toku_ft_loader_set_size_factor (uint32_t factor); - -void ft_loader_set_os_fwrite (size_t (*fwrite_fun)(const void*,size_t,size_t,FILE*)); +void toku_ft_loader_set_size_factor(uint32_t factor); size_t ft_loader_leafentry_size(size_t key_size, size_t val_size, TXNID xid); diff --git a/storage/tokudb/PerconaFT/ft/logger/log-internal.h b/storage/tokudb/PerconaFT/ft/logger/log-internal.h index bee74fac346..be19e1342cd 100644 --- a/storage/tokudb/PerconaFT/ft/logger/log-internal.h +++ b/storage/tokudb/PerconaFT/ft/logger/log-internal.h @@ -70,11 +70,11 @@ struct mylock { }; static inline void ml_init(struct mylock *l) { - toku_mutex_init(&l->lock, 0); -} -static inline void ml_lock(struct mylock *l) { - toku_mutex_lock(&l->lock); + toku_mutex_init(*log_internal_lock_mutex_key, &l->lock, nullptr); } +// TODO: source location info might have be to be pulled up one caller +// to be useful +static inline void ml_lock(struct mylock *l) { toku_mutex_lock(&l->lock); } static inline void ml_unlock(struct mylock *l) { toku_mutex_unlock(&l->lock); } diff --git a/storage/tokudb/PerconaFT/ft/logger/logcursor.cc b/storage/tokudb/PerconaFT/ft/logger/logcursor.cc index f13419ae43e..494d3b1d531 100644 --- a/storage/tokudb/PerconaFT/ft/logger/logcursor.cc +++ b/storage/tokudb/PerconaFT/ft/logger/logcursor.cc @@ -85,10 +85,10 @@ static int lc_close_cur_logfile(TOKULOGCURSOR lc) { } static toku_off_t lc_file_len(const char *name) { - toku_struct_stat buf; - int r = toku_stat(name, &buf); - assert(r == 0); - return buf.st_size; + toku_struct_stat buf; + int r = toku_stat(name, &buf, *tokudb_file_data_key); + assert(r == 0); + return buf.st_size; } // Cat the file and throw away the contents. This brings the file into the file system cache diff --git a/storage/tokudb/PerconaFT/ft/logger/logger.cc b/storage/tokudb/PerconaFT/ft/logger/logger.cc index eacec9cb83f..3f13fe10feb 100644 --- a/storage/tokudb/PerconaFT/ft/logger/logger.cc +++ b/storage/tokudb/PerconaFT/ft/logger/logger.cc @@ -49,11 +49,17 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/status.h" -static const int log_format_version=TOKU_LOG_VERSION; +static const int log_format_version = TOKU_LOG_VERSION; -static int open_logfile (TOKULOGGER logger); -static void logger_write_buffer (TOKULOGGER logger, LSN *fsynced_lsn); -static void delete_logfile(TOKULOGGER logger, long long index, uint32_t version); +toku_instr_key *result_output_condition_lock_mutex_key; +toku_instr_key *result_output_condition_key; +toku_instr_key *tokudb_file_log_key; + +static int open_logfile(TOKULOGGER logger); +static void logger_write_buffer(TOKULOGGER logger, LSN *fsynced_lsn); +static void delete_logfile(TOKULOGGER logger, + long long index, + uint32_t version); static void grab_output(TOKULOGGER logger, LSN *fsynced_lsn); static void release_output(TOKULOGGER logger, LSN fsynced_lsn); @@ -131,10 +137,13 @@ int toku_logger_create (TOKULOGGER *resultp) { // n_in_file is uninitialized result->write_block_size = FT_DEFAULT_NODE_SIZE; // default logging size is the same as the default ft block size toku_logfilemgr_create(&result->logfilemgr); - *resultp=result; + *resultp = result; ml_init(&result->input_lock); - toku_mutex_init(&result->output_condition_lock, NULL); - toku_cond_init(&result->output_condition, NULL); + toku_mutex_init(*result_output_condition_lock_mutex_key, + &result->output_condition_lock, + nullptr); + toku_cond_init( + *result_output_condition_key, &result->output_condition, nullptr); result->rollback_cachefile = NULL; result->output_is_available = true; toku_txn_manager_init(&result->txn_manager); @@ -300,10 +309,10 @@ int toku_logger_close(TOKULOGGER *loggerp) { grab_output(logger, &fsynced_lsn); logger_write_buffer(logger, &fsynced_lsn); if (logger->fd!=-1) { - if ( logger->write_log_files ) { + if (logger->write_log_files) { toku_file_fsync_without_accounting(logger->fd); } - r = close(logger->fd); + r = toku_os_close(logger->fd); assert(r == 0); } r = close_logdir(logger); @@ -345,9 +354,13 @@ static int close_and_open_logfile (TOKULOGGER logger, LSN *fsynced_lsn) if (logger->write_log_files) { toku_file_fsync_without_accounting(logger->fd); *fsynced_lsn = logger->written_lsn; - toku_logfilemgr_update_last_lsn(logger->logfilemgr, logger->written_lsn); // fixes t:2294 + toku_logfilemgr_update_last_lsn(logger->logfilemgr, + logger->written_lsn); // fixes t:2294 } - r = close(logger->fd); if (r!=0) return get_error_errno(); + r = toku_os_close(logger->fd); + + if (r != 0) + return get_error_errno(); return open_logfile(logger); } @@ -677,18 +690,28 @@ static int open_logfile (TOKULOGGER logger) { int fnamelen = strlen(logger->directory)+50; char fname[fnamelen]; - snprintf(fname, fnamelen, "%s/log%012lld.tokulog%d", logger->directory, logger->next_log_file_number, TOKU_LOG_VERSION); + snprintf(fname, + fnamelen, + "%s/log%012lld.tokulog%d", + logger->directory, + logger->next_log_file_number, + TOKU_LOG_VERSION); long long index = logger->next_log_file_number; if (logger->write_log_files) { - logger->fd = open(fname, O_CREAT+O_WRONLY+O_TRUNC+O_EXCL+O_BINARY, S_IRUSR+S_IWUSR); - if (logger->fd==-1) { + logger->fd = + toku_os_open(fname, + O_CREAT + O_WRONLY + O_TRUNC + O_EXCL + O_BINARY, + S_IRUSR + S_IWUSR, + *tokudb_file_log_key); + if (logger->fd == -1) { return get_error_errno(); } fsync_logdir(logger); logger->next_log_file_number++; } else { - logger->fd = open(DEV_NULL_FILE, O_WRONLY+O_BINARY); - if (logger->fd==-1) { + logger->fd = toku_os_open( + DEV_NULL_FILE, O_WRONLY + O_BINARY, S_IWUSR, *tokudb_file_log_key); + if (logger->fd == -1) { return get_error_errno(); } } @@ -834,10 +857,11 @@ int toku_logger_restart(TOKULOGGER logger, LSN lastlsn) logger_write_buffer(logger, &fsynced_lsn); // close the log file - if ( logger->write_log_files) { // fsyncs don't work to /dev/null + if (logger->write_log_files) { // fsyncs don't work to /dev/null toku_file_fsync_without_accounting(logger->fd); } - r = close(logger->fd); assert(r == 0); + r = toku_os_close(logger->fd); + assert(r == 0); logger->fd = -1; // reset the LSN's to the lastlsn when the logger was opened @@ -1237,11 +1261,13 @@ void toku_txnid2txn(TOKULOGGER logger, TXNID_PAIR txnid, TOKUTXN *result) { } // Find the earliest LSN in a log. No locks are needed. -static int peek_at_log (TOKULOGGER logger, char* filename, LSN *first_lsn) { - int fd = open(filename, O_RDONLY+O_BINARY); - if (fd<0) { +static int peek_at_log(TOKULOGGER logger, char *filename, LSN *first_lsn) { + int fd = toku_os_open( + filename, O_RDONLY + O_BINARY, S_IRUSR, *tokudb_file_log_key); + if (fd < 0) { int er = get_error_errno(); - if (logger->write_log_files) printf("couldn't open: %s\n", strerror(er)); + if (logger->write_log_files) + printf("couldn't open: %s\n", strerror(er)); return er; } enum { SKIP = 12+1+4 }; // read the 12 byte header, the first message, and the first len @@ -1258,10 +1284,13 @@ static int peek_at_log (TOKULOGGER logger, char* filename, LSN *first_lsn) { lsn = rbuf_ulonglong(&rb); } - r=close(fd); - if (r!=0) { return 0; } + r = toku_os_close(fd); + + if (r != 0) { + return 0; + } - first_lsn->lsn=lsn; + first_lsn->lsn = lsn; return 0; } diff --git a/storage/tokudb/PerconaFT/ft/logger/recover.cc b/storage/tokudb/PerconaFT/ft/logger/recover.cc index 9eaa56bdc53..9a9a1214ecb 100644 --- a/storage/tokudb/PerconaFT/ft/logger/recover.cc +++ b/storage/tokudb/PerconaFT/ft/logger/recover.cc @@ -954,14 +954,14 @@ static int toku_recover_frename(struct logtype_frename *l, RECOVER_ENV renv) { std::unique_ptr new_iname_full( toku_construct_full_name(2, data_dir, l->new_iname.data), &toku_free); - if (toku_stat(old_iname_full.get(), &stat) == -1) { + if (toku_stat(old_iname_full.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == errno) old_exist = false; else return 1; } - if (toku_stat(new_iname_full.get(), &stat) == -1) { + if (toku_stat(new_iname_full.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == errno) new_exist = false; else @@ -980,7 +980,7 @@ static int toku_recover_frename(struct logtype_frename *l, RECOVER_ENV renv) { // 'stalled cachefiles' container the new file is removed // and the old file is renamed. if (old_exist && new_exist && - (toku_os_unlink(new_iname_full.get()) == -1 || + (toku_os_delete(new_iname_full.get()) == -1 || toku_os_rename(old_iname_full.get(), new_iname_full.get()) == -1 || toku_fsync_directory(old_iname_full.get()) == -1 || toku_fsync_directory(new_iname_full.get()) == -1)) @@ -1473,9 +1473,13 @@ static int do_recovery(RECOVER_ENV renv, const char *env_dir, const char *log_di { toku_struct_stat buf; - if (toku_stat(env_dir, &buf)!=0) { + if (toku_stat(env_dir, &buf, toku_uninstrumented)) { rr = get_error_errno(); - fprintf(stderr, "%.24s PerconaFT recovery error: directory does not exist: %s\n", ctime(&tnow), env_dir); + fprintf(stderr, + "%.24s PerconaFT recovery error: directory does not exist: " + "%s\n", + ctime(&tnow), + env_dir); goto errorexit; } else if (!S_ISDIR(buf.st_mode)) { fprintf(stderr, "%.24s PerconaFT recovery error: this file is supposed to be a directory, but is not: %s\n", ctime(&tnow), env_dir); diff --git a/storage/tokudb/PerconaFT/ft/serialize/block_allocator.cc b/storage/tokudb/PerconaFT/ft/serialize/block_allocator.cc index 19811373d16..29f6daa293a 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/block_allocator.cc +++ b/storage/tokudb/PerconaFT/ft/serialize/block_allocator.cc @@ -40,6 +40,7 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include +#include "toku_portability.h" #include "portability/memory.h" #include "portability/toku_assert.h" #include "portability/toku_stdint.h" diff --git a/storage/tokudb/PerconaFT/ft/serialize/block_table.cc b/storage/tokudb/PerconaFT/ft/serialize/block_table.cc index d2532134d96..56d51f56915 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/block_table.cc +++ b/storage/tokudb/PerconaFT/ft/serialize/block_table.cc @@ -54,6 +54,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/nb_mutex.h" #include "util/scoped_malloc.h" + +toku_instr_key *block_table_mutex_key; +toku_instr_key *safe_file_size_lock_mutex_key; +toku_instr_key *safe_file_size_lock_rwlock_key; + // indicates the end of a freelist static const BLOCKNUM freelist_null = {-1}; @@ -99,8 +104,10 @@ void block_table::_create_internal() { memset(&_checkpointed, 0, sizeof(struct translation)); memset(&_mutex, 0, sizeof(_mutex)); _bt_block_allocator = new BlockAllocator(); - toku_mutex_init(&_mutex, nullptr); - nb_mutex_init(&_safe_file_size_lock); + toku_mutex_init(*block_table_mutex_key, &_mutex, nullptr); + nb_mutex_init(*safe_file_size_lock_mutex_key, + *safe_file_size_lock_rwlock_key, + &_safe_file_size_lock); } // Fill in the checkpointed translation from buffer, and copy checkpointed to @@ -128,7 +135,7 @@ int block_table::create_from_buffer( _copy_translation(&_current, &_checkpointed, TRANSLATION_CURRENT); // Determine the file size - int64_t file_size; + int64_t file_size = 0; r = toku_os_get_file_size(fd, &file_size); lazy_assert_zero(r); invariant(file_size >= 0); diff --git a/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc b/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc index fcab9fc675e..b24d72a5dff 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc +++ b/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc @@ -417,8 +417,10 @@ static size_t serialize_ft_min_size(uint32_t version) { switch (version) { case FT_LAYOUT_VERSION_29: size += sizeof(uint64_t); // logrows in ft + // fallthrough case FT_LAYOUT_VERSION_28: size += sizeof(uint32_t); // fanout in ft + // fallthrough case FT_LAYOUT_VERSION_27: case FT_LAYOUT_VERSION_26: case FT_LAYOUT_VERSION_25: @@ -427,10 +429,12 @@ static size_t serialize_ft_min_size(uint32_t version) { case FT_LAYOUT_VERSION_22: case FT_LAYOUT_VERSION_21: size += sizeof(MSN); // max_msn_in_ft + // fallthrough case FT_LAYOUT_VERSION_20: case FT_LAYOUT_VERSION_19: size += 1; // compression method size += sizeof(MSN); // highest_unused_msn_for_upgrade + // fallthrough case FT_LAYOUT_VERSION_18: size += sizeof(uint64_t); // time_of_last_optimize_begin size += sizeof(uint64_t); // time_of_last_optimize_end @@ -438,9 +442,11 @@ static size_t serialize_ft_min_size(uint32_t version) { size += sizeof(MSN); // msn_at_start_of_last_completed_optimize size -= 8; // removed num_blocks_to_upgrade_14 size -= 8; // removed num_blocks_to_upgrade_13 + // fallthrough case FT_LAYOUT_VERSION_17: size += 16; invariant(sizeof(STAT64INFO_S) == 16); + // fallthrough case FT_LAYOUT_VERSION_16: case FT_LAYOUT_VERSION_15: size += 4; // basement node size @@ -448,8 +454,10 @@ static size_t serialize_ft_min_size(uint32_t version) { // num_blocks_to_upgrade, now one int each for upgrade // from 13, 14 size += 8; // time of last verification + // fallthrough case FT_LAYOUT_VERSION_14: size += 8; // TXNID that created + // fallthrough case FT_LAYOUT_VERSION_13: size += (4 // build_id + @@ -459,7 +467,7 @@ static size_t serialize_ft_min_size(uint32_t version) { + 8 // time_of_last_modification ); - // fall through + // fallthrough case FT_LAYOUT_VERSION_12: size += (+8 // "tokudata" + diff --git a/storage/tokudb/PerconaFT/ft/serialize/sub_block.cc b/storage/tokudb/PerconaFT/ft/serialize/sub_block.cc index c967d4b4c1c..6dc1f82844a 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/sub_block.cc +++ b/storage/tokudb/PerconaFT/ft/serialize/sub_block.cc @@ -51,6 +51,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/threadpool.h" #include "util/x1764.h" +toku_instr_key *workset_lock_mutex_key; +toku_instr_key *ws_worker_wait_key; + SUB_BLOCK sub_block_creat(void) { SUB_BLOCK XMALLOC(sb); sub_block_init(sb); diff --git a/storage/tokudb/PerconaFT/ft/serialize/workset.h b/storage/tokudb/PerconaFT/ft/serialize/workset.h index 073741fccb1..295eb73cec9 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/workset.h +++ b/storage/tokudb/PerconaFT/ft/serialize/workset.h @@ -41,6 +41,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include #include +extern toku_instr_key *ws_worker_wait_key; + // The work struct is the base class for work to be done by some threads struct work { struct toku_list next; @@ -54,16 +56,14 @@ struct workset { toku_cond_t worker_wait; // a condition variable used to wait for all of the worker to release their reference on the workset }; -static inline void -workset_init(struct workset *ws) { - toku_mutex_init(&ws->lock, NULL); +static inline void workset_init(struct workset *ws) { + toku_mutex_init(*workset_lock_mutex_key, &ws->lock, nullptr); toku_list_init(&ws->worklist); - ws->refs = 1; // the calling thread gets a reference - toku_cond_init(&ws->worker_wait, NULL); + ws->refs = 1; // the calling thread gets a reference + toku_cond_init(*ws_worker_wait_key, &ws->worker_wait, nullptr); } -static inline void -workset_destroy(struct workset *ws) { +static inline void workset_destroy(struct workset *ws) { invariant(toku_list_empty(&ws->worklist)); toku_cond_destroy(&ws->worker_wait); toku_mutex_destroy(&ws->lock); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-4357.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-4357.cc index 8bbda295462..0af5c8185a9 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-4357.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-4357.cc @@ -71,21 +71,26 @@ cachetable_test (void) { void* v1; long s1; - r = toku_cachetable_get_and_pin( - f1, - make_blocknum(1), - toku_cachetable_hash(f1, make_blocknum(1)), - &v1, - &s1, - def_write_callback(NULL), def_fetch, def_pf_req_callback, def_pf_callback, - true, - NULL - ); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + toku_cachetable_hash(f1, make_blocknum(1)), + &v1, + &s1, + def_write_callback(NULL), + def_fetch, + def_pf_req_callback, + def_pf_callback, + true, + NULL); toku_pthread_t pin_nonblocking_tid; - r = toku_pthread_create(&pin_nonblocking_tid, NULL, pin_nonblocking, NULL); - assert_zero(r); + r = toku_pthread_create(toku_uninstrumented, + &pin_nonblocking_tid, + nullptr, + pin_nonblocking, + nullptr); + assert_zero(r); // sleep 3 seconds - usleep(3*1024*1024); + usleep(3 * 1024 * 1024); r = toku_test_cachetable_unpin_and_remove(f1, make_blocknum(1), NULL, NULL); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-4365.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-4365.cc index 9c54c086f5b..7bee0b80770 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-4365.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-4365.cc @@ -71,15 +71,16 @@ static void *put_same_key(void *arg) { return arg; } - toku_pthread_t put_tid; -static void test_remove_key(CACHEKEY* UU(cachekey), bool UU(for_checkpoint), void* UU(extra)) { - int r = toku_pthread_create(&put_tid, NULL, put_same_key, NULL); - assert_zero(r); +static void test_remove_key(CACHEKEY *UU(cachekey), + bool UU(for_checkpoint), + void *UU(extra)) { + int r = toku_pthread_create( + toku_uninstrumented, &put_tid, nullptr, put_same_key, nullptr); + assert_zero(r); } - static void cachetable_test (void) { const int test_limit = 12; @@ -92,21 +93,26 @@ cachetable_test (void) { void* v1; long s1; - r = toku_cachetable_get_and_pin( - f1, - make_blocknum(1), - toku_cachetable_hash(f1, make_blocknum(1)), - &v1, - &s1, - def_write_callback(NULL), def_fetch, def_pf_req_callback, def_pf_callback, - true, - NULL - ); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + toku_cachetable_hash(f1, make_blocknum(1)), + &v1, + &s1, + def_write_callback(nullptr), + def_fetch, + def_pf_req_callback, + def_pf_callback, + true, + nullptr); toku_pthread_t pin_nonblocking_tid; - r = toku_pthread_create(&pin_nonblocking_tid, NULL, pin_nonblocking, NULL); - assert_zero(r); + r = toku_pthread_create(toku_uninstrumented, + &pin_nonblocking_tid, + nullptr, + pin_nonblocking, + nullptr); + assert_zero(r); // sleep 3 seconds - usleep(3*1024*1024); + usleep(3 * 1024 * 1024); r = toku_test_cachetable_unpin_and_remove(f1, make_blocknum(1), test_remove_key, NULL); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-5097.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-5097.cc index c1b6e0a94f2..5ab0df88e08 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-5097.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-5097.cc @@ -153,13 +153,16 @@ cachetable_test (void) { assert(r == 0); } - // at this point, we have a dirty PAIR in the cachetable associated with cachefile f1 - // launch a thread that will put another PAIR in the cachetable, and get partial eviction started + // at this point, we have a dirty PAIR in the cachetable associated with + // cachefile f1 + // launch a thread that will put another PAIR in the cachetable, and get + // partial eviction started toku_pthread_t tid; - r = toku_pthread_create(&tid, NULL, f2_pin, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, f2_pin, nullptr); assert_zero(r); - usleep(2*1024*1024); + usleep(2 * 1024 * 1024); check_flush = true; toku_cachefile_close(&f1, false, ZERO_LSN); if (enable_partial_eviction) diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc index b462d76eeee..0b5110ddd99 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc @@ -114,14 +114,14 @@ unpin_two (void* UU(v)) { ); assert_zero(r); - // at this point, we have p1 pinned, want to start a thread to do an unpin_and_remove - // on p1 - r = toku_pthread_create( - &unpin_and_remove_tid, - NULL, - unpin_and_remove_one, - NULL - ); + // at this point, we have p1 pinned, want to start a thread to do an + // unpin_and_remove + // on p1 + r = toku_pthread_create(toku_uninstrumented, + &unpin_and_remove_tid, + nullptr, + unpin_and_remove_one, + nullptr); assert_zero(r); // sleep to give a chance for the unpin_and_remove to get going usleep(512*1024); @@ -173,9 +173,9 @@ cachetable_test (void) { r = toku_cachetable_get_and_pin(f1, make_blocknum(2), 2, &v1, &s1, wc, fetch_two, def_pf_req_callback, def_pf_callback, true, NULL); assert_zero(r); - toku_pthread_t tid1; - r = toku_pthread_create(&tid1, NULL, repin_one, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid1, nullptr, repin_one, nullptr); assert_zero(r); void *ret; diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-5978.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-5978.cc index ee68ab3ef0b..a4ff6c33e6a 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-5978.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-5978.cc @@ -199,9 +199,11 @@ cachetable_test (void) { toku_pthread_t tid1; toku_pthread_t tid2; - r = toku_pthread_create(&tid1, NULL, repin_one, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid1, nullptr, repin_one, nullptr); assert_zero(r); - r = toku_pthread_create(&tid2, NULL, repin_two, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid2, nullptr, repin_two, nullptr); assert_zero(r); // unpin 1 and 2 so tid1 and tid2 can make progress diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-checkpoint-pending.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-checkpoint-pending.cc index 3dd3a15e2de..5e87fed740d 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-checkpoint-pending.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-checkpoint-pending.cc @@ -158,14 +158,24 @@ static void checkpoint_pending(void) { // the checkpoint should cause n writes, but since n <= the cachetable size, // all items should be kept in the cachetable - n_flush = n_write_me = n_keep_me = n_fetch = 0; expect_value = 42; - //printf("E42\n"); + n_flush = n_write_me = n_keep_me = n_fetch = 0; + expect_value = 42; + // printf("E42\n"); toku_pthread_t checkpoint_thread, update_thread; - r = toku_pthread_create(&checkpoint_thread, NULL, do_checkpoint, NULL); assert(r==0); - r = toku_pthread_create(&update_thread, NULL, do_update, NULL); assert(r==0); - r = toku_pthread_join(checkpoint_thread, 0); assert(r==0); - r = toku_pthread_join(update_thread, 0); assert(r==0); - + r = toku_pthread_create(toku_uninstrumented, + &checkpoint_thread, + nullptr, + do_checkpoint, + nullptr); + assert(r == 0); + r = toku_pthread_create( + toku_uninstrumented, &update_thread, nullptr, do_update, nullptr); + assert(r == 0); + r = toku_pthread_join(checkpoint_thread, 0); + assert(r == 0); + r = toku_pthread_join(update_thread, 0); + assert(r == 0); + assert(n_flush == N && n_write_me == N && n_keep_me == N); // after the checkpoint, all of the items should be 43 diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-cleaner-thread-attrs-accumulate.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-cleaner-thread-attrs-accumulate.cc index c1e7b373e83..dd6c674af24 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-cleaner-thread-attrs-accumulate.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-cleaner-thread-attrs-accumulate.cc @@ -91,7 +91,7 @@ run_test (void) { const int test_limit = 1000; int r; CACHETABLE ct; - toku_mutex_init(&attr_mutex, NULL); + toku_mutex_init(toku_uninstrumented, &attr_mutex, nullptr); toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr); const char *fname1 = TOKU_TEST_FILENAME; diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-clone-checkpoint.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-clone-checkpoint.cc index 50bd20f492e..99d595b1ff1 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-clone-checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-clone-checkpoint.cc @@ -112,14 +112,17 @@ cachetable_test (void) { CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct); toku_cachetable_begin_checkpoint(cp, NULL); - clone_flush_started = false; clone_flush_completed = false; toku_pthread_t checkpoint_tid; - r = toku_pthread_create(&checkpoint_tid, NULL, run_end_checkpoint, NULL); - assert_zero(r); + r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + run_end_checkpoint, + nullptr); + assert_zero(r); - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-pin-checkpoint.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-pin-checkpoint.cc index 8a270af0566..65b02aebaec 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-pin-checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-pin-checkpoint.cc @@ -386,19 +386,28 @@ cachetable_test (void) { run_test = true; for (int i = 0; i < NUM_MOVER_THREADS; i++) { - r = toku_pthread_create(&read_random_tid[i], NULL, read_random_numbers, NULL); + r = toku_pthread_create(toku_uninstrumented, + &read_random_tid[i], + nullptr, + read_random_numbers, + nullptr); assert_zero(r); } for (int i = 0; i < NUM_MOVER_THREADS; i++) { - r = toku_pthread_create(&move_tid[i], NULL, move_numbers, NULL); + r = toku_pthread_create(toku_uninstrumented, + &move_tid[i], + nullptr, + move_numbers, + nullptr); assert_zero(r); } - r = toku_pthread_create(&checkpoint_tid, NULL, checkpoints, NULL); - assert_zero(r); - r = toku_pthread_create(&time_tid, NULL, test_time, NULL); + r = toku_pthread_create( + toku_uninstrumented, &checkpoint_tid, nullptr, checkpoints, nullptr); + assert_zero(r); + r = toku_pthread_create( + toku_uninstrumented, &time_tid, nullptr, test_time, nullptr); assert_zero(r); - void *ret; r = toku_pthread_join(time_tid, &ret); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-put-checkpoint.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-put-checkpoint.cc index afc95471116..4cf1678449b 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-put-checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-put-checkpoint.cc @@ -518,19 +518,28 @@ cachetable_test (void) { run_test = true; for (int i = 0; i < NUM_MOVER_THREADS; i++) { - r = toku_pthread_create(&move_tid[i], NULL, move_numbers, NULL); + r = toku_pthread_create(toku_uninstrumented, + &move_tid[i], + nullptr, + move_numbers, + nullptr); assert_zero(r); } for (int i = 0; i < NUM_MOVER_THREADS; i++) { - r = toku_pthread_create(&merge_and_split_tid[i], NULL, merge_and_split, NULL); + r = toku_pthread_create(toku_uninstrumented, + &merge_and_split_tid[i], + nullptr, + merge_and_split, + nullptr); assert_zero(r); } - r = toku_pthread_create(&checkpoint_tid, NULL, checkpoints, NULL); - assert_zero(r); - r = toku_pthread_create(&time_tid, NULL, test_time, NULL); + r = toku_pthread_create( + toku_uninstrumented, &checkpoint_tid, nullptr, checkpoints, nullptr); + assert_zero(r); + r = toku_pthread_create( + toku_uninstrumented, &time_tid, nullptr, test_time, nullptr); assert_zero(r); - void *ret; r = toku_pthread_join(time_tid, &ret); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-rwlock-test.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-rwlock-test.cc index 9a62f99e1fa..6d8bc28026c 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-rwlock-test.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-rwlock-test.cc @@ -40,24 +40,22 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // test create and destroy -static void -test_create_destroy (void) { - struct rwlock the_rwlock, *rwlock = &the_rwlock; +static void test_create_destroy(void) { + struct st_rwlock the_rwlock, *rwlock = &the_rwlock; - rwlock_init(rwlock); + rwlock_init(toku_uninstrumented, rwlock); rwlock_destroy(rwlock); } // test read lock and unlock with no writers -static void -test_simple_read_lock (int n) { - struct rwlock the_rwlock, *rwlock = &the_rwlock; +static void test_simple_read_lock(int n) { + struct st_rwlock the_rwlock, *rwlock = &the_rwlock; - rwlock_init(rwlock); + rwlock_init(toku_uninstrumented, rwlock); assert(rwlock_readers(rwlock) == 0); int i; - for (i=1; i<=n; i++) { + for (i = 1; i <= n; i++) { rwlock_read_lock(rwlock, 0); assert(rwlock_readers(rwlock) == i); assert(rwlock_users(rwlock) == i); @@ -72,11 +70,10 @@ test_simple_read_lock (int n) { // test write lock and unlock with no readers -static void -test_simple_write_lock (void) { - struct rwlock the_rwlock, *rwlock = &the_rwlock; +static void test_simple_write_lock(void) { + struct st_rwlock the_rwlock, *rwlock = &the_rwlock; - rwlock_init(rwlock); + rwlock_init(toku_uninstrumented, rwlock); assert(rwlock_users(rwlock) == 0); rwlock_write_lock(rwlock, 0); assert(rwlock_writers(rwlock) == 1); @@ -88,19 +85,17 @@ test_simple_write_lock (void) { struct rw_event { int e; - struct rwlock the_rwlock; + struct st_rwlock the_rwlock; toku_mutex_t mutex; }; -static void -rw_event_init (struct rw_event *rwe) { +static void rw_event_init(struct rw_event *rwe) { rwe->e = 0; - rwlock_init(&rwe->the_rwlock); - toku_mutex_init(&rwe->mutex, 0); + rwlock_init(toku_uninstrumented, &rwe->the_rwlock); + toku_mutex_init(toku_uninstrumented, &rwe->mutex, nullptr); } -static void -rw_event_destroy (struct rw_event *rwe) { +static void rw_event_destroy(struct rw_event *rwe) { rwlock_destroy(&rwe->the_rwlock); toku_mutex_destroy(&rwe->mutex); } @@ -138,10 +133,12 @@ test_writer_priority (void) { toku_mutex_unlock(&rwe->mutex); toku_pthread_t tid; - r = toku_pthread_create(&tid, 0, test_writer_priority_thread, rwe); + r = toku_pthread_create( + toku_uninstrumented, &tid, 0, test_writer_priority_thread, rwe); sleep(1); toku_mutex_lock(&rwe->mutex); - rwe->e++; assert(rwe->e == 2); + rwe->e++; + assert(rwe->e == 2); toku_mutex_unlock(&rwe->mutex); sleep(1); @@ -196,10 +193,12 @@ test_single_writer (void) { toku_mutex_unlock(&rwe->mutex); toku_pthread_t tid; - r = toku_pthread_create(&tid, 0, test_single_writer_thread, rwe); + r = toku_pthread_create( + toku_uninstrumented, &tid, 0, test_single_writer_thread, rwe); sleep(1); toku_mutex_lock(&rwe->mutex); - rwe->e++; assert(rwe->e == 2); + rwe->e++; + assert(rwe->e == 2); assert(rwlock_writers(&rwe->the_rwlock) == 1); assert(rwlock_users(&rwe->the_rwlock) == 2); rwlock_write_unlock(&rwe->the_rwlock); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin-nonblocking.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin-nonblocking.cc index 8fd8828737a..ebe05e50883 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin-nonblocking.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin-nonblocking.cc @@ -111,9 +111,20 @@ run_test (void) { toku_pthread_t fetch_tid; fetch_called = false; - r = toku_pthread_create(&fetch_tid, NULL, run_expensive_fetch, NULL); + r = toku_pthread_create( + toku_uninstrumented, &fetch_tid, nullptr, run_expensive_fetch, nullptr); sleep(1); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + 1, + &v1, + &s1, + wc, + sleep_fetch, + def_pf_req_callback, + def_pf_callback, + false, + NULL); assert_zero(r); assert(fetch_called); r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); @@ -133,9 +144,20 @@ run_test (void) { toku_pthread_t pf_tid; pf_called = false; - r = toku_pthread_create(&pf_tid, NULL, run_expensive_pf, NULL); + r = toku_pthread_create( + toku_uninstrumented, &pf_tid, nullptr, run_expensive_pf, nullptr); sleep(1); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + 1, + &v1, + &s1, + wc, + sleep_fetch, + def_pf_req_callback, + def_pf_callback, + false, + NULL); assert_zero(r); assert(pf_called); r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin.cc index 63ca871a459..dd5d59df002 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin.cc @@ -117,9 +117,20 @@ run_test (void) { toku_pthread_t fetch_tid; fetch_called = false; - r = toku_pthread_create(&fetch_tid, NULL, run_expensive_fetch, NULL); + r = toku_pthread_create( + toku_uninstrumented, &fetch_tid, nullptr, run_expensive_fetch, nullptr); sleep(1); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + 1, + &v1, + &s1, + wc, + sleep_fetch, + def_pf_req_callback, + def_pf_callback, + false, + NULL); assert_zero(r); assert(fetch_called); r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); @@ -141,9 +152,20 @@ run_test (void) { toku_pthread_t pf_tid; pf_called = false; - r = toku_pthread_create(&pf_tid, NULL, run_expensive_pf, NULL); + r = toku_pthread_create( + toku_uninstrumented, &pf_tid, nullptr, run_expensive_pf, nullptr); sleep(1); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + 1, + &v1, + &s1, + wc, + sleep_fetch, + def_pf_req_callback, + def_pf_callback, + false, + NULL); assert_zero(r); assert(pf_called); r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-test.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-test.cc index e4bb5fb0aea..64f688c470d 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-test.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-test.cc @@ -42,15 +42,13 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // global data, especially between the test thread and the cachetable // writeback threads -toku_mutex_t test_mutex; +toku_mutex_t test_mutex; static inline void test_mutex_init(void) { - toku_mutex_init(&test_mutex, 0); + toku_mutex_init(toku_uninstrumented, &test_mutex, nullptr); } -static inline void test_mutex_destroy(void) { - toku_mutex_destroy(&test_mutex); -} +static inline void test_mutex_destroy(void) { toku_mutex_destroy(&test_mutex); } static inline void test_mutex_lock(void) { toku_mutex_lock(&test_mutex); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-unpin-remove-and-checkpoint.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-unpin-remove-and-checkpoint.cc index 11baa36e51b..0e44bf10349 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-unpin-remove-and-checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-unpin-remove-and-checkpoint.cc @@ -86,11 +86,22 @@ run_test (void) { // now this should mark the pair for checkpoint CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct); toku_cachetable_begin_checkpoint(cp, NULL); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), toku_cachetable_hash(f1, make_blocknum(1)), &v1, &s1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + toku_cachetable_hash(f1, make_blocknum(1)), + &v1, + &s1, + wc, + def_fetch, + def_pf_req_callback, + def_pf_callback, + true, + NULL); toku_pthread_t mytid; - r = toku_pthread_create(&mytid, NULL, run_end_chkpt, NULL); - assert(r==0); + r = toku_pthread_create( + toku_uninstrumented, &mytid, nullptr, run_end_chkpt, nullptr); + assert(r == 0); // give checkpoint thread a chance to start waiting on lock sleep(1); diff --git a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-extractor-errors.cc b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-extractor-errors.cc index 872b674c784..4bff52ceb1b 100644 --- a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-extractor-errors.cc +++ b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-extractor-errors.cc @@ -141,7 +141,7 @@ static void test_extractor(int nrows, int nrowsets, bool expect_fail, const char // setup error injection toku_set_func_malloc(my_malloc); toku_set_func_realloc(my_realloc); - ft_loader_set_os_fwrite(bad_fwrite); + toku_set_func_fwrite(bad_fwrite); toku_set_func_write(bad_write); toku_set_func_pwrite(bad_pwrite); ft_loader_set_poll_function(&loader->poll_callback, loader_poll_callback, NULL); @@ -157,7 +157,7 @@ static void test_extractor(int nrows, int nrowsets, bool expect_fail, const char toku_set_func_malloc(NULL); toku_set_func_realloc(NULL); - ft_loader_set_os_fwrite(NULL); + toku_set_func_fwrite(nullptr); toku_set_func_write(NULL); toku_set_func_pwrite(NULL); diff --git a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-merge-files-dbufio.cc b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-merge-files-dbufio.cc index d1aeff198ff..0b121316738 100644 --- a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-merge-files-dbufio.cc +++ b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-merge-files-dbufio.cc @@ -393,13 +393,17 @@ static void test (const char *directory, bool is_error) { toku_pthread_t consumer; struct consumer_thunk cthunk = {q, 0}; { - int r = toku_pthread_create(&consumer, NULL, consumer_thread, (void*)&cthunk); - assert(r==0); + int r = toku_pthread_create(toku_uninstrumented, + &consumer, + nullptr, + consumer_thread, + static_cast(&cthunk)); + assert(r == 0); } toku_set_func_malloc_only(my_malloc); toku_set_func_realloc_only(my_realloc); - ft_loader_set_os_fwrite(bad_fwrite); + toku_set_func_fwrite(bad_fwrite); toku_set_func_write(bad_write); toku_set_func_pwrite(bad_pwrite); toku_set_func_fdopen(bad_fdopen); @@ -427,7 +431,7 @@ static void test (const char *directory, bool is_error) { toku_set_func_malloc(NULL); toku_set_func_realloc(NULL); - ft_loader_set_os_fwrite(NULL); + toku_set_func_fwrite(nullptr); toku_set_func_write(NULL); toku_set_func_pwrite(NULL); toku_set_func_fdopen(NULL); diff --git a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-writer-errors.cc b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-writer-errors.cc index 0784ca87a26..e4423319518 100644 --- a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-writer-errors.cc +++ b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-writer-errors.cc @@ -154,7 +154,7 @@ static int write_dbfile (char *tf_template, int n, char *output_name, bool expec toku_set_func_malloc_only(my_malloc); toku_set_func_realloc_only(my_realloc); - ft_loader_set_os_fwrite(bad_fwrite); + toku_set_func_fwrite(bad_fwrite); toku_set_func_write(bad_write); toku_set_func_pwrite(bad_pwrite); ft_loader_set_error_function(&bl.error_callback, NULL, NULL); @@ -164,7 +164,7 @@ static int write_dbfile (char *tf_template, int n, char *output_name, bool expec toku_set_func_malloc_only(NULL); toku_set_func_realloc_only(NULL); - ft_loader_set_os_fwrite(NULL); + toku_set_func_fwrite(nullptr); toku_set_func_write(NULL); toku_set_func_pwrite(NULL); diff --git a/storage/tokudb/PerconaFT/ft/tests/log-test4.cc b/storage/tokudb/PerconaFT/ft/tests/log-test4.cc index a31181deb30..e0bbedb95bf 100644 --- a/storage/tokudb/PerconaFT/ft/tests/log-test4.cc +++ b/storage/tokudb/PerconaFT/ft/tests/log-test4.cc @@ -63,11 +63,14 @@ test_main (int argc __attribute__((__unused__)), r = toku_logger_close(&logger); assert(r == 0); { - toku_struct_stat statbuf; - sprintf(logname, "%s/log000000000000.tokulog%d", TOKU_TEST_FILENAME, TOKU_LOG_VERSION); - r = toku_stat(logname, &statbuf); - assert(r==0); - assert(statbuf.st_size==12+5); + toku_struct_stat statbuf; + sprintf(logname, + "%s/log000000000000.tokulog%d", + TOKU_TEST_FILENAME, + TOKU_LOG_VERSION); + r = toku_stat(logname, &statbuf, toku_uninstrumented); + assert(r == 0); + assert(statbuf.st_size == 12 + 5); } toku_os_recursive_delete(TOKU_TEST_FILENAME); return 0; diff --git a/storage/tokudb/PerconaFT/ft/tests/log-test5.cc b/storage/tokudb/PerconaFT/ft/tests/log-test5.cc index d4e31af22dc..fed9467a4ae 100644 --- a/storage/tokudb/PerconaFT/ft/tests/log-test5.cc +++ b/storage/tokudb/PerconaFT/ft/tests/log-test5.cc @@ -81,14 +81,14 @@ test_main (int argc __attribute__((__unused__)), struct dirent *dirent; while ((dirent=readdir(dir))) { if (strncmp(dirent->d_name, "log", 3)!=0) continue; - char fname[TOKU_PATH_MAX+1]; - toku_path_join(fname, 2, TOKU_TEST_FILENAME, dirent->d_name); - toku_struct_stat statbuf; - r = toku_stat(fname, &statbuf); - assert(r==0); - assert(statbuf.st_size<=LSIZE+10); - } - r = closedir(dir); + char fname[TOKU_PATH_MAX + 1]; + toku_path_join(fname, 2, TOKU_TEST_FILENAME, dirent->d_name); + toku_struct_stat statbuf; + r = toku_stat(fname, &statbuf, toku_uninstrumented); + assert(r == 0); + assert(statbuf.st_size <= LSIZE + 10); + } + r = closedir(dir); assert(r==0); } toku_os_recursive_delete(TOKU_TEST_FILENAME); diff --git a/storage/tokudb/PerconaFT/ft/tests/log-test6.cc b/storage/tokudb/PerconaFT/ft/tests/log-test6.cc index 4d17488c57c..0e8b94566df 100644 --- a/storage/tokudb/PerconaFT/ft/tests/log-test6.cc +++ b/storage/tokudb/PerconaFT/ft/tests/log-test6.cc @@ -86,11 +86,14 @@ test_main (int argc __attribute__((__unused__)), { char logname[PATH_MAX]; - toku_struct_stat statbuf; - sprintf(logname, "%s/log000000000000.tokulog%d", TOKU_TEST_FILENAME, TOKU_LOG_VERSION); - r = toku_stat(logname, &statbuf); - assert(r==0); - assert(statbuf.st_size<=LSIZE); + toku_struct_stat statbuf; + sprintf(logname, + "%s/log000000000000.tokulog%d", + TOKU_TEST_FILENAME, + TOKU_LOG_VERSION); + r = toku_stat(logname, &statbuf, toku_uninstrumented); + assert(r == 0); + assert(statbuf.st_size <= LSIZE); } toku_os_recursive_delete(TOKU_TEST_FILENAME); return 0; diff --git a/storage/tokudb/PerconaFT/ft/tests/recovery-bad-last-entry.cc b/storage/tokudb/PerconaFT/ft/tests/recovery-bad-last-entry.cc index 431ee4b5e50..a3c934d1f4b 100644 --- a/storage/tokudb/PerconaFT/ft/tests/recovery-bad-last-entry.cc +++ b/storage/tokudb/PerconaFT/ft/tests/recovery-bad-last-entry.cc @@ -83,11 +83,16 @@ run_test(void) { r = toku_dup2(devnul, fileno(stderr)); assert(r==fileno(stderr)); r = close(devnul); assert(r==0); - char fname[TOKU_PATH_MAX+1]; - sprintf(fname, "%s/%s%d", TOKU_TEST_FILENAME, "log000000000000.tokulog", TOKU_LOG_VERSION); - - r = toku_stat(fname, &st); assert(r==0); - if ( st.st_size - trim > magic_begin_end_checkpoint_sz ) { + char fname[TOKU_PATH_MAX + 1]; + sprintf(fname, + "%s/%s%d", + TOKU_TEST_FILENAME, + "log000000000000.tokulog", + TOKU_LOG_VERSION); + + r = toku_stat(fname, &st, toku_uninstrumented); + assert(r == 0); + if (st.st_size - trim > magic_begin_end_checkpoint_sz) { r = truncate(fname, st.st_size - trim); CKERR(r); } diff --git a/storage/tokudb/PerconaFT/ft/tests/test-bjm.cc b/storage/tokudb/PerconaFT/ft/tests/test-bjm.cc index 97e00c42b95..6afe5b9f7c4 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-bjm.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-bjm.cc @@ -71,12 +71,16 @@ static void bjm_test(void) { bjm_reset(bjm); r = bjm_add_background_job(bjm); - assert_zero(r); - toku_pthread_t tid; - r = toku_pthread_create(&tid, NULL, finish_bjm, NULL); assert_zero(r); - usleep(2*1024*1024); - // should return non-zero because tid is waiting + toku_pthread_t tid; + r = toku_pthread_create(toku_uninstrumented, + &tid, + nullptr, + finish_bjm, + nullptr); + assert_zero(r); + usleep(2 * 1024 * 1024); + // should return non-zero because tid is waiting // for background jobs to finish r = bjm_add_background_job(bjm); assert(r != 0); diff --git a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-flush.cc b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-flush.cc index 3e5d9bba817..06a26614885 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-flush.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-flush.cc @@ -113,10 +113,14 @@ static void flusher_callback(int state, void* extra) { if ((state == flt_flush_before_child_pin && !after_child_pin) || (state == ft_flush_aflter_child_pin && after_child_pin)) { checkpoint_called = true; - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint, + nullptr); assert_zero(r); while (!checkpoint_callback_called) { - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); } } } diff --git a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-merge.cc b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-merge.cc index cb316127ef7..1029dfef320 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-merge.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-merge.cc @@ -103,10 +103,14 @@ static void flusher_callback(int state, void* extra) { } if (state == desired_state) { checkpoint_called = true; - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint, + nullptr); assert_zero(r); while (!checkpoint_callback_called) { - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); } } } diff --git a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-rebalance.cc b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-rebalance.cc index 5f8485ac4ec..208ebe3ca31 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-rebalance.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-rebalance.cc @@ -103,10 +103,14 @@ static void flusher_callback(int state, void* extra) { } if (state == desired_state) { checkpoint_called = true; - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint, + nullptr); assert_zero(r); while (!checkpoint_callback_called) { - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); } } } diff --git a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-split.cc b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-split.cc index 70c3ba22a0c..2b29de409b1 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-split.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-split.cc @@ -113,10 +113,14 @@ static void flusher_callback(int state, void* extra) { if ((state == flt_flush_before_split && !after_split) || (state == flt_flush_during_split && after_split)) { checkpoint_called = true; - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint, + nullptr); assert_zero(r); while (!checkpoint_callback_called) { - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); } } } diff --git a/storage/tokudb/PerconaFT/ft/tests/test3681.cc b/storage/tokudb/PerconaFT/ft/tests/test3681.cc index e5e24a88246..9e4a46e8dfe 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test3681.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test3681.cc @@ -91,13 +91,35 @@ static void *startb (void *n) { return NULL; } -static void test3681 (void) { +static void test3681(void) { setup(); - toku_pthread_t a,b; - { int r; r = toku_pthread_create(&a, NULL, starta, NULL); assert(r==0); } - { int r; r = toku_pthread_create(&b, NULL, startb, NULL); assert(r==0); } - { int r; void *v; r = toku_pthread_join(a, &v); assert(r==0); assert(v==NULL); } - { int r; void *v; r = toku_pthread_join(b, &v); assert(r==0); assert(v==NULL); } + toku_pthread_t a, b; + { + int r; + r = toku_pthread_create( + toku_uninstrumented, &a, nullptr, starta, nullptr); + assert(r == 0); + } + { + int r; + r = toku_pthread_create( + toku_uninstrumented, &b, nullptr, startb, nullptr); + assert(r == 0); + } + { + int r; + void *v; + r = toku_pthread_join(a, &v); + assert(r == 0); + assert(v == NULL); + } + { + int r; + void *v; + r = toku_pthread_join(b, &v); + assert(r == 0); + assert(v == NULL); + } finish(); } diff --git a/storage/tokudb/PerconaFT/ft/txn/roll.cc b/storage/tokudb/PerconaFT/ft/txn/roll.cc index 97afd2f5bdb..7228de06f34 100644 --- a/storage/tokudb/PerconaFT/ft/txn/roll.cc +++ b/storage/tokudb/PerconaFT/ft/txn/roll.cc @@ -195,14 +195,14 @@ int toku_rollback_frename(BYTESTRING old_iname, toku_cachetable_get_fname_in_cwd(cachetable, new_iname.data), &toku_free); - if (toku_stat(old_iname_full.get(), &stat) == -1) { + if (toku_stat(old_iname_full.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == errno) old_exist = false; else return 1; } - if (toku_stat(new_iname_full.get(), &stat) == -1) { + if (toku_stat(new_iname_full.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == errno || ENAMETOOLONG == errno) new_exist = false; else @@ -220,7 +220,7 @@ int toku_rollback_frename(BYTESTRING old_iname, // removed // and the new file is renamed. if (old_exist && new_exist && - (toku_os_unlink(old_iname_full.get()) == -1 || + (toku_os_delete(old_iname_full.get()) == -1 || toku_os_rename(new_iname_full.get(), old_iname_full.get()) == -1 || toku_fsync_directory(new_iname_full.get()) == -1 || toku_fsync_directory(old_iname_full.get()) == -1)) diff --git a/storage/tokudb/PerconaFT/ft/txn/rollback_log_node_cache.cc b/storage/tokudb/PerconaFT/ft/txn/rollback_log_node_cache.cc index 71b1e79277c..5e1ab746936 100644 --- a/storage/tokudb/PerconaFT/ft/txn/rollback_log_node_cache.cc +++ b/storage/tokudb/PerconaFT/ft/txn/rollback_log_node_cache.cc @@ -41,7 +41,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "txn/rollback_log_node_cache.h" -void rollback_log_node_cache::init (uint32_t max_num_avail_nodes) { +toku_instr_key* rollback_log_node_cache_mutex_key; + +void rollback_log_node_cache::init(uint32_t max_num_avail_nodes) { XMALLOC_N(max_num_avail_nodes, m_avail_blocknums); m_max_num_avail = max_num_avail_nodes; m_first = 0; @@ -49,7 +51,7 @@ void rollback_log_node_cache::init (uint32_t max_num_avail_nodes) { toku_pthread_mutexattr_t attr; toku_mutexattr_init(&attr); toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE); - toku_mutex_init(&m_mutex, &attr); + toku_mutex_init(*rollback_log_node_cache_mutex_key, &m_mutex, &attr); toku_mutexattr_destroy(&attr); } diff --git a/storage/tokudb/PerconaFT/ft/txn/txn.cc b/storage/tokudb/PerconaFT/ft/txn/txn.cc index a3ce6beb7b0..7327cbd9d24 100644 --- a/storage/tokudb/PerconaFT/ft/txn/txn.cc +++ b/storage/tokudb/PerconaFT/ft/txn/txn.cc @@ -45,8 +45,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "ft/txn/txn_manager.h" #include "util/status.h" -void -toku_txn_get_status(TXN_STATUS s) { +toku_instr_key *txn_lock_mutex_key; +toku_instr_key *txn_state_lock_mutex_key; +toku_instr_key *result_state_cond_key; + +void toku_txn_get_status(TXN_STATUS s) { txn_status.init(); *s = txn_status; } @@ -225,74 +228,74 @@ static void toku_txn_create_txn ( static txn_child_manager tcm; - struct tokutxn new_txn = { - .txnid = {.parent_id64 = TXNID_NONE, .child_id64 = TXNID_NONE }, - .snapshot_txnid64 = TXNID_NONE, - .snapshot_type = for_recovery ? TXN_SNAPSHOT_NONE : snapshot_type, - .for_recovery = for_recovery, - .logger = logger, - .parent = parent_tokutxn, - .child = NULL, - .child_manager_s = tcm, - .child_manager = NULL, - .container_db_txn = container_db_txn, - .live_root_txn_list = nullptr, - .xids = NULL, - .snapshot_next = NULL, - .snapshot_prev = NULL, - .begin_was_logged = false, - .declared_read_only = read_only, - .do_fsync = false, - .force_fsync_on_commit = false, - .do_fsync_lsn = ZERO_LSN, - .xa_xid = {0, 0, 0, ""}, - .progress_poll_fun = NULL, - .progress_poll_fun_extra = NULL, - - // You cannot initialize txn_lock a TOKU_MUTEX_INITIALIZER, because we - // will initialize it in the code below, and it cannot already - // be initialized at that point. Also, in general, you don't - // get to use PTHREAD_MUTEX_INITALIZER (which is what is inside - // TOKU_MUTEX_INITIALIZER) except in static variables, and this - // is initializing an auto variable. - // - // And we cannot simply avoid initializing these fields - // because, although it avoids -Wmissing-field-initializer - // errors under gcc, it gets other errors about non-trivial - // designated initializers not being supported. - - .txn_lock = ZERO_MUTEX_INITIALIZER, // Not TOKU_MUTEX_INITIALIZER - .open_fts = open_fts, - .roll_info = roll_info, - .state_lock = ZERO_MUTEX_INITIALIZER, // Not TOKU_MUTEX_INITIALIZER - .state_cond = ZERO_COND_INITIALIZER, // Not TOKU_COND_INITIALIZER - .state = TOKUTXN_LIVE, - .num_pin = 0, - .client_id = 0, - .client_extra = nullptr, - .start_time = time(NULL), - }; +struct tokutxn new_txn = { + .txnid = {.parent_id64 = TXNID_NONE, .child_id64 = TXNID_NONE }, + .snapshot_txnid64 = TXNID_NONE, + .snapshot_type = for_recovery ? TXN_SNAPSHOT_NONE : snapshot_type, + .for_recovery = for_recovery, + .logger = logger, + .parent = parent_tokutxn, + .child = NULL, + .child_manager_s = tcm, + .child_manager = NULL, + .container_db_txn = container_db_txn, + .live_root_txn_list = nullptr, + .xids = NULL, + .snapshot_next = NULL, + .snapshot_prev = NULL, + .begin_was_logged = false, + .declared_read_only = read_only, + .do_fsync = false, + .force_fsync_on_commit = false, + .do_fsync_lsn = ZERO_LSN, + .xa_xid = {0, 0, 0, ""}, + .progress_poll_fun = NULL, + .progress_poll_fun_extra = NULL, + + // You cannot initialize txn_lock a TOKU_MUTEX_INITIALIZER, because we + // will initialize it in the code below, and it cannot already + // be initialized at that point. Also, in general, you don't + // get to use PTHREAD_MUTEX_INITALIZER (which is what is inside + // TOKU_MUTEX_INITIALIZER) except in static variables, and this + // is initializing an auto variable. + // + // And we cannot simply avoid initializing these fields + // because, although it avoids -Wmissing-field-initializer + // errors under gcc, it gets other errors about non-trivial + // designated initializers not being supported. + + .txn_lock = ZERO_MUTEX_INITIALIZER, // Not TOKU_MUTEX_INITIALIZER + .open_fts = open_fts, + .roll_info = roll_info, + .state_lock = ZERO_MUTEX_INITIALIZER, // Not TOKU_MUTEX_INITIALIZER + .state_cond = ZERO_COND_INITIALIZER, // Not TOKU_COND_INITIALIZER + .state = TOKUTXN_LIVE, + .num_pin = 0, + .client_id = 0, + .client_extra = nullptr, + .start_time = time(NULL), +}; - TOKUTXN result = NULL; - XMEMDUP(result, &new_txn); - invalidate_xa_xid(&result->xa_xid); - if (parent_tokutxn == NULL) { - result->child_manager = &result->child_manager_s; - result->child_manager->init(result); +TOKUTXN result = NULL; +XMEMDUP(result, &new_txn); +invalidate_xa_xid(&result->xa_xid); +if (parent_tokutxn == NULL) { + result->child_manager = &result->child_manager_s; + result->child_manager->init(result); } else { result->child_manager = parent_tokutxn->child_manager; } - toku_mutex_init(&result->txn_lock, nullptr); + toku_mutex_init(*txn_lock_mutex_key, &result->txn_lock, nullptr); toku_pthread_mutexattr_t attr; toku_mutexattr_init(&attr); toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE); - toku_mutex_init(&result->state_lock, &attr); + toku_mutex_init(*txn_state_lock_mutex_key, &result->state_lock, &attr); toku_mutexattr_destroy(&attr); - toku_cond_init(&result->state_cond, nullptr); + toku_cond_init(*result_state_cond_key, &result->state_cond, nullptr); *tokutxn = result; diff --git a/storage/tokudb/PerconaFT/ft/txn/txn_child_manager.cc b/storage/tokudb/PerconaFT/ft/txn/txn_child_manager.cc index db110127c55..99a21331b0a 100644 --- a/storage/tokudb/PerconaFT/ft/txn/txn_child_manager.cc +++ b/storage/tokudb/PerconaFT/ft/txn/txn_child_manager.cc @@ -39,6 +39,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "ft/logger/log-internal.h" #include "ft/txn/txn_child_manager.h" +toku_instr_key *txn_child_manager_mutex_key; + // // initialized a txn_child_manager, // when called, root->txnid.parent_id64 may not yet be set @@ -53,7 +55,7 @@ void txn_child_manager::init(TOKUTXN root) { toku_pthread_mutexattr_t attr; toku_mutexattr_init(&attr); toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE); - toku_mutex_init(&m_mutex, &attr); + toku_mutex_init(*txn_child_manager_mutex_key, &m_mutex, &attr); toku_mutexattr_destroy(&attr); } diff --git a/storage/tokudb/PerconaFT/ft/txn/txn_manager.cc b/storage/tokudb/PerconaFT/ft/txn/txn_manager.cc index 88eca36a261..384a960b1f3 100644 --- a/storage/tokudb/PerconaFT/ft/txn/txn_manager.cc +++ b/storage/tokudb/PerconaFT/ft/txn/txn_manager.cc @@ -56,7 +56,10 @@ void set_test_txn_sync_callback(void (*cb) (pthread_t, void *), void *extra) { } bool garbage_collection_debug = false; -static bool txn_records_snapshot(TXN_SNAPSHOT_TYPE snapshot_type, struct tokutxn *parent) { +toku_instr_key *txn_manager_lock_mutex_key; + +static bool txn_records_snapshot(TXN_SNAPSHOT_TYPE snapshot_type, + struct tokutxn *parent) { if (snapshot_type == TXN_COPIES_SNAPSHOT) { return false; } @@ -248,9 +251,10 @@ verify_snapshot_system(TXN_MANAGER txn_manager UU()) { live_root_txns_omt.destroy(); } -void toku_txn_manager_init(TXN_MANAGER* txn_managerp) { +void toku_txn_manager_init(TXN_MANAGER *txn_managerp) { TXN_MANAGER XCALLOC(txn_manager); - toku_mutex_init(&txn_manager->txn_manager_lock, NULL); + toku_mutex_init( + *txn_manager_lock_mutex_key, &txn_manager->txn_manager_lock, nullptr); txn_manager->live_root_txns.create(); txn_manager->live_root_ids.create(); txn_manager->snapshot_head = NULL; diff --git a/storage/tokudb/PerconaFT/locktree/lock_request.cc b/storage/tokudb/PerconaFT/locktree/lock_request.cc index 10fd2e7a208..8d49ccf8a1f 100644 --- a/storage/tokudb/PerconaFT/locktree/lock_request.cc +++ b/storage/tokudb/PerconaFT/locktree/lock_request.cc @@ -62,7 +62,7 @@ void lock_request::create(void) { m_state = state::UNINITIALIZED; m_info = nullptr; - toku_cond_init(&m_wait_cond, nullptr); + toku_cond_init(*lock_request_m_wait_cond_key, &m_wait_cond, nullptr); m_start_test_callback = nullptr; m_start_before_pending_test_callback = nullptr; diff --git a/storage/tokudb/PerconaFT/locktree/locktree.cc b/storage/tokudb/PerconaFT/locktree/locktree.cc index 2fbf078bdd6..069aae26f66 100644 --- a/storage/tokudb/PerconaFT/locktree/locktree.cc +++ b/storage/tokudb/PerconaFT/locktree/locktree.cc @@ -51,7 +51,6 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // the locktree source file instead of the header. #include "concurrent_tree.h" - namespace toku { // A locktree represents the set of row locks owned by all transactions @@ -87,12 +86,13 @@ void lt_lock_request_info::init(void) { pending_lock_requests.create(); pending_is_empty = true; ZERO_STRUCT(mutex); - toku_mutex_init(&mutex, nullptr); + toku_mutex_init(*locktree_request_info_mutex_key, &mutex, nullptr); retry_want = retry_done = 0; ZERO_STRUCT(counters); ZERO_STRUCT(retry_mutex); - toku_mutex_init(&retry_mutex, nullptr); - toku_cond_init(&retry_cv, nullptr); + toku_mutex_init( + *locktree_request_info_retry_mutex_key, &retry_mutex, nullptr); + toku_cond_init(*locktree_request_info_retry_cv_key, &retry_cv, nullptr); running_retry = false; TOKU_VALGRIND_HG_DISABLE_CHECKING(&pending_is_empty, diff --git a/storage/tokudb/PerconaFT/locktree/manager.cc b/storage/tokudb/PerconaFT/locktree/manager.cc index 91ff7c5a007..6bb5c77bf32 100644 --- a/storage/tokudb/PerconaFT/locktree/manager.cc +++ b/storage/tokudb/PerconaFT/locktree/manager.cc @@ -56,9 +56,8 @@ void locktree_manager::create(lt_create_cb create_cb, lt_destroy_cb destroy_cb, m_lt_destroy_callback = destroy_cb; m_lt_escalate_callback = escalate_cb; m_lt_escalate_callback_extra = escalate_extra; - ZERO_STRUCT(m_mutex); - toku_mutex_init(&m_mutex, nullptr); + toku_mutex_init(*manager_mutex_key, &m_mutex, nullptr); ZERO_STRUCT(m_lt_counters); @@ -346,7 +345,8 @@ int locktree_manager::check_current_lock_constraints(bool big_txn) { void locktree_manager::escalator_init(void) { ZERO_STRUCT(m_escalation_mutex); - toku_mutex_init(&m_escalation_mutex, nullptr); + toku_mutex_init( + *manager_escalation_mutex_key, &m_escalation_mutex, nullptr); m_escalation_count = 0; m_escalation_time = 0; m_wait_escalation_count = 0; @@ -403,8 +403,8 @@ struct escalate_args { void locktree_manager::locktree_escalator::create(void) { ZERO_STRUCT(m_escalator_mutex); - toku_mutex_init(&m_escalator_mutex, nullptr); - toku_cond_init(&m_escalator_done, nullptr); + toku_mutex_init(*manager_escalator_mutex_key, &m_escalator_mutex, nullptr); + toku_cond_init(*manager_m_escalator_done_key, &m_escalator_done, nullptr); m_escalator_running = false; } diff --git a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_1big7lt_1small.cc b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_1big7lt_1small.cc index 6c143f963ba..32029b5bddd 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_1big7lt_1small.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_1big7lt_1small.cc @@ -201,12 +201,14 @@ int main(int argc, const char *argv[]) { locktree *small_lt = mgr.get_lt(dict_id, dbt_comparator, 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); + struct big_arg big_arg = {&mgr, big_lt, n_big, 1000}; + r = toku_pthread_create( + toku_uninstrumented, &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); + struct small_arg small_arg = {&mgr, small_lt, 2000, 0}; + r = toku_pthread_create( + toku_uninstrumented, &small_id, nullptr, small_f, &small_arg); assert(r == 0); // wait for some escalations to occur diff --git a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_1lt.cc b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_1lt.cc index 17eb07060d4..ff59a7bdd5c 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_1lt.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_1lt.cc @@ -169,8 +169,10 @@ int main(int argc, const char *argv[]) { 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]); + big_arg[i] = { + &mgr, lt[i % n_lt], (TXNID)(1000 + i), i == 0 ? 1 : -1000000000}; + r = toku_pthread_create( + toku_uninstrumented, &big_ids[i], nullptr, big_f, &big_arg[i]); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_2lt.cc b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_2lt.cc index 4326e8fafc2..be1ddaba9d0 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_2lt.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_2lt.cc @@ -169,8 +169,10 @@ int main(int argc, const char *argv[]) { 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]); + big_arg[i] = { + &mgr, lt[i % n_lt], (TXNID)(1000 + i), i == 0 ? 1 : -1000000000}; + r = toku_pthread_create( + toku_uninstrumented, &big_ids[i], nullptr, big_f, &big_arg[i]); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_stalls.cc b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_stalls.cc index d146d94e337..9dc9596a7ed 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_stalls.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_stalls.cc @@ -182,9 +182,10 @@ int main(int argc, const char *argv[]) { locktree *lt_1 = mgr.get_lt(dict_id_1, dbt_comparator, nullptr); // create the worker threads - struct arg big_arg = { &mgr, lt_0, 1000 }; + struct arg big_arg = {&mgr, lt_0, 1000}; pthread_t big_id; - r = toku_pthread_create(&big_id, nullptr, big_f, &big_arg); + r = toku_pthread_create( + toku_uninstrumented, &big_id, nullptr, big_f, &big_arg); assert(r == 0); const int n_small = 7; @@ -192,8 +193,12 @@ int main(int argc, const char *argv[]) { struct arg small_args[n_small]; for (int i = 0; i < n_small; i++) { - small_args[i] = { &mgr, lt_1, (TXNID)(2000+i), i }; - r = toku_pthread_create(&small_ids[i], nullptr, small_f, &small_args[i]); + small_args[i] = {&mgr, lt_1, (TXNID)(2000 + i), i}; + r = toku_pthread_create(toku_uninstrumented, + &small_ids[i], + nullptr, + small_f, + &small_args[i]); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/locktree/tests/manager_parallel_locktree_get_release.cc b/storage/tokudb/PerconaFT/locktree/tests/manager_parallel_locktree_get_release.cc index ec9ef21583c..08ce63140a5 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/manager_parallel_locktree_get_release.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/manager_parallel_locktree_get_release.cc @@ -71,7 +71,8 @@ void manager_unit_test::test_reference_release_lt(void) { const int nthreads = 2; pthread_t ids[nthreads]; for (int i = 0; i < nthreads; i++) { - r = toku_pthread_create(&ids[i], nullptr, my_tester, &mgr); + r = toku_pthread_create( + toku_uninstrumented, &ids[i], nullptr, my_tester, &mgr); assert(r == 0); } for (int i = 0; i < nthreads; i++) { diff --git a/storage/tokudb/PerconaFT/locktree/treenode.cc b/storage/tokudb/PerconaFT/locktree/treenode.cc index 4f43291fe76..cc3a4969643 100644 --- a/storage/tokudb/PerconaFT/locktree/treenode.cc +++ b/storage/tokudb/PerconaFT/locktree/treenode.cc @@ -38,9 +38,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include -void treenode::mutex_lock(void) { - toku_mutex_lock(&m_mutex); -} +// TODO: source location info might have to be pulled up one caller +// to be useful +void treenode::mutex_lock(void) { toku_mutex_lock(&m_mutex); } void treenode::mutex_unlock(void) { toku_mutex_unlock(&m_mutex); @@ -58,7 +58,7 @@ void treenode::init(const comparator *cmp) { toku_pthread_mutexattr_t attr; toku_mutexattr_init(&attr); toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE); - toku_mutex_init(&m_mutex, &attr); + toku_mutex_init(*treenode_mutex_key, &m_mutex, &attr); toku_mutexattr_destroy(&attr); m_left_child.set(nullptr); m_right_child.set(nullptr); diff --git a/storage/tokudb/PerconaFT/portability/CMakeLists.txt b/storage/tokudb/PerconaFT/portability/CMakeLists.txt index 93dcf1d1675..f24cf84a829 100644 --- a/storage/tokudb/PerconaFT/portability/CMakeLists.txt +++ b/storage/tokudb/PerconaFT/portability/CMakeLists.txt @@ -8,6 +8,7 @@ set(tokuportability_srcs portability toku_assert toku_crash + toku_instr_mysql toku_path toku_pthread toku_time @@ -55,6 +56,10 @@ if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING) DESTINATION ${INSTALL_LIBDIR} COMPONENT tokukv_libs_shared ) +else () + set_property(SOURCE toku_pthread portability APPEND PROPERTY + COMPILE_DEFINITIONS MYSQL_TOKUDB_ENGINE=1 ) + target_link_libraries(${LIBTOKUPORTABILITY} LINK_PRIVATE mysys) endif () add_subdirectory(tests) diff --git a/storage/tokudb/PerconaFT/portability/file.cc b/storage/tokudb/PerconaFT/portability/file.cc index 0e3efc1a12a..485bfac8514 100644 --- a/storage/tokudb/PerconaFT/portability/file.cc +++ b/storage/tokudb/PerconaFT/portability/file.cc @@ -52,9 +52,12 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "toku_path.h" #include +toku_instr_key *tokudb_file_data_key; + static int toku_assert_on_write_enospc = 0; static const int toku_write_enospc_sleep = 1; -static uint64_t toku_write_enospc_last_report; // timestamp of most recent report to error log +static uint64_t toku_write_enospc_last_report; // timestamp of most recent + // report to error log static time_t toku_write_enospc_last_time; // timestamp of most recent ENOSPC static uint32_t toku_write_enospc_current; // number of threads currently blocked on ENOSPC static uint64_t toku_write_enospc_total; // total number of times ENOSPC was returned from an attempt to write @@ -142,11 +145,17 @@ static ssize_t (*t_full_pwrite)(int, const void *, size_t, off_t); static FILE * (*t_fdopen)(int, const char *); static FILE * (*t_fopen)(const char *, const char *); static int (*t_open)(const char *, int, int); -static int (*t_fclose)(FILE *); +static int (*t_fclose)(FILE *); static ssize_t (*t_read)(int, void *, size_t); static ssize_t (*t_pread)(int, void *, size_t, off_t); +static size_t (*os_fwrite_fun)(const void *, size_t, size_t, FILE *) = nullptr; + +void toku_set_func_fwrite( + size_t (*fwrite_fun)(const void *, size_t, size_t, FILE *)) { + os_fwrite_fun = fwrite_fun; +} -void toku_set_func_write (ssize_t (*write_fun)(int, const void *, size_t)) { +void toku_set_func_write(ssize_t (*write_fun)(int, const void *, size_t)) { t_write = write_fun; } @@ -186,9 +195,63 @@ void toku_set_func_pread (ssize_t (*pread_fun)(int, void *, size_t, off_t)) { t_pread = pread_fun; } -void -toku_os_full_write (int fd, const void *buf, size_t len) { - const char *bp = (const char *) buf; +int toku_os_delete_with_source_location(const char *name, + const char *src_file, + uint src_line) { + + toku_io_instrumentation io_annotation; + toku_instr_file_name_close_begin(io_annotation, + *tokudb_file_data_key, + toku_instr_file_op::file_delete, + name, + src_file, + src_line); + const int result = unlink(name); + + /* Register the result value with the instrumentation system */ + toku_instr_file_close_end(io_annotation, result); + + return result; +} + +int toku_os_rename_with_source_location(const char *old_name, + const char *new_name, + const char *src_file, + uint src_line) { + int result; + + toku_io_instrumentation io_annotation; + toku_instr_file_name_io_begin(io_annotation, + *tokudb_file_data_key, + toku_instr_file_op::file_rename, + new_name, + 0, + src_file, + src_line); + + result = rename(old_name, new_name); + /* Regsiter the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, 0); + + return result; +} + +void toku_os_full_write_with_source_location(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line) { + const char *bp = (const char *)buf; + size_t bytes_written = len; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_write, + fd, + len, + src_file, + src_line); + while (len > 0) { ssize_t r; if (t_full_write) { @@ -205,14 +268,30 @@ toku_os_full_write (int fd, const void *buf, size_t len) { } } assert(len == 0); + + /* Register the result value with the instrumentaion system */ + toku_instr_file_io_end(io_annotation, bytes_written); } -int -toku_os_write (int fd, const void *buf, size_t len) { - const char *bp = (const char *) buf; +int toku_os_write_with_source_location(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line) { + const char *bp = (const char *)buf; int result = 0; + ssize_t r; + + size_t bytes_written = len; + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_write, + fd, + len, + src_file, + src_line); + while (len > 0) { - ssize_t r; if (t_write) { r = t_write(fd, bp, len); } else { @@ -222,17 +301,33 @@ toku_os_write (int fd, const void *buf, size_t len) { result = errno; break; } - len -= r; - bp += r; + len -= r; + bp += r; } + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_written - len); + return result; } -void -toku_os_full_pwrite (int fd, const void *buf, size_t len, toku_off_t off) { - assert(0==((long long)buf)%512); - assert((len%512 == 0) && (off%512)==0); // to make pwrite work. - const char *bp = (const char *) buf; +void toku_os_full_pwrite_with_source_location(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line) { + assert(0 == ((long long)buf) % 512); + assert((len % 512 == 0) && (off % 512) == 0); // to make pwrite work. + const char *bp = (const char *)buf; + + size_t bytes_written = len; + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_write, + fd, + len, + src_file, + src_line); while (len > 0) { ssize_t r; if (t_full_pwrite) { @@ -250,71 +345,209 @@ toku_os_full_pwrite (int fd, const void *buf, size_t len, toku_off_t off) { } } assert(len == 0); -} -ssize_t -toku_os_pwrite (int fd, const void *buf, size_t len, toku_off_t off) { - assert(0==((long long)buf)%512); // these asserts are to ensure that direct I/O will work. - assert(0==len %512); - assert(0==off %512); - const char *bp = (const char *) buf; + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_written); +} + +ssize_t toku_os_pwrite_with_source_location(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line) { + assert(0 == + ((long long)buf) % + 512); // these asserts are to ensure that direct I/O will work. + assert(0 == len % 512); + assert(0 == off % 512); + const char *bp = (const char *)buf; ssize_t result = 0; + ssize_t r; + + size_t bytes_written = len; + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_write, + fd, + len, + src_file, + src_line); while (len > 0) { - ssize_t r; - if (t_pwrite) { - r = t_pwrite(fd, bp, len, off); - } else { - r = pwrite(fd, bp, len, off); - } + r = (t_pwrite) ? t_pwrite(fd, bp, len, off) : pwrite(fd, bp, len, off); + if (r < 0) { result = errno; break; } len -= r; - bp += r; - off += r; + bp += r; + off += r; + } + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_written - len); + + return result; +} + +int toku_os_fwrite_with_source_location(const void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line) { + int result = 0; + size_t bytes_written; + + toku_io_instrumentation io_annotation; + toku_instr_file_stream_io_begin(io_annotation, + toku_instr_file_op::file_write, + *stream, + nmemb, + src_file, + src_line); + + if (os_fwrite_fun) { + bytes_written = os_fwrite_fun(ptr, size, nmemb, stream->file); + } else { + bytes_written = fwrite(ptr, size, nmemb, stream->file); + } + + if (bytes_written != nmemb) { + if (os_fwrite_fun) // if using hook to induce artificial errors (for + // testing) ... + result = get_maybe_error_errno(); // ... then there is no error in + // the stream, but there is one + // in errno + else + result = ferror(stream->file); + invariant(result != 0); // Should we assert here? + } + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_written); + + return result; +} + +int toku_os_fread_with_source_location(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line) { + int result = 0; + size_t bytes_read; + + toku_io_instrumentation io_annotation; + toku_instr_file_stream_io_begin(io_annotation, + toku_instr_file_op::file_read, + *stream, + nmemb, + src_file, + src_line); + + if ((bytes_read = fread(ptr, size, nmemb, stream->file)) != nmemb) { + if ((feof(stream->file))) + result = EOF; + else + result = ferror(stream->file); + invariant(result != 0); // Should we assert here? } + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_read); + return result; } -FILE * -toku_os_fdopen(int fildes, const char *mode) { - FILE * rval; - if (t_fdopen) - rval = t_fdopen(fildes, mode); - else - rval = fdopen(fildes, mode); +TOKU_FILE *toku_os_fdopen_with_source_location(int fildes, + const char *mode, + const char *filename, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) { + TOKU_FILE *XMALLOC(rval); + if (FT_LIKELY(rval != nullptr)) { + toku_io_instrumentation io_annotation; + toku_instr_file_open_begin(io_annotation, + instr_key, + toku_instr_file_op::file_stream_open, + filename, + src_file, + src_line); + + rval->file = (t_fdopen) ? t_fdopen(fildes, mode) : fdopen(fildes, mode); + toku_instr_file_stream_open_end(io_annotation, *rval); + + if (FT_UNLIKELY(rval->file == nullptr)) { + toku_free(rval); + rval = nullptr; + } + } return rval; } - -FILE * -toku_os_fopen(const char *filename, const char *mode){ - FILE * rval; - if (t_fopen) - rval = t_fopen(filename, mode); - else - rval = fopen(filename, mode); +TOKU_FILE *toku_os_fopen_with_source_location(const char *filename, + const char *mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) { + TOKU_FILE *XMALLOC(rval); + if (FT_UNLIKELY(rval == nullptr)) + return nullptr; + + toku_io_instrumentation io_annotation; + toku_instr_file_open_begin(io_annotation, + instr_key, + toku_instr_file_op::file_stream_open, + filename, + src_file, + src_line); + rval->file = t_fopen ? t_fopen(filename, mode) : fopen(filename, mode); + /* Register the returning "file" value with the system */ + toku_instr_file_stream_open_end(io_annotation, *rval); + + if (FT_UNLIKELY(rval->file == nullptr)) { + toku_free(rval); + rval = nullptr; + } return rval; } -int -toku_os_open(const char *path, int oflag, int mode) { - int rval; +int toku_os_open_with_source_location(const char *path, + int oflag, + int mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) { + int fd; + toku_io_instrumentation io_annotation; + /* register a file open or creation depending on "oflag" */ + toku_instr_file_open_begin( + io_annotation, + instr_key, + ((oflag & O_CREAT) ? toku_instr_file_op::file_create + : toku_instr_file_op::file_open), + path, + src_file, + src_line); if (t_open) - rval = t_open(path, oflag, mode); + fd = t_open(path, oflag, mode); else - rval = open(path, oflag, mode); - return rval; + fd = open(path, oflag, mode); + + toku_instr_file_open_end(io_annotation, fd); + return fd; } -int -toku_os_open_direct(const char *path, int oflag, int mode) { +int toku_os_open_direct(const char *path, + int oflag, + int mode, + const toku_instr_key &instr_key) { int rval; #if defined(HAVE_O_DIRECT) - rval = toku_os_open(path, oflag | O_DIRECT, mode); + rval = toku_os_open(path, oflag | O_DIRECT, mode, instr_key); #elif defined(HAVE_F_NOCACHE) - rval = toku_os_open(path, oflag, mode); + rval = toku_os_open(path, oflag, mode, instr_key); if (rval >= 0) { int r = fcntl(rval, F_NOCACHE, 1); if (r == -1) { @@ -327,63 +560,112 @@ toku_os_open_direct(const char *path, int oflag, int mode) { return rval; } -int -toku_os_fclose(FILE * stream) { +int toku_os_fclose_with_source_location(TOKU_FILE *stream, + const char *src_file, + uint src_line) { int rval = -1; - if (t_fclose) - rval = t_fclose(stream); - else { // if EINTR, retry until success - while (rval != 0) { - rval = fclose(stream); - if (rval && (errno != EINTR)) - break; - } + if (FT_LIKELY(stream != nullptr)) { + /* register a file stream close " */ + toku_io_instrumentation io_annotation; + toku_instr_file_stream_close_begin( + io_annotation, + toku_instr_file_op::file_stream_close, + *stream, + src_file, + src_line); + + if (t_fclose) + rval = t_fclose(stream->file); + else { // if EINTR, retry until success + while (rval != 0) { + rval = fclose(stream->file); + if (rval && (errno != EINTR)) + break; + } + } + /* Register the returning "rval" value with the system */ + toku_instr_file_close_end(io_annotation, rval); + toku_free(stream); + stream = nullptr; } return rval; } -int -toku_os_close(int fd) { // if EINTR, retry until success +int toku_os_close_with_source_location( + int fd, + const char *src_file, + uint src_line) { // if EINTR, retry until success + /* register the file close */ int r = -1; + + /* register a file descriptor close " */ + toku_io_instrumentation io_annotation; + toku_instr_file_fd_close_begin( + io_annotation, toku_instr_file_op::file_close, fd, src_file, src_line); while (r != 0) { - r = close(fd); - if (r) { - int rr = errno; - if (rr!=EINTR) printf("rr=%d (%s)\n", rr, strerror(rr)); - assert(rr==EINTR); - } + r = close(fd); + if (r) { + int rr = errno; + if (rr != EINTR) + printf("rr=%d (%s)\n", rr, strerror(rr)); + assert(rr == EINTR); + } } - return r; -} - -int toku_os_rename(const char *old_name, const char *new_name) { - return rename(old_name, new_name); -} -int toku_os_unlink(const char *path) { return unlink(path); } + /* Regsiter the returning value with the system */ + toku_instr_file_close_end(io_annotation, r); -ssize_t -toku_os_read(int fd, void *buf, size_t count) { - ssize_t r; - if (t_read) - r = t_read(fd, buf, count); - else - r = read(fd, buf, count); return r; } -ssize_t -toku_os_pread (int fd, void *buf, size_t count, off_t offset) { - assert(0==((long long)buf)%512); - assert(0==count%512); - assert(0==offset%512); - ssize_t r; +ssize_t toku_os_read_with_source_location(int fd, + void *buf, + size_t count, + const char *src_file, + uint src_line) { + ssize_t bytes_read; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_read, + fd, + count, + src_file, + src_line); + + bytes_read = (t_read) ? t_read(fd, buf, count) : read(fd, buf, count); + + toku_instr_file_io_end(io_annotation, bytes_read); + + return bytes_read; +} + +ssize_t inline_toku_os_pread_with_source_location(int fd, + void *buf, + size_t count, + off_t offset, + const char *src_file, + uint src_line) { + assert(0 == ((long long)buf) % 512); + assert(0 == count % 512); + assert(0 == offset % 512); + ssize_t bytes_read; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_read, + fd, + count, + src_file, + src_line); if (t_pread) { - r = t_pread(fd, buf, count, offset); + bytes_read = t_pread(fd, buf, count, offset); } else { - r = pread(fd, buf, count, offset); + bytes_read = pread(fd, buf, count, offset); } - return r; + toku_instr_file_io_end(io_annotation, bytes_read); + + return bytes_read; } void toku_os_recursive_delete(const char *path) { @@ -411,13 +693,24 @@ void toku_set_func_fsync(int (*fsync_function)(int)) { } // keep trying if fsync fails because of EINTR -static void file_fsync_internal (int fd) { +void file_fsync_internal_with_source_location(int fd, + const char *src_file, + uint src_line) { uint64_t tstart = toku_current_time_microsec(); int r = -1; uint64_t eintr_count = 0; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_sync, + fd, + 0, + src_file, + src_line); + while (r != 0) { - if (t_fsync) { - r = t_fsync(fd); + if (t_fsync) { + r = t_fsync(fd); } else { r = fsync(fd); } @@ -429,6 +722,9 @@ static void file_fsync_internal (int fd) { toku_sync_fetch_and_add(&toku_fsync_count, 1); uint64_t duration = toku_current_time_microsec() - tstart; toku_sync_fetch_and_add(&toku_fsync_time, duration); + + toku_instr_file_io_end(io_annotation, 0); + 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); diff --git a/storage/tokudb/PerconaFT/portability/portability.cc b/storage/tokudb/PerconaFT/portability/portability.cc index ccebf91de51..13e9658edd9 100644 --- a/storage/tokudb/PerconaFT/portability/portability.cc +++ b/storage/tokudb/PerconaFT/portability/portability.cc @@ -76,6 +76,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "toku_os.h" #include "toku_time.h" #include "memory.h" + +#include "toku_instrumentation.h" + #include #include @@ -165,13 +168,26 @@ toku_os_get_phys_memory_size(void) { #endif } -int -toku_os_get_file_size(int fildes, int64_t *fsize) { +int toku_os_get_file_size_with_source_location(int fildes, + int64_t *fsize, + const char *src_file, + uint src_line) { toku_struct_stat sbuf; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_stat, + fildes, + 0, + src_file, + src_line); + int r = fstat(fildes, &sbuf); - if (r==0) { + if (r == 0) { *fsize = sbuf.st_size; } + toku_instr_file_io_end(io_annotation, 0); + return r; } @@ -265,15 +281,39 @@ toku_os_get_max_process_data_size(uint64_t *maxdata) { return r; } -int -toku_stat(const char *name, toku_struct_stat *buf) { +int toku_stat_with_source_location(const char *name, + toku_struct_stat *buf, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) { + toku_io_instrumentation io_annotation; + toku_instr_file_name_io_begin(io_annotation, + instr_key, + toku_instr_file_op::file_stat, + name, + 0, + src_file, + src_line); int r = stat(name, buf); + + toku_instr_file_io_end(io_annotation, 0); return r; } -int -toku_fstat(int fd, toku_struct_stat *buf) { +int toku_os_fstat_with_source_location(int fd, + toku_struct_stat *buf, + const char *src_file, + uint src_line) { + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_stat, + fd, + 0, + src_file, + src_line); + int r = fstat(fd, buf); + toku_instr_file_io_end(io_annotation, 0); return r; } @@ -415,5 +455,9 @@ void __attribute__((constructor)) toku_portability_helgrind_ignore(void); void toku_portability_helgrind_ignore(void) { TOKU_VALGRIND_HG_DISABLE_CHECKING(&toku_cached_hz, sizeof toku_cached_hz); - TOKU_VALGRIND_HG_DISABLE_CHECKING(&toku_cached_pagesize, sizeof toku_cached_pagesize); + TOKU_VALGRIND_HG_DISABLE_CHECKING(&toku_cached_pagesize, + sizeof toku_cached_pagesize); } + +static const pfs_key_t pfs_not_instrumented = 0xFFFFFFFF; +toku_instr_key toku_uninstrumented(pfs_not_instrumented); diff --git a/storage/tokudb/PerconaFT/portability/tests/rwlock_condvar.h b/storage/tokudb/PerconaFT/portability/tests/rwlock_condvar.h index 92f2fb354f7..d1ebc81e1dc 100644 --- a/storage/tokudb/PerconaFT/portability/tests/rwlock_condvar.h +++ b/storage/tokudb/PerconaFT/portability/tests/rwlock_condvar.h @@ -107,10 +107,10 @@ get_waitstate(void) #endif int toku_cv_fair_rwlock_init (toku_cv_fair_rwlock_t *rwlock) { - rwlock->state=0; + rwlock->state = 0; rwlock->waiters_head = NULL; rwlock->waiters_tail = NULL; - toku_mutex_init(&rwlock->mutex, NULL); + toku_mutex_init(toku_uninstrumented, &rwlock->mutex, nullptr); return 0; } diff --git a/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rdlock.cc b/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rdlock.cc index 364bd7d3766..62aa5205f3c 100644 --- a/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rdlock.cc +++ b/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rdlock.cc @@ -48,7 +48,7 @@ int test_main(int argc __attribute__((__unused__)), char *const argv[] __attribu toku_pthread_rwlock_t rwlock; ZERO_STRUCT(rwlock); - toku_pthread_rwlock_init(&rwlock, NULL); + toku_pthread_rwlock_init(toku_uninstrumented, &rwlock, nullptr); toku_pthread_rwlock_rdlock(&rwlock); toku_pthread_rwlock_rdlock(&rwlock); toku_pthread_rwlock_rdunlock(&rwlock); diff --git a/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rwr.cc b/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rwr.cc index 3ca9e06bff7..92b30421ba9 100644 --- a/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rwr.cc +++ b/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rwr.cc @@ -71,13 +71,19 @@ int test_main(int argc , char *const argv[] ) { toku_pthread_t tid; void *retptr; - toku_pthread_rwlock_init(&rwlock, NULL); - state = 37; if (verbose) printf("%s:%d\n", __FUNCTION__, __LINE__); + toku_pthread_rwlock_init(toku_uninstrumented, &rwlock, nullptr); + state = 37; + if (verbose) + printf("%s:%d\n", __FUNCTION__, __LINE__); toku_pthread_rwlock_rdlock(&rwlock); - r = toku_pthread_create(&tid, NULL, f, &rwlock); assert(r == 0); + r = toku_pthread_create(toku_uninstrumented, &tid, nullptr, f, &rwlock); + assert(r == 0); - assert(state==37); state = 42; if (verbose) printf("%s:%d\n", __FUNCTION__, __LINE__); + assert(state == 37); + state = 42; + if (verbose) + printf("%s:%d\n", __FUNCTION__, __LINE__); sleep(4); assert(state==16); state = 44; if (verbose) printf("%s:%d\n", __FUNCTION__, __LINE__); toku_pthread_rwlock_rdlock(&rwlock); diff --git a/storage/tokudb/PerconaFT/portability/tests/test-stat.cc b/storage/tokudb/PerconaFT/portability/tests/test-stat.cc index 494a17bd074..57201764afb 100644 --- a/storage/tokudb/PerconaFT/portability/tests/test-stat.cc +++ b/storage/tokudb/PerconaFT/portability/tests/test-stat.cc @@ -47,10 +47,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. static void test_stat(const char *dirname, int result, int ex_errno) { int r; toku_struct_stat buf; - r = toku_stat(dirname, &buf); - //printf("stat %s %d %d\n", dirname, r, errno); fflush(stdout); - assert(r==result); - if (r!=0) assert(get_maybe_error_errno() == ex_errno); + r = toku_stat(dirname, &buf, toku_uninstrumented); + // printf("stat %s %d %d\n", dirname, r, errno); fflush(stdout); + assert(r == result); + if (r != 0) + assert(get_maybe_error_errno() == ex_errno); } int main(void) { diff --git a/storage/tokudb/PerconaFT/portability/tests/test-toku-malloc.cc b/storage/tokudb/PerconaFT/portability/tests/test-toku-malloc.cc index 1e1c7533c15..0d99b36b51a 100644 --- a/storage/tokudb/PerconaFT/portability/tests/test-toku-malloc.cc +++ b/storage/tokudb/PerconaFT/portability/tests/test-toku-malloc.cc @@ -53,10 +53,12 @@ int main(void) { int i; const int max_threads = 2; toku_pthread_t tids[max_threads]; - for (i=0; i= 5) && (MYSQL_VERSION_MINOR >= 7) + return PSI_THREAD_CALL(spawn_thread)( + key.id(), reinterpret_cast(thread), + attr, start_routine, arg); +#else + return PSI_THREAD_CALL(spawn_thread)( + key.id(), thread, attr, start_routine, arg); +#endif +} + +void toku_instr_register_current_thread(const toku_instr_key &key) { + struct PSI_thread *psi_thread = + PSI_THREAD_CALL(new_thread)(key.id(), nullptr, 0); + PSI_THREAD_CALL(set_thread)(psi_thread); +} + +void toku_instr_delete_current_thread() { + PSI_THREAD_CALL(delete_current_thread)(); +} + +// I/O instrumentation + +void toku_instr_file_open_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + const char *src_file, + int src_line) { + io_instr.locker = + PSI_FILE_CALL(get_thread_file_name_locker)( + &io_instr.state, key.id(), static_cast(op), + name, io_instr.locker); + if (io_instr.locker != nullptr) { + PSI_FILE_CALL(start_file_open_wait) + (io_instr.locker, src_file, src_line); + } +} + +void toku_instr_file_stream_open_end(toku_io_instrumentation &io_instr, + TOKU_FILE &file) { + file.key = nullptr; + if (FT_LIKELY(io_instr.locker)) { + file.key = + PSI_FILE_CALL(end_file_open_wait)(io_instr.locker, file.file); + } +} + +void toku_instr_file_open_end(toku_io_instrumentation &io_instr, int fd) { + if (FT_LIKELY(io_instr.locker)) + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor) + (io_instr.locker, fd); +} + +void toku_instr_file_name_close_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + const char *src_file, + int src_line) { + io_instr.locker = + PSI_FILE_CALL(get_thread_file_name_locker)( + &io_instr.state, key.id(), static_cast(op), + name, + io_instr.locker); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_close_wait) + (io_instr.locker, src_file, src_line); + } +} + +void toku_instr_file_stream_close_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + const TOKU_FILE &file, + const char *src_file, + int src_line) { + io_instr.locker = nullptr; + if (FT_LIKELY(file.key)) { + io_instr.locker = PSI_FILE_CALL(get_thread_file_stream_locker)( + &io_instr.state, file.key, (PSI_file_operation)op); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_close_wait) + (io_instr.locker, src_file, src_line); + } + } +} + +void toku_instr_file_fd_close_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + int fd, + const char *src_file, + int src_line) { + io_instr.locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &io_instr.state, fd, (PSI_file_operation)op); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_close_wait) + (io_instr.locker, src_file, src_line); + } +} + +void toku_instr_file_close_end(const toku_io_instrumentation &io_instr, + int result) { + if (FT_LIKELY(io_instr.locker)) + PSI_FILE_CALL(end_file_close_wait) + (io_instr.locker, result); +} + +void toku_instr_file_io_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + int fd, + ssize_t count, + const char *src_file, + int src_line) { + io_instr.locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &io_instr.state, fd, (PSI_file_operation)op); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_wait) + (io_instr.locker, count, src_file, src_line); + } +} + +void toku_instr_file_name_io_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + ssize_t count, + const char *src_file, + int src_line) { + io_instr.locker = + PSI_FILE_CALL(get_thread_file_name_locker)(&io_instr.state, + key.id(), + (PSI_file_operation)op, + name, + &io_instr.locker); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_wait) + (io_instr.locker, count, src_file, src_line); + } +} + +void toku_instr_file_stream_io_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + const TOKU_FILE &file, + ssize_t count, + const char *src_file, + int src_line) { + io_instr.locker = nullptr; + if (FT_LIKELY(file.key)) { + io_instr.locker = PSI_FILE_CALL(get_thread_file_stream_locker)( + &io_instr.state, file.key, (PSI_file_operation)op); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_wait) + (io_instr.locker, count, src_file, src_line); + } + } +} + +void toku_instr_file_io_end(toku_io_instrumentation &io_instr, ssize_t count) { + if (FT_LIKELY(io_instr.locker)) + PSI_FILE_CALL(end_file_wait) + (io_instr.locker, count); +} + +// Mutex instrumentation + +void toku_instr_mutex_init(const toku_instr_key &key, toku_mutex_t &mutex) { + mutex.psi_mutex = PSI_MUTEX_CALL(init_mutex)(key.id(), &mutex.pmutex); +#if TOKU_PTHREAD_DEBUG + mutex.instr_key_id = key.id(); +#endif +} + +void toku_instr_mutex_destroy(PSI_mutex *&mutex_instr) { + if (mutex_instr != nullptr) { + PSI_MUTEX_CALL(destroy_mutex)(mutex_instr); + mutex_instr = nullptr; + } +} + +void toku_instr_mutex_lock_start(toku_mutex_instrumentation &mutex_instr, + toku_mutex_t &mutex, + const char *src_file, + int src_line) { + mutex_instr.locker = nullptr; + if (mutex.psi_mutex) { + mutex_instr.locker = + PSI_MUTEX_CALL(start_mutex_wait)(&mutex_instr.state, + mutex.psi_mutex, + PSI_MUTEX_LOCK, + src_file, + src_line); + } +} + +void toku_instr_mutex_trylock_start(toku_mutex_instrumentation &mutex_instr, + toku_mutex_t &mutex, + const char *src_file, + int src_line) { + mutex_instr.locker = nullptr; + if (mutex.psi_mutex) { + mutex_instr.locker = + PSI_MUTEX_CALL(start_mutex_wait)(&mutex_instr.state, + mutex.psi_mutex, + PSI_MUTEX_TRYLOCK, + src_file, + src_line); + } +} + +void toku_instr_mutex_lock_end(toku_mutex_instrumentation &mutex_instr, + int pthread_mutex_lock_result) { + if (mutex_instr.locker) + PSI_MUTEX_CALL(end_mutex_wait) + (mutex_instr.locker, pthread_mutex_lock_result); +} + +void toku_instr_mutex_unlock(PSI_mutex *mutex_instr) { + if (mutex_instr) + PSI_MUTEX_CALL(unlock_mutex)(mutex_instr); +} + +// Condvar instrumentation + +void toku_instr_cond_init(const toku_instr_key &key, toku_cond_t &cond) { + cond.psi_cond = PSI_COND_CALL(init_cond)(key.id(), &cond.pcond); +#if TOKU_PTHREAD_DEBUG + cond.instr_key_id = key.id(); +#endif +} + +void toku_instr_cond_destroy(PSI_cond *&cond_instr) { + if (cond_instr != nullptr) { + PSI_COND_CALL(destroy_cond)(cond_instr); + cond_instr = nullptr; + } +} + +void toku_instr_cond_wait_start(toku_cond_instrumentation &cond_instr, + toku_instr_cond_op op, + toku_cond_t &cond, + toku_mutex_t &mutex, + const char *src_file, + int src_line) { + cond_instr.locker = nullptr; + if (cond.psi_cond) { + /* Instrumentation start */ + cond_instr.locker = + PSI_COND_CALL(start_cond_wait)(&cond_instr.state, + cond.psi_cond, + mutex.psi_mutex, + (PSI_cond_operation)op, + src_file, + src_line); + } +} + +void toku_instr_cond_wait_end(toku_cond_instrumentation &cond_instr, + int pthread_cond_wait_result) { + if (cond_instr.locker) + PSI_COND_CALL(end_cond_wait) + (cond_instr.locker, pthread_cond_wait_result); +} + +void toku_instr_cond_signal(const toku_cond_t &cond) { + if (cond.psi_cond) + PSI_COND_CALL(signal_cond)(cond.psi_cond); +} + +void toku_instr_cond_broadcast(const toku_cond_t &cond) { + if (cond.psi_cond) + PSI_COND_CALL(broadcast_cond)(cond.psi_cond); +} + +// rwlock instrumentation + +void toku_instr_rwlock_init(const toku_instr_key &key, + toku_pthread_rwlock_t &rwlock) { + rwlock.psi_rwlock = PSI_RWLOCK_CALL(init_rwlock)(key.id(), &rwlock.rwlock); +#if TOKU_PTHREAD_DEBUG + rwlock.instr_key_id = key.id(); +#endif +} + +void toku_instr_rwlock_destroy(PSI_rwlock *&rwlock_instr) { + if (rwlock_instr != nullptr) { + PSI_RWLOCK_CALL(destroy_rwlock)(rwlock_instr); + rwlock_instr = nullptr; + } +} + +void toku_instr_rwlock_rdlock_wait_start( + toku_rwlock_instrumentation &rwlock_instr, + toku_pthread_rwlock_t &rwlock, + const char *src_file, + int src_line) { + rwlock_instr.locker = nullptr; + if (rwlock.psi_rwlock) { + /* Instrumentation start */ + rwlock_instr.locker = + PSI_RWLOCK_CALL(start_rwlock_rdwait)(&rwlock_instr.state, + rwlock.psi_rwlock, + PSI_RWLOCK_READLOCK, + src_file, + src_line); + } +} + +void toku_instr_rwlock_wrlock_wait_start( + toku_rwlock_instrumentation &rwlock_instr, + toku_pthread_rwlock_t &rwlock, + const char *src_file, + int src_line) { + rwlock_instr.locker = nullptr; + if (rwlock.psi_rwlock) { + /* Instrumentation start */ + rwlock_instr.locker = + PSI_RWLOCK_CALL(start_rwlock_wrwait)(&rwlock_instr.state, + rwlock.psi_rwlock, + PSI_RWLOCK_WRITELOCK, + src_file, + src_line); + } +} + +void toku_instr_rwlock_rdlock_wait_end( + toku_rwlock_instrumentation &rwlock_instr, + int pthread_rwlock_wait_result) { + if (rwlock_instr.locker) + PSI_RWLOCK_CALL(end_rwlock_rdwait) + (rwlock_instr.locker, pthread_rwlock_wait_result); +} + +void toku_instr_rwlock_wrlock_wait_end( + toku_rwlock_instrumentation &rwlock_instr, + int pthread_rwlock_wait_result) { + if (rwlock_instr.locker) + PSI_RWLOCK_CALL(end_rwlock_wrwait) + (rwlock_instr.locker, pthread_rwlock_wait_result); +} + +void toku_instr_rwlock_unlock(toku_pthread_rwlock_t &rwlock) { + if (rwlock.psi_rwlock) + PSI_RWLOCK_CALL(unlock_rwlock)(rwlock.psi_rwlock); +} + +#endif // MYSQL_TOKUDB_ENGINE diff --git a/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h new file mode 100644 index 00000000000..d6b0ed35ce9 --- /dev/null +++ b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h @@ -0,0 +1,249 @@ +#ifdef TOKU_INSTR_MYSQL_H +// This file can be included only from toku_instumentation.h because +// it replaces the defintitions for the case if MySQL PFS is available +#error "toku_instr_mysql.h can be included only once" +#else // TOKU_INSTR_MYSQL_H +#define TOKU_INSTR_MYSQL_H + +#include + +// As these macros are defined in my_global.h +// and they are also defined in command line +// undefine them here to avoid compilation errors. +#undef __STDC_FORMAT_MACROS +#undef __STDC_LIMIT_MACROS +#include // PSI_file +#include // PSI_mutex + +#ifndef HAVE_PSI_MUTEX_INTERFACE +#error HAVE_PSI_MUTEX_INTERFACE required +#endif +#ifndef HAVE_PSI_RWLOCK_INTERFACE +#error HAVE_PSI_RWLOCK_INTERFACE required +#endif +#ifndef HAVE_PSI_THREAD_INTERFACE +#error HAVE_PSI_THREAD_INTERFACE required +#endif + +// Instrumentation keys + +class toku_instr_key { + private: + pfs_key_t m_id; + + public: + toku_instr_key(toku_instr_object_type type, + const char *group, + const char *name) { + switch (type) { + case toku_instr_object_type::mutex: { + PSI_mutex_info mutex_info{&m_id, name, 0}; + mysql_mutex_register(group, &mutex_info, 1); + } break; + case toku_instr_object_type::rwlock: { + PSI_rwlock_info rwlock_info{&m_id, name, 0}; + mysql_rwlock_register(group, &rwlock_info, 1); + } break; + case toku_instr_object_type::cond: { + PSI_cond_info cond_info{&m_id, name, 0}; + mysql_cond_register(group, &cond_info, 1); + } break; + case toku_instr_object_type::thread: { + PSI_thread_info thread_info{&m_id, name, 0}; + mysql_thread_register(group, &thread_info, 1); + } break; + case toku_instr_object_type::file: { + PSI_file_info file_info{&m_id, name, 0}; + mysql_file_register(group, &file_info, 1); + } break; + } + } + + explicit toku_instr_key(pfs_key_t key_id) : m_id(key_id) {} + + pfs_key_t id() const { return m_id; } +}; + +// Thread instrumentation +int toku_pthread_create(const toku_instr_key &key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg); +void toku_instr_register_current_thread(const toku_instr_key &key); +void toku_instr_delete_current_thread(); + +// I/O instrumentation + +enum class toku_instr_file_op { + file_stream_open = PSI_FILE_STREAM_OPEN, + file_create = PSI_FILE_CREATE, + file_open = PSI_FILE_OPEN, + file_delete = PSI_FILE_DELETE, + file_rename = PSI_FILE_RENAME, + file_read = PSI_FILE_READ, + file_write = PSI_FILE_WRITE, + file_sync = PSI_FILE_SYNC, + file_stream_close = PSI_FILE_STREAM_CLOSE, + file_close = PSI_FILE_CLOSE, + file_stat = PSI_FILE_STAT +}; + +struct toku_io_instrumentation { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + + toku_io_instrumentation() : locker(nullptr) {} +}; + +void toku_instr_file_open_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + const char *src_file, + int src_line); +void toku_instr_file_stream_open_end(toku_io_instrumentation &io_instr, + TOKU_FILE &file); +void toku_instr_file_open_end(toku_io_instrumentation &io_instr, int fd); +void toku_instr_file_name_close_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + const char *src_file, + int src_line); +void toku_instr_file_stream_close_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + const TOKU_FILE &file, + const char *src_file, + int src_line); +void toku_instr_file_fd_close_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + int fd, + const char *src_file, + int src_line); +void toku_instr_file_close_end(const toku_io_instrumentation &io_instr, + int result); +void toku_instr_file_io_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + int fd, + ssize_t count, + const char *src_file, + int src_line); +void toku_instr_file_name_io_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + ssize_t count, + const char *src_file, + int src_line); +void toku_instr_file_stream_io_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + const TOKU_FILE &file, + ssize_t count, + const char *src_file, + int src_line); +void toku_instr_file_io_end(toku_io_instrumentation &io_instr, ssize_t count); + +// Mutex instrumentation + +struct toku_mutex_instrumentation { + struct PSI_mutex_locker *locker; + PSI_mutex_locker_state state; + + toku_mutex_instrumentation() : locker(nullptr) {} +}; + +void toku_instr_mutex_init(const toku_instr_key &key, toku_mutex_t &mutex); +void toku_instr_mutex_destroy(PSI_mutex *&mutex_instr); +void toku_instr_mutex_lock_start(toku_mutex_instrumentation &mutex_instr, + toku_mutex_t &mutex, + const char *src_file, + int src_line); +void toku_instr_mutex_trylock_start(toku_mutex_instrumentation &mutex_instr, + toku_mutex_t &mutex, + const char *src_file, + int src_line); +void toku_instr_mutex_lock_end(toku_mutex_instrumentation &mutex_instr, + int pthread_mutex_lock_result); +void toku_instr_mutex_unlock(PSI_mutex *mutex_instr); + +// Instrumentation probes + +class toku_instr_probe_pfs { + private: + std::unique_ptr mutex; + toku_mutex_instrumentation mutex_instr; + + public: + explicit toku_instr_probe_pfs(const toku_instr_key &key); + + ~toku_instr_probe_pfs(); + + void start_with_source_location(const char *src_file, int src_line) { + mutex_instr.locker = nullptr; + toku_instr_mutex_lock_start(mutex_instr, *mutex, src_file, src_line); + } + + void stop() { toku_instr_mutex_lock_end(mutex_instr, 0); } +}; + +typedef toku_instr_probe_pfs toku_instr_probe; + +// Condvar instrumentation + +struct toku_cond_instrumentation { + struct PSI_cond_locker *locker; + PSI_cond_locker_state state; + + toku_cond_instrumentation() : locker(nullptr) {} +}; + +enum class toku_instr_cond_op { + cond_wait = PSI_COND_WAIT, + cond_timedwait = PSI_COND_TIMEDWAIT, +}; + +void toku_instr_cond_init(const toku_instr_key &key, toku_cond_t &cond); +void toku_instr_cond_destroy(PSI_cond *&cond_instr); +void toku_instr_cond_wait_start(toku_cond_instrumentation &cond_instr, + toku_instr_cond_op op, + toku_cond_t &cond, + toku_mutex_t &mutex, + const char *src_file, + int src_line); +void toku_instr_cond_wait_end(toku_cond_instrumentation &cond_instr, + int pthread_cond_wait_result); +void toku_instr_cond_signal(const toku_cond_t &cond); +void toku_instr_cond_broadcast(const toku_cond_t &cond); + +// rwlock instrumentation + +struct toku_rwlock_instrumentation { + struct PSI_rwlock_locker *locker; + PSI_rwlock_locker_state state; + + toku_rwlock_instrumentation() : locker(nullptr) { } +}; + +void toku_instr_rwlock_init(const toku_instr_key &key, + toku_pthread_rwlock_t &rwlock); +void toku_instr_rwlock_destroy(PSI_rwlock *&rwlock_instr); +void toku_instr_rwlock_rdlock_wait_start( + toku_rwlock_instrumentation &rwlock_instr, + toku_pthread_rwlock_t &rwlock, + const char *src_file, + int src_line); +void toku_instr_rwlock_wrlock_wait_start( + toku_rwlock_instrumentation &rwlock_instr, + toku_pthread_rwlock_t &rwlock, + const char *src_file, + int src_line); +void toku_instr_rwlock_rdlock_wait_end( + toku_rwlock_instrumentation &rwlock_instr, + int pthread_rwlock_wait_result); +void toku_instr_rwlock_wrlock_wait_end( + toku_rwlock_instrumentation &rwlock_instr, + int pthread_rwlock_wait_result); +void toku_instr_rwlock_unlock(toku_pthread_rwlock_t &rwlock); + +#endif // TOKU_INSTR_MYSQL_H diff --git a/storage/tokudb/PerconaFT/portability/toku_instrumentation.h b/storage/tokudb/PerconaFT/portability/toku_instrumentation.h new file mode 100644 index 00000000000..8c9390edc0a --- /dev/null +++ b/storage/tokudb/PerconaFT/portability/toku_instrumentation.h @@ -0,0 +1,339 @@ +#pragma once + +#include // FILE + +// Performance instrumentation object identifier type +typedef unsigned int pfs_key_t; + +enum class toku_instr_object_type { mutex, rwlock, cond, thread, file }; + +struct PSI_file; + +struct TOKU_FILE { + /** The real file. */ + FILE *file; + struct PSI_file *key; + TOKU_FILE() : file(nullptr), key(nullptr) {} +}; + +struct PSI_mutex; +struct PSI_cond; +struct PSI_rwlock; + +struct toku_mutex_t; +struct toku_cond_t; +struct toku_pthread_rwlock_t; + +class toku_instr_key; + +class toku_instr_probe_empty { + public: + explicit toku_instr_probe_empty(UU(const toku_instr_key &key)) {} + + void start_with_source_location(UU(const char *src_file), + UU(int src_line)) {} + + void stop() {} +}; + +#define TOKU_PROBE_START(p) p->start_with_source_location(__FILE__, __LINE__) +#define TOKU_PROBE_STOP(p) p->stop + +extern toku_instr_key toku_uninstrumented; + +#ifndef MYSQL_TOKUDB_ENGINE + +#include + +class toku_instr_key { + public: + toku_instr_key(UU(toku_instr_object_type type), + UU(const char *group), + UU(const char *name)) {} + + explicit toku_instr_key(UU(pfs_key_t key_id)) {} +}; + +typedef toku_instr_probe_empty toku_instr_probe; + +enum class toku_instr_file_op { + file_stream_open, + file_create, + file_open, + file_delete, + file_rename, + file_read, + file_write, + file_sync, + file_stream_close, + file_close, + file_stat +}; + +struct PSI_file {}; +struct PSI_mutex {}; + +struct toku_io_instrumentation {}; + +inline int toku_pthread_create(UU(const toku_instr_key &key), + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg) { + return pthread_create(thread, attr, start_routine, arg); +} + +inline void toku_instr_register_current_thread() {} + +inline void toku_instr_delete_current_thread() {} + +// Instrument file creation, opening, closing, and renaming +inline void toku_instr_file_open_begin(UU(toku_io_instrumentation &io_instr), + UU(const toku_instr_key &key), + UU(toku_instr_file_op op), + UU(const char *name), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_stream_open_end( + UU(toku_io_instrumentation &io_instr), + UU(TOKU_FILE &file)) {} + +inline void toku_instr_file_open_end(UU(toku_io_instrumentation &io_instr), + UU(int fd)) {} + +inline void toku_instr_file_name_close_begin( + UU(toku_io_instrumentation &io_instr), + UU(const toku_instr_key &key), + UU(toku_instr_file_op op), + UU(const char *name), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_stream_close_begin( + UU(toku_io_instrumentation &io_instr), + UU(toku_instr_file_op op), + UU(TOKU_FILE &file), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_fd_close_begin( + UU(toku_io_instrumentation &io_instr), + UU(toku_instr_file_op op), + UU(int fd), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_close_end(UU(toku_io_instrumentation &io_instr), + UU(int result)) {} + +inline void toku_instr_file_io_begin(UU(toku_io_instrumentation &io_instr), + UU(toku_instr_file_op op), + UU(int fd), + UU(unsigned int count), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_name_io_begin(UU(toku_io_instrumentation &io_instr), + UU(const toku_instr_key &key), + UU(toku_instr_file_op op), + UU(const char *name), + UU(unsigned int count), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_stream_io_begin( + UU(toku_io_instrumentation &io_instr), + UU(toku_instr_file_op op), + UU(TOKU_FILE &file), + UU(unsigned int count), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_io_end(UU(toku_io_instrumentation &io_instr), + UU(unsigned int count)) {} + +struct toku_mutex_t; + +struct toku_mutex_instrumentation {}; + +inline PSI_mutex *toku_instr_mutex_init(UU(const toku_instr_key &key), + UU(toku_mutex_t &mutex)) { + return nullptr; +} + +inline void toku_instr_mutex_destroy(UU(PSI_mutex *&mutex_instr)) {} + +inline void toku_instr_mutex_lock_start( + UU(toku_mutex_instrumentation &mutex_instr), + UU(toku_mutex_t &mutex), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_mutex_trylock_start( + UU(toku_mutex_instrumentation &mutex_instr), + UU(toku_mutex_t &mutex), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_mutex_lock_end( + UU(toku_mutex_instrumentation &mutex_instr), + UU(int pthread_mutex_lock_result)) {} + +inline void toku_instr_mutex_unlock(UU(PSI_mutex *mutex_instr)) {} + +struct toku_cond_instrumentation {}; + +enum class toku_instr_cond_op { + cond_wait, + cond_timedwait, +}; + +inline PSI_cond *toku_instr_cond_init(UU(const toku_instr_key &key), + UU(toku_cond_t &cond)) { + return nullptr; +} + +inline void toku_instr_cond_destroy(UU(PSI_cond *&cond_instr)) {} + +inline void toku_instr_cond_wait_start( + UU(toku_cond_instrumentation &cond_instr), + UU(toku_instr_cond_op op), + UU(toku_cond_t &cond), + UU(toku_mutex_t &mutex), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_cond_wait_end(UU(toku_cond_instrumentation &cond_instr), + UU(int pthread_cond_wait_result)) {} + +inline void toku_instr_cond_signal(UU(toku_cond_t &cond)) {} + +inline void toku_instr_cond_broadcast(UU(toku_cond_t &cond)) {} + +// rwlock instrumentation +struct toku_rwlock_instrumentation {}; + +inline PSI_rwlock *toku_instr_rwlock_init(UU(const toku_instr_key &key), + UU(toku_pthread_rwlock_t &rwlock)) { + return nullptr; +} + +inline void toku_instr_rwlock_destroy(UU(PSI_rwlock *&rwlock_instr)) {} + +inline void toku_instr_rwlock_rdlock_wait_start( + UU(toku_rwlock_instrumentation &rwlock_instr), + UU(toku_pthread_rwlock_t &rwlock), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_rwlock_wrlock_wait_start( + UU(toku_rwlock_instrumentation &rwlock_instr), + UU(toku_pthread_rwlock_t &rwlock), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_rwlock_rdlock_wait_end( + UU(toku_rwlock_instrumentation &rwlock_instr), + UU(int pthread_rwlock_wait_result)) {} + +inline void toku_instr_rwlock_wrlock_wait_end( + UU(toku_rwlock_instrumentation &rwlock_instr), + UU(int pthread_rwlock_wait_result)) {} + +inline void toku_instr_rwlock_unlock(UU(toku_pthread_rwlock_t &rwlock)) {} + +#else // MYSQL_TOKUDB_ENGINE +// There can be not only mysql but also mongodb or any other PFS stuff +#include +#endif // MYSQL_TOKUDB_ENGINE + +extern toku_instr_key toku_uninstrumented; + +extern toku_instr_probe *toku_instr_probe_1; + +// threads +extern toku_instr_key *extractor_thread_key; +extern toku_instr_key *fractal_thread_key; +extern toku_instr_key *io_thread_key; +extern toku_instr_key *eviction_thread_key; +extern toku_instr_key *kibbutz_thread_key; +extern toku_instr_key *minicron_thread_key; +extern toku_instr_key *tp_internal_thread_key; + +// Files +extern toku_instr_key *tokudb_file_data_key; +extern toku_instr_key *tokudb_file_load_key; +extern toku_instr_key *tokudb_file_tmp_key; +extern toku_instr_key *tokudb_file_log_key; + +// Mutexes +extern toku_instr_key *kibbutz_mutex_key; +extern toku_instr_key *minicron_p_mutex_key; +extern toku_instr_key *queue_result_mutex_key; +extern toku_instr_key *tpool_lock_mutex_key; +extern toku_instr_key *workset_lock_mutex_key; +extern toku_instr_key *bjm_jobs_lock_mutex_key; +extern toku_instr_key *log_internal_lock_mutex_key; +extern toku_instr_key *cachetable_ev_thread_lock_mutex_key; +extern toku_instr_key *cachetable_disk_nb_mutex_key; +extern toku_instr_key *cachetable_m_mutex_key; +extern toku_instr_key *safe_file_size_lock_mutex_key; +extern toku_instr_key *checkpoint_safe_mutex_key; +extern toku_instr_key *ft_ref_lock_mutex_key; +extern toku_instr_key *loader_error_mutex_key; +extern toku_instr_key *bfs_mutex_key; +extern toku_instr_key *loader_bl_mutex_key; +extern toku_instr_key *loader_fi_lock_mutex_key; +extern toku_instr_key *loader_out_mutex_key; +extern toku_instr_key *result_output_condition_lock_mutex_key; +extern toku_instr_key *block_table_mutex_key; +extern toku_instr_key *rollback_log_node_cache_mutex_key; +extern toku_instr_key *txn_lock_mutex_key; +extern toku_instr_key *txn_state_lock_mutex_key; +extern toku_instr_key *txn_child_manager_mutex_key; +extern toku_instr_key *txn_manager_lock_mutex_key; +extern toku_instr_key *treenode_mutex_key; +extern toku_instr_key *manager_mutex_key; +extern toku_instr_key *manager_escalation_mutex_key; +extern toku_instr_key *manager_escalator_mutex_key; +extern toku_instr_key *db_txn_struct_i_txn_mutex_key; +extern toku_instr_key *indexer_i_indexer_lock_mutex_key; +extern toku_instr_key *indexer_i_indexer_estimate_lock_mutex_key; +extern toku_instr_key *locktree_request_info_mutex_key; +extern toku_instr_key *locktree_request_info_retry_mutex_key; + +// condition vars +extern toku_instr_key *result_state_cond_key; +extern toku_instr_key *bjm_jobs_wait_key; +extern toku_instr_key *cachetable_p_refcount_wait_key; +extern toku_instr_key *cachetable_m_flow_control_cond_key; +extern toku_instr_key *cachetable_m_ev_thread_cond_key; +extern toku_instr_key *bfs_cond_key; +extern toku_instr_key *result_output_condition_key; +extern toku_instr_key *manager_m_escalator_done_key; +extern toku_instr_key *lock_request_m_wait_cond_key; +extern toku_instr_key *queue_result_cond_key; +extern toku_instr_key *ws_worker_wait_key; +extern toku_instr_key *rwlock_wait_read_key; +extern toku_instr_key *rwlock_wait_write_key; +extern toku_instr_key *rwlock_cond_key; +extern toku_instr_key *tp_thread_wait_key; +extern toku_instr_key *tp_pool_wait_free_key; +extern toku_instr_key *frwlock_m_wait_read_key; +extern toku_instr_key *kibbutz_k_cond_key; +extern toku_instr_key *minicron_p_condvar_key; +extern toku_instr_key *locktree_request_info_retry_cv_key; + +// rwlocks +extern toku_instr_key *multi_operation_lock_key; +extern toku_instr_key *low_priority_multi_operation_lock_key; +extern toku_instr_key *cachetable_m_list_lock_key; +extern toku_instr_key *cachetable_m_pending_lock_expensive_key; +extern toku_instr_key *cachetable_m_pending_lock_cheap_key; +extern toku_instr_key *cachetable_m_lock_key; +extern toku_instr_key *result_i_open_dbs_rwlock_key; +extern toku_instr_key *checkpoint_safe_rwlock_key; +extern toku_instr_key *cachetable_value_key; +extern toku_instr_key *safe_file_size_lock_rwlock_key; +extern toku_instr_key *cachetable_disk_nb_rwlock_key; diff --git a/storage/tokudb/PerconaFT/portability/toku_os.h b/storage/tokudb/PerconaFT/portability/toku_os.h index 3a0e7376971..d7cfcfefb9a 100644 --- a/storage/tokudb/PerconaFT/portability/toku_os.h +++ b/storage/tokudb/PerconaFT/portability/toku_os.h @@ -116,12 +116,10 @@ int toku_fsync_dir_by_name_without_accounting(const char *dir_name); // *free_size is set to the bytes of free space in the file system // *total_size is set to the total bytes in the file system // Return 0 on success, otherwise an error number -int toku_get_filesystem_sizes(const char *path, uint64_t *avail_size, uint64_t *free_size, uint64_t *total_size); - -// Portable linux 'stat' -int toku_stat(const char *name, toku_struct_stat *statbuf) __attribute__((__visibility__("default"))); -// Portable linux 'fstat' -int toku_fstat(int fd, toku_struct_stat *statbuf) __attribute__((__visibility__("default"))); +int toku_get_filesystem_sizes(const char *path, + uint64_t *avail_size, + uint64_t *free_size, + uint64_t *total_size); // Portable linux 'dup2' int toku_dup2(int fd, int fd2) __attribute__((__visibility__("default"))); diff --git a/storage/tokudb/PerconaFT/portability/toku_portability.h b/storage/tokudb/PerconaFT/portability/toku_portability.h index 28ea8014f53..1096467a35d 100644 --- a/storage/tokudb/PerconaFT/portability/toku_portability.h +++ b/storage/tokudb/PerconaFT/portability/toku_portability.h @@ -125,6 +125,33 @@ typedef int64_t toku_off_t; #define UU(x) x __attribute__((__unused__)) +// Branch prediction macros. +// If supported by the compiler, will hint in inctruction caching for likely +// branching. Should only be used where there is a very good idea of the correct +// branch heuristics as determined by profiling. Mostly copied from InnoDB. +// Use: +// "if (FT_LIKELY(x))" where the chances of "x" evaluating true are higher +// "if (FT_UNLIKELY(x))" where the chances of "x" evaluating false are higher +#if defined(__GNUC__) && (__GNUC__ > 2) && !defined(__INTEL_COMPILER) + +// Tell the compiler that 'expr' probably evaluates to 'constant'. +#define FT_EXPECT(expr, constant) __builtin_expect(expr, constant) + +#else + +#warning "No FT branch prediction operations in use!" +#define FT_EXPECT(expr, constant) (expr) + +#endif // defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER) + +// Tell the compiler that cond is likely to hold +#define FT_LIKELY(cond) FT_EXPECT(bool(cond), true) + +// Tell the compiler that cond is unlikely to hold +#define FT_UNLIKELY(cond) FT_EXPECT(bool(cond), false) + +#include "toku_instrumentation.h" + #if defined(__cplusplus) extern "C" { #endif @@ -240,28 +267,272 @@ void toku_os_full_write (int fd, const void *buf, size_t len) __attribute__((__v // os_write returns 0 on success, otherwise an errno. ssize_t toku_os_pwrite (int fd, const void *buf, size_t len, toku_off_t off) __attribute__((__visibility__("default"))); -int toku_os_write (int fd, const void *buf, size_t len) __attribute__((__visibility__("default"))); +int toku_os_write(int fd, const void *buf, size_t len) + __attribute__((__visibility__("default"))); // wrappers around file system calls -FILE * toku_os_fdopen(int fildes, const char *mode); -FILE * toku_os_fopen(const char *filename, const char *mode); -int toku_os_open(const char *path, int oflag, int mode); -int toku_os_open_direct(const char *path, int oflag, int mode); -int toku_os_close(int fd); -int toku_os_fclose(FILE * stream); -int toku_os_rename(const char *old_name, const char *new_name); -int toku_os_unlink(const char *path); -ssize_t toku_os_read(int fd, void *buf, size_t count); -ssize_t toku_os_pread(int fd, void *buf, size_t count, off_t offset); void toku_os_recursive_delete(const char *path); +TOKU_FILE *toku_os_fdopen_with_source_location(int fildes, + const char *mode, + const char *filename, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line); +#define toku_os_fdopen(FD, M, FN, K) \ + toku_os_fdopen_with_source_location(FD, M, FN, K, __FILE__, __LINE__) + +TOKU_FILE *toku_os_fopen_with_source_location(const char *filename, + const char *mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line); +#define toku_os_fopen(F, M, K) \ + toku_os_fopen_with_source_location(F, M, K, __FILE__, __LINE__) + +int toku_os_open_with_source_location(const char *path, + int oflag, + int mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line); +#define toku_os_open(FD, F, M, K) \ + toku_os_open_with_source_location(FD, F, M, K, __FILE__, __LINE__) + +int toku_os_open_direct(const char *path, + int oflag, + int mode, + const toku_instr_key &instr_key); + +int toku_os_delete_with_source_location(const char *name, + const char *src_file, + uint src_line); +#define toku_os_delete(FN) \ + toku_os_delete_with_source_location(FN, __FILE__, __LINE__) + +int toku_os_rename_with_source_location(const char *old_name, + const char *new_name, + const char *src_file, + uint src_line); +#define toku_os_rename(old_name, new_name) \ + toku_os_rename_with_source_location(old_name, new_name, __FILE__, __LINE__) + +void toku_os_full_write_with_source_location(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line); +#define toku_os_full_write(FD, B, L) \ + toku_os_full_write_with_source_location(FD, B, L, __FILE__, __LINE__) + +int toku_os_write_with_source_location(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line); +#define toku_os_write(FD, B, L) \ + toku_os_write_with_source_location(FD, B, L, __FILE__, __LINE__) + +void toku_os_full_pwrite_with_source_location(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line); +#define toku_os_full_pwrite(FD, B, L, O) \ + toku_os_full_pwrite_with_source_location(FD, B, L, O, __FILE__, __LINE__) + +ssize_t toku_os_pwrite_with_source_location(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line); + +#define toku_os_pwrite(FD, B, L, O) \ + toku_os_pwrite_with_source_location(FD, B, L, O, __FILE__, __LINE__) + +int toku_os_fwrite_with_source_location(const void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line); + +#define toku_os_fwrite(P, S, N, FS) \ + toku_os_fwrite_with_source_location(P, S, N, FS, __FILE__, __LINE__) + +int toku_os_fread_with_source_location(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line); +#define toku_os_fread(P, S, N, FS) \ + toku_os_fread_with_source_location(P, S, N, FS, __FILE__, __LINE__) + +TOKU_FILE *toku_os_fopen_with_source_location(const char *filename, + const char *mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line); + +int toku_os_fclose_with_source_location(TOKU_FILE *stream, + const char *src_file, + uint src_line); + +#define toku_os_fclose(FS) \ + toku_os_fclose_with_source_location(FS, __FILE__, __LINE__) + +int toku_os_close_with_source_location(int fd, + const char *src_file, + uint src_line); +#define toku_os_close(FD) \ + toku_os_close_with_source_location(FD, __FILE__, __LINE__) + +ssize_t toku_os_read_with_source_location(int fd, + void *buf, + size_t count, + const char *src_file, + uint src_line); + +#define toku_os_read(FD, B, C) \ + toku_os_read_with_source_location(FD, B, C, __FILE__, __LINE__); + +ssize_t inline_toku_os_pread_with_source_location(int fd, + void *buf, + size_t count, + off_t offset, + const char *src_file, + uint src_line); +#define toku_os_pread(FD, B, C, O) \ + inline_toku_os_pread_with_source_location(FD, B, C, O, __FILE__, __LINE__); + +void file_fsync_internal_with_source_location(int fd, + const char *src_file, + uint src_line); + +#define file_fsync_internal(FD) \ + file_fsync_internal_with_source_location(FD, __FILE__, __LINE__); + +int toku_os_get_file_size_with_source_location(int fildes, + int64_t *fsize, + const char *src_file, + uint src_line); + +#define toku_os_get_file_size(D, S) \ + toku_os_get_file_size_with_source_location(D, S, __FILE__, __LINE__) + +// TODO: should this prototype be moved to toku_os.h? +int toku_stat_with_source_location(const char *name, + toku_struct_stat *buf, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) + __attribute__((__visibility__("default"))); + +#define toku_stat(N, B, K) \ + toku_stat_with_source_location(N, B, K, __FILE__, __LINE__) + +int toku_os_fstat_with_source_location(int fd, + toku_struct_stat *buf, + const char *src_file, + uint src_line) + __attribute__((__visibility__("default"))); + +#define toku_os_fstat(FD, B) \ + toku_os_fstat_with_source_location(FD, B, __FILE__, __LINE__) + +#ifdef HAVE_PSI_FILE_INTERFACE2 +int inline_toku_os_close(int fd, const char *src_file, uint src_line); +int inline_toku_os_fclose(TOKU_FILE *stream, + const char *src_file, + uint src_line); +ssize_t inline_toku_os_read(int fd, + void *buf, + size_t count, + const char *src_file, + uint src_line); +ssize_t inline_toku_os_pread(int fd, + void *buf, + size_t count, + off_t offset, + const char *src_file, + uint src_line); +int inline_toku_os_fwrite(const void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line); +int inline_toku_os_fread(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line); +int inline_toku_os_write(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line); +ssize_t inline_toku_os_pwrite(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line); +void inline_toku_os_full_write(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line); +void inline_toku_os_full_pwrite(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line); +int inline_toku_os_delete(const char *name, + const char *srv_file, + uint src_line); +//#else +int inline_toku_os_close(int fd); +int inline_toku_os_fclose(TOKU_FILE *stream); +ssize_t inline_toku_os_read(int fd, void *buf, size_t count); +ssize_t inline_toku_os_pread(int fd, void *buf, size_t count, off_t offset); +int inline_toku_os_fwrite(const void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream); +int inline_toku_os_fread(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream); +int inline_toku_os_write(int fd, const void *buf, size_t len); +ssize_t inline_toku_os_pwrite(int fd, + const void *buf, + size_t len, + toku_off_t off); +void inline_toku_os_full_write(int fd, const void *buf, size_t len); +void inline_toku_os_full_pwrite(int fd, + const void *buf, + size_t len, + toku_off_t off); +int inline_toku_os_delete(const char *name); +#endif + // wrapper around fsync -void toku_file_fsync_without_accounting(int fd); void toku_file_fsync(int fd); int toku_fsync_directory(const char *fname); +void toku_file_fsync_without_accounting(int fd); // get the number of fsync calls and the fsync times (total) -void toku_get_fsync_times(uint64_t *fsync_count, uint64_t *fsync_time, uint64_t *long_fsync_threshold, uint64_t *long_fsync_count, uint64_t *long_fsync_time); +void toku_get_fsync_times(uint64_t *fsync_count, + uint64_t *fsync_time, + uint64_t *long_fsync_threshold, + uint64_t *long_fsync_count, + uint64_t *long_fsync_time); void toku_set_func_fsync (int (*fsync_function)(int)); void toku_set_func_pwrite (ssize_t (*)(int, const void *, size_t, toku_off_t)); @@ -271,9 +542,11 @@ void toku_set_func_full_write (ssize_t (*)(int, const void *, size_t)); void toku_set_func_fdopen (FILE * (*)(int, const char *)); void toku_set_func_fopen (FILE * (*)(const char *, const char *)); void toku_set_func_open (int (*)(const char *, int, int)); -void toku_set_func_fclose(int (*)(FILE*)); +void toku_set_func_fclose(int (*)(FILE *)); void toku_set_func_read(ssize_t (*)(int, void *, size_t)); -void toku_set_func_pread (ssize_t (*)(int, void *, size_t, off_t)); +void toku_set_func_pread(ssize_t (*)(int, void *, size_t, off_t)); +void toku_set_func_fwrite( + size_t (*fwrite_fun)(const void *, size_t, size_t, FILE *)); int toku_portability_init(void); void toku_portability_destroy(void); @@ -283,28 +556,3 @@ void toku_portability_destroy(void); static inline uint64_t roundup_to_multiple(uint64_t alignment, uint64_t v) { return (v + alignment - 1) & ~(alignment - 1); } - -// Branch prediction macros. -// If supported by the compiler, will hint in inctruction caching for likely -// branching. Should only be used where there is a very good idea of the correct -// branch heuristics as determined by profiling. Mostly copied from InnoDB. -// Use: -// "if (FT_LIKELY(x))" where the chances of "x" evaluating true are higher -// "if (FT_UNLIKELY(x))" where the chances of "x" evaluating false are higher -#if defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER) - -// Tell the compiler that 'expr' probably evaluates to 'constant'. -#define FT_EXPECT(expr,constant) __builtin_expect(expr, constant) - -#else - -#warning "No FT branch prediction operations in use!" -#define FT_EXPECT(expr,constant) (expr) - -#endif // defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER) - -// Tell the compiler that cond is likely to hold -#define FT_LIKELY(cond) FT_EXPECT(cond, 1) - -// Tell the compiler that cond is unlikely to hold -#define FT_UNLIKELY(cond) FT_EXPECT(cond, 0) diff --git a/storage/tokudb/PerconaFT/portability/toku_pthread.h b/storage/tokudb/PerconaFT/portability/toku_pthread.h index 84c27736201..44de01244d2 100644 --- a/storage/tokudb/PerconaFT/portability/toku_pthread.h +++ b/storage/tokudb/PerconaFT/portability/toku_pthread.h @@ -42,31 +42,62 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include #include +#include "toku_portability.h" #include "toku_assert.h" +// TODO: some things moved toku_instrumentation.h, not necessarily the best +// place typedef pthread_attr_t toku_pthread_attr_t; typedef pthread_t toku_pthread_t; -typedef pthread_mutexattr_t toku_pthread_mutexattr_t; typedef pthread_mutex_t toku_pthread_mutex_t; typedef pthread_condattr_t toku_pthread_condattr_t; typedef pthread_cond_t toku_pthread_cond_t; -typedef pthread_rwlock_t toku_pthread_rwlock_t; -typedef pthread_rwlockattr_t toku_pthread_rwlockattr_t; +typedef pthread_rwlockattr_t toku_pthread_rwlockattr_t; typedef pthread_key_t toku_pthread_key_t; typedef struct timespec toku_timespec_t; -#ifndef TOKU_PTHREAD_DEBUG -# define TOKU_PTHREAD_DEBUG 0 -#endif +// TODO: break this include loop +#include +typedef pthread_mutexattr_t toku_pthread_mutexattr_t; -typedef struct toku_mutex { +struct toku_mutex_t { pthread_mutex_t pmutex; + struct PSI_mutex + *psi_mutex; /* The performance schema instrumentation hook */ #if TOKU_PTHREAD_DEBUG - pthread_t owner; // = pthread_self(); // for debugging + pthread_t owner; // = pthread_self(); // for debugging bool locked; bool valid; + pfs_key_t instr_key_id; +#endif +}; + +struct toku_cond_t { + pthread_cond_t pcond; + struct PSI_cond *psi_cond; +#if TOKU_PTHREAD_DEBUG + pfs_key_t instr_key_id; +#endif +}; + +#ifdef TOKU_PTHREAD_DEBUG +#define TOKU_COND_INITIALIZER \ + { \ + .pcond = PTHREAD_COND_INITIALIZER, .psi_cond = nullptr, \ + .instr_key_id = 0 \ + } +#else +#define TOKU_COND_INITIALIZER \ + { .pcond = PTHREAD_COND_INITIALIZER, .psi_cond = nullptr } #endif -} toku_mutex_t; + +struct toku_pthread_rwlock_t { + pthread_rwlock_t rwlock; + struct PSI_rwlock *psi_rwlock; +#if TOKU_PTHREAD_DEBUG + pfs_key_t instr_key_id; +#endif +}; typedef struct toku_mutex_aligned { toku_mutex_t aligned_mutex __attribute__((__aligned__(64))); @@ -83,45 +114,68 @@ typedef struct toku_mutex_aligned { // In general it will be a lot of busy work to make this codebase compile // cleanly with -Wmissing-field-initializers -# define ZERO_MUTEX_INITIALIZER {} +#define ZERO_MUTEX_INITIALIZER \ + {} #if TOKU_PTHREAD_DEBUG -# define TOKU_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER, .owner = 0, .locked = false, .valid = true } +#define TOKU_MUTEX_INITIALIZER \ + { \ + .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr, .owner = 0, \ + .locked = false, .valid = true, .instr_key_id = 0 \ + } #else -# define TOKU_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER } +#define TOKU_MUTEX_INITIALIZER \ + { .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr } #endif // Darwin doesn't provide adaptive mutexes #if defined(__APPLE__) -# define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_DEFAULT -# if TOKU_PTHREAD_DEBUG -# define TOKU_ADAPTIVE_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER, .owner = 0, .locked = false, .valid = true } -# else -# define TOKU_ADAPTIVE_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER } -# endif -#else // __FreeBSD__, __linux__, at least -# define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_ADAPTIVE_NP -# if TOKU_PTHREAD_DEBUG -# define TOKU_ADAPTIVE_MUTEX_INITIALIZER { .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, .owner = 0, .locked = false, .valid = true } -# else -# define TOKU_ADAPTIVE_MUTEX_INITIALIZER { .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP } -# endif +#define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_DEFAULT +#if TOKU_PTHREAD_DEBUG +#define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ + { \ + .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr, .owner = 0, \ + .locked = false, .valid = true, .instr_key_id = 0 \ + } +#else +#define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ + { .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr } #endif - -static inline void -toku_mutex_init(toku_mutex_t *mutex, const toku_pthread_mutexattr_t *attr) { - int r = pthread_mutex_init(&mutex->pmutex, attr); - assert_zero(r); +#else // __FreeBSD__, __linux__, at least +#define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_ADAPTIVE_NP #if TOKU_PTHREAD_DEBUG - mutex->locked = false; - invariant(!mutex->valid); - mutex->valid = true; - mutex->owner = 0; +#define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ + { \ + .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, .psi_mutex = nullptr, \ + .owner = 0, .locked = false, .valid = true, .instr_key_id = 0 \ + } +#else +#define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ + { .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, .psi_mutex = nullptr } +#endif #endif -} -static inline void -toku_mutexattr_init(toku_pthread_mutexattr_t *attr) { +// Different OSes implement mutexes as different amounts of nested structs. +// C++ will fill out all missing values with zeroes if you provide at least one +// zero, but it needs the right amount of nesting. +#if defined(__FreeBSD__) +#define ZERO_COND_INITIALIZER \ + { 0 } +#elif defined(__APPLE__) +#define ZERO_COND_INITIALIZER \ + { \ + { 0 } \ + } +#else // __linux__, at least +#define ZERO_COND_INITIALIZER \ + { \ + { \ + { 0 } \ + } \ + } +#endif + +static inline void toku_mutexattr_init(toku_pthread_mutexattr_t *attr) { int r = pthread_mutexattr_init(attr); assert_zero(r); } @@ -138,61 +192,8 @@ toku_mutexattr_destroy(toku_pthread_mutexattr_t *attr) { assert_zero(r); } -static inline void -toku_mutex_destroy(toku_mutex_t *mutex) { #if TOKU_PTHREAD_DEBUG - invariant(mutex->valid); - mutex->valid = false; - invariant(!mutex->locked); -#endif - int r = pthread_mutex_destroy(&mutex->pmutex); - assert_zero(r); -} - -static inline void -toku_mutex_lock(toku_mutex_t *mutex) { - int r = pthread_mutex_lock(&mutex->pmutex); - assert_zero(r); -#if TOKU_PTHREAD_DEBUG - invariant(mutex->valid); - invariant(!mutex->locked); - invariant(mutex->owner == 0); - mutex->locked = true; - mutex->owner = pthread_self(); -#endif -} - -static inline int -toku_mutex_trylock(toku_mutex_t *mutex) { - int r = pthread_mutex_trylock(&mutex->pmutex); -#if TOKU_PTHREAD_DEBUG - if (r == 0) { - invariant(mutex->valid); - invariant(!mutex->locked); - invariant(mutex->owner == 0); - mutex->locked = true; - mutex->owner = pthread_self(); - } -#endif - return r; -} - -static inline void -toku_mutex_unlock(toku_mutex_t *mutex) { -#if TOKU_PTHREAD_DEBUG - invariant(mutex->owner == pthread_self()); - invariant(mutex->valid); - invariant(mutex->locked); - mutex->locked = false; - mutex->owner = 0; -#endif - int r = pthread_mutex_unlock(&mutex->pmutex); - assert_zero(r); -} - -#if TOKU_PTHREAD_DEBUG -static inline void -toku_mutex_assert_locked(const toku_mutex_t *mutex) { +static inline void toku_mutex_assert_locked(const toku_mutex_t *mutex) { invariant(mutex->locked); invariant(mutex->owner == pthread_self()); } @@ -217,40 +218,123 @@ toku_mutex_assert_unlocked(toku_mutex_t *mutex) { invariant(!mutex->locked); } #else -static inline void -toku_mutex_assert_unlocked(toku_mutex_t *mutex __attribute__((unused))) { +static inline void toku_mutex_assert_unlocked(toku_mutex_t *mutex + __attribute__((unused))) {} +#endif + +#define toku_mutex_lock(M) \ + toku_mutex_lock_with_source_location(M, __FILE__, __LINE__) + +static inline void toku_cond_init(toku_cond_t *cond, + const toku_pthread_condattr_t *attr) { + int r = pthread_cond_init(&cond->pcond, attr); + assert_zero(r); +} + +#define toku_mutex_trylock(M) \ + toku_mutex_trylock_with_source_location(M, __FILE__, __LINE__) + +inline void toku_mutex_unlock(toku_mutex_t *mutex) { +#if TOKU_PTHREAD_DEBUG + invariant(mutex->owner == pthread_self()); + invariant(mutex->valid); + invariant(mutex->locked); + mutex->locked = false; + mutex->owner = 0; +#endif + toku_instr_mutex_unlock(mutex->psi_mutex); + int r = pthread_mutex_unlock(&mutex->pmutex); + assert_zero(r); } + +inline void toku_mutex_lock_with_source_location(toku_mutex_t *mutex, + const char *src_file, + int src_line) { + + toku_mutex_instrumentation mutex_instr; + toku_instr_mutex_lock_start(mutex_instr, *mutex, src_file, src_line); + + const int r = pthread_mutex_lock(&mutex->pmutex); + toku_instr_mutex_lock_end(mutex_instr, r); + + assert_zero(r); +#if TOKU_PTHREAD_DEBUG + invariant(mutex->valid); + invariant(!mutex->locked); + invariant(mutex->owner == 0); + mutex->locked = true; + mutex->owner = pthread_self(); #endif +} -typedef struct toku_cond { - pthread_cond_t pcond; -} toku_cond_t; +inline int toku_mutex_trylock_with_source_location(toku_mutex_t *mutex, + const char *src_file, + int src_line) { -// Same considerations as for ZERO_MUTEX_INITIALIZER apply -#define ZERO_COND_INITIALIZER {} + toku_mutex_instrumentation mutex_instr; + toku_instr_mutex_trylock_start(mutex_instr, *mutex, src_file, src_line); -#define TOKU_COND_INITIALIZER {PTHREAD_COND_INITIALIZER} + const int r = pthread_mutex_lock(&mutex->pmutex); + toku_instr_mutex_lock_end(mutex_instr, r); -static inline void -toku_cond_init(toku_cond_t *cond, const toku_pthread_condattr_t *attr) { +#if TOKU_PTHREAD_DEBUG + if (r == 0) { + invariant(mutex->valid); + invariant(!mutex->locked); + invariant(mutex->owner == 0); + mutex->locked = true; + mutex->owner = pthread_self(); + } +#endif + return r; +} + +#define toku_cond_wait(C, M) \ + toku_cond_wait_with_source_location(C, M, __FILE__, __LINE__) + +#define toku_cond_timedwait(C, M, W) \ + toku_cond_timedwait_with_source_location(C, M, W, __FILE__, __LINE__) + +inline void toku_cond_init(const toku_instr_key &key, + toku_cond_t *cond, + const pthread_condattr_t *attr) { + toku_instr_cond_init(key, *cond); int r = pthread_cond_init(&cond->pcond, attr); assert_zero(r); } -static inline void -toku_cond_destroy(toku_cond_t *cond) { +inline void toku_cond_destroy(toku_cond_t *cond) { + toku_instr_cond_destroy(cond->psi_cond); int r = pthread_cond_destroy(&cond->pcond); assert_zero(r); } -static inline void -toku_cond_wait(toku_cond_t *cond, toku_mutex_t *mutex) { +inline void toku_cond_wait_with_source_location(toku_cond_t *cond, + toku_mutex_t *mutex, + const char *src_file, + uint src_line) { + #if TOKU_PTHREAD_DEBUG invariant(mutex->locked); mutex->locked = false; mutex->owner = 0; #endif - int r = pthread_cond_wait(&cond->pcond, &mutex->pmutex); + + /* Instrumentation start */ + toku_cond_instrumentation cond_instr; + toku_instr_cond_wait_start(cond_instr, + toku_instr_cond_op::cond_wait, + *cond, + *mutex, + src_file, + src_line); + + /* Instrumented code */ + const int r = pthread_cond_wait(&cond->pcond, &mutex->pmutex); + + /* Instrumentation end */ + toku_instr_cond_wait_end(cond_instr, r); + assert_zero(r); #if TOKU_PTHREAD_DEBUG invariant(!mutex->locked); @@ -259,14 +343,33 @@ toku_cond_wait(toku_cond_t *cond, toku_mutex_t *mutex) { #endif } -static inline int -toku_cond_timedwait(toku_cond_t *cond, toku_mutex_t *mutex, toku_timespec_t *wakeup_at) { +inline int toku_cond_timedwait_with_source_location(toku_cond_t *cond, + toku_mutex_t *mutex, + toku_timespec_t *wakeup_at, + const char *src_file, + uint src_line) { #if TOKU_PTHREAD_DEBUG invariant(mutex->locked); mutex->locked = false; mutex->owner = 0; #endif - int r = pthread_cond_timedwait(&cond->pcond, &mutex->pmutex, wakeup_at); + + /* Instrumentation start */ + toku_cond_instrumentation cond_instr; + toku_instr_cond_wait_start(cond_instr, + toku_instr_cond_op::cond_timedwait, + *cond, + *mutex, + src_file, + src_line); + + /* Instrumented code */ + const int r = pthread_cond_timedwait( + &cond->pcond, &mutex->pmutex, wakeup_at); + + /* Instrumentation end */ + toku_instr_cond_wait_end(cond_instr, r); + #if TOKU_PTHREAD_DEBUG invariant(!mutex->locked); mutex->locked = true; @@ -275,69 +378,116 @@ toku_cond_timedwait(toku_cond_t *cond, toku_mutex_t *mutex, toku_timespec_t *wak return r; } -static inline void -toku_cond_signal(toku_cond_t *cond) { - int r = pthread_cond_signal(&cond->pcond); +inline void toku_cond_signal(toku_cond_t *cond) { + toku_instr_cond_signal(*cond); + const int r = pthread_cond_signal(&cond->pcond); assert_zero(r); } -static inline void -toku_cond_broadcast(toku_cond_t *cond) { - int r =pthread_cond_broadcast(&cond->pcond); +inline void toku_cond_broadcast(toku_cond_t *cond) { + toku_instr_cond_broadcast(*cond); + const int r = pthread_cond_broadcast(&cond->pcond); assert_zero(r); } -int -toku_pthread_yield(void) __attribute__((__visibility__("default"))); - -static inline toku_pthread_t -toku_pthread_self(void) { - return pthread_self(); +inline void toku_mutex_init(const toku_instr_key &key, + toku_mutex_t *mutex, + const toku_pthread_mutexattr_t *attr) { +#if TOKU_PTHREAD_DEBUG + mutex->valid = true; +#endif + toku_instr_mutex_init(key, *mutex); + const int r = pthread_mutex_init(&mutex->pmutex, attr); + assert_zero(r); +#if TOKU_PTHREAD_DEBUG + mutex->locked = false; + invariant(mutex->valid); + mutex->valid = true; + mutex->owner = 0; +#endif } -static inline void -toku_pthread_rwlock_init(toku_pthread_rwlock_t *__restrict rwlock, const toku_pthread_rwlockattr_t *__restrict attr) { - int r = pthread_rwlock_init(rwlock, attr); +inline void toku_mutex_destroy(toku_mutex_t *mutex) { +#if TOKU_PTHREAD_DEBUG + invariant(mutex->valid); + mutex->valid = false; + invariant(!mutex->locked); +#endif + toku_instr_mutex_destroy(mutex->psi_mutex); + int r = pthread_mutex_destroy(&mutex->pmutex); assert_zero(r); } -static inline void -toku_pthread_rwlock_destroy(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_destroy(rwlock); +#define toku_pthread_rwlock_rdlock(RW) \ + toku_pthread_rwlock_rdlock_with_source_location(RW, __FILE__, __LINE__) + +#define toku_pthread_rwlock_wrlock(RW) \ + toku_pthread_rwlock_wrlock_with_source_location(RW, __FILE__, __LINE__) + +inline void toku_pthread_rwlock_init( + const toku_instr_key &key, + toku_pthread_rwlock_t *__restrict rwlock, + const toku_pthread_rwlockattr_t *__restrict attr) { + toku_instr_rwlock_init(key, *rwlock); + int r = pthread_rwlock_init(&rwlock->rwlock, attr); assert_zero(r); } -static inline void -toku_pthread_rwlock_rdlock(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_rdlock(rwlock); +inline void toku_pthread_rwlock_destroy(toku_pthread_rwlock_t *rwlock) { + toku_instr_rwlock_destroy(rwlock->psi_rwlock); + int r = pthread_rwlock_destroy(&rwlock->rwlock); assert_zero(r); } -static inline void -toku_pthread_rwlock_rdunlock(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_unlock(rwlock); +inline void toku_pthread_rwlock_rdlock_with_source_location( + toku_pthread_rwlock_t *rwlock, + const char *src_file, + uint src_line) { + + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_rdlock_wait_start( + rwlock_instr, *rwlock, src_file, src_line); + /* Instrumented code */ + const int r = pthread_rwlock_rdlock(&rwlock->rwlock); + + /* Instrumentation end */ + toku_instr_rwlock_rdlock_wait_end(rwlock_instr, r); + assert_zero(r); } -static inline void -toku_pthread_rwlock_wrlock(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_wrlock(rwlock); +inline void toku_pthread_rwlock_wrlock_with_source_location( + toku_pthread_rwlock_t *rwlock, + const char *src_file, + uint src_line) { + + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_wrlock_wait_start( + rwlock_instr, *rwlock, src_file, src_line); + /* Instrumented code */ + const int r = pthread_rwlock_wrlock(&rwlock->rwlock); + + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, r); + assert_zero(r); } -static inline void -toku_pthread_rwlock_wrunlock(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_unlock(rwlock); +inline void toku_pthread_rwlock_rdunlock(toku_pthread_rwlock_t *rwlock) { + toku_instr_rwlock_unlock(*rwlock); + const int r = pthread_rwlock_unlock(&rwlock->rwlock); assert_zero(r); } -static inline int -toku_pthread_create(toku_pthread_t *thread, const toku_pthread_attr_t *attr, void *(*start_function)(void *), void *arg) { - return pthread_create(thread, attr, start_function, arg); +inline void toku_pthread_rwlock_wrunlock(toku_pthread_rwlock_t *rwlock) { + toku_instr_rwlock_unlock(*rwlock); + const int r = pthread_rwlock_unlock(&rwlock->rwlock); + assert_zero(r); } -static inline int -toku_pthread_join(toku_pthread_t thread, void **value_ptr) { +static inline int toku_pthread_join(toku_pthread_t thread, void **value_ptr) { return pthread_join(thread, value_ptr); } @@ -361,7 +511,15 @@ toku_pthread_getspecific(toku_pthread_key_t key) { return pthread_getspecific(key); } -static inline int -toku_pthread_setspecific(toku_pthread_key_t key, void *data) { +static inline int toku_pthread_setspecific(toku_pthread_key_t key, void *data) { return pthread_setspecific(key, data); } + +int toku_pthread_yield(void) __attribute__((__visibility__("default"))); + +static inline toku_pthread_t toku_pthread_self(void) { return pthread_self(); } + +static inline void *toku_pthread_done(void *exit_value) { + toku_instr_delete_current_thread(); + pthread_exit(exit_value); +} diff --git a/storage/tokudb/PerconaFT/src/indexer-undo-do.cc b/storage/tokudb/PerconaFT/src/indexer-undo-do.cc index 4c7f5336161..cc86402751b 100644 --- a/storage/tokudb/PerconaFT/src/indexer-undo-do.cc +++ b/storage/tokudb/PerconaFT/src/indexer-undo-do.cc @@ -571,6 +571,7 @@ indexer_ft_delete_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xi oldest_referenced_xid_estimate, true); toku_ft_send_delete(db_struct_i(hotdb)->ft_handle, hotkey, xids, &gc_info); + toku_ft_adjust_logical_row_count(db_struct_i(hotdb)->ft_handle->ft, -1); } } return result; @@ -616,6 +617,7 @@ indexer_ft_insert_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, DBT *ho oldest_referenced_xid_estimate, true); toku_ft_send_insert(db_struct_i(hotdb)->ft_handle, hotkey, hotval, xids, FT_INSERT, &gc_info); + toku_ft_adjust_logical_row_count(db_struct_i(hotdb)->ft_handle->ft, 1); } } return result; diff --git a/storage/tokudb/PerconaFT/src/indexer.cc b/storage/tokudb/PerconaFT/src/indexer.cc index b475b08beb5..044ffac917c 100644 --- a/storage/tokudb/PerconaFT/src/indexer.cc +++ b/storage/tokudb/PerconaFT/src/indexer.cc @@ -253,16 +253,21 @@ toku_indexer_create_indexer(DB_ENV *env, indexer->set_error_callback = toku_indexer_set_error_callback; indexer->set_poll_function = toku_indexer_set_poll_function; indexer->build = build_index; - indexer->close = close_indexer; - indexer->abort = abort_indexer; - - toku_mutex_init(&indexer->i->indexer_lock, NULL); - toku_mutex_init(&indexer->i->indexer_estimate_lock, NULL); + indexer->close = close_indexer; + indexer->abort = abort_indexer; + + toku_mutex_init( + *indexer_i_indexer_lock_mutex_key, &indexer->i->indexer_lock, nullptr); + toku_mutex_init(*indexer_i_indexer_estimate_lock_mutex_key, + &indexer->i->indexer_estimate_lock, + nullptr); toku_init_dbt(&indexer->i->position_estimate); // - // create and close a dummy loader to get redirection going for the hot indexer - // This way, if the hot index aborts, but other transactions have references to the + // create and close a dummy loader to get redirection going for the hot + // indexer + // This way, if the hot index aborts, but other transactions have references + // to the // underlying FT, then those transactions can do dummy operations on the FT // while the DB gets redirected back to an empty dictionary // diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-first-empty.cc b/storage/tokudb/PerconaFT/src/tests/blocking-first-empty.cc index d9d865254f1..3b53911e614 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-first-empty.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-first-empty.cc @@ -99,12 +99,14 @@ static void *blocking_first_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_first_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_first_thread, &a); assert(r == 0); + struct blocking_first_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_first_thread, &a); + assert(r == 0); } blocking_first(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-first.cc b/storage/tokudb/PerconaFT/src/tests/blocking-first.cc index 9f3f8f4eb6a..c104eabd6c3 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-first.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-first.cc @@ -116,12 +116,14 @@ static void *blocking_first_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_first_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_first_thread, &a); assert(r == 0); + struct blocking_first_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_first_thread, &a); + assert(r == 0); } blocking_first(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-last.cc b/storage/tokudb/PerconaFT/src/tests/blocking-last.cc index a62d83eb46f..3a702e3f115 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-last.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-last.cc @@ -116,12 +116,14 @@ static void *blocking_last_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_last_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_last_thread, &a); assert(r == 0); + struct blocking_last_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_last_thread, &a); + assert(r == 0); } blocking_last(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-next-prev-deadlock.cc b/storage/tokudb/PerconaFT/src/tests/blocking-next-prev-deadlock.cc index bd5697ba526..781708cc627 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-next-prev-deadlock.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-next-prev-deadlock.cc @@ -181,12 +181,14 @@ static void *blocking_next_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_next_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_next_thread, &a); assert(r == 0); + struct blocking_next_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_next_thread, &a); + assert(r == 0); } blocking_prev(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-next-prev.cc b/storage/tokudb/PerconaFT/src/tests/blocking-next-prev.cc index 729473bb7cf..aa179e88d76 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-next-prev.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-next-prev.cc @@ -188,12 +188,14 @@ static void *blocking_next_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_next_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_next_thread, &a); assert(r == 0); + struct blocking_next_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_next_thread, &a); + assert(r == 0); } blocking_prev(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-prelock-range.cc b/storage/tokudb/PerconaFT/src/tests/blocking-prelock-range.cc index 8821b39aa8a..38875a2f8ec 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-prelock-range.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-prelock-range.cc @@ -140,12 +140,17 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); toku_pthread_t tids[nthreads]; - struct blocking_range_lock_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_range_lock_thread, &a); assert(r == 0); + struct blocking_range_lock_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create(toku_uninstrumented, + &tids[i], + nullptr, + blocking_range_lock_thread, + &a); + assert(r == 0); } blocking_range_lock(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-put-timeout.cc b/storage/tokudb/PerconaFT/src/tests/blocking-put-timeout.cc index a31e173fd83..bf4a8a24f47 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-put-timeout.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-put-timeout.cc @@ -57,8 +57,8 @@ struct test_seq { static void test_seq_init(struct test_seq *seq) { seq->state = 0; - toku_mutex_init(&seq->lock, NULL); - toku_cond_init(&seq->cv, NULL); + toku_mutex_init(toku_uninstrumented, &seq->lock, nullptr); + toku_cond_init(toku_uninstrumented, &seq->cv, nullptr); } static void test_seq_destroy(struct test_seq *seq) { @@ -172,13 +172,18 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); // run test - struct test_seq seq; ZERO_STRUCT(seq); test_seq_init(&seq); + struct test_seq seq; + ZERO_STRUCT(seq); + test_seq_init(&seq); toku_pthread_t t_a_id; - struct t_a_args t_a_args = { db_env, db, &seq }; - r = toku_pthread_create(&t_a_id, NULL, t_a_thread, &t_a_args); assert(r == 0); + struct t_a_args t_a_args = {db_env, db, &seq}; + r = toku_pthread_create( + toku_uninstrumented, &t_a_id, nullptr, t_a_thread, &t_a_args); + assert(r == 0); t_b(db_env, db, &seq); void *ret; - r = toku_pthread_join(t_a_id, &ret); assert(r == 0); + r = toku_pthread_join(t_a_id, &ret); + assert(r == 0); test_seq_destroy(&seq); // close env diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-put-wakeup.cc b/storage/tokudb/PerconaFT/src/tests/blocking-put-wakeup.cc index 615cdb5d17c..dba7962de35 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-put-wakeup.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-put-wakeup.cc @@ -58,8 +58,8 @@ struct test_seq { static void test_seq_init(struct test_seq *seq) { seq->state = 0; - toku_mutex_init(&seq->lock, NULL); - toku_cond_init(&seq->cv, NULL); + toku_mutex_init(toku_uninstrumented, &seq->lock, nullptr); + toku_cond_init(toku_uninstrumented, &seq->cv, nullptr); } static void test_seq_destroy(struct test_seq *seq) { @@ -167,13 +167,18 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); // run test - struct test_seq seq; ZERO_STRUCT(seq); test_seq_init(&seq); + struct test_seq seq; + ZERO_STRUCT(seq); + test_seq_init(&seq); toku_pthread_t t_a_id; - struct t_a_args t_a_args = { db_env, db, &seq }; - r = toku_pthread_create(&t_a_id, NULL, t_a_thread, &t_a_args); assert(r == 0); + struct t_a_args t_a_args = {db_env, db, &seq}; + r = toku_pthread_create( + toku_uninstrumented, &t_a_id, nullptr, t_a_thread, &t_a_args); + assert(r == 0); t_b(db_env, db, &seq); void *ret; - r = toku_pthread_join(t_a_id, &ret); assert(r == 0); + r = toku_pthread_join(t_a_id, &ret); + assert(r == 0); test_seq_destroy(&seq); // close env diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-put.cc b/storage/tokudb/PerconaFT/src/tests/blocking-put.cc index 0fa56325007..95481062483 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-put.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-put.cc @@ -139,12 +139,14 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); toku_pthread_t tids[nthreads]; - struct blocking_put_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_put_thread, &a); assert(r == 0); + struct blocking_put_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_put_thread, &a); + assert(r == 0); } blocking_put(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-0.cc b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-0.cc index a0e03ab3293..7c2e7b0fb26 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-0.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-0.cc @@ -126,12 +126,15 @@ static void *blocking_set_range_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime, uint64_t the_key) { int r; toku_pthread_t tids[nthreads]; - struct blocking_set_range_args a = { db_env, db, nrows, sleeptime, the_key }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_set_range_thread, &a); assert(r == 0); + struct blocking_set_range_args a = {db_env, db, nrows, sleeptime, the_key}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, + blocking_set_range_thread, &a); + assert(r == 0); } blocking_set_range(db_env, db, nrows, sleeptime, the_key); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-n.cc b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-n.cc index 056d74dbdd2..54a5846eb5e 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-n.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-n.cc @@ -121,12 +121,15 @@ static void *blocking_set_range_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime, uint64_t the_key) { int r; toku_pthread_t tids[nthreads]; - struct blocking_set_range_args a = { db_env, db, nrows, sleeptime, the_key }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_set_range_thread, &a); assert(r == 0); + struct blocking_set_range_args a = {db_env, db, nrows, sleeptime, the_key}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, + blocking_set_range_thread, &a); + assert(r == 0); } blocking_set_range(db_env, db, nrows, sleeptime, the_key); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-reverse-0.cc b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-reverse-0.cc index 1e7fca85bff..59e582547bf 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-reverse-0.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-reverse-0.cc @@ -126,12 +126,15 @@ static void *blocking_set_range_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime, uint64_t the_key) { int r; toku_pthread_t tids[nthreads]; - struct blocking_set_range_args a = { db_env, db, nrows, sleeptime, the_key }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_set_range_thread, &a); assert(r == 0); + struct blocking_set_range_args a = {db_env, db, nrows, sleeptime, the_key}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, + blocking_set_range_thread, &a); + assert(r == 0); } blocking_set_range(db_env, db, nrows, sleeptime, the_key); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-set.cc b/storage/tokudb/PerconaFT/src/tests/blocking-set.cc index ba64989842a..aa433c87be1 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-set.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-set.cc @@ -182,12 +182,14 @@ int test_main(int argc, char * const argv[]) { populate(db_env, db, nrows); toku_pthread_t tids[nthreads]; - struct blocking_set_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_set_thread, &a); assert(r == 0); + struct blocking_set_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_set_thread, &a); + assert(r == 0); } blocking_set(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-table-lock.cc b/storage/tokudb/PerconaFT/src/tests/blocking-table-lock.cc index 9ae33c56621..0953a4e80de 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-table-lock.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-table-lock.cc @@ -133,12 +133,17 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); toku_pthread_t tids[nthreads]; - struct blocking_table_lock_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_table_lock_thread, &a); assert(r == 0); + struct blocking_table_lock_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create(toku_uninstrumented, + &tids[i], + nullptr, + blocking_table_lock_thread, + &a); + assert(r == 0); } blocking_table_lock(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/checkpoint_fairness.cc b/storage/tokudb/PerconaFT/src/tests/checkpoint_fairness.cc index be82f8c352f..f62dfbc76d3 100644 --- a/storage/tokudb/PerconaFT/src/tests/checkpoint_fairness.cc +++ b/storage/tokudb/PerconaFT/src/tests/checkpoint_fairness.cc @@ -113,10 +113,14 @@ int test_main(int argc, char * const argv[]) { { int chk_r = db->open(db, NULL, "db", NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT, 0666); CKERR(chk_r); } pthread_t thds[n_threads]; - int ids[n_threads]; - for (int i=0; i(dictionaries)); + CKERR(r); + // this thead will scribble over dictionary 0 before crash to verify + // that + // post-checkpoint inserts are not in the database + DB* db = dictionaries[0].db; + if (iter & 1) + scribble(db, iter); + else + thin_out(db, iter); + uint32_t delay = myrandom(); + delay &= + 0xFFF; // select lower 12 bits, shifted up 8 for random number ... + delay = delay << 8; // ... uniformly distributed between 0 and 1M ... + usleep(delay); // ... to sleep up to one second (1M usec) + drop_dead(); } else { for (i = 0; i < NUM_DICTIONARIES; i++) { diff --git a/storage/tokudb/PerconaFT/src/tests/db-put-simple-deadlock-threads.cc b/storage/tokudb/PerconaFT/src/tests/db-put-simple-deadlock-threads.cc index ada46bd7516..e5bcc6af7bb 100644 --- a/storage/tokudb/PerconaFT/src/tests/db-put-simple-deadlock-threads.cc +++ b/storage/tokudb/PerconaFT/src/tests/db-put-simple-deadlock-threads.cc @@ -57,8 +57,8 @@ struct test_seq { static void test_seq_init(struct test_seq *seq) { seq->state = 0; - toku_mutex_init(&seq->lock, NULL); - toku_cond_init(&seq->cv, NULL); + toku_mutex_init(toku_uninstrumented, &seq->lock, nullptr); + toku_cond_init(toku_uninstrumented, &seq->cv, nullptr); } static void test_seq_destroy(struct test_seq *seq) { @@ -146,8 +146,9 @@ static void simple_deadlock(DB_ENV *db_env, DB *db, int do_txn, int n) { struct test_seq test_seq; ZERO_STRUCT(test_seq); test_seq_init(&test_seq); toku_pthread_t tid; - struct run_txn_b_arg arg = { &test_seq, txn_b, db, n}; - r = toku_pthread_create(&tid, NULL, run_txn_b, &arg); + struct run_txn_b_arg arg = {&test_seq, txn_b, db, n}; + r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, run_txn_b, &arg); test_seq_sleep(&test_seq, 0); insert_row(db, txn_a, htonl(0), 0, 0); diff --git a/storage/tokudb/PerconaFT/src/tests/db-put-simple-lockwait.cc b/storage/tokudb/PerconaFT/src/tests/db-put-simple-lockwait.cc index 365ea39eced..0fbe851532e 100644 --- a/storage/tokudb/PerconaFT/src/tests/db-put-simple-lockwait.cc +++ b/storage/tokudb/PerconaFT/src/tests/db-put-simple-lockwait.cc @@ -95,10 +95,11 @@ static void simple_lockwait(DB_ENV *db_env, DB *db, int do_txn, int nrows, int n insert_row(db, txns[0], htonl(0), 0, 0); toku_pthread_t tids[ntxns]; - for (int i = 1 ; i < ntxns; i++) { + for (int i = 1; i < ntxns; i++) { struct insert_one_arg *XMALLOC(arg); - *arg = (struct insert_one_arg) { txns[i], db}; - r = toku_pthread_create(&tids[i], NULL, insert_one, arg); + *arg = (struct insert_one_arg){txns[i], db}; + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, insert_one, arg); } sleep(10); diff --git a/storage/tokudb/PerconaFT/src/tests/db-put-update-deadlock.cc b/storage/tokudb/PerconaFT/src/tests/db-put-update-deadlock.cc index 3660f11d1bd..7a968058d7f 100644 --- a/storage/tokudb/PerconaFT/src/tests/db-put-update-deadlock.cc +++ b/storage/tokudb/PerconaFT/src/tests/db-put-update-deadlock.cc @@ -128,10 +128,12 @@ static void update_deadlock(DB_ENV *db_env, DB *db, int do_txn, int nrows, int n // get write locks toku_pthread_t tids[ntxns]; - for (int i = 0 ; i < ntxns; i++) { + for (int i = 0; i < ntxns; i++) { struct write_one_arg *XMALLOC(arg); - *arg = (struct write_one_arg) { txns[i], db, (int) htonl((i + 1) % ntxns), 0}; - r = toku_pthread_create(&tids[i], NULL, write_one_f, arg); + *arg = + (struct write_one_arg){txns[i], db, (int)htonl((i + 1) % ntxns), 0}; + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, write_one_f, arg); } #else // get read locks @@ -141,10 +143,11 @@ static void update_deadlock(DB_ENV *db_env, DB *db, int do_txn, int nrows, int n // get write locks toku_pthread_t tids[ntxns]; - for (int i = 0 ; i < ntxns; i++) { + for (int i = 0; i < ntxns; i++) { struct write_one_arg *XMALLOC(arg); - *arg = (struct write_one_arg) { txns[i], db, (int) htonl(0), 0}; - r = toku_pthread_create(&tids[i], NULL, write_one_f, arg); + *arg = (struct write_one_arg){txns[i], db, (int)htonl(0), 0}; + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, write_one_f, arg); } #endif diff --git a/storage/tokudb/PerconaFT/src/tests/filesize.cc b/storage/tokudb/PerconaFT/src/tests/filesize.cc index 6ab22245e68..9dfeea131c6 100644 --- a/storage/tokudb/PerconaFT/src/tests/filesize.cc +++ b/storage/tokudb/PerconaFT/src/tests/filesize.cc @@ -170,11 +170,9 @@ get_file_pathname(void) { if (verbose) printf("path = %s\n", path); } - -static int -getsizeM(void) { +static int getsizeM(void) { toku_struct_stat buf; - int r = toku_stat(path, &buf); + int r = toku_stat(path, &buf, toku_uninstrumented); CKERR(r); int sizeM = (int)buf.st_size >> 20; check_fragmentation(); diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-bw.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-bw.cc index 82471f30e45..5336bc3329f 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-bw.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-bw.cc @@ -302,12 +302,19 @@ static void test_indexer(DB *src, DB **dbs) CKERR(r); toku_mutex_unlock(&put_lock); - // start threads doing additional inserts - no lock issues since indexer already created - r = toku_pthread_create(&client_threads[0], 0, client, (void *)&client_specs[0]); CKERR(r); -// r = toku_pthread_create(&client_threads[1], 0, client, (void *)&client_specs[1]); CKERR(r); + // start threads doing additional inserts - no lock issues since indexer + // already created + r = toku_pthread_create(toku_uninstrumented, + &client_threads[0], + nullptr, + client, + static_cast(&client_specs[0])); + CKERR(r); + // r = toku_pthread_create(toku_uninstrumented, &client_threads[1], 0, + // client, (void *)&client_specs[1]); CKERR(r); struct timeval start, now; - if ( verbose ) { + if (verbose) { printf("test_indexer build\n"); gettimeofday(&start,0); } @@ -342,14 +349,13 @@ static void test_indexer(DB *src, DB **dbs) if ( verbose ) printf("test_indexer done\n"); } - -static void run_test(void) -{ +static void run_test(void) { int r; - toku_mutex_init(&put_lock, NULL); + toku_mutex_init(toku_uninstrumented, &put_lock, nullptr); toku_os_recursive_delete(TOKU_TEST_FILENAME); - r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); - char logname[TOKU_PATH_MAX+1]; + r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU + S_IRWXG + S_IRWXO); + CKERR(r); + char logname[TOKU_PATH_MAX + 1]; r = toku_os_mkdir(toku_path_join(logname, 2, TOKU_TEST_FILENAME, "log"), S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); r = db_env_create(&env, 0); CKERR(r); diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-multiclient.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-multiclient.cc index eefc621f80a..004a19eccec 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-multiclient.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-multiclient.cc @@ -303,13 +303,25 @@ static void test_indexer(DB *src, DB **dbs) r = indexer->set_poll_function(indexer, poll_print, NULL); CKERR(r); - // start threads doing additional inserts - no lock issues since indexer already created - r = toku_pthread_create(&client_threads[0], 0, client, (void *)&client_specs[0]); CKERR(r); - r = toku_pthread_create(&client_threads[1], 0, client, (void *)&client_specs[1]); CKERR(r); -// r = toku_pthread_create(&client_threads[2], 0, client, (void *)&client_specs[2]); CKERR(r); + // start threads doing additional inserts - no lock issues since indexer + // already created + r = toku_pthread_create(toku_uninstrumented, + &client_threads[0], + nullptr, + client, + static_cast(&client_specs[0])); + CKERR(r); + r = toku_pthread_create(toku_uninstrumented, + &client_threads[1], + nullptr, + client, + static_cast(&client_specs[1])); + CKERR(r); + // r = toku_pthread_create(toku_uninstrumented, &client_threads[2], 0, + // client, (void *)&client_specs[2]); CKERR(r); struct timeval start, now; - if ( verbose ) { + if (verbose) { printf("test_indexer build\n"); gettimeofday(&start,0); } diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-put-abort.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-put-abort.cc index 27501291b15..f4dd9c53ed5 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-put-abort.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-put-abort.cc @@ -142,11 +142,14 @@ run_test(void) { } // run the indexer - struct indexer_arg indexer_arg = { env, src_db, 1, &dest_db }; + struct indexer_arg indexer_arg = {env, src_db, 1, &dest_db}; toku_pthread_t pid; - r = toku_pthread_create(&pid, NULL, indexer_thread, &indexer_arg); assert_zero(r); + r = toku_pthread_create( + toku_uninstrumented, &pid, nullptr, indexer_thread, &indexer_arg); + assert_zero(r); - r = txn->abort(txn); assert_zero(r); + r = txn->abort(txn); + assert_zero(r); void *ret; r = toku_pthread_join(pid, &ret); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-put-commit.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-put-commit.cc index 59b40037125..99c9bf301cc 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-put-commit.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-put-commit.cc @@ -166,12 +166,16 @@ run_test(void) { } // run the indexer - struct indexer_arg indexer_arg = { env, src_db, 1, &dest_db }; + struct indexer_arg indexer_arg = {env, src_db, 1, &dest_db}; toku_pthread_t pid; - r = toku_pthread_create(&pid, NULL, indexer_thread, &indexer_arg); assert_zero(r); - - if (verbose) fprintf(stderr, "commit start\n"); - r = txn->commit(txn, 0); assert_zero(r); + r = toku_pthread_create( + toku_uninstrumented, &pid, nullptr, indexer_thread, &indexer_arg); + assert_zero(r); + + if (verbose) + fprintf(stderr, "commit start\n"); + r = txn->commit(txn, 0); + assert_zero(r); if (verbose) fprintf(stderr, "commit end\n"); void *ret; diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-with-queries.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-with-queries.cc index a0be49c1617..2bc60142f3c 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-with-queries.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-with-queries.cc @@ -114,10 +114,12 @@ static void query_only(DB *src) client_init(); // start thread doing query - r = toku_pthread_create(client_thread, 0, client, (void *)src); + r = toku_pthread_create( + toku_uninstrumented, client_thread, nullptr, + client, static_cast(src)); CKERR(r); - r = toku_pthread_join(*client_thread, &t0); + r = toku_pthread_join(*client_thread, &t0); CKERR(r); client_cleanup(); @@ -150,10 +152,13 @@ static void test_indexer(DB *src, DB **dbs) CKERR(r); // start thread doing query - r = toku_pthread_create(client_thread, 0, client, (void *)src); CKERR(r); + r = toku_pthread_create( + toku_uninstrumented, client_thread, nullptr, + client, static_cast(src)); + CKERR(r); struct timeval start, now; - if ( verbose ) { + if (verbose) { printf("test_indexer build\n"); gettimeofday(&start,0); } diff --git a/storage/tokudb/PerconaFT/src/tests/locktree_escalation_stalls.cc b/storage/tokudb/PerconaFT/src/tests/locktree_escalation_stalls.cc index b4874472bcb..e6c1b18b2b6 100644 --- a/storage/tokudb/PerconaFT/src/tests/locktree_escalation_stalls.cc +++ b/storage/tokudb/PerconaFT/src/tests/locktree_escalation_stalls.cc @@ -191,17 +191,22 @@ static void run_test(uint64_t max_i, int n_small) { env, big_db, max_i, big_test, }; toku_pthread_t big_id; - r = toku_pthread_create(&big_id, NULL, test_f, &big_test_args); + r = toku_pthread_create( + toku_uninstrumented, &big_id, nullptr, 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]); + small_test_args[i] = {env, small_db, max_i, small_test}; + r = toku_pthread_create(toku_uninstrumented, + &small_id[i], + nullptr, + test_f, + &small_test_args[i]); assert(r == 0); } - + void *big_ret; r = toku_pthread_join(big_id, &big_ret); assert(r == 0); diff --git a/storage/tokudb/PerconaFT/src/tests/recover-test_crash_in_flusher_thread.h b/storage/tokudb/PerconaFT/src/tests/recover-test_crash_in_flusher_thread.h index 0ed68207ed4..5c10d0cb712 100644 --- a/storage/tokudb/PerconaFT/src/tests/recover-test_crash_in_flusher_thread.h +++ b/storage/tokudb/PerconaFT/src/tests/recover-test_crash_in_flusher_thread.h @@ -70,13 +70,18 @@ static void *do_checkpoint_and_crash(void *arg) { static void flt_callback(int flt_state, void* extra) { cnt++; if (verbose) printf("flt_state!! %d\n", flt_state); - if (cnt > 0 && !starting_a_chkpt && flt_state == state_to_crash) { - starting_a_chkpt = true; - if (verbose) printf("flt_state %d\n", flt_state); - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint_and_crash, extra); - assert(r==0); - usleep(2*1000*1000); - } + if (cnt > 0 && !starting_a_chkpt && flt_state == state_to_crash) { + starting_a_chkpt = true; + if (verbose) + printf("flt_state %d\n", flt_state); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint_and_crash, + extra); + assert(r == 0); + usleep(2 * 1000 * 1000); + } } diff --git a/storage/tokudb/PerconaFT/src/tests/recovery_stress.cc b/storage/tokudb/PerconaFT/src/tests/recovery_stress.cc index b1f5f98a90a..1646030cc85 100644 --- a/storage/tokudb/PerconaFT/src/tests/recovery_stress.cc +++ b/storage/tokudb/PerconaFT/src/tests/recovery_stress.cc @@ -515,19 +515,8 @@ static void run_test (int iter) { // if requesting crash, randomly do other non-committed acts, then "drop_dead" if (iter > 0) { - if (verbose) printf("dying\n"); -#if 0 - // separate thread will perform random acts on other dictionaries (not 0) - r = toku_pthread_create(&thread, 0, random_acts, (void *) dictionaries); - CKERR(r); - // this thead will scribble over dictionary 0 before crash to verify that - // post-checkpoint inserts are not in the database - DB* db = dictionaries[0].db; - if (iter & 1) - scribble(db, iter); - else - thin_out(db, iter); -#endif + if (verbose) + printf("dying\n"); uint32_t delay = myrandom(); delay &= 0xFFF; // select lower 12 bits, shifted up 8 for random number ... delay = delay << 8; // ... uniformly distributed between 0 and 1M ... diff --git a/storage/tokudb/PerconaFT/src/tests/stress_openclose.h b/storage/tokudb/PerconaFT/src/tests/stress_openclose.h index 3f10bfe8aeb..3a55ca4486f 100644 --- a/storage/tokudb/PerconaFT/src/tests/stress_openclose.h +++ b/storage/tokudb/PerconaFT/src/tests/stress_openclose.h @@ -245,19 +245,16 @@ stress_table(DB_ENV *env, DB **dbp, struct cli_args *cli_args) { // which they can choose a random db to either touch or query XMALLOC_N(num_buckets, buckets); for (int i = 0; i < num_buckets; i++) { - struct db_bucket bucket = { - .env = env, - .db = dbp[i], - .is_open = true - }; + struct db_bucket bucket = {.env = env, .db = dbp[i], .is_open = true}; buckets[i] = bucket; - toku_mutex_init(&buckets[i].mutex, NULL); + toku_mutex_init(toku_uninstrumented, &buckets[i].mutex, nullptr); } // run all of the query and update workers. they may randomly open // and close the dbs in each db_bucket to be some random dictionary, // so when they're done we'll have to clean up the mess so this // stress test can exit gracefully expecting db[i] = the ith db - //verbose_printf("stressing %d tables using %d update threads, %d query threads\n", + // verbose_printf("stressing %d tables using %d update threads, %d query + // threads\n", // num_buckets, update_threads, query_threads); verbose_printf("stressing %d tables using %d update threads\n", num_buckets, update_threads); diff --git a/storage/tokudb/PerconaFT/src/tests/test3039.cc b/storage/tokudb/PerconaFT/src/tests/test3039.cc index 54a2b3bf730..6c38fa13592 100644 --- a/storage/tokudb/PerconaFT/src/tests/test3039.cc +++ b/storage/tokudb/PerconaFT/src/tests/test3039.cc @@ -184,30 +184,36 @@ void do_threads (unsigned long long N, int do_nonlocal) { toku_pthread_t ths[2]; struct reader_thread_state rstates[2] = {{.elapsed_time = 0.0, .n_did_read = 0, - .n_to_read = (long long signed) N, - .do_local = 1, - .finish = 0}, + .n_to_read = (long long signed)N, + .do_local = 1, + .finish = 0}, {.elapsed_time = 0.0, .n_did_read = 0, .n_to_read = -1, - .do_local = 0, - .finish = 0}}; + .do_local = 0, + .finish = 0}}; int n_to_create = do_nonlocal ? 2 : 1; - for (int i=0; i(&rstates[i])); + CKERR(r); } - for (int i=0; i. + +---------------------------------------- + + PerconaFT is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + PerconaFT 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with PerconaFT. If not, see . +======= */ + +#ident \ + "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include "test.h" +// to verify the DB_LOCKING_READ works to lock the read rows for snapshot +// isolaton. +// we create a db, then init a read transaction with repeatable-read isolation +// and +// locking read flag, then we start another transaction to grab the write lock. +// DB_LOCKING_READ is defined here to just make the before and after tests work +// (before +// test did not have DB_LOCKING_READ flag). +#if !defined(DB_LOCKING_READ) +#define DB_LOCKING_READ 0 +#endif +static int prelock_range(DBC *cursor, int left, int right) { + DBT key_left; + dbt_init(&key_left, &left, sizeof left); + DBT key_right; + dbt_init(&key_right, &right, sizeof right); + int r = cursor->c_set_bounds(cursor, &key_left, &key_right, true, 0); + return r; +} + +static void test_read_write_range(DB_ENV *env, + DB *db, + uint32_t iso_flags, + int expect_r) { + int r; + + DB_TXN *txn_a = NULL; + r = env->txn_begin(env, NULL, &txn_a, iso_flags); + assert_zero(r); + DB_TXN *txn_b = NULL; + r = env->txn_begin(env, NULL, &txn_b, iso_flags); + assert_zero(r); + + DBC *cursor_a = NULL; + r = db->cursor(db, txn_a, &cursor_a, DB_LOCKING_READ); + assert_zero(r); + DBC *cursor_b = NULL; + r = db->cursor(db, txn_b, &cursor_b, DB_RMW); + assert_zero(r); + + r = prelock_range(cursor_a, htonl(10), htonl(100)); + assert_zero(r); + r = prelock_range(cursor_b, htonl(50), htonl(200)); + assert(r == expect_r); + + r = cursor_a->c_close(cursor_a); + assert_zero(r); + r = cursor_b->c_close(cursor_b); + assert_zero(r); + + r = txn_a->commit(txn_a, 0); + assert_zero(r); + r = txn_b->commit(txn_b, 0); + assert_zero(r); +} + +static void test_read_write_point(DB_ENV *env, + DB *db, + uint32_t iso_flags, + int expect_r) { + int r; + + DB_TXN *txn1 = NULL; + r = env->txn_begin(env, NULL, &txn1, iso_flags); + assert_zero(r); + + DB_TXN *txn2 = NULL; + r = env->txn_begin(env, NULL, &txn2, iso_flags); + assert_zero(r); + + DBC *c1 = NULL; + r = db->cursor(db, txn1, &c1, DB_LOCKING_READ); + assert_zero(r); + + DBC *c2 = NULL; + r = db->cursor(db, txn2, &c2, DB_RMW); + assert_zero(r); + + int k = htonl(42); + DBT key; + dbt_init(&key, &k, sizeof k); + DBT val; + memset(&val, 0, sizeof val); + r = c1->c_get(c1, &key, &val, DB_SET); + assert_zero(r); + + r = c2->c_get(c2, &key, &val, DB_SET); + assert(r == expect_r); + + r = c1->c_close(c1); + assert_zero(r); + r = c2->c_close(c2); + assert_zero(r); + + r = txn1->commit(txn1, 0); + assert_zero(r); + r = txn2->commit(txn2, 0); + assert_zero(r); +} + +int test_main(int argc, char *const argv[]) { + int r; + + const char *env_dir = TOKU_TEST_FILENAME; + const char *db_filename = "lockingreadtest"; + + parse_args(argc, argv); + + char rm_cmd[strlen(env_dir) + strlen("rm -rf ") + 1]; + snprintf(rm_cmd, sizeof(rm_cmd), "rm -rf %s", env_dir); + r = system(rm_cmd); + assert_zero(r); + + r = toku_os_mkdir(env_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + assert_zero(r); + + DB_ENV *env = NULL; + r = db_env_create(&env, 0); + assert_zero(r); + int env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN | + DB_INIT_LOCK | DB_INIT_LOG; + r = env->open( + env, env_dir, env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + assert_zero(r); + + // create the db + DB *db = NULL; + r = db_create(&db, env, 0); + assert_zero(r); + DB_TXN *create_txn = NULL; + r = env->txn_begin(env, NULL, &create_txn, 0); + assert_zero(r); + r = db->open(db, + create_txn, + db_filename, + NULL, + DB_BTREE, + DB_CREATE, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + assert_zero(r); + r = create_txn->commit(create_txn, 0); + assert_zero(r); + + // add a record + + DB_TXN *write_txn = NULL; + r = env->txn_begin(env, NULL, &write_txn, 0); + assert_zero(r); + + int k = htonl(42); + int v = 42; + DBT key; + dbt_init(&key, &k, sizeof k); + DBT val; + dbt_init(&val, &v, sizeof v); + r = db->put(db, write_txn, &key, &val, DB_NOOVERWRITE); + assert_zero(r); + r = write_txn->commit(write_txn, 0); + assert_zero(r); + + test_read_write_range(env, db, DB_TXN_SNAPSHOT, DB_LOCK_NOTGRANTED); + test_read_write_point(env, db, DB_TXN_SNAPSHOT, DB_LOCK_NOTGRANTED); + + r = db->close(db, 0); + assert_zero(r); + + r = env->close(env, 0); + assert_zero(r); + return 0; +} diff --git a/storage/tokudb/PerconaFT/src/tests/test_3645.cc b/storage/tokudb/PerconaFT/src/tests/test_3645.cc index bb5566b032d..e1fa37bef54 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_3645.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_3645.cc @@ -239,33 +239,61 @@ test_evictions (void) { // make the forward fast scanner myargs[0].fast = true; myargs[0].fwd = true; - { int chk_r = toku_pthread_create(&mytids[0], NULL, scan_db, &myargs[0]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[0], nullptr, scan_db, &myargs[0]); + CKERR(chk_r); + } // make the forward slow scanner myargs[1].fast = false; myargs[1].fwd = true; - { int chk_r = toku_pthread_create(&mytids[1], NULL, scan_db, &myargs[1]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[1], nullptr, scan_db, &myargs[1]); + CKERR(chk_r); + } // make the backward fast scanner myargs[2].fast = true; myargs[2].fwd = false; - { int chk_r = toku_pthread_create(&mytids[2], NULL, scan_db, &myargs[2]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[2], nullptr, scan_db, &myargs[2]); + CKERR(chk_r); + } // make the backward slow scanner myargs[3].fast = false; myargs[3].fwd = false; - { int chk_r = toku_pthread_create(&mytids[3], NULL, scan_db, &myargs[3]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[3], nullptr, scan_db, &myargs[3]); + CKERR(chk_r); + } // make the guy that updates the db - { int chk_r = toku_pthread_create(&mytids[4], NULL, update_db, &myargs[4]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[4], nullptr, update_db, &myargs[4]); + CKERR(chk_r); + } // make the guy that does point queries - { int chk_r = toku_pthread_create(&mytids[5], NULL, ptquery_db, &myargs[5]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[5], nullptr, ptquery_db, &myargs[5]); + CKERR(chk_r); + } // make the guy that sleeps - { int chk_r = toku_pthread_create(&mytids[6], NULL, test_time, NULL); CKERR(chk_r); } - - for (uint32_t i = 0; i < sizeof(myargs)/sizeof(myargs[0]); i++) { + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[6], nullptr, test_time, nullptr); + CKERR(chk_r); + } + + for (uint32_t i = 0; i < sizeof(myargs) / sizeof(myargs[0]); i++) { void *ret; r = toku_pthread_join(mytids[i], &ret); assert_zero(r); } diff --git a/storage/tokudb/PerconaFT/src/tests/test_4015.cc b/storage/tokudb/PerconaFT/src/tests/test_4015.cc index dc18242b489..1231e3b4bca 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_4015.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_4015.cc @@ -151,10 +151,18 @@ int test_main(int argc, char * const argv[]) { { int chk_r = db->open(db, NULL, "db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(chk_r); } DBT desc; dbt_init(&desc, "foo", sizeof("foo")); - IN_TXN_COMMIT(env, NULL, txn, 0, - { int chk_r = db->change_descriptor(db, txn, &desc, DB_UPDATE_CMP_DESCRIPTOR); CKERR(chk_r); }); + IN_TXN_COMMIT(env, NULL, txn, 0, { + int chk_r = + db->change_descriptor(db, txn, &desc, DB_UPDATE_CMP_DESCRIPTOR); + CKERR(chk_r); + }); pthread_t thd; - { int chk_r = toku_pthread_create(&thd, NULL, startA, NULL); CKERR(chk_r); } + { + int chk_r = + toku_pthread_create( + toku_uninstrumented, &thd, nullptr, startA, nullptr); + CKERR(chk_r); + } startB(); diff --git a/storage/tokudb/PerconaFT/src/tests/test_abort1.cc b/storage/tokudb/PerconaFT/src/tests/test_abort1.cc index 55449610ffb..7b60364878b 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_abort1.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_abort1.cc @@ -87,10 +87,12 @@ test_db_open_aborts (void) { CKERR2(r, DB_NOTFOUND); } toku_struct_stat statbuf; - char filename[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), &statbuf); - assert(r!=0); - assert(errno==ENOENT); + char filename[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), + &statbuf, + toku_uninstrumented); + assert(r != 0); + assert(errno == ENOENT); } r=env->close(env, 0); assert(r==0); @@ -153,10 +155,12 @@ test_db_put_aborts (void) { CAST_FROM_VOIDP(filename, iname.data); assert(filename); } - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } // But the item should not be in it. diff --git a/storage/tokudb/PerconaFT/src/tests/test_abort4.cc b/storage/tokudb/PerconaFT/src/tests/test_abort4.cc index e67efb465b2..e797fc640d8 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_abort4.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_abort4.cc @@ -160,10 +160,12 @@ verify_and_tear_down(int close_first) { CAST_FROM_VOIDP(filename, iname.data); assert(filename); } - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } CKERR(r); diff --git a/storage/tokudb/PerconaFT/src/tests/test_abort5.cc b/storage/tokudb/PerconaFT/src/tests/test_abort5.cc index 728afcce1b9..d5d056d5126 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_abort5.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_abort5.cc @@ -191,10 +191,12 @@ verify_and_tear_down(int close_first) { CAST_FROM_VOIDP(filename, iname.data); assert(filename); } - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } if (close_first) { diff --git a/storage/tokudb/PerconaFT/src/tests/test_forkjoin.cc b/storage/tokudb/PerconaFT/src/tests/test_forkjoin.cc index 910cf46e513..766372a15c2 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_forkjoin.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_forkjoin.cc @@ -48,12 +48,13 @@ f (void *arg) { return arg; } -int -test_main(int argc, char *const argv[]) { +int test_main(int argc, char *const argv[]) { parse_args(argc, argv); toku_pthread_t t; - int r = toku_pthread_create(&t, 0, f, 0); assert(r == 0); + int r = toku_pthread_create(toku_uninstrumented, &t, nullptr, f, nullptr); + assert(r == 0); void *ret; - r = toku_pthread_join(t, &ret); assert(r == 0); + r = toku_pthread_join(t, &ret); + assert(r == 0); return 0; } diff --git a/storage/tokudb/PerconaFT/src/tests/test_groupcommit_count.cc b/storage/tokudb/PerconaFT/src/tests/test_groupcommit_count.cc index 414ddd2b70a..35104c2a569 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_groupcommit_count.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_groupcommit_count.cc @@ -87,12 +87,16 @@ test_groupcommit (int nthreads) { int i; toku_pthread_t threads[nthreads]; int whichthread[nthreads]; - for (i=0; iclose(db, 0); assert(r==0); diff --git a/storage/tokudb/PerconaFT/src/tests/test_groupcommit_perf.cc b/storage/tokudb/PerconaFT/src/tests/test_groupcommit_perf.cc index 94eaf2a01a9..6f872d10a32 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_groupcommit_perf.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_groupcommit_perf.cc @@ -84,12 +84,16 @@ test_groupcommit (int nthreads) { int i; toku_pthread_t threads[nthreads]; int whichthread[nthreads]; - for (i=0; itxn_begin(env, 0, &tid, 0); CKERR(r); diff --git a/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc b/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc index f2bf0a2c756..66471a74af2 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc @@ -112,12 +112,17 @@ int test_main(int UU(argc), char *const UU(argv[])) { acquire_lock(txn1, magic_key); acquire_lock_extra e1(txn2, magic_key); - r = toku_pthread_create(&thread1, NULL, acquire_lock_thread, &e1); CKERR(r); + r = toku_pthread_create( + toku_uninstrumented, &thread1, nullptr, acquire_lock_thread, &e1); + CKERR(r); acquire_lock_extra e2(txn3, magic_key); - r = toku_pthread_create(&thread2, NULL, acquire_lock_thread, &e2); CKERR(r); + r = toku_pthread_create( + toku_uninstrumented, &thread2, nullptr, acquire_lock_thread, &e2); + CKERR(r); sleep(1); - r = env->iterate_pending_lock_requests(env, iterate_callback, NULL); CKERR(r); + r = env->iterate_pending_lock_requests(env, iterate_callback, NULL); + CKERR(r); invariant(iterate_callback_called == 2); void *v; diff --git a/storage/tokudb/PerconaFT/src/tests/test_lock_timeout_callback.cc b/storage/tokudb/PerconaFT/src/tests/test_lock_timeout_callback.cc index 75ea49ec858..571bae69916 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_lock_timeout_callback.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_lock_timeout_callback.cc @@ -118,7 +118,8 @@ int test_main(int UU(argc), char *const UU(argv[])) { acquire_lock(txn2, magic_key + 1); toku_pthread_t thread; acquire_lock_extra e(txn1, magic_key + 1); - r = toku_pthread_create(&thread, NULL, acquire_lock_thread, &e); + r = toku_pthread_create( + toku_uninstrumented, &thread, nullptr, acquire_lock_thread, &e); usleep(100000); acquire_lock(txn2, magic_key); invariant(callback_calls == 2); diff --git a/storage/tokudb/PerconaFT/src/tests/test_log1.cc b/storage/tokudb/PerconaFT/src/tests/test_log1.cc index 65fa1d830ef..5473a8e3d5e 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_log1.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_log1.cc @@ -87,10 +87,12 @@ static void make_db (bool close_env) { r=tid->commit(tid, 0); assert(r==0); r=db->close(db, 0); assert(r==0); { - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } if (close_env) { diff --git a/storage/tokudb/PerconaFT/src/tests/test_log1_abort.cc b/storage/tokudb/PerconaFT/src/tests/test_log1_abort.cc index 92c3657a154..c66409fb823 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_log1_abort.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_log1_abort.cc @@ -80,11 +80,13 @@ test_main (int UU(argc), char UU(*const argv[])) { r=env->close(env, 0); assert(r==0); { - toku_struct_stat statbuf; - char filename[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), &statbuf); - assert(r==-1); - assert(errno==ENOENT); + toku_struct_stat statbuf; + char filename[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), + &statbuf, + toku_uninstrumented); + assert(r == -1); + assert(errno == ENOENT); } return 0; } diff --git a/storage/tokudb/PerconaFT/src/tests/test_logmax.cc b/storage/tokudb/PerconaFT/src/tests/test_logmax.cc index e5de0a5d906..133eb36ddb5 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_logmax.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_logmax.cc @@ -50,14 +50,19 @@ check_logmax (int max) { struct dirent *ent; while ((ent=readdir(dir))) { if ((ent->d_type==DT_REG || ent->d_type==DT_UNKNOWN) && strncmp(ent->d_name, "log", 3)==0) { - // It is a "log*" file - char full_fname[TOKU_PATH_MAX+1]; - toku_struct_stat sbuf; - int r = toku_stat(toku_path_join(full_fname, 2, TOKU_TEST_FILENAME, ent->d_name), &sbuf); - assert(r==0); - if (verbose) - printf("%s is of size %" PRId64 "\n", ent->d_name, (int64_t)sbuf.st_size); - if (sbuf.st_size > max) any_too_big=1; + // It is a "log*" file + char full_fname[TOKU_PATH_MAX + 1]; + toku_struct_stat sbuf; + int r = toku_stat( + toku_path_join(full_fname, 2, TOKU_TEST_FILENAME, ent->d_name), + &sbuf, + toku_uninstrumented); + assert(r == 0); + if (verbose) + printf("%s is of size %" PRId64 "\n", + ent->d_name, + (int64_t)sbuf.st_size); + if (sbuf.st_size > max) any_too_big=1; } } assert(!any_too_big); diff --git a/storage/tokudb/PerconaFT/src/tests/test_multiple_checkpoints_block_commit.cc b/storage/tokudb/PerconaFT/src/tests/test_multiple_checkpoints_block_commit.cc index 66e9f4a5ec8..da53a7bfe11 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_multiple_checkpoints_block_commit.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_multiple_checkpoints_block_commit.cc @@ -101,10 +101,17 @@ static void run_test(void) { toku_pthread_t chkpt1_tid; toku_pthread_t chkpt2_tid; - - { int chk_r = toku_pthread_create(&chkpt1_tid, NULL, run_checkpoint, NULL); CKERR(chk_r); } - { int chk_r = toku_pthread_create(&chkpt2_tid, NULL, run_checkpoint, NULL); CKERR(chk_r); } - usleep(2*1024*1024); + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &chkpt1_tid, nullptr, run_checkpoint, nullptr); + CKERR(chk_r); + } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &chkpt2_tid, nullptr, run_checkpoint, nullptr); + CKERR(chk_r); + } + usleep(2 * 1024 * 1024); struct timeval tstart; gettimeofday(&tstart, NULL); DB_TXN *txn = NULL; diff --git a/storage/tokudb/PerconaFT/src/tests/test_stress_hot_indexing.cc b/storage/tokudb/PerconaFT/src/tests/test_stress_hot_indexing.cc index e0bf0d2ec6f..6395f591660 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_stress_hot_indexing.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_stress_hot_indexing.cc @@ -312,12 +312,11 @@ stress_table(DB_ENV *env, DB **dbp, struct cli_args *cli_args) { run_workers(myargs, num_threads, cli_args->num_seconds, false, cli_args); } -int -test_main(int argc, char *const argv[]) { +int test_main(int argc, char *const argv[]) { gid_count = 0; memset(hi_gid, 0, sizeof(hi_gid)); - toku_mutex_init(&hi_lock, NULL); - toku_mutex_init(&fops_lock, NULL); + toku_mutex_init(toku_uninstrumented, &hi_lock, nullptr); + toku_mutex_init(toku_uninstrumented, &fops_lock, nullptr); hot_db = NULL; struct cli_args args = get_default_args(); // let's make default checkpointing period really slow diff --git a/storage/tokudb/PerconaFT/src/tests/test_thread_insert.cc b/storage/tokudb/PerconaFT/src/tests/test_thread_insert.cc index 0d5245e8f80..a266de638f1 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_thread_insert.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_thread_insert.cc @@ -150,10 +150,13 @@ test_main(int argc, char *const argv[]) { work[i].endno = n; } - if (verbose) printf("pid:%d\n", toku_os_getpid()); + if (verbose) + printf("pid:%d\n", toku_os_getpid()); - for (i=1; iclose(env, 0); assert(r == 0); diff --git a/storage/tokudb/PerconaFT/src/tests/threaded_stress_test_helpers.h b/storage/tokudb/PerconaFT/src/tests/threaded_stress_test_helpers.h index f2bacceed9d..e232f327d10 100644 --- a/storage/tokudb/PerconaFT/src/tests/threaded_stress_test_helpers.h +++ b/storage/tokudb/PerconaFT/src/tests/threaded_stress_test_helpers.h @@ -469,11 +469,11 @@ static int get_commit_flags(struct cli_args *args) { } struct worker_extra { - struct arg* thread_arg; + struct arg *thread_arg; toku_mutex_t *operation_lock_mutex; - struct rwlock *operation_lock; + struct st_rwlock *operation_lock; uint64_t *counters; - int64_t pad[4]; // pad to 64 bytes + int64_t pad[4]; // pad to 64 bytes }; static void lock_worker_op(struct worker_extra* we) { @@ -1772,11 +1772,12 @@ static int run_workers( ) { int r; - const struct perf_formatter *perf_formatter = &perf_formatters[cli_args->perf_output_format]; + const struct perf_formatter *perf_formatter = + &perf_formatters[cli_args->perf_output_format]; toku_mutex_t mutex = ZERO_MUTEX_INITIALIZER; - toku_mutex_init(&mutex, nullptr); - struct rwlock rwlock; - rwlock_init(&rwlock); + toku_mutex_init(toku_uninstrumented, &mutex, nullptr); + struct st_rwlock rwlock; + rwlock_init(toku_uninstrumented, &rwlock); toku_pthread_t tids[num_threads]; toku_pthread_t time_tid; if (cli_args->print_performance) { @@ -1798,15 +1799,26 @@ static int run_workers( worker_extra[i].thread_arg = &thread_args[i]; worker_extra[i].operation_lock = &rwlock; worker_extra[i].operation_lock_mutex = &mutex; - XCALLOC_N((int) NUM_OPERATION_TYPES, worker_extra[i].counters); + XCALLOC_N((int)NUM_OPERATION_TYPES, worker_extra[i].counters); TOKU_DRD_IGNORE_VAR(worker_extra[i].counters); - { int chk_r = toku_pthread_create(&tids[i], nullptr, worker, &worker_extra[i]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create(toku_uninstrumented, + &tids[i], + nullptr, + worker, + &worker_extra[i]); + CKERR(chk_r); + } if (verbose) - printf("%lu created\n", (unsigned long) tids[i]); + printf("%lu created\n", (unsigned long)tids[i]); + } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &time_tid, nullptr, test_time, &tte); + CKERR(chk_r); } - { int chk_r = toku_pthread_create(&time_tid, nullptr, test_time, &tte); CKERR(chk_r); } if (verbose) - printf("%lu created\n", (unsigned long) time_tid); + printf("%lu created\n", (unsigned long)time_tid); void *ret; r = toku_pthread_join(time_tid, &ret); assert_zero(r); @@ -1817,17 +1829,22 @@ static int run_workers( // threads (i.e. there is some runaway thread). struct sleep_and_crash_extra sac_extra; ZERO_STRUCT(sac_extra); - toku_mutex_init(&sac_extra.mutex, nullptr); - toku_cond_init(&sac_extra.cond, nullptr); + toku_mutex_init(toku_uninstrumented, &sac_extra.mutex, nullptr); + toku_cond_init(toku_uninstrumented, &sac_extra.cond, nullptr); sac_extra.seconds = cli_args->join_timeout; sac_extra.is_setup = false; sac_extra.threads_have_joined = false; toku_mutex_lock(&sac_extra.mutex); toku_pthread_t sac_thread; - r = toku_pthread_create(&sac_thread, nullptr, sleep_and_crash, &sac_extra); + r = toku_pthread_create(toku_uninstrumented, + &sac_thread, + nullptr, + sleep_and_crash, + &sac_extra); assert_zero(r); - // Wait for sleep_and_crash thread to get set up, spinning is ok, this should be quick. + // Wait for sleep_and_crash thread to get set up, spinning is ok, this + // should be quick. while (!sac_extra.is_setup) { toku_mutex_unlock(&sac_extra.mutex); r = toku_pthread_yield(); diff --git a/storage/tokudb/PerconaFT/src/tests/txn_manager_handle_snapshot_atomicity.cc b/storage/tokudb/PerconaFT/src/tests/txn_manager_handle_snapshot_atomicity.cc index 30cc16d73a7..469e78f492f 100644 --- a/storage/tokudb/PerconaFT/src/tests/txn_manager_handle_snapshot_atomicity.cc +++ b/storage/tokudb/PerconaFT/src/tests/txn_manager_handle_snapshot_atomicity.cc @@ -52,8 +52,8 @@ struct test_sync { static void test_sync_init(struct test_sync *UU(sync)) { #if TOKU_DEBUG_TXN_SYNC sync->state = 0; - toku_mutex_init(&sync->lock, NULL); - toku_cond_init(&sync->cv, NULL); + toku_mutex_init(toku_uninstrumented, &sync->lock, nullptr); + toku_cond_init(toku_uninstrumented, &sync->cv, nullptr); #endif } diff --git a/storage/tokudb/PerconaFT/src/ydb.cc b/storage/tokudb/PerconaFT/src/ydb.cc index abf8d3dfd17..a172773bca3 100644 --- a/storage/tokudb/PerconaFT/src/ydb.cc +++ b/storage/tokudb/PerconaFT/src/ydb.cc @@ -227,7 +227,7 @@ env_fs_poller(void *arg) { int in_red; // set true to prevent certain operations (returning ENOSPC) // get the fs sizes for the home dir - uint64_t avail_size, total_size; + uint64_t avail_size = 0, total_size = 0; r = toku_get_filesystem_sizes(env->i->dir, &avail_size, NULL, &total_size); assert(r == 0); in_yellow = (avail_size < 2 * env_fs_redzone(env, total_size)); @@ -643,7 +643,7 @@ static int validate_env(DB_ENV *env, path = toku_construct_full_name( 2, env->i->dir, toku_product_name_strings.environmentdictionary); assert(path); - r = toku_stat(path, &buf); + r = toku_stat(path, &buf, toku_uninstrumented); if (r == 0) { expect_newenv = false; // persistent info exists } else { @@ -668,7 +668,7 @@ static int validate_env(DB_ENV *env, path = toku_construct_full_name( 2, env->i->dir, toku_product_name_strings.rollback_cachefile); assert(path); - r = toku_stat(path, &buf); + r = toku_stat(path, &buf, toku_uninstrumented); if (r == 0) { if (expect_newenv) // rollback cachefile exists, but persistent env // is missing @@ -710,7 +710,7 @@ static int validate_env(DB_ENV *env, path = toku_construct_full_name( 2, env->i->dir, toku_product_name_strings.fileopsdirectory); assert(path); - r = toku_stat(path, &buf); + r = toku_stat(path, &buf, toku_uninstrumented); if (r == 0) { if (expect_newenv) // fileops directory exists, but persistent env // is missing @@ -856,10 +856,11 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) { // Verify that the home exists. toku_struct_stat buf; - r = toku_stat(home, &buf); + r = toku_stat(home, &buf, toku_uninstrumented); if (r != 0) { int e = get_error_errno(); - r = toku_ydb_do_error(env, e, "Error from toku_stat(\"%s\",...)\n", home); + r = toku_ydb_do_error( + env, e, "Error from toku_stat(\"%s\",...)\n", home); goto cleanup; } unused_flags &= ~DB_PRIVATE; @@ -875,13 +876,22 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) { env->i->open_flags = flags; env->i->open_mode = mode; + // Instrumentation probe start + TOKU_PROBE_START(toku_instr_probe_1); + env_setup_real_data_dir(env); env_setup_real_log_dir(env); env_setup_real_tmp_dir(env); - r = toku_single_process_lock(env->i->dir, "environment", &env->i->envdir_lockfd); - if (r!=0) goto cleanup; - r = toku_single_process_lock(env->i->real_data_dir, "data", &env->i->datadir_lockfd); + // Instrumentation probe stop + toku_instr_probe_1->stop(); + + r = toku_single_process_lock( + env->i->dir, "environment", &env->i->envdir_lockfd); + if (r != 0) + goto cleanup; + r = toku_single_process_lock( + env->i->real_data_dir, "data", &env->i->datadir_lockfd); if (r!=0) goto cleanup; r = toku_single_process_lock(env->i->real_log_dir, "logs", &env->i->logdir_lockfd); if (r!=0) goto cleanup; @@ -2924,7 +2934,8 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) { result->i->open_dbs_by_dname->create(); XMALLOC(result->i->open_dbs_by_dict_id); result->i->open_dbs_by_dict_id->create(); - toku_pthread_rwlock_init(&result->i->open_dbs_rwlock, NULL); + toku_pthread_rwlock_init( + *result_i_open_dbs_rwlock_key, &result->i->open_dbs_rwlock, nullptr); *envp = result; r = 0; diff --git a/storage/tokudb/PerconaFT/src/ydb_db.cc b/storage/tokudb/PerconaFT/src/ydb_db.cc index 100d1bfa20b..40c4a7f6577 100644 --- a/storage/tokudb/PerconaFT/src/ydb_db.cc +++ b/storage/tokudb/PerconaFT/src/ydb_db.cc @@ -83,53 +83,56 @@ ydb_db_layer_get_status(YDB_DB_LAYER_STATUS statp) { *statp = ydb_db_layer_status; } -void create_iname_hint(const char *dname, char *hint) { +void create_iname_hint(DB_ENV *env, const char *dname, char *hint) { //Requires: size of hint array must be > strlen(dname) //Copy alphanumeric characters only. //Replace strings of non-alphanumeric characters with a single underscore. - bool underscored = false; - while (*dname) { - if (isalnum(*dname)) { - char c = *dname++; - *hint++ = c; - underscored = false; - } - else { - if (!underscored) - *hint++ = '_'; - dname++; - underscored = true; + if (env->get_dir_per_db(env) && !toku_os_is_absolute_name(dname)) { + assert(dname); + if (*dname == '.') + ++dname; + if (*dname == '/') + ++dname; + bool underscored = false; + bool dbdir_is_parsed = false; + // Do not change the first '/' because this is + // delimiter which splits name into database dir + // and table dir. + while (*dname) { + if (isalnum(*dname) || (*dname == '/' && !dbdir_is_parsed)) { + char c = *dname++; + *hint++ = c; + if (c == '/') + dbdir_is_parsed = true; + underscored = false; + } else if (!dbdir_is_parsed) { + char c = *dname++; + *hint++ = c; + } else { + if (!underscored) + *hint++ = '_'; + dname++; + underscored = true; + } } - } - *hint = '\0'; -} - -void create_iname_hint_for_dbdir(const char *dname, char *hint) { - assert(dname); - if (*dname == '.') - ++dname; - if (*dname == '/') - ++dname; - bool underscored = false; - bool dbdir_is_parsed = false; - // Do not change the first '/' because this is - // delimiter which splits name into database dir - // and table dir. - while (*dname) { - if (isalnum(*dname) || (*dname == '/' && !dbdir_is_parsed)) { - char c = *dname++; - *hint++ = c; - if (c == '/') - dbdir_is_parsed = true; - underscored = false; - } else { - if (!underscored) - *hint++ = '_'; - dname++; - underscored = true; + *hint = '\0'; + } else { + bool underscored = false; + while (*dname) { + if (isalnum(*dname)) { + char c = *dname++; + *hint++ = c; + underscored = false; + } + else { + if (!underscored) + *hint++ = '_'; + dname++; + underscored = true; + } } + *hint = '\0'; } - *hint = '\0'; } // n < 0 means to ignore mark and ignore n @@ -187,10 +190,7 @@ std::unique_ptr generate_iname_for_rename_or_open( } else if (is_open) id1 = toku_sync_fetch_and_add(&nontransactional_open_id, 1); - if (env->get_dir_per_db(env) && !toku_os_is_absolute_name(dname)) - create_iname_hint_for_dbdir(dname, hint); - else - create_iname_hint(dname, hint); + create_iname_hint(env, dname, hint); result.reset(create_iname(env, id1, id2, hint, NULL, -1)); @@ -1221,15 +1221,18 @@ load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[/*N*/], const char * new for (i = 0; i < N; i++) { char * dname = dbs[i]->i->dname; toku_fill_dbt(&dname_dbt, dname, strlen(dname)+1); + // now create new iname char hint[strlen(dname) + 1]; - if (env->get_dir_per_db(env) && !toku_os_is_absolute_name(dname)) - create_iname_hint_for_dbdir(dname, hint); - else - create_iname_hint(dname, hint); - const char *new_iname = create_iname(env, xid.parent_id64, xid.child_id64, hint, mark, i); // allocates memory for iname_in_env + create_iname_hint(env, dname, hint); + + // allocates memory for iname_in_env + const char *new_iname = + create_iname(env, xid.parent_id64, xid.child_id64, hint, mark, i); new_inames_in_env[i] = new_iname; - toku_fill_dbt(&iname_dbt, new_iname, strlen(new_iname) + 1); // iname_in_env goes in directory + + // iname_in_env goes in directory + toku_fill_dbt(&iname_dbt, new_iname, strlen(new_iname) + 1); rval = toku_db_put(env->i->directory, txn, &dname_dbt, &iname_dbt, 0, true); if (rval) break; } diff --git a/storage/tokudb/PerconaFT/src/ydb_db.h b/storage/tokudb/PerconaFT/src/ydb_db.h index 8be28857c14..ab8fcd2a401 100644 --- a/storage/tokudb/PerconaFT/src/ydb_db.h +++ b/storage/tokudb/PerconaFT/src/ydb_db.h @@ -122,8 +122,7 @@ toku_db_destruct_autotxn(DB_TXN *txn, int r, bool changed) { return r; } -void create_iname_hint_for_dbdir(const char *dname, char *hint); -void create_iname_hint(const char *dname, char *hint); +void create_iname_hint(DB_ENV *env, const char *dname, char *hint); char *create_iname(DB_ENV *env, uint64_t id1, uint64_t id2, diff --git a/storage/tokudb/PerconaFT/src/ydb_env_func.cc b/storage/tokudb/PerconaFT/src/ydb_env_func.cc index 13c56fec6bf..b8f0a634116 100644 --- a/storage/tokudb/PerconaFT/src/ydb_env_func.cc +++ b/storage/tokudb/PerconaFT/src/ydb_env_func.cc @@ -109,7 +109,7 @@ void db_env_set_func_pread (ssize_t (*fun)(int, void *, size_t, off_t)) { } void db_env_set_func_loader_fwrite (size_t (*fwrite_fun)(const void*,size_t,size_t,FILE*)) { - ft_loader_set_os_fwrite(fwrite_fun); + toku_set_func_fwrite(fwrite_fun); } void db_env_set_func_malloc (void *(*f)(size_t)) { diff --git a/storage/tokudb/PerconaFT/src/ydb_txn.cc b/storage/tokudb/PerconaFT/src/ydb_txn.cc index 40b479055f2..dd5fb3b8f0c 100644 --- a/storage/tokudb/PerconaFT/src/ydb_txn.cc +++ b/storage/tokudb/PerconaFT/src/ydb_txn.cc @@ -540,10 +540,12 @@ int toku_txn_begin(DB_ENV *env, DB_TXN * stxn, DB_TXN ** txn, uint32_t flags) { db_txn_struct_i(result)->iso = child_isolation; db_txn_struct_i(result)->lt_map.create_no_array(); - toku_mutex_init(&db_txn_struct_i(result)->txn_mutex, NULL); + toku_mutex_init(*db_txn_struct_i_txn_mutex_key, + &db_txn_struct_i(result)->txn_mutex, + nullptr); TXN_SNAPSHOT_TYPE snapshot_type; - switch(db_txn_struct_i(result)->iso){ + switch (db_txn_struct_i(result)->iso) { case(TOKU_ISO_SNAPSHOT): { snapshot_type = TXN_SNAPSHOT_ROOT; @@ -603,7 +605,9 @@ void toku_keep_prepared_txn_callback (DB_ENV *env, TOKUTXN tokutxn) { toku_txn_set_container_db_txn(tokutxn, result); - toku_mutex_init(&db_txn_struct_i(result)->txn_mutex, NULL); + toku_mutex_init(*db_txn_struct_i_txn_mutex_key, + &db_txn_struct_i(result)->txn_mutex, + nullptr); } // Test-only function diff --git a/storage/tokudb/PerconaFT/tools/CMakeLists.txt b/storage/tokudb/PerconaFT/tools/CMakeLists.txt index b64c9b9c45a..c5bce6453a7 100644 --- a/storage/tokudb/PerconaFT/tools/CMakeLists.txt +++ b/storage/tokudb/PerconaFT/tools/CMakeLists.txt @@ -12,6 +12,7 @@ foreach(tool ${tools}) (CMAKE_CXX_FLAGS_DEBUG MATCHES " -DENABLED_DEBUG_SYNC")) target_link_libraries(${tool} sql binlog rpl master slave) endif() + target_link_libraries(${tool} perconaserverclient) endif () add_space_separated_property(TARGET ${tool} COMPILE_FLAGS -fvisibility=hidden) diff --git a/storage/tokudb/PerconaFT/util/dbt.cc b/storage/tokudb/PerconaFT/util/dbt.cc index 5bc1cb7446f..b6d2a584a45 100644 --- a/storage/tokudb/PerconaFT/util/dbt.cc +++ b/storage/tokudb/PerconaFT/util/dbt.cc @@ -199,7 +199,8 @@ int toku_dbt_set(uint32_t len, const void *val, DBT *d, struct simple_dbt *sdbt) case (DB_DBT_MALLOC): d->data = NULL; d->ulen = 0; - //Fall through to DB_DBT_REALLOC + // fallthrough + // to DB_DBT_REALLOC case (DB_DBT_REALLOC): if (d->ulen < len) { d->ulen = len*2; diff --git a/storage/tokudb/PerconaFT/util/fmutex.h b/storage/tokudb/PerconaFT/util/fmutex.h index 9ff95978a16..fed1bc24a92 100644 --- a/storage/tokudb/PerconaFT/util/fmutex.h +++ b/storage/tokudb/PerconaFT/util/fmutex.h @@ -38,6 +38,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #pragma once +extern toku_instr_key *fmutex_cond_key; + // fair mutex struct fmutex { pthread_mutex_t mutex; @@ -98,8 +100,8 @@ void fmutex_lock(struct fmutex *fm) { } pthread_cond_t cond; - pthread_cond_init(&cond, NULL); - struct queue_item item = { .cond = &cond, .next = NULL }; + pthread_cond_init(*fmutex_cond_key, &cond, nullptr); + struct queue_item item = {.cond = &cond, .next = NULL}; enq_item(fm, &item); // Wait for our turn. diff --git a/storage/tokudb/PerconaFT/util/frwlock.cc b/storage/tokudb/PerconaFT/util/frwlock.cc index ce1e33e85d3..1f821fe5f54 100644 --- a/storage/tokudb/PerconaFT/util/frwlock.cc +++ b/storage/tokudb/PerconaFT/util/frwlock.cc @@ -41,271 +41,311 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include #include +toku_instr_key *frwlock_m_wait_read_key; + 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; - - m_num_readers = 0; - m_num_writers = 0; - m_num_want_write = 0; - m_num_want_read = 0; - m_num_signaled_readers = 0; - m_num_expensive_want_write = 0; - - toku_cond_init(&m_wait_read, nullptr); - m_queue_item_read.cond = &m_wait_read; - m_queue_item_read.next = nullptr; - 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; -} - -void frwlock::deinit(void) { - toku_cond_destroy(&m_wait_read); -} - -bool frwlock::queue_is_empty(void) const { - return m_wait_head == nullptr; -} - -void frwlock::enq_item(queue_item *const item) { - paranoid_invariant_null(item->next); - if (m_wait_tail != nullptr) { - m_wait_tail->next = item; - } else { - paranoid_invariant_null(m_wait_head); - m_wait_head = item; + 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; } - m_wait_tail = item; -} - -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; - m_wait_head = m_wait_head->next; - if (m_wait_tail == item) { + + void frwlock::init(toku_mutex_t *const mutex +#if defined(TOKU_MYSQL_WITH_PFS) + , + const toku_instr_key &rwlock_instr_key +#endif + ) { + m_mutex = mutex; + + m_num_readers = 0; + m_num_writers = 0; + m_num_want_write = 0; + m_num_want_read = 0; + m_num_signaled_readers = 0; + m_num_expensive_want_write = 0; +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_init(rwlock_instr_key, &m_rwlock, nullptr); +#endif + toku_cond_init(toku_uninstrumented, &m_wait_read, nullptr); + m_queue_item_read.cond = &m_wait_read; + m_queue_item_read.next = nullptr; + 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; } - return item->cond; -} - -// Prerequisite: Holds m_mutex. -void frwlock::write_lock(bool expensive) { - toku_mutex_assert_locked(m_mutex); - if (this->try_write_lock(expensive)) { - return; + + void frwlock::deinit(void) { + toku_cond_destroy(&m_wait_read); +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_destroy(&m_rwlock); +#endif } - toku_cond_t cond = TOKU_COND_INITIALIZER; - queue_item item = { .cond = &cond, .next = nullptr }; - this->enq_item(&item); + bool frwlock::queue_is_empty(void) const { return m_wait_head == nullptr; } - // Wait for our turn. - ++m_num_want_write; - 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); - - // Now it's our turn. - paranoid_invariant(m_num_want_write > 0); - paranoid_invariant_zero(m_num_readers); - paranoid_invariant_zero(m_num_writers); - paranoid_invariant_zero(m_num_signaled_readers); - - // Not waiting anymore; grab the lock. - --m_num_want_write; - if (expensive) { - --m_num_expensive_want_write; + void frwlock::enq_item(queue_item *const item) { + paranoid_invariant_null(item->next); + if (m_wait_tail != nullptr) { + m_wait_tail->next = item; + } else { + paranoid_invariant_null(m_wait_head); + m_wait_head = item; + } + m_wait_tail = item; } - 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(); -} - -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; + + 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; + m_wait_head = m_wait_head->next; + if (m_wait_tail == item) { + m_wait_tail = nullptr; + } + return item->cond; } - // No one holds the lock. Grant the write lock. - paranoid_invariant_zero(m_num_want_write); - 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; -} - -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) { - // Throw the read cond_t onto the queue. - paranoid_invariant(m_num_signaled_readers == m_num_want_read); - m_queue_item_read.next = nullptr; - this->enq_item(&m_queue_item_read); - m_wait_read_is_in_queue = true; - paranoid_invariant(!m_read_wait_expensive); - m_read_wait_expensive = ( - m_current_writer_expensive || - (m_num_expensive_want_write > 0) - ); + + // Prerequisite: Holds m_mutex. + void frwlock::write_lock(bool expensive) { +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_wrlock_wait_start( + rwlock_instr, m_rwlock, __FILE__, __LINE__); +#endif + + toku_mutex_assert_locked(m_mutex); + if (this->try_write_lock(expensive)) { +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, 0); +#endif + return; } - // Note this contention event in engine status. - toku_context_note_frwlock_contention( - toku_thread_get_context()->get_id(), - m_blocking_writer_context_id - ); + toku_cond_t cond = TOKU_COND_INITIALIZER; + queue_item item = {.cond = &cond, .next = nullptr}; + this->enq_item(&item); // Wait for our turn. - ++m_num_want_read; - toku_cond_wait(&m_wait_read, m_mutex); + ++m_num_want_write; + 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); // Now it's our turn. + paranoid_invariant(m_num_want_write > 0); + paranoid_invariant_zero(m_num_readers); paranoid_invariant_zero(m_num_writers); - paranoid_invariant(m_num_want_read > 0); - paranoid_invariant(m_num_signaled_readers > 0); + paranoid_invariant_zero(m_num_signaled_readers); // Not waiting anymore; grab the lock. - --m_num_want_read; - --m_num_signaled_readers; + --m_num_want_write; + if (expensive) { + --m_num_expensive_want_write; + } + 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(); + +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, 0); +#endif + } + + 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; + } + // No one holds the lock. Grant the write lock. + paranoid_invariant_zero(m_num_want_write); + 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; } - ++m_num_readers; -} -bool frwlock::try_read_lock(void) { - toku_mutex_assert_locked(m_mutex); - if (m_num_writers > 0 || m_num_want_write > 0) { - return false; + void frwlock::read_lock(void) { +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_rdlock_wait_start( + rwlock_instr, m_rwlock, __FILE__, __LINE__); +#endif + toku_mutex_assert_locked(m_mutex); + if (m_num_writers > 0 || m_num_want_write > 0) { + if (!m_wait_read_is_in_queue) { + // Throw the read cond_t onto the queue. + paranoid_invariant(m_num_signaled_readers == m_num_want_read); + m_queue_item_read.next = nullptr; + this->enq_item(&m_queue_item_read); + m_wait_read_is_in_queue = true; + paranoid_invariant(!m_read_wait_expensive); + m_read_wait_expensive = (m_current_writer_expensive || + (m_num_expensive_want_write > 0)); + } + + // 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); + + // Now it's our turn. + paranoid_invariant_zero(m_num_writers); + paranoid_invariant(m_num_want_read > 0); + paranoid_invariant(m_num_signaled_readers > 0); + + // Not waiting anymore; grab the lock. + --m_num_want_read; + --m_num_signaled_readers; + } + ++m_num_readers; +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation end */ + toku_instr_rwlock_rdlock_wait_end(rwlock_instr, 0); +#endif } - // No writer holds the lock. - // No writers are waiting. - // Grant the read lock. - ++m_num_readers; - return true; -} - -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); - // Grant write lock to waiting writer. - paranoid_invariant(m_num_want_write > 0); - toku_cond_signal(cond); + + bool frwlock::try_read_lock(void) { + toku_mutex_assert_locked(m_mutex); + if (m_num_writers > 0 || m_num_want_write > 0) { + return false; + } + // No writer holds the lock. + // No writers are waiting. + // Grant the read lock. + ++m_num_readers; + return true; } -} - -void frwlock::read_unlock(void) { - toku_mutex_assert_locked(m_mutex); - paranoid_invariant(m_num_writers == 0); - paranoid_invariant(m_num_readers > 0); - --m_num_readers; - this->maybe_signal_next_writer(); -} - -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; + + 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); + // Grant write lock to waiting writer. + paranoid_invariant(m_num_want_write > 0); + toku_cond_signal(cond); + } + } + + void frwlock::read_unlock(void) { +#ifdef TOKU_MYSQL_WITH_PFS + toku_instr_rwlock_unlock(m_rwlock); +#endif + toku_mutex_assert_locked(m_mutex); + paranoid_invariant(m_num_writers == 0); + paranoid_invariant(m_num_readers > 0); + --m_num_readers; + this->maybe_signal_next_writer(); } - else { - return m_current_writer_expensive || (m_num_expensive_want_write > 0); + + 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; + } else { + return m_current_writer_expensive || + (m_num_expensive_want_write > 0); + } } -} + void frwlock::maybe_signal_or_broadcast_next(void) { + paranoid_invariant(m_num_signaled_readers == 0); -void frwlock::maybe_signal_or_broadcast_next(void) { - paranoid_invariant(m_num_signaled_readers == 0); + if (this->queue_is_empty()) { + paranoid_invariant(m_num_want_write == 0); + paranoid_invariant(m_num_want_read == 0); + return; + } + toku_cond_t *cond = this->deq_item(); + if (cond == &m_wait_read) { + // Grant read locks to all waiting readers + paranoid_invariant(m_wait_read_is_in_queue); + paranoid_invariant(m_num_want_read > 0); + m_num_signaled_readers = m_num_want_read; + m_wait_read_is_in_queue = false; + m_read_wait_expensive = false; + toku_cond_broadcast(cond); + } else { + // Grant write lock to waiting writer. + paranoid_invariant(m_num_want_write > 0); + toku_cond_signal(cond); + } + } - if (this->queue_is_empty()) { - paranoid_invariant(m_num_want_write == 0); - paranoid_invariant(m_num_want_read == 0); - return; + void frwlock::write_unlock(void) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_rwlock_unlock(m_rwlock); +#endif + 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(); } - toku_cond_t *cond = this->deq_item(); - if (cond == &m_wait_read) { - // Grant read locks to all waiting readers - paranoid_invariant(m_wait_read_is_in_queue); - paranoid_invariant(m_num_want_read > 0); - m_num_signaled_readers = m_num_want_read; - m_wait_read_is_in_queue = false; - m_read_wait_expensive = false; - toku_cond_broadcast(cond); + bool frwlock::write_lock_is_expensive(void) { + toku_mutex_assert_locked(m_mutex); + return (m_num_expensive_want_write > 0) || (m_current_writer_expensive); } - else { - // Grant write lock to waiting writer. - paranoid_invariant(m_num_want_write > 0); - toku_cond_signal(cond); + + 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; + } + uint32_t frwlock::blocked_users(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_want_read + m_num_want_write; + } + 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; + } + uint32_t frwlock::blocked_writers(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_want_write; + } + uint32_t frwlock::readers(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_readers; + } + uint32_t frwlock::blocked_readers(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_want_read; } -} - -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(); -} -bool frwlock::write_lock_is_expensive(void) { - toku_mutex_assert_locked(m_mutex); - return (m_num_expensive_want_write > 0) || (m_current_writer_expensive); -} - - -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; -} -uint32_t frwlock::blocked_users(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_want_read + m_num_want_write; -} -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; -} -uint32_t frwlock::blocked_writers(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_want_write; -} -uint32_t frwlock::readers(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_readers; -} -uint32_t frwlock::blocked_readers(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_want_read; -} } // namespace toku diff --git a/storage/tokudb/PerconaFT/util/frwlock.h b/storage/tokudb/PerconaFT/util/frwlock.h index 52b98a8d727..b02d95e545c 100644 --- a/storage/tokudb/PerconaFT/util/frwlock.h +++ b/storage/tokudb/PerconaFT/util/frwlock.h @@ -48,76 +48,82 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. namespace toku { -class frwlock { -public: - - void init(toku_mutex_t *const mutex); - void deinit(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 - bool write_lock_is_expensive(void); - - void read_lock(void); - bool try_read_lock(void); - void read_unlock(void); - // returns true if acquiring a read lock will be expensive - bool read_lock_is_expensive(void); - - 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 { - toku_cond_t *cond; - struct queue_item *next; + class frwlock { + public: + void init(toku_mutex_t *const mutex +#if defined(TOKU_MYSQL_WITH_PFS) + , + const toku_instr_key &rwlock_instr_key +#endif + ); + void deinit(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 + bool write_lock_is_expensive(void); + + void read_lock(void); + bool try_read_lock(void); + void read_unlock(void); + // returns true if acquiring a read lock will be expensive + bool read_lock_is_expensive(void); + + 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 { + toku_cond_t *cond; + struct queue_item *next; + }; + + 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; + + uint32_t m_num_readers; + uint32_t m_num_writers; + uint32_t m_num_want_write; + uint32_t m_num_want_read; + uint32_t m_num_signaled_readers; + // number of writers waiting that are expensive + // MUST be < m_num_want_write + uint32_t m_num_expensive_want_write; + // bool that states if the current writer is expensive + // if there is no current writer, then is false + bool m_current_writer_expensive; + // bool that states if waiting for a read + // 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; + queue_item m_queue_item_read; + bool m_wait_read_is_in_queue; + + toku_cond_t m_wait_read; +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_t m_rwlock; +#endif + queue_item *m_wait_head; + queue_item *m_wait_tail; }; - 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; - - uint32_t m_num_readers; - uint32_t m_num_writers; - uint32_t m_num_want_write; - uint32_t m_num_want_read; - uint32_t m_num_signaled_readers; - // number of writers waiting that are expensive - // MUST be < m_num_want_write - uint32_t m_num_expensive_want_write; - // bool that states if the current writer is expensive - // if there is no current writer, then is false - bool m_current_writer_expensive; - // bool that states if waiting for a read - // 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; - bool m_wait_read_is_in_queue; - - queue_item *m_wait_head; - queue_item *m_wait_tail; -}; - -ENSURE_POD(frwlock); + ENSURE_POD(frwlock); } // namespace toku diff --git a/storage/tokudb/PerconaFT/util/kibbutz.cc b/storage/tokudb/PerconaFT/util/kibbutz.cc index 7fc24bae727..409bf6bdd7b 100644 --- a/storage/tokudb/PerconaFT/util/kibbutz.cc +++ b/storage/tokudb/PerconaFT/util/kibbutz.cc @@ -72,14 +72,18 @@ struct kibbutz { uint64_t total_execution_time; }; -static void *work_on_kibbutz (void *); +static void *work_on_kibbutz(void *); -int toku_kibbutz_create (int n_workers, KIBBUTZ *kb_ret) { +toku_instr_key *kibbutz_mutex_key; +toku_instr_key *kibbutz_k_cond_key; +toku_instr_key *kibbutz_thread_key; + +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); + toku_mutex_init(*kibbutz_mutex_key, &k->mutex, nullptr); + toku_cond_init(*kibbutz_k_cond_key, &k->cond, nullptr); k->please_shutdown = false; k->head = NULL; k->tail = NULL; @@ -93,7 +97,11 @@ int toku_kibbutz_create (int n_workers, KIBBUTZ *kb_ret) { XMALLOC_N(n_workers, k->ids); for (int i = 0; i < n_workers; i++) { k->ids[i].k = k; - r = toku_pthread_create(&k->workers[i], NULL, work_on_kibbutz, &k->ids[i]); + r = toku_pthread_create(*kibbutz_thread_key, + &k->workers[i], + nullptr, + work_on_kibbutz, + &k->ids[i]); if (r != 0) { k->n_workers = i; toku_kibbutz_destroy(k); @@ -153,10 +161,14 @@ static void *work_on_kibbutz (void *kidv) { // if there's another item on k->head, then we'll just go grab it now, without waiting for a signal. } if (k->please_shutdown) { - // Don't follow this unless the work is all done, so that when we set please_shutdown, all the work finishes before any threads quit. - ksignal(k); // must wake up anyone else who is waiting, so they can shut down. + // Don't follow this unless the work is all done, so that when we + // set please_shutdown, all the work finishes before any threads + // quit. + ksignal(k); // must wake up anyone else who is waiting, so they can + // shut down. kunlock(k); - return NULL; + toku_instr_delete_current_thread(); + return nullptr; } // There is no work to do and it's not time to shutdown, so wait. kwait(k); diff --git a/storage/tokudb/PerconaFT/util/minicron.cc b/storage/tokudb/PerconaFT/util/minicron.cc index 737c6ef6a4f..c1412015be0 100644 --- a/storage/tokudb/PerconaFT/util/minicron.cc +++ b/storage/tokudb/PerconaFT/util/minicron.cc @@ -43,8 +43,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "portability/toku_assert.h" #include "util/minicron.h" -static void -toku_gettime (toku_timespec_t *a) { +toku_instr_key *minicron_p_mutex_key; +toku_instr_key *minicron_p_condvar_key; +toku_instr_key *minicron_thread_key; + +static void toku_gettime(toku_timespec_t *a) { struct timeval tv; gettimeofday(&tv, 0); a->tv_sec = tv.tv_sec; @@ -74,7 +77,8 @@ minicron_do (void *pv) while (1) { if (p->do_shutdown) { toku_mutex_unlock(&p->mutex); - return 0; + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); } if (p->period_in_ms == 0) { // if we aren't supposed to do it then just do an untimed wait. @@ -104,7 +108,8 @@ minicron_do (void *pv) // Now we woke up, and we should figure out what to do if (p->do_shutdown) { toku_mutex_unlock(&p->mutex); - return 0; + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); } if (p->period_in_ms > 1000) { toku_timespec_t now; @@ -137,17 +142,17 @@ toku_minicron_setup(struct minicron *p, uint32_t period_in_ms, int(*f)(void *), p->f = f; p->arg = arg; toku_gettime(&p->time_of_last_call_to_f); - //printf("now=%.6f", p->time_of_last_call_to_f.tv_sec + p->time_of_last_call_to_f.tv_nsec*1e-9); - p->period_in_ms = period_in_ms; + // printf("now=%.6f", p->time_of_last_call_to_f.tv_sec + + // p->time_of_last_call_to_f.tv_nsec*1e-9); + p->period_in_ms = period_in_ms; p->do_shutdown = false; - toku_mutex_init(&p->mutex, 0); - toku_cond_init (&p->condvar, 0); - return toku_pthread_create(&p->thread, 0, minicron_do, p); + toku_mutex_init(*minicron_p_mutex_key, &p->mutex, nullptr); + toku_cond_init(*minicron_p_condvar_key, &p->condvar, nullptr); + return toku_pthread_create( + *minicron_thread_key, &p->thread, nullptr, minicron_do, p); } - -void -toku_minicron_change_period(struct minicron *p, uint32_t new_period) -{ + +void toku_minicron_change_period(struct minicron *p, uint32_t new_period) { toku_mutex_lock(&p->mutex); p->period_in_ms = new_period; toku_cond_signal(&p->condvar); diff --git a/storage/tokudb/PerconaFT/util/nb_mutex.h b/storage/tokudb/PerconaFT/util/nb_mutex.h index 3490c1b365c..d777961ad78 100644 --- a/storage/tokudb/PerconaFT/util/nb_mutex.h +++ b/storage/tokudb/PerconaFT/util/nb_mutex.h @@ -49,35 +49,67 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // increase parallelism at the expense of single thread performance, we // are experimenting with a single higher level lock. +extern toku_instr_key *nb_mutex_key; + typedef struct nb_mutex *NB_MUTEX; struct nb_mutex { - struct rwlock lock; + struct st_rwlock lock; +#if defined(TOKU_MYSQL_WITH_PFS) + toku_mutex_t toku_mutex; +#endif }; +#if defined(TOKU_MYSQL_WITH_PFS) +#define nb_mutex_init(MK, RK, M) \ + inline_nb_mutex_init(MK, RK, M) +#else +#define nb_mutex_init(MK, RK, M) inline_nb_mutex_init(M) +#endif + // initialize an nb mutex -static __attribute__((__unused__)) -void -nb_mutex_init(NB_MUTEX nb_mutex) { - rwlock_init(&nb_mutex->lock); +inline void inline_nb_mutex_init( +#if defined(TOKU_MYSQL_WITH_PFS) + const toku_instr_key &mutex_instr_key, + const toku_instr_key &rwlock_instr_key, +#endif + NB_MUTEX nb_mutex) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_mutex_init(mutex_instr_key, &nb_mutex->toku_mutex, nullptr); +#endif + rwlock_init(rwlock_instr_key, &nb_mutex->lock); } // destroy a read write lock -static __attribute__((__unused__)) -void -nb_mutex_destroy(NB_MUTEX nb_mutex) { +inline void nb_mutex_destroy(NB_MUTEX nb_mutex) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_mutex_destroy(nb_mutex->toku_mutex.psi_mutex); +#endif rwlock_destroy(&nb_mutex->lock); } // obtain a write lock // expects: mutex is locked -static inline void nb_mutex_lock(NB_MUTEX nb_mutex, toku_mutex_t *mutex) { +inline void nb_mutex_lock(NB_MUTEX nb_mutex, toku_mutex_t *mutex) { +#ifdef TOKU_MYSQL_WITH_PFS + toku_mutex_instrumentation mutex_instr; + toku_instr_mutex_lock_start(mutex_instr, + *mutex, + __FILE__, + __LINE__); // TODO: pull these to caller? +#endif rwlock_write_lock(&nb_mutex->lock, mutex); +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_mutex_lock_end(mutex_instr, 0); +#endif } // release a write lock // expects: mutex is locked -static inline void nb_mutex_unlock(NB_MUTEX nb_mutex) { +inline void nb_mutex_unlock(NB_MUTEX nb_mutex) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_mutex_unlock(nb_mutex->toku_mutex.psi_mutex); +#endif rwlock_write_unlock(&nb_mutex->lock); } diff --git a/storage/tokudb/PerconaFT/util/queue.cc b/storage/tokudb/PerconaFT/util/queue.cc index 0716dfb2f59..39dfbbc699a 100644 --- a/storage/tokudb/PerconaFT/util/queue.cc +++ b/storage/tokudb/PerconaFT/util/queue.cc @@ -44,6 +44,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "memory.h" #include +toku_instr_key *queue_result_mutex_key; +toku_instr_key *queue_result_cond_key; + struct qitem; struct qitem { @@ -81,11 +84,11 @@ int toku_queue_create (QUEUE *q, uint64_t weight_limit) if (result==NULL) return get_error_errno(); result->contents_weight = 0; result->weight_limit = weight_limit; - result->head = NULL; - result->tail = NULL; - result->eof = false; - toku_mutex_init(&result->mutex, NULL); - toku_cond_init(&result->cond, NULL); + result->head = NULL; + result->tail = NULL; + result->eof = false; + toku_mutex_init(*queue_result_mutex_key, &result->mutex, nullptr); + toku_cond_init(*queue_result_cond_key, &result->cond, nullptr); *q = result; return 0; } diff --git a/storage/tokudb/PerconaFT/util/rwlock.h b/storage/tokudb/PerconaFT/util/rwlock.h index 47f78df70d1..d9a13ba9014 100644 --- a/storage/tokudb/PerconaFT/util/rwlock.h +++ b/storage/tokudb/PerconaFT/util/rwlock.h @@ -39,6 +39,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #pragma once #include +#include +#include /* Readers/writers locks implementation * @@ -147,53 +149,81 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // increase parallelism at the expense of single thread performance, we // are experimenting with a single higher level lock. -typedef struct rwlock *RWLOCK; -struct rwlock { - int reader; // the number of readers - int want_read; // the number of blocked readers +extern toku_instr_key *rwlock_cond_key; +extern toku_instr_key *rwlock_wait_read_key; +extern toku_instr_key *rwlock_wait_write_key; + +typedef struct st_rwlock *RWLOCK; +struct st_rwlock { + int reader; // the number of readers + int want_read; // the number of blocked readers toku_cond_t wait_read; int writer; // the number of writers int want_write; // the number of blocked writers toku_cond_t wait_write; - toku_cond_t* wait_users_go_to_zero; + toku_cond_t *wait_users_go_to_zero; +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_t prwlock; +#endif }; // returns: the sum of the number of readers, pending readers, writers, and // pending writers static inline int rwlock_users(RWLOCK rwlock) { - return rwlock->reader + rwlock->want_read + rwlock->writer + rwlock->want_write; + return rwlock->reader + rwlock->want_read + rwlock->writer + + rwlock->want_write; } -// initialize a read write lock +#if defined(TOKU_MYSQL_WITH_PFS) +#define rwlock_init(K, R) inline_rwlock_init(K, R) +#else +#define rwlock_init(K, R) inline_rwlock_init(R) +#endif -static __attribute__((__unused__)) -void -rwlock_init(RWLOCK rwlock) { +// initialize a read write lock +static inline __attribute__((__unused__)) void inline_rwlock_init( +#if defined(TOKU_MYSQL_WITH_PFS) + const toku_instr_key &rwlock_instr_key, +#endif + RWLOCK rwlock) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_init(rwlock_instr_key, &rwlock->prwlock, nullptr); +#endif rwlock->reader = rwlock->want_read = 0; - toku_cond_init(&rwlock->wait_read, 0); rwlock->writer = rwlock->want_write = 0; - toku_cond_init(&rwlock->wait_write, 0); + toku_cond_init(toku_uninstrumented, &rwlock->wait_read, nullptr); + toku_cond_init(toku_uninstrumented, &rwlock->wait_write, nullptr); rwlock->wait_users_go_to_zero = NULL; } // destroy a read write lock -static __attribute__((__unused__)) -void -rwlock_destroy(RWLOCK rwlock) { +static inline __attribute__((__unused__)) void rwlock_destroy(RWLOCK rwlock) { paranoid_invariant(rwlock->reader == 0); paranoid_invariant(rwlock->want_read == 0); paranoid_invariant(rwlock->writer == 0); paranoid_invariant(rwlock->want_write == 0); toku_cond_destroy(&rwlock->wait_read); toku_cond_destroy(&rwlock->wait_write); +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_destroy(&rwlock->prwlock); +#endif } // obtain a read lock // expects: mutex is locked static inline void rwlock_read_lock(RWLOCK rwlock, toku_mutex_t *mutex) { +#ifdef TOKU_MYSQL_WITH_PFS + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + // TODO: pull location information up to caller + toku_instr_rwlock_rdlock_wait_start( + rwlock_instr, rwlock->prwlock, __FILE__, __LINE__); + +#endif + paranoid_invariant(!rwlock->wait_users_go_to_zero); if (rwlock->writer || rwlock->want_write) { rwlock->want_read++; @@ -203,12 +233,19 @@ static inline void rwlock_read_lock(RWLOCK rwlock, toku_mutex_t *mutex) { rwlock->want_read--; } rwlock->reader++; +#ifdef TOKU_MYSQL_WITH_PFS + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, 0); +#endif } // release a read lock // expects: mutex is locked static inline void rwlock_read_unlock(RWLOCK rwlock) { +#ifdef TOKU_MYSQL_WITH_PFS + toku_instr_rwlock_unlock(rwlock->prwlock); +#endif paranoid_invariant(rwlock->reader > 0); paranoid_invariant(rwlock->writer == 0); rwlock->reader--; @@ -224,6 +261,12 @@ static inline void rwlock_read_unlock(RWLOCK rwlock) { // expects: mutex is locked static inline void rwlock_write_lock(RWLOCK rwlock, toku_mutex_t *mutex) { +#ifdef TOKU_MYSQL_WITH_PFS + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_wrlock_wait_start( + rwlock_instr, rwlock->prwlock, __FILE__, __LINE__); +#endif paranoid_invariant(!rwlock->wait_users_go_to_zero); if (rwlock->reader || rwlock->writer) { rwlock->want_write++; @@ -233,12 +276,19 @@ static inline void rwlock_write_lock(RWLOCK rwlock, toku_mutex_t *mutex) { rwlock->want_write--; } rwlock->writer++; +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, 0); +#endif } // release a write lock // expects: mutex is locked static inline void rwlock_write_unlock(RWLOCK rwlock) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_rwlock_unlock(rwlock->prwlock); +#endif paranoid_invariant(rwlock->reader == 0); paranoid_invariant(rwlock->writer == 1); rwlock->writer--; @@ -284,14 +334,10 @@ static inline int rwlock_read_will_block(RWLOCK rwlock) { return (rwlock->writer > 0 || rwlock->want_write > 0); } -static inline void rwlock_wait_for_users( - RWLOCK rwlock, - toku_mutex_t *mutex - ) -{ +static inline void rwlock_wait_for_users(RWLOCK rwlock, toku_mutex_t *mutex) { paranoid_invariant(!rwlock->wait_users_go_to_zero); toku_cond_t cond; - toku_cond_init(&cond, NULL); + toku_cond_init(toku_uninstrumented, &cond, nullptr); while (rwlock_users(rwlock) > 0) { rwlock->wait_users_go_to_zero = &cond; toku_cond_wait(&cond, mutex); diff --git a/storage/tokudb/PerconaFT/util/tests/marked-omt-test.cc b/storage/tokudb/PerconaFT/util/tests/marked-omt-test.cc index bce1b1a885b..7e60c711c66 100644 --- a/storage/tokudb/PerconaFT/util/tests/marked-omt-test.cc +++ b/storage/tokudb/PerconaFT/util/tests/marked-omt-test.cc @@ -156,7 +156,7 @@ int int_heaviside(const uint32_t &v, const uint32_t &target) { struct stress_shared { stress_omt *omt; volatile bool running; - struct rwlock lock; + struct st_rwlock lock; toku_mutex_t mutex; int num_marker_threads; }; @@ -400,8 +400,8 @@ static void stress_test(int nelts) { struct stress_shared extra; ZERO_STRUCT(extra); extra.omt = &omt; - toku_mutex_init(&extra.mutex, NULL); - rwlock_init(&extra.lock); + toku_mutex_init(toku_uninstrumented, &extra.mutex, nullptr); + rwlock_init(toku_uninstrumented, &extra.lock); extra.running = true; extra.num_marker_threads = num_marker_threads; @@ -422,11 +422,19 @@ static void stress_test(int nelts) { r = myinitstate_r(seed, reader.buf_write, 8, &reader.rand_write); invariant_zero(r); - toku_pthread_create(&marker_threads[i], NULL, stress_mark_worker, &reader); + toku_pthread_create(toku_uninstrumented, + &marker_threads[i], + nullptr, + stress_mark_worker, + &reader); } toku_pthread_t deleter_thread; - toku_pthread_create(&deleter_thread, NULL, stress_delete_worker, &readers[0]); + toku_pthread_create(toku_uninstrumented, + &deleter_thread, + nullptr, + stress_delete_worker, + &readers[0]); toku_pthread_join(deleter_thread, NULL); for (int i = 0; i < num_marker_threads; ++i) { diff --git a/storage/tokudb/PerconaFT/util/tests/minicron-test.cc b/storage/tokudb/PerconaFT/util/tests/minicron-test.cc index a2ddbdeabdf..026ab7446d3 100644 --- a/storage/tokudb/PerconaFT/util/tests/minicron-test.cc +++ b/storage/tokudb/PerconaFT/util/tests/minicron-test.cc @@ -206,11 +206,12 @@ test_main (int argc, const char *argv[]) { toku_pthread_t tests[N]; unsigned int i; - for (i=0; istate=0; + rwlock->state = 0; rwlock->waiters_head = NULL; rwlock->waiters_tail = NULL; - toku_mutex_init(&rwlock->mutex, NULL); + toku_mutex_init(toku_uninstrumented, &rwlock->mutex, nullptr); } -void toku_cv_fair_rwlock_destroy (toku_cv_fair_rwlock_t *rwlock) { +void toku_cv_fair_rwlock_destroy(toku_cv_fair_rwlock_t *rwlock) { toku_mutex_destroy(&rwlock->mutex); } diff --git a/storage/tokudb/PerconaFT/util/tests/sm-basic.cc b/storage/tokudb/PerconaFT/util/tests/sm-basic.cc index 80bc965fd31..0e5eb8364e2 100644 --- a/storage/tokudb/PerconaFT/util/tests/sm-basic.cc +++ b/storage/tokudb/PerconaFT/util/tests/sm-basic.cc @@ -64,7 +64,8 @@ int main(void) { // run the test toku_pthread_t tid; int r; - r = toku_pthread_create(&tid, NULL, sm_test_f, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, sm_test_f, nullptr); assert_zero(r); void *ret; r = toku_pthread_join(tid, &ret); diff --git a/storage/tokudb/PerconaFT/util/tests/sm-crash-double-free.cc b/storage/tokudb/PerconaFT/util/tests/sm-crash-double-free.cc index c5d7e3e53a7..5aa3565510b 100644 --- a/storage/tokudb/PerconaFT/util/tests/sm-crash-double-free.cc +++ b/storage/tokudb/PerconaFT/util/tests/sm-crash-double-free.cc @@ -64,10 +64,12 @@ int main(void) { toku_scoped_malloc_init(); toku_pthread_t tid; int r; - r = toku_pthread_create(&tid, NULL, sm_test_f, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, sm_test_f, nullptr); assert_zero(r); void *ret; - while (state != 1) sleep(1); + while (state != 1) + sleep(1); toku_scoped_malloc_destroy_set(); state = 2; r = toku_pthread_join(tid, &ret); diff --git a/storage/tokudb/PerconaFT/util/tests/test-frwlock-fair-writers.cc b/storage/tokudb/PerconaFT/util/tests/test-frwlock-fair-writers.cc index 7fd4801fe11..9a625c32aeb 100644 --- a/storage/tokudb/PerconaFT/util/tests/test-frwlock-fair-writers.cc +++ b/storage/tokudb/PerconaFT/util/tests/test-frwlock-fair-writers.cc @@ -66,9 +66,9 @@ static void *t1_func(void *arg) { int main(void) { int r; - toku_mutex_init(&rwlock_mutex, NULL); + toku_mutex_init(toku_uninstrumented, &rwlock_mutex, nullptr); rwlock.init(&rwlock_mutex); - + const int nthreads = 2; pthread_t tids[nthreads]; for (int i = 0; i < nthreads; i++) { diff --git a/storage/tokudb/PerconaFT/util/tests/test-rwlock-cheapness.cc b/storage/tokudb/PerconaFT/util/tests/test-rwlock-cheapness.cc index 0075ddf9bcb..c0b43c2db1c 100644 --- a/storage/tokudb/PerconaFT/util/tests/test-rwlock-cheapness.cc +++ b/storage/tokudb/PerconaFT/util/tests/test-rwlock-cheapness.cc @@ -101,7 +101,8 @@ static void *do_read_wait(void *arg) { static void launch_cheap_waiter(void) { toku_pthread_t tid; - int r = toku_pthread_create(&tid, NULL, do_cheap_wait, NULL); + int r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, do_cheap_wait, nullptr); assert_zero(r); toku_pthread_detach(tid); sleep(1); @@ -109,7 +110,8 @@ static void launch_cheap_waiter(void) { static void launch_expensive_waiter(void) { toku_pthread_t tid; - int r = toku_pthread_create(&tid, NULL, do_expensive_wait, NULL); + int r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, do_expensive_wait, nullptr); assert_zero(r); toku_pthread_detach(tid); sleep(1); @@ -117,7 +119,8 @@ static void launch_expensive_waiter(void) { static void launch_reader(void) { toku_pthread_t tid; - int r = toku_pthread_create(&tid, NULL, do_read_wait, NULL); + int r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, do_read_wait, nullptr); assert_zero(r); toku_pthread_detach(tid); sleep(1); @@ -132,7 +135,7 @@ static bool locks_are_expensive(void) { } static void test_write_cheapness(void) { - toku_mutex_init(&mutex, NULL); + toku_mutex_init(toku_uninstrumented, &mutex, nullptr); w.init(&mutex); // single expensive write lock diff --git a/storage/tokudb/PerconaFT/util/tests/test-rwlock.cc b/storage/tokudb/PerconaFT/util/tests/test-rwlock.cc index 18ca1229f56..56dd3f6b480 100644 --- a/storage/tokudb/PerconaFT/util/tests/test-rwlock.cc +++ b/storage/tokudb/PerconaFT/util/tests/test-rwlock.cc @@ -245,14 +245,14 @@ static void util_rwlock_unlock (RWLOCK rwlock, toku_mutex_t *mutex) { } // 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; +void time_util_rwlock(void) __attribute((__noinline__)); +void time_util_rwlock(void) { + struct st_rwlock rwlock; toku_mutex_t external_mutex; - toku_mutex_init(&external_mutex, NULL); - rwlock_init(&rwlock); - struct timeval start,end; - + toku_mutex_init(toku_uninstrumented, &external_mutex, nullptr); + rwlock_init(toku_uninstrumented, &rwlock); + struct timeval start, end; + util_rwlock_lock(&rwlock, &external_mutex); util_rwlock_unlock(&rwlock, &external_mutex); for (int t=0; tthreadpool, max_threads); assert(r == 0); + r = toku_thread_pool_create(&my_threadpool->threadpool, max_threads); + assert(r == 0); assert(my_threadpool != 0); - toku_mutex_init(&my_threadpool->mutex, 0); - toku_cond_init(&my_threadpool->wait, 0); + toku_mutex_init(toku_uninstrumented, &my_threadpool->mutex, nullptr); + toku_cond_init(toku_uninstrumented, &my_threadpool->wait, nullptr); my_threadpool->closed = 0; my_threadpool->counter = 0; } diff --git a/storage/tokudb/PerconaFT/util/threadpool.cc b/storage/tokudb/PerconaFT/util/threadpool.cc index 146cc63242a..6e0ccf05f93 100644 --- a/storage/tokudb/PerconaFT/util/threadpool.cc +++ b/storage/tokudb/PerconaFT/util/threadpool.cc @@ -48,6 +48,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "threadpool.h" +toku_instr_key *tpool_lock_mutex_key; +toku_instr_key *tp_thread_wait_key; +toku_instr_key *tp_pool_wait_free_key; +toku_instr_key *tp_internal_thread_key; + struct toku_thread { struct toku_thread_pool *pool; toku_pthread_t tid; @@ -84,8 +89,12 @@ toku_thread_create(struct toku_thread_pool *pool, struct toku_thread **toku_thre } else { memset(thread, 0, sizeof *thread); thread->pool = pool; - toku_cond_init(&thread->wait, nullptr); - r = toku_pthread_create(&thread->tid, nullptr, toku_thread_run_internal, thread); + toku_cond_init(*tp_thread_wait_key, &thread->wait, nullptr); + r = toku_pthread_create(*tp_internal_thread_key, + &thread->tid, + nullptr, + toku_thread_run_internal, + thread); if (r) { toku_cond_destroy(&thread->wait); toku_free(thread); @@ -105,11 +114,11 @@ toku_thread_run(struct toku_thread *thread, void *(*f)(void *arg), void *arg) { toku_thread_pool_unlock(thread->pool); } -static void -toku_thread_destroy(struct toku_thread *thread) { +static void toku_thread_destroy(struct toku_thread *thread) { int r; void *ret; - r = toku_pthread_join(thread->tid, &ret); invariant(r == 0 && ret == thread); + r = toku_pthread_join(thread->tid, &ret); + invariant(r == 0 && ret == thread); struct toku_thread_pool *pool = thread->pool; toku_thread_pool_lock(pool); toku_list_remove(&thread->free_link); @@ -147,20 +156,20 @@ toku_thread_run_internal(void *arg) { thread->f = nullptr; toku_list_push(&pool->free_threads, &thread->free_link); } - return arg; -} + return toku_pthread_done(arg); +} -int -toku_thread_pool_create(struct toku_thread_pool **pool_return, int max_threads) { +int toku_thread_pool_create(struct toku_thread_pool **pool_return, + int max_threads) { int r; struct toku_thread_pool *CALLOC(pool); if (pool == nullptr) { r = get_error_errno(); } else { - toku_mutex_init(&pool->lock, nullptr); + toku_mutex_init(*tpool_lock_mutex_key, &pool->lock, nullptr); toku_list_init(&pool->free_threads); toku_list_init(&pool->all_threads); - toku_cond_init(&pool->wait_free, nullptr); + toku_cond_init(*tp_pool_wait_free_key, &pool->wait_free, nullptr); pool->cur_threads = 0; pool->max_threads = max_threads; *pool_return = pool; diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc index 36db1f41d4d..8354a35cb70 100644 --- a/storage/tokudb/ha_tokudb.cc +++ b/storage/tokudb/ha_tokudb.cc @@ -31,6 +31,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "ha_tokudb.h" #include "sql_db.h" +pfs_key_t ha_tokudb_mutex_key; +pfs_key_t num_DBs_lock_key; HASH TOKUDB_SHARE::_open_tables; tokudb::thread::mutex_t TOKUDB_SHARE::_open_tables_mutex; @@ -174,13 +176,9 @@ const char* TOKUDB_SHARE::get_state_string(share_state_t state) { void* TOKUDB_SHARE::operator new(size_t sz) { return tokudb::memory::malloc(sz, MYF(MY_WME|MY_ZEROFILL|MY_FAE)); } -void TOKUDB_SHARE::operator delete(void* p) { - tokudb::memory::free(p); -} -TOKUDB_SHARE::TOKUDB_SHARE() : - _num_DBs_lock(), - _mutex() { -} +void TOKUDB_SHARE::operator delete(void* p) { tokudb::memory::free(p); } +TOKUDB_SHARE::TOKUDB_SHARE() + : _num_DBs_lock(num_DBs_lock_key), _mutex(ha_tokudb_mutex_key) {} void TOKUDB_SHARE::init(const char* table_name) { _use_count = 0; thr_lock_init(&_thr_lock); @@ -215,20 +213,15 @@ void TOKUDB_SHARE::destroy() { thr_lock_delete(&_thr_lock); TOKUDB_SHARE_DBUG_VOID_RETURN(); } -TOKUDB_SHARE* TOKUDB_SHARE::get_share( - const char* table_name, - TABLE_SHARE* table_share, - THR_LOCK_DATA* data, - bool create_new) { - - _open_tables_mutex.lock(); +TOKUDB_SHARE* TOKUDB_SHARE::get_share(const char* table_name, + TABLE_SHARE* table_share, + THR_LOCK_DATA* data, + bool create_new) { + mutex_t_lock(_open_tables_mutex); int error = 0; - uint length = (uint) strlen(table_name); - TOKUDB_SHARE* share = - (TOKUDB_SHARE*)my_hash_search( - &_open_tables, - (uchar*)table_name, - length); + uint length = (uint)strlen(table_name); + TOKUDB_SHARE* share = (TOKUDB_SHARE*)my_hash_search( + &_open_tables, (uchar*)table_name, length); TOKUDB_TRACE_FOR_FLAGS( TOKUDB_DEBUG_SHARE, @@ -263,28 +256,27 @@ TOKUDB_SHARE* TOKUDB_SHARE::get_share( thr_lock_data_init(&(share->_thr_lock), data, NULL); exit: - _open_tables_mutex.unlock(); + mutex_t_unlock(_open_tables_mutex); return share; } void TOKUDB_SHARE::drop_share(TOKUDB_SHARE* share) { - TOKUDB_TRACE_FOR_FLAGS( - TOKUDB_DEBUG_SHARE, - "share[%p]:file[%s]:state[%s]:use_count[%d]", - share, - share->_full_table_name.ptr(), - get_state_string(share->_state), - share->_use_count); - - _open_tables_mutex.lock(); + TOKUDB_TRACE_FOR_FLAGS(TOKUDB_DEBUG_SHARE, + "share[%p]:file[%s]:state[%s]:use_count[%d]", + share, + share->_full_table_name.ptr(), + get_state_string(share->_state), + share->_use_count); + + mutex_t_lock(_open_tables_mutex); my_hash_delete(&_open_tables, (uchar*)share); - _open_tables_mutex.unlock(); + mutex_t_unlock(_open_tables_mutex); } TOKUDB_SHARE::share_state_t TOKUDB_SHARE::addref() { TOKUDB_SHARE_TRACE_FOR_FLAGS((TOKUDB_DEBUG_ENTER & TOKUDB_DEBUG_SHARE), - "file[%s]:state[%s]:use_count[%d]", - _full_table_name.ptr(), - get_state_string(_state), - _use_count); + "file[%s]:state[%s]:use_count[%d]", + _full_table_name.ptr(), + get_state_string(_state), + _use_count); lock(); _use_count++; @@ -299,7 +291,7 @@ int TOKUDB_SHARE::release() { int error, result = 0; - _mutex.lock(); + mutex_t_lock(_mutex); assert_always(_use_count != 0); _use_count--; if (_use_count == 0 && _state == TOKUDB_SHARE::OPENED) { @@ -343,7 +335,7 @@ int TOKUDB_SHARE::release() { _state = TOKUDB_SHARE::CLOSED; } - _mutex.unlock(); + mutex_t_unlock(_mutex); TOKUDB_SHARE_DBUG_RETURN(result); } @@ -1195,8 +1187,10 @@ static int generate_row_for_put( ha_tokudb::ha_tokudb(handlerton * hton, TABLE_SHARE * table_arg):handler(hton, table_arg) { TOKUDB_HANDLER_DBUG_ENTER(""); share = NULL; - int_table_flags = HA_REC_NOT_IN_SEQ | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_PRIMARY_KEY_IN_READ_INDEX | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | - HA_FILE_BASED | HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX | HA_CAN_WRITE_DURING_OPTIMIZE; + int_table_flags = HA_REC_NOT_IN_SEQ | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS + | HA_PRIMARY_KEY_IN_READ_INDEX | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION + | HA_FILE_BASED | HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX + | HA_CAN_WRITE_DURING_OPTIMIZE | HA_ONLINE_ANALYZE; alloc_ptr = NULL; rec_buff = NULL; rec_update_buff = NULL; @@ -3313,12 +3307,12 @@ void ha_tokudb::start_bulk_insert(ha_rows rows) { delay_updating_ai_metadata = true; ai_metadata_update_required = false; abort_loader = false; - - share->_num_DBs_lock.lock_read(); + + rwlock_t_lock_read(share->_num_DBs_lock); uint curr_num_DBs = table->s->keys + tokudb_test(hidden_primary_key); num_DBs_locked_in_bulk = true; lock_count = 0; - + if ((rows == 0 || rows > 1) && share->try_table_lock) { if (tokudb::sysvars::prelock_empty(thd) && may_table_be_empty(transaction) && @@ -4029,14 +4023,13 @@ int ha_tokudb::write_row(uchar * record) { // grab reader lock on numDBs_lock // if (!num_DBs_locked_in_bulk) { - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); num_DBs_locked = true; - } - else { + } else { lock_count++; if (lock_count >= 2000) { share->_num_DBs_lock.unlock(); - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); lock_count = 0; } } @@ -4208,7 +4201,7 @@ int ha_tokudb::update_row(const uchar * old_row, uchar * new_row) { // bool num_DBs_locked = false; if (!num_DBs_locked_in_bulk) { - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); num_DBs_locked = true; } curr_num_DBs = share->num_DBs; @@ -4350,7 +4343,7 @@ int ha_tokudb::delete_row(const uchar * record) { // bool num_DBs_locked = false; if (!num_DBs_locked_in_bulk) { - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); num_DBs_locked = true; } curr_num_DBs = share->num_DBs; @@ -4641,6 +4634,9 @@ int ha_tokudb::index_init(uint keynr, bool sorted) { if (tokudb::sysvars::disable_prefetching(thd)) { cursor_flags |= DBC_DISABLE_PREFETCHING; } + if (lock.type == TL_READ_WITH_SHARED_LOCKS) { + cursor_flags |= DB_LOCKING_READ; + } if ((error = share->key_file[keynr]->cursor(share->key_file[keynr], transaction, &cursor, cursor_flags))) { @@ -6212,6 +6208,8 @@ int ha_tokudb::info(uint flag) { } if ((flag & HA_STATUS_CONST)) { stats.max_data_file_length = 9223372036854775807ULL; + } + if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST)) { share->set_cardinality_counts_in_table(table); } @@ -6295,7 +6293,7 @@ int ha_tokudb::acquire_table_lock (DB_TXN* trans, TABLE_LOCK_TYPE lt) { TOKUDB_HANDLER_DBUG_ENTER("%p %s", trans, lt == lock_read ? "r" : "w"); int error = ENOSYS; if (!num_DBs_locked_in_bulk) { - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); } uint curr_num_DBs = share->num_DBs; if (lt == lock_read) { @@ -6651,8 +6649,9 @@ THR_LOCK_DATA* *ha_tokudb::store_lock( if (sql_command == SQLCOM_CREATE_INDEX && tokudb::sysvars::create_index_online(thd)) { // hot indexing - share->_num_DBs_lock.lock_read(); - if (share->num_DBs == (table->s->keys + tokudb_test(hidden_primary_key))) { + rwlock_t_lock_read(share->_num_DBs_lock); + if (share->num_DBs == + (table->s->keys + tokudb_test(hidden_primary_key))) { lock_type = TL_WRITE_ALLOW_WRITE; } share->_num_DBs_lock.unlock(); @@ -7225,10 +7224,28 @@ int ha_tokudb::create( const tokudb::sysvars::format_t row_format = (tokudb::sysvars::row_format_t)form->s->option_struct->row_format; #else - const tokudb::sysvars::row_format_t row_format = - (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) - ? row_type_to_row_format(create_info->row_type) - : tokudb::sysvars::row_format(thd); + // TDB-76 : CREATE TABLE ... LIKE ... does not use source row_format on + // target table + // Original code would only use create_info->row_type if + // create_info->used_fields & HA_CREATE_USED_ROW_FORMAT was true. This + // would cause us to skip transferring the row_format for a table created + // via CREATE TABLE tn LIKE tn. We also take on more InnoDB like behavior + // and throw a warning if we get a row_format that we can't translate into + // a known TokuDB row_format. + tokudb::sysvars::row_format_t row_format = + tokudb::sysvars::row_format(thd); + + if ((create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) || + create_info->row_type != ROW_TYPE_DEFAULT) { + row_format = row_type_to_row_format(create_info->row_type); + if (row_format == tokudb::sysvars::SRV_ROW_FORMAT_DEFAULT && + create_info->row_type != ROW_TYPE_DEFAULT) { + push_warning(thd, + Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "TokuDB: invalid ROW_FORMAT specifier."); + } + } #endif const toku_compression_method compression_method = row_format_to_toku_compression_method(row_format); @@ -8099,8 +8116,8 @@ int ha_tokudb::tokudb_add_index( } } } - - share->_num_DBs_lock.lock_write(); + + rwlock_t_lock_write(share->_num_DBs_lock); rw_lock_taken = true; // // open all the DB files and set the appropriate variables in share @@ -8210,7 +8227,7 @@ int ha_tokudb::tokudb_add_index( goto cleanup; } - share->_num_DBs_lock.lock_write(); + rwlock_t_lock_write(share->_num_DBs_lock); error = indexer->close(indexer); share->_num_DBs_lock.unlock(); if (error) { @@ -8444,7 +8461,7 @@ cleanup: if (indexer != NULL) { sprintf(status_msg, "aborting creation of indexes."); thd_proc_info(thd, status_msg); - share->_num_DBs_lock.lock_write(); + rwlock_t_lock_write(share->_num_DBs_lock); indexer->abort(indexer); share->_num_DBs_lock.unlock(); } @@ -8493,10 +8510,10 @@ void ha_tokudb::restore_add_index( // // need to restore num_DBs, and we have to do it before we close the dictionaries - // so that there is not a window + // so that there is not a window // if (incremented_numDBs) { - share->_num_DBs_lock.lock_write(); + rwlock_t_lock_write(share->_num_DBs_lock); share->num_DBs--; } if (modified_DBs) { diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h index f90f4130b37..9c6af2550cd 100644 --- a/storage/tokudb/ha_tokudb.h +++ b/storage/tokudb/ha_tokudb.h @@ -318,18 +318,18 @@ inline int TOKUDB_SHARE::use_count() const { } inline void TOKUDB_SHARE::lock() const { TOKUDB_SHARE_DBUG_ENTER("file[%s]:state[%s]:use_count[%d]", - _full_table_name.ptr(), - get_state_string(_state), - _use_count); - _mutex.lock(); + _full_table_name.ptr(), + get_state_string(_state), + _use_count); + mutex_t_lock(_mutex); TOKUDB_SHARE_DBUG_VOID_RETURN(); } inline void TOKUDB_SHARE::unlock() const { TOKUDB_SHARE_DBUG_ENTER("file[%s]:state[%s]:use_count[%d]", - _full_table_name.ptr(), - get_state_string(_state), - _use_count); - _mutex.unlock(); + _full_table_name.ptr(), + get_state_string(_state), + _use_count); + mutex_t_unlock(_mutex); TOKUDB_SHARE_DBUG_VOID_RETURN(); } inline TOKUDB_SHARE::share_state_t TOKUDB_SHARE::state() const { diff --git a/storage/tokudb/ha_tokudb_update.cc b/storage/tokudb/ha_tokudb_update.cc index 23de81f3d8a..9fe5e729ec4 100644 --- a/storage/tokudb/ha_tokudb_update.cc +++ b/storage/tokudb/ha_tokudb_update.cc @@ -918,7 +918,7 @@ int ha_tokudb::send_update_message( marshall_update(update_message, lhs_item, rhs_item, table, share); } - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); // hot index in progress if (share->num_DBs > table->s->keys + tokudb_test(hidden_primary_key)) { @@ -1108,7 +1108,7 @@ int ha_tokudb::send_upsert_message( marshall_update(update_message, lhs_item, rhs_item, table, share); } - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); // hot index in progress if (share->num_DBs > table->s->keys + tokudb_test(hidden_primary_key)) { diff --git a/storage/tokudb/hatoku_cmp.cc b/storage/tokudb/hatoku_cmp.cc index d400c3f7bd3..0c4b5be7eb7 100644 --- a/storage/tokudb/hatoku_cmp.cc +++ b/storage/tokudb/hatoku_cmp.cc @@ -1984,6 +1984,7 @@ static uint32_t pack_desc_key_length_info(uchar* buf, KEY_AND_COL_INFO* kc_info, case (toku_type_fixstring): field_length = field->pack_length(); set_if_smaller(key_part_length, field_length); + // fallthrough case (toku_type_varbinary): case (toku_type_varstring): case (toku_type_blob): diff --git a/storage/tokudb/hatoku_defines.h b/storage/tokudb/hatoku_defines.h index 83f8a8a21d2..05a06ac8142 100644 --- a/storage/tokudb/hatoku_defines.h +++ b/storage/tokudb/hatoku_defines.h @@ -246,4 +246,22 @@ inline uint tokudb_uint3korr(const uchar *a) { return uint3korr(b); } -#endif // _HATOKU_DEFINES_H +typedef unsigned int pfs_key_t; + +#if defined(HAVE_PSI_MUTEX_INTERFACE) +#define mutex_t_lock(M) M.lock(__FILE__, __LINE__) +#define mutex_t_unlock(M) M.unlock(__FILE__, __LINE__) +#else // HAVE_PSI_MUTEX_INTERFACE +#define mutex_t_lock(M) M.lock() +#define mutex_t_unlock(M) M.unlock() +#endif // HAVE_PSI_MUTEX_INTERFACE + +#if defined(HAVE_PSI_RWLOCK_INTERFACE) +#define rwlock_t_lock_read(M) M.lock_read(__FILE__, __LINE__) +#define rwlock_t_lock_write(M) M.lock_write(__FILE__, __LINE__) +#else // HAVE_PSI_RWLOCK_INTERFACE +#define rwlock_t_lock_read(M) M.lock_read() +#define rwlock_t_lock_write(M) M.lock_write() +#endif // HAVE_PSI_RWLOCK_INTERFACE + +#endif // _HATOKU_DEFINES_H diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc index 2ae9cdc071b..1cfe4e0a8bc 100644 --- a/storage/tokudb/hatoku_hton.cc +++ b/storage/tokudb/hatoku_hton.cc @@ -28,6 +28,17 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #define TOKU_METADB_NAME "tokudb_meta" +static pfs_key_t tokudb_map_mutex_key; + +static PSI_mutex_info all_tokudb_mutexes[] = { + {&tokudb_map_mutex_key, "tokudb_map_mutex", 0}, + {&ha_tokudb_mutex_key, "ha_tokudb_mutex", 0}, +}; + +static PSI_rwlock_info all_tokudb_rwlocks[] = { + {&num_DBs_lock_key, "num_DBs_lock", 0}, +}; + typedef struct savepoint_info { DB_TXN* txn; tokudb_trx_data* trx; @@ -219,6 +230,10 @@ extern "C" { // use constructor and destructor functions to create and destroy // the lock before and after main(), respectively. int tokudb_hton_initialized; + +// tokudb_hton_initialized_lock can not be instrumented as it must be +// initialized before mysql_mutex_register() call to protect +// some globals from race condition. tokudb::thread::rwlock_t tokudb_hton_initialized_lock; static SHOW_VAR *toku_global_status_variables = NULL; @@ -274,10 +289,23 @@ static int tokudb_init_func(void *p) { int r; // 3938: lock the handlerton's initialized status flag for writing - tokudb_hton_initialized_lock.lock_write(); + rwlock_t_lock_write(tokudb_hton_initialized_lock); + +#ifdef HAVE_PSI_INTERFACE + /* Register TokuDB mutex keys with MySQL performance schema */ + int count; + + count = array_elements(all_tokudb_mutexes); + mysql_mutex_register("tokudb", all_tokudb_mutexes, count); + + count = array_elements(all_tokudb_rwlocks); + mysql_rwlock_register("tokudb", all_tokudb_rwlocks, count); + + tokudb_map_mutex.reinit(tokudb_map_mutex_key); +#endif /* HAVE_PSI_INTERFACE */ db_env = NULL; - tokudb_hton = (handlerton *) p; + tokudb_hton = (handlerton*)p; if (tokudb::sysvars::check_jemalloc) { typedef int (*mallctl_type)( @@ -674,7 +702,7 @@ int tokudb_end(handlerton* hton, ha_panic_function type) { // initialized. grab a writer lock for the duration of the // call, so we can drop the flag and destroy the mutexes // in isolation. - tokudb_hton_initialized_lock.lock_write(); + rwlock_t_lock_write(tokudb_hton_initialized_lock); assert_always(tokudb_hton_initialized); tokudb::background::destroy(); @@ -754,16 +782,16 @@ static int tokudb_close_connection(handlerton* hton, THD* thd) { } tokudb::memory::free(trx); #if TOKU_THDVAR_MEMALLOC_BUG - tokudb_map_mutex.lock(); - struct tokudb_map_pair key = { thd, NULL }; + mutex_t_lock(tokudb_map_mutex); + struct tokudb_map_pair key = {thd, NULL}; struct tokudb_map_pair* found_key = - (struct tokudb_map_pair*) tree_search(&tokudb_map, &key, NULL); + (struct tokudb_map_pair*)tree_search(&tokudb_map, &key, NULL); if (found_key) { tokudb::memory::free(found_key->last_lock_timeout); tree_delete(&tokudb_map, found_key, sizeof(*found_key), NULL); } - tokudb_map_mutex.unlock(); + mutex_t_unlock(tokudb_map_mutex); #endif return error; } @@ -1721,12 +1749,12 @@ static void tokudb_lock_timeout_callback( tokudb::memory::strdup(log_str.c_ptr(), MY_FAE); tokudb::sysvars::set_last_lock_timeout(thd, new_lock_timeout); #if TOKU_THDVAR_MEMALLOC_BUG - tokudb_map_mutex.lock(); - struct tokudb_map_pair old_key = { thd, old_lock_timeout }; + mutex_t_lock(tokudb_map_mutex); + struct tokudb_map_pair old_key = {thd, old_lock_timeout}; tree_delete(&tokudb_map, &old_key, sizeof old_key, NULL); - struct tokudb_map_pair new_key = { thd, new_lock_timeout }; + struct tokudb_map_pair new_key = {thd, new_lock_timeout}; tree_insert(&tokudb_map, &new_key, sizeof new_key, NULL); - tokudb_map_mutex.unlock(); + mutex_t_unlock(tokudb_map_mutex); #endif tokudb::memory::free(old_lock_timeout); } diff --git a/storage/tokudb/hatoku_hton.h b/storage/tokudb/hatoku_hton.h index ade7be128a5..7efc50b96e3 100644 --- a/storage/tokudb/hatoku_hton.h +++ b/storage/tokudb/hatoku_hton.h @@ -39,6 +39,9 @@ extern handlerton* tokudb_hton; extern DB_ENV* db_env; +extern pfs_key_t ha_tokudb_mutex_key; +extern pfs_key_t num_DBs_lock_key; + inline tokudb::sysvars::row_format_t toku_compression_method_to_row_format( toku_compression_method method) { @@ -180,9 +183,7 @@ inline bool tokudb_killed_thd_callback(void *extra, uint64_t deleted_rows) { return thd_killed(thd) != 0; } - extern HASH tokudb_open_tables; -extern tokudb::thread::mutex_t tokudb_mutex; extern const char* tokudb_hton_name; extern int tokudb_hton_initialized; extern tokudb::thread::rwlock_t tokudb_hton_initialized_lock; diff --git a/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result b/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result index cfd7e38179c..981433fac91 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result @@ -1,7 +1,7 @@ -set global tokudb_cardinality_scale_percent = 10; analyze table tt; Table Op Msg_type Msg_text test.tt analyze status OK +set global tokudb_cardinality_scale_percent = 10; show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE @@ -9,9 +9,6 @@ tt 1 b 1 b A 4000 NULL NULL YES BTREE tt 1 c 1 c A 4000 NULL NULL YES BTREE tt 1 d 1 d A 4000 NULL NULL YES BTREE set global tokudb_cardinality_scale_percent = 50; -analyze table tt; -Table Op Msg_type Msg_text -test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE @@ -19,9 +16,6 @@ tt 1 b 1 b A 4000 NULL NULL YES BTREE tt 1 c 1 c A 4000 NULL NULL YES BTREE tt 1 d 1 d A 2000 NULL NULL YES BTREE set global tokudb_cardinality_scale_percent = 100; -analyze table tt; -Table Op Msg_type Msg_text -test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE @@ -31,9 +25,6 @@ tt 1 d 1 d A 1000 NULL NULL YES BTREE set global tokudb_cardinality_scale_percent = 200; Warnings: Warning 1292 Truncated incorrect tokudb_cardinality_scale_percent value: '200' -analyze table tt; -Table Op Msg_type Msg_text -test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE diff --git a/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-1.result b/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-1.result new file mode 100644 index 00000000000..c9fcb5e2273 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-1.result @@ -0,0 +1,13 @@ +create table t (a int primary key, b int) ENGINE=TokuDB; +insert into t values (1,0); +set session transaction isolation level repeatable read; +begin; +select * from t where a=1 lock in share mode; +a b +1 0 +set session transaction isolation level repeatable read; +begin; +update t set b=b+1 where a=1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +commit; +drop table t; diff --git a/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-2.result b/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-2.result new file mode 100644 index 00000000000..f1b214e514c --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-2.result @@ -0,0 +1,17 @@ +create table t (a int primary key, b int) ENGINE=TokuDB; +insert into t values (1,0); +insert into t values (2,1); +insert into t values (3,2); +set session transaction isolation level repeatable read; +begin; +select * from t lock in share mode; +a b +1 0 +2 1 +3 2 +set session transaction isolation level repeatable read; +begin; +update t set b=b+1 where a=2; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +commit; +drop table t; diff --git a/storage/tokudb/mysql-test/tokudb/r/nonflushing_analyze_debug.result b/storage/tokudb/mysql-test/tokudb/r/nonflushing_analyze_debug.result new file mode 100644 index 00000000000..e8f51edee04 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/r/nonflushing_analyze_debug.result @@ -0,0 +1,19 @@ +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=TokuDB; +INSERT INTO t1 VALUES (1), (2), (3); +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t1; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SELECT * FROM t1; +a +1 +2 +3 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +a +1 +2 +3 +DROP TABLE t1; diff --git a/storage/tokudb/mysql-test/tokudb/r/row_format.result b/storage/tokudb/mysql-test/tokudb/r/row_format.result index cb669148445..15d4f9fe12a 100644 --- a/storage/tokudb/mysql-test/tokudb/r/row_format.result +++ b/storage/tokudb/mysql-test/tokudb/r/row_format.result @@ -1,4 +1,6 @@ CREATE TABLE tokudb_row_format_test_1 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_DEFAULT; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. CREATE TABLE tokudb_row_format_test_2 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_FAST; CREATE TABLE tokudb_row_format_test_3 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_SMALL; CREATE TABLE tokudb_row_format_test_4 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_UNCOMPRESSED; @@ -6,6 +8,41 @@ CREATE TABLE tokudb_row_format_test_5 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_ZL CREATE TABLE tokudb_row_format_test_6 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_LZMA; CREATE TABLE tokudb_row_format_test_7 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_QUICKLZ; CREATE TABLE tokudb_row_format_test_8 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_SNAPPY; +CREATE TABLE tdb76_1 LIKE tokudb_row_format_test_1; +CREATE TABLE tdb76_2 LIKE tokudb_row_format_test_2; +CREATE TABLE tdb76_3 LIKE tokudb_row_format_test_3; +CREATE TABLE tdb76_4 LIKE tokudb_row_format_test_4; +CREATE TABLE tdb76_5 LIKE tokudb_row_format_test_5; +CREATE TABLE tdb76_6 LIKE tokudb_row_format_test_6; +CREATE TABLE tdb76_7 LIKE tokudb_row_format_test_7; +CREATE TABLE tdb76_8 LIKE tokudb_row_format_test_8; +CREATE TABLE tdb76_compact(a INT) ENGINE=TokuDB ROW_FORMAT=COMPACT; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. +CREATE TABLE tdb76_redundant(a INT) ENGINE=TokuDB ROW_FORMAT=REDUNDANT; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. +CREATE TABLE tdb76_dynamic(a INT) ENGINE=TokuDB ROW_FORMAT=DYNAMIC; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. +CREATE TABLE tdb76_compressed(a INT) ENGINE=TokuDB ROW_FORMAT=COMPRESSED; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. +SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name like 'tdb76_%' ORDER BY table_name; +table_name row_format engine +tdb76_1 tokudb_zlib TokuDB +tdb76_2 tokudb_quicklz TokuDB +tdb76_3 tokudb_lzma TokuDB +tdb76_4 tokudb_uncompressed TokuDB +tdb76_5 tokudb_zlib TokuDB +tdb76_6 tokudb_lzma TokuDB +tdb76_7 tokudb_quicklz TokuDB +tdb76_8 tokudb_snappy TokuDB +tdb76_compact tokudb_zlib TokuDB +tdb76_compressed tokudb_zlib TokuDB +tdb76_dynamic tokudb_zlib TokuDB +tdb76_redundant tokudb_zlib TokuDB +DROP TABLE tdb76_1, tdb76_2, tdb76_3, tdb76_4, tdb76_5, tdb76_6, tdb76_7, tdb76_8, tdb76_compact, tdb76_redundant, tdb76_dynamic, tdb76_compressed; SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name like 'tokudb_row_format_test%' ORDER BY table_name; table_name row_format engine tokudb_row_format_test_1 tokudb_zlib TokuDB @@ -45,6 +82,8 @@ SELECT table_name, row_format, engine FROM information_schema.tables WHERE table table_name row_format engine tokudb_row_format_test_1 tokudb_lzma TokuDB ALTER TABLE tokudb_row_format_test_1 ENGINE=TokuDB ROW_FORMAT=TOKUDB_DEFAULT; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name = 'tokudb_row_format_test_1'; table_name row_format engine tokudb_row_format_test_1 tokudb_zlib TokuDB diff --git a/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test b/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test index 47f1eb37989..75c53611308 100644 --- a/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test +++ b/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test @@ -30,20 +30,18 @@ set session tokudb_analyze_throttle=0; -- enable_query_log -set global tokudb_cardinality_scale_percent = 10; analyze table tt; + +set global tokudb_cardinality_scale_percent = 10; show indexes from tt; set global tokudb_cardinality_scale_percent = 50; -analyze table tt; show indexes from tt; set global tokudb_cardinality_scale_percent = 100; -analyze table tt; show indexes from tt; set global tokudb_cardinality_scale_percent = 200; -analyze table tt; show indexes from tt; -- disable_query_log diff --git a/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-1.test b/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-1.test new file mode 100644 index 00000000000..c5ef0f0703e --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-1.test @@ -0,0 +1,23 @@ +source include/have_tokudb.inc; +source include/count_sessions.inc; +create table t (a int primary key, b int) ENGINE=TokuDB; +insert into t values (1,0); +set session transaction isolation level repeatable read; +begin; +# t1 select in share mode +select * from t where a=1 lock in share mode; +# t2 update +connect(conn1,localhost,root); +set session transaction isolation level repeatable read; +begin; +# t2 select for update, should hang until t1 commits +send update t set b=b+1 where a=1; +--error ER_LOCK_WAIT_TIMEOUT +reap; +# t2 update +connection default; +commit; +disconnect conn1; +drop table t; + +source include/wait_until_count_sessions.inc; diff --git a/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-2.test b/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-2.test new file mode 100644 index 00000000000..20a4549c45f --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-2.test @@ -0,0 +1,29 @@ +#the difference of this test from locking-read-repeatable-read-1 +#is that this test is on range query(gap lock) which actually +#examines a different patch + +source include/have_tokudb.inc; +source include/count_sessions.inc; +create table t (a int primary key, b int) ENGINE=TokuDB; +insert into t values (1,0); +insert into t values (2,1); +insert into t values (3,2); +set session transaction isolation level repeatable read; +begin; +# t1 select in share mode +select * from t lock in share mode; +# t2 update +connect(conn1,localhost,root); +set session transaction isolation level repeatable read; +begin; +# t2 select for update, should hang until t1 commits +send update t set b=b+1 where a=2; +--error ER_LOCK_WAIT_TIMEOUT +reap; +# t2 update +connection default; +commit; +disconnect conn1; +drop table t; + +source include/wait_until_count_sessions.inc; diff --git a/storage/tokudb/mysql-test/tokudb/t/nonflushing_analyze_debug.test b/storage/tokudb/mysql-test/tokudb/t/nonflushing_analyze_debug.test new file mode 100644 index 00000000000..0c4c01b3dc0 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/t/nonflushing_analyze_debug.test @@ -0,0 +1,10 @@ +--source include/have_debug_sync.inc +--source include/have_tokudb.inc + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=TokuDB; +INSERT INTO t1 VALUES (1), (2), (3); + +--let $percona_nonflushing_analyze_table= t1 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t1; diff --git a/storage/tokudb/mysql-test/tokudb/t/row_format.test b/storage/tokudb/mysql-test/tokudb/t/row_format.test index 6533f8c06be..9c5c6e6403e 100644 --- a/storage/tokudb/mysql-test/tokudb/t/row_format.test +++ b/storage/tokudb/mysql-test/tokudb/t/row_format.test @@ -12,6 +12,27 @@ CREATE TABLE tokudb_row_format_test_6 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_LZ CREATE TABLE tokudb_row_format_test_7 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_QUICKLZ; CREATE TABLE tokudb_row_format_test_8 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_SNAPPY; +# TDB-76 : CREATE TABLE ... LIKE ... does not use source row_format on target table +CREATE TABLE tdb76_1 LIKE tokudb_row_format_test_1; +CREATE TABLE tdb76_2 LIKE tokudb_row_format_test_2; +CREATE TABLE tdb76_3 LIKE tokudb_row_format_test_3; +CREATE TABLE tdb76_4 LIKE tokudb_row_format_test_4; +CREATE TABLE tdb76_5 LIKE tokudb_row_format_test_5; +CREATE TABLE tdb76_6 LIKE tokudb_row_format_test_6; +CREATE TABLE tdb76_7 LIKE tokudb_row_format_test_7; +CREATE TABLE tdb76_8 LIKE tokudb_row_format_test_8; + +CREATE TABLE tdb76_compact(a INT) ENGINE=TokuDB ROW_FORMAT=COMPACT; +CREATE TABLE tdb76_redundant(a INT) ENGINE=TokuDB ROW_FORMAT=REDUNDANT; +CREATE TABLE tdb76_dynamic(a INT) ENGINE=TokuDB ROW_FORMAT=DYNAMIC; +CREATE TABLE tdb76_compressed(a INT) ENGINE=TokuDB ROW_FORMAT=COMPRESSED; + +SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name like 'tdb76_%' ORDER BY table_name; + +DROP TABLE tdb76_1, tdb76_2, tdb76_3, tdb76_4, tdb76_5, tdb76_6, tdb76_7, tdb76_8, tdb76_compact, tdb76_redundant, tdb76_dynamic, tdb76_compressed; + + + SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name like 'tokudb_row_format_test%' ORDER BY table_name; ALTER TABLE tokudb_row_format_test_1 ENGINE=TokuDB ROW_FORMAT=TOKUDB_FAST; diff --git a/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_add_key.result b/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_add_key.result index 687c60e4e05..e81bd96d15a 100644 --- a/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_add_key.result +++ b/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_add_key.result @@ -43,6 +43,8 @@ Warnings: Warning 1265 Data truncated for column 'c19' at row 1 UPDATE t SET c27=0; ALTER TABLE t ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. UPDATE t SET c27=0; set tokudb_disable_hot_alter=0; set tokudb_disable_slow_alter=1; diff --git a/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_col_rename.result b/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_col_rename.result index 05895bf4b76..c1d3b7e72dd 100644 --- a/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_col_rename.result +++ b/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_col_rename.result @@ -43,6 +43,8 @@ Warnings: Warning 1265 Data truncated for column 'c19' at row 1 UPDATE t SET c27=0; ALTER TABLE t ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. UPDATE t SET c27=0; set tokudb_disable_hot_alter=0; set tokudb_disable_slow_alter=1; diff --git a/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_default.result b/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_default.result index ae524926195..f4cd3183b1e 100644 --- a/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_default.result +++ b/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_default.result @@ -43,6 +43,8 @@ Warnings: Warning 1265 Data truncated for column 'c19' at row 1 UPDATE t SET c27=0; ALTER TABLE t ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. UPDATE t SET c27=0; set tokudb_disable_hot_alter=0; set tokudb_disable_slow_alter=1; diff --git a/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_key.result b/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_key.result index c209c80b4bb..88aaad24226 100644 --- a/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_key.result +++ b/storage/tokudb/mysql-test/tokudb_alter_table/r/null_bytes_drop_key.result @@ -45,6 +45,8 @@ UPDATE t SET c27=0; ALTER TABLE t ADD KEY (c25); UPDATE t SET c27=0; ALTER TABLE t ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. UPDATE t SET c27=0; set tokudb_disable_hot_alter=0; set tokudb_disable_slow_alter=1; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result index 5ba5da21789..caaa963c325 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result @@ -17,5 +17,5 @@ test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment t 0 PRIMARY 1 id A 7 NULL NULL BTREE -t 1 x 1 x A 3 NULL NULL YES BTREE +t 1 x 1 x A 7 NULL NULL YES BTREE drop table t; diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/nonflushing_analyze_debug.result b/storage/tokudb/mysql-test/tokudb_parts/r/nonflushing_analyze_debug.result new file mode 100644 index 00000000000..5a7bfb369df --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_parts/r/nonflushing_analyze_debug.result @@ -0,0 +1,50 @@ +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=TokuDB +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (3), +PARTITION p1 VALUES LESS THAN (10)); +INSERT INTO t1 VALUES (1), (2), (3), (4); +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t1; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SELECT * FROM t1; +a +1 +2 +3 +4 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +a +1 +2 +3 +4 +DROP TABLE t1; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=TokuDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (A) +SUBPARTITIONS 2 ( +PARTITION p0 VALUES LESS THAN (3), +PARTITION p1 VALUES LESS THAN (10)); +INSERT INTO t2 VALUES (1), (2), (3), (4); +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t2; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status OK +SELECT * FROM t2; +a +2 +1 +4 +3 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +a +2 +1 +4 +3 +DROP TABLE t2; diff --git a/storage/tokudb/mysql-test/tokudb_parts/t/nonflushing_analyze_debug.test b/storage/tokudb/mysql-test/tokudb_parts/t/nonflushing_analyze_debug.test new file mode 100644 index 00000000000..c99206acfe3 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_parts/t/nonflushing_analyze_debug.test @@ -0,0 +1,29 @@ +--source include/have_debug_sync.inc +--source include/have_tokudb.inc +--source include/have_partition.inc + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=TokuDB + PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (3), + PARTITION p1 VALUES LESS THAN (10)); + +INSERT INTO t1 VALUES (1), (2), (3), (4); + +--let $percona_nonflushing_analyze_table= t1 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t1; + +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=TokuDB + PARTITION BY RANGE (a) + SUBPARTITION BY HASH (A) + SUBPARTITIONS 2 ( + PARTITION p0 VALUES LESS THAN (3), + PARTITION p1 VALUES LESS THAN (10)); + +INSERT INTO t2 VALUES (1), (2), (3), (4); + +--let $percona_nonflushing_analyze_table= t2 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t2; diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/r/crash_tokudb.result b/storage/tokudb/mysql-test/tokudb_perfschema/r/crash_tokudb.result new file mode 100644 index 00000000000..189d6bef14e --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/r/crash_tokudb.result @@ -0,0 +1,30 @@ +SELECT COUNT(*) > 0 FROM performance_schema.setup_consumers +WHERE ENABLED = "NO"; +COUNT(*) > 0 +0 +SELECT COUNT(*) > 0 FROM performance_schema.setup_instruments +WHERE NAME LIKE "%/fti/%" AND (ENABLED = 'NO' OR TIMED = "NO"); +COUNT(*) > 0 +0 +CREATE TABLE t(a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE=TokuDB; +INSERT INTO t (b) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO t (b) SELECT b FROM t; +UPDATE t SET b = 11 WHERE b = 10; +DELETE FROM t WHERE b = 1; +ALTER TABLE t ADD COLUMN c CHAR(10) default NULL; +TRUNCATE TABLE t; +RENAME TABLE t TO t1; +RENAME TABLE t1 TO t; +SELECT COUNT(*) > 0 FROM t; +COUNT(*) > 0 +0 +DROP TABLE t; diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/r/start_server_tokudb.result b/storage/tokudb/mysql-test/tokudb_perfschema/r/start_server_tokudb.result new file mode 100644 index 00000000000..2e220916ec3 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/r/start_server_tokudb.result @@ -0,0 +1,114 @@ +show databases; +Database +information_schema +mtr +mysql +performance_schema +test +select count(*) from performance_schema.performance_timers; +count(*) +5 +select count(*) from performance_schema.setup_consumers; +count(*) +12 +select count(*) > 3 from performance_schema.setup_instruments; +count(*) > 3 +1 +select count(*) from performance_schema.setup_timers; +count(*) +4 +select * from performance_schema.accounts; +select * from performance_schema.cond_instances; +select * from performance_schema.events_stages_current; +select * from performance_schema.events_stages_history; +select * from performance_schema.events_stages_history_long; +select * from performance_schema.events_stages_summary_by_account_by_event_name; +select * from performance_schema.events_stages_summary_by_host_by_event_name; +select * from performance_schema.events_stages_summary_by_thread_by_event_name; +select * from performance_schema.events_stages_summary_by_user_by_event_name; +select * from performance_schema.events_stages_summary_global_by_event_name; +select * from performance_schema.events_statements_current; +select * from performance_schema.events_statements_history; +select * from performance_schema.events_statements_history_long; +select * from performance_schema.events_statements_summary_by_account_by_event_name; +select * from performance_schema.events_statements_summary_by_digest; +select * from performance_schema.events_statements_summary_by_host_by_event_name; +select * from performance_schema.events_statements_summary_by_thread_by_event_name; +select * from performance_schema.events_statements_summary_by_user_by_event_name; +select * from performance_schema.events_statements_summary_global_by_event_name; +select * from performance_schema.events_waits_current; +select * from performance_schema.events_waits_history; +select * from performance_schema.events_waits_history_long; +select * from performance_schema.events_waits_summary_by_account_by_event_name; +select * from performance_schema.events_waits_summary_by_host_by_event_name; +select * from performance_schema.events_waits_summary_by_instance; +select * from performance_schema.events_waits_summary_by_thread_by_event_name; +select * from performance_schema.events_waits_summary_by_user_by_event_name; +select * from performance_schema.events_waits_summary_global_by_event_name; +select * from performance_schema.file_instances; +select * from performance_schema.file_summary_by_event_name; +select * from performance_schema.file_summary_by_instance; +select * from performance_schema.host_cache; +select * from performance_schema.hosts; +select * from performance_schema.mutex_instances; +select * from performance_schema.objects_summary_global_by_type; +select * from performance_schema.performance_timers; +select * from performance_schema.rwlock_instances; +select * from performance_schema.session_account_connect_attrs; +select * from performance_schema.session_connect_attrs; +select * from performance_schema.setup_actors; +select * from performance_schema.setup_consumers; +select * from performance_schema.setup_instruments; +select * from performance_schema.setup_objects; +select * from performance_schema.setup_timers; +select * from performance_schema.socket_instances; +select * from performance_schema.socket_summary_by_instance; +select * from performance_schema.socket_summary_by_event_name; +select * from performance_schema.table_io_waits_summary_by_index_usage; +select * from performance_schema.table_io_waits_summary_by_table; +select * from performance_schema.table_lock_waits_summary_by_table; +select * from performance_schema.threads; +select * from performance_schema.users; +show variables where +`Variable_name` != "performance_schema_max_statement_classes" and +`Variable_name` like "performance_schema%"; +Variable_name Value +performance_schema ON +performance_schema_accounts_size 100 +performance_schema_digests_size 200 +performance_schema_events_stages_history_long_size 1000 +performance_schema_events_stages_history_size 10 +performance_schema_events_statements_history_long_size 1000 +performance_schema_events_statements_history_size 10 +performance_schema_events_waits_history_long_size 10000 +performance_schema_events_waits_history_size 10 +performance_schema_hosts_size 100 +performance_schema_max_cond_classes 80 +performance_schema_max_cond_instances 1000 +performance_schema_max_digest_length 1024 +performance_schema_max_file_classes 50 +performance_schema_max_file_handles 32768 +performance_schema_max_file_instances 10000 +performance_schema_max_mutex_classes 200 +performance_schema_max_mutex_instances 5000 +performance_schema_max_rwlock_classes 40 +performance_schema_max_rwlock_instances 5000 +performance_schema_max_socket_classes 10 +performance_schema_max_socket_instances 1000 +performance_schema_max_stage_classes 150 +performance_schema_max_table_handles 1000 +performance_schema_max_table_instances 500 +performance_schema_max_thread_classes 50 +performance_schema_max_thread_instances 200 +performance_schema_session_connect_attrs_size 2048 +performance_schema_setup_actors_size 100 +performance_schema_setup_objects_size 100 +performance_schema_users_size 100 +show engine PERFORMANCE_SCHEMA status; +show status like "performance_schema%"; +SELECT COUNT(NAME) > 0 FROM performance_schema.setup_instruments WHERE NAME LIKE "%/fti/%"; +COUNT(NAME) > 0 +1 +SELECT COUNT(NAME) > 0 FROM performance_schema.threads WHERE NAME LIKE "%kibbutz%"; +COUNT(NAME) > 0 +1 diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/t/crash_tokudb.test b/storage/tokudb/mysql-test/tokudb_perfschema/t/crash_tokudb.test new file mode 100644 index 00000000000..31757a20259 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/t/crash_tokudb.test @@ -0,0 +1,36 @@ +# TokuDB PFS crash test: +# Make sure FTI instrumentation is on, execute base DDL, DML queries +# and make sure there is no crash. + +--source include/not_embedded.inc +--source include/have_perfschema.inc +--source include/have_tokudb.inc + +SELECT COUNT(*) > 0 FROM performance_schema.setup_consumers + WHERE ENABLED = "NO"; +SELECT COUNT(*) > 0 FROM performance_schema.setup_instruments + WHERE NAME LIKE "%/fti/%" AND (ENABLED = 'NO' OR TIMED = "NO"); + +CREATE TABLE t(a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE=TokuDB; +INSERT INTO t (b) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO t (b) SELECT b FROM t; + +UPDATE t SET b = 11 WHERE b = 10; +DELETE FROM t WHERE b = 1; + +ALTER TABLE t ADD COLUMN c CHAR(10) default NULL; +TRUNCATE TABLE t; +RENAME TABLE t TO t1; +RENAME TABLE t1 TO t; + +SELECT COUNT(*) > 0 FROM t; +DROP TABLE t; diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/t/start_server_tokudb.test b/storage/tokudb/mysql-test/tokudb_perfschema/t/start_server_tokudb.test new file mode 100644 index 00000000000..4034fba0549 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/t/start_server_tokudb.test @@ -0,0 +1,10 @@ +# Tests for PERFORMANCE_SCHEMA + +--source include/not_embedded.inc +--source include/have_perfschema.inc +--source include/have_tokudb.inc + +--source ../../perfschema/include/start_server_common.inc + +SELECT COUNT(NAME) > 0 FROM performance_schema.setup_instruments WHERE NAME LIKE "%/fti/%"; +SELECT COUNT(NAME) > 0 FROM performance_schema.threads WHERE NAME LIKE "%kibbutz%"; diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/t/suite.opt b/storage/tokudb/mysql-test/tokudb_perfschema/t/suite.opt new file mode 100644 index 00000000000..6d826fe91d1 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/t/suite.opt @@ -0,0 +1 @@ +--loose-enable-performance-schema $TOKUDB_OPT $TOKUDB_LOAD_ADD --loose-tokudb-check-jemalloc=0 --loose-tokudb-cache-size=512M --loose-tokudb-block-size=1M diff --git a/storage/tokudb/tokudb_background.cc b/storage/tokudb/tokudb_background.cc index e019e41c788..13e0e9321cc 100644 --- a/storage/tokudb/tokudb_background.cc +++ b/storage/tokudb/tokudb_background.cc @@ -66,13 +66,13 @@ void job_manager_t::destroy() { _sem.set_interrupt(); while (_background_jobs.size()) { - _mutex.lock(); + mutex_t_lock(_mutex); job_t* job = _background_jobs.front(); if (!job->cancelled()) cancel(job); _background_jobs.pop_front(); delete job; - _mutex.unlock(); + mutex_t_unlock(_mutex); } void* result; @@ -83,7 +83,7 @@ bool job_manager_t::run_job(job_t* newjob, bool background) { bool ret = false; const char* jobkey = newjob->key(); - _mutex.lock(); + mutex_t_lock(_mutex); assert_always(!_shutdown); for (jobs_t::iterator it = _background_jobs.begin(); @@ -138,15 +138,16 @@ bool job_manager_t::run_job(job_t* newjob, bool background) { } cleanup: - _mutex.unlock(); + mutex_t_unlock(_mutex); return ret; } bool job_manager_t::cancel_job(const char* key) { bool ret = false; - _mutex.lock(); + mutex_t_lock(_mutex); for (jobs_t::iterator it = _background_jobs.begin(); - it != _background_jobs.end(); it++) { + it != _background_jobs.end(); + it++) { job_t* job = *it; if (!job->cancelled() && strcmp(job->key(), key) == 0) { @@ -155,12 +156,11 @@ bool job_manager_t::cancel_job(const char* key) { } } - _mutex.unlock(); + mutex_t_unlock(_mutex); return ret; } void job_manager_t::iterate_jobs(pfn_iterate_t callback, void* extra) const { - - _mutex.lock(); + mutex_t_lock(_mutex); for (jobs_t::const_iterator it = _background_jobs.begin(); it != _background_jobs.end(); @@ -171,7 +171,7 @@ void job_manager_t::iterate_jobs(pfn_iterate_t callback, void* extra) const { } } - _mutex.unlock(); + mutex_t_unlock(_mutex); } void* job_manager_t::thread_func(void* v) { return ((tokudb::background::job_manager_t*)v)->real_thread_func(); @@ -189,14 +189,14 @@ void* job_manager_t::real_thread_func() { tokudb::time::sleep_microsec(250000); continue; } -#endif // TOKUDB_DEBUG +#endif // TOKUDB_DEBUG - _mutex.lock(); + mutex_t_lock(_mutex); assert_debug(_background_jobs.size() > 0); job_t* job = _background_jobs.front(); run(job); _background_jobs.pop_front(); - _mutex.unlock(); + mutex_t_unlock(_mutex); delete job; } } @@ -205,11 +205,11 @@ void* job_manager_t::real_thread_func() { void job_manager_t::run(job_t* job) { assert_debug(_mutex.is_owned_by_me()); if (!job->cancelled()) { - _mutex.unlock(); + mutex_t_unlock(_mutex); // do job job->run(); // done job - _mutex.lock(); + mutex_t_lock(_mutex); } if (!job->cancelled()) { job->destroy(); diff --git a/storage/tokudb/tokudb_background.h b/storage/tokudb/tokudb_background.h index 29991ab325d..bf5eb97a619 100644 --- a/storage/tokudb/tokudb_background.h +++ b/storage/tokudb/tokudb_background.h @@ -174,11 +174,11 @@ bool destroy(); inline void job_manager_t::lock() { assert_debug(!_mutex.is_owned_by_me()); - _mutex.lock(); + mutex_t_lock(_mutex); } inline void job_manager_t::unlock() { assert_debug(_mutex.is_owned_by_me()); - _mutex.unlock(); + mutex_t_unlock(_mutex); } inline void job_manager_t::job_t::run() { diff --git a/storage/tokudb/tokudb_information_schema.cc b/storage/tokudb/tokudb_information_schema.cc index fb9e76f340b..6d4569c522d 100644 --- a/storage/tokudb/tokudb_information_schema.cc +++ b/storage/tokudb/tokudb_information_schema.cc @@ -97,7 +97,7 @@ int trx_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { TOKUDB_DBUG_ENTER(""); int error; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -232,7 +232,7 @@ int lock_waits_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { TOKUDB_DBUG_ENTER(""); int error; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -375,7 +375,7 @@ int locks_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { TOKUDB_DBUG_ENTER(""); int error; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -519,7 +519,7 @@ int file_map_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { int error; TABLE* table = tables->table; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -726,7 +726,7 @@ int fractal_tree_info_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { // 3938: Get a read lock on the status flag, since we must // read it before safely proceeding - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -1023,7 +1023,7 @@ int fractal_tree_block_map_fill_table( // 3938: Get a read lock on the status flag, since we must // read it before safely proceeding - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -1160,7 +1160,7 @@ int background_job_status_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) { int error; TABLE* table = tables->table; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; diff --git a/storage/tokudb/tokudb_thread.cc b/storage/tokudb/tokudb_thread.cc index f27e803a065..6fc1191975d 100644 --- a/storage/tokudb/tokudb_thread.cc +++ b/storage/tokudb/tokudb_thread.cc @@ -29,6 +29,7 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. namespace tokudb { namespace thread { +const pfs_key_t pfs_not_instrumented = 0xFFFFFFFF; pthread_t mutex_t::_null_owner = 0; } // namespace thread diff --git a/storage/tokudb/tokudb_thread.h b/storage/tokudb/tokudb_thread.h index dcb1fd6ec63..dec58f3fd35 100644 --- a/storage/tokudb/tokudb_thread.h +++ b/storage/tokudb/tokudb_thread.h @@ -34,95 +34,68 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. namespace tokudb { namespace thread { -#if (defined(__MACH__) || defined(__APPLE__)) && _POSIX_TIMERS <= 0 - -#define _x_min(a, b) ((a) < (b) ? (a) : (b)) - -#define timed_lock_define(timed_func_name, lock_type_name, lock_func_name) \ -inline int timed_func_name(lock_type_name *mutex, \ - const struct timespec *abs_timeout) { \ - int pthread_rc; \ - struct timespec remaining, slept, ts; \ - static const int sleep_step = 1000000; \ - \ - remaining = *abs_timeout; \ - while ((pthread_rc = lock_func_name(mutex)) == EBUSY) { \ - ts.tv_sec = 0; \ - ts.tv_nsec = (remaining.tv_sec > 0 ? \ - sleep_step : \ - _x_min(remaining.tv_nsec,sleep_step)); \ - nanosleep(&ts, &slept); \ - ts.tv_nsec -= slept.tv_nsec; \ - if (ts.tv_nsec <= remaining.tv_nsec) { \ - remaining.tv_nsec -= ts.tv_nsec; \ - } else { \ - remaining.tv_sec--; \ - remaining.tv_nsec = \ - (sleep_step - (ts.tv_nsec - remaining.tv_nsec)); \ - } \ - if (remaining.tv_sec < 0 || \ - (!remaining.tv_sec && remaining.tv_nsec <= 0)) { \ - return ETIMEDOUT; \ - } \ - } \ - \ - return pthread_rc; \ -} - -timed_lock_define(pthread_mutex_timedlock, - pthread_mutex_t, - pthread_mutex_trylock); - -timed_lock_define(pthread_rwlock_timedrdlock, - pthread_rwlock_t, - pthread_rwlock_tryrdlock); - -timed_lock_define(pthread_rwlock_timedwrlock, - pthread_rwlock_t, - pthread_rwlock_trywrlock); - -#endif //(defined(__MACH__) || defined(__APPLE__)) && _POSIX_TIMERS <= 0 +extern const pfs_key_t pfs_not_instrumented; uint my_tid(void); // Your basic mutex class mutex_t { public: - mutex_t(void); + explicit mutex_t(pfs_key_t key); + mutex_t(void) : mutex_t(pfs_not_instrumented) {} ~mutex_t(void); - void lock(void); - int lock(ulonglong microseconds); - void unlock(void); + void reinit(pfs_key_t key); + void lock( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ); + void unlock( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ); #ifdef TOKUDB_DEBUG bool is_owned_by_me(void) const; #endif private: static pthread_t _null_owner; - pthread_mutex_t _mutex; + mysql_mutex_t _mutex; #ifdef TOKUDB_DEBUG - uint _owners; - pthread_t _owner; + uint _owners; + pthread_t _owner; #endif }; // Simple read write lock class rwlock_t { public: - rwlock_t(void); + explicit rwlock_t(pfs_key_t key); + rwlock_t(void) : rwlock_t(pfs_not_instrumented) {} ~rwlock_t(void); - void lock_read(void); - int lock_read(ulonglong microseconds); - void lock_write(void); - int lock_write(ulonglong microseconds); + void lock_read( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + ); + void lock_write( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + ); void unlock(void); private: rwlock_t(const rwlock_t&); rwlock_t& operator=(const rwlock_t&); - pthread_rwlock_t _rwlock; + mysql_rwlock_t _rwlock; }; // Simple event signal/wait class @@ -224,57 +197,76 @@ private: pthread_t _thread; }; +inline uint my_tid(void) { return (uint)toku_os_gettid(); } -inline uint my_tid(void) { - return (uint)toku_os_gettid(); -} - - -inline mutex_t::mutex_t(void) { - #ifdef TOKUDB_DEBUG - _owners = 0; - _owner = _null_owner; - #endif - int r = pthread_mutex_init(&_mutex, MY_MUTEX_INIT_FAST); +inline mutex_t::mutex_t(pfs_key_t key) { +#ifdef TOKUDB_DEBUG + _owners = 0; + _owner = _null_owner; +#endif + int r MY_ATTRIBUTE((unused)) = mysql_mutex_init(key, &_mutex, MY_MUTEX_INIT_FAST); assert_debug(r == 0); } inline mutex_t::~mutex_t(void) { - #ifdef TOKUDB_DEBUG - assert_debug(_owners == 0); - #endif - int r = pthread_mutex_destroy(&_mutex); +#ifdef TOKUDB_DEBUG + assert_debug(_owners == 0); +#endif + int r MY_ATTRIBUTE((unused)) = mysql_mutex_destroy(&_mutex); assert_debug(r == 0); } -inline void mutex_t::lock(void) { - assert_debug(is_owned_by_me() == false); - int r = pthread_mutex_lock(&_mutex); +inline void mutex_t::reinit(pfs_key_t key) { +#ifdef TOKUDB_DEBUG + assert_debug(_owners == 0); +#endif + int r MY_ATTRIBUTE((unused)); + r = mysql_mutex_destroy(&_mutex); + assert_debug(r == 0); + r = mysql_mutex_init(key, &_mutex, MY_MUTEX_INIT_FAST); assert_debug(r == 0); - #ifdef TOKUDB_DEBUG - _owners++; - _owner = pthread_self(); - #endif } -inline int mutex_t::lock(ulonglong microseconds) { +inline void mutex_t::lock( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ) { assert_debug(is_owned_by_me() == false); - timespec waittime = time::offset_timespec(microseconds); - int r = pthread_mutex_timedlock(&_mutex, &waittime); - #ifdef TOKUDB_DEBUG - if (r == 0) { - _owners++; - _owner = pthread_self(); - } - #endif - assert_debug(r == 0 || r == ETIMEDOUT); - return r; + int r MY_ATTRIBUTE((unused)) = inline_mysql_mutex_lock(&_mutex +#ifdef HAVE_PSI_MUTEX_INTERFACE + , + src_file, + src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ); + assert_debug(r == 0); +#ifdef TOKUDB_DEBUG + _owners++; + _owner = pthread_self(); +#endif } -inline void mutex_t::unlock(void) { - #ifdef TOKUDB_DEBUG - assert_debug(_owners > 0); - assert_debug(is_owned_by_me()); - _owners--; - _owner = _null_owner; - #endif - int r = pthread_mutex_unlock(&_mutex); +inline void mutex_t::unlock( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ) { +#ifndef SAFE_MUTEX + (void)(src_file); + (void)(src_line); +#endif // SAFE_MUTEX +#ifdef TOKUDB_DEBUG + assert_debug(_owners > 0); + assert_debug(is_owned_by_me()); + _owners--; + _owner = _null_owner; +#endif + int r MY_ATTRIBUTE((unused)) = inline_mysql_mutex_unlock(&_mutex +#ifdef SAFE_MUTEX + , + src_file, + src_line +#endif // SAFE_MUTEX + ); assert_debug(r == 0); } #ifdef TOKUDB_DEBUG @@ -283,44 +275,28 @@ inline bool mutex_t::is_owned_by_me(void) const { } #endif - -inline rwlock_t::rwlock_t(void) { - int r = pthread_rwlock_init(&_rwlock, NULL); +inline rwlock_t::rwlock_t(pfs_key_t key) { + int r MY_ATTRIBUTE((unused)) = mysql_rwlock_init(key, &_rwlock); assert_debug(r == 0); } inline rwlock_t::~rwlock_t(void) { - int r = pthread_rwlock_destroy(&_rwlock); - assert_debug(r == 0); -} -inline void rwlock_t::lock_read(void) { - int r; - while ((r = pthread_rwlock_rdlock(&_rwlock)) != 0) { - if (r == EBUSY || r == EAGAIN) { - time::sleep_microsec(1000); - continue; - } - break; - } - assert_debug(r == 0); -} -inline int rwlock_t::lock_read(ulonglong microseconds) { - int r; - timespec waittime = time::offset_timespec(microseconds); - while ((r = pthread_rwlock_timedrdlock(&_rwlock, &waittime)) != 0) { - if (r == EBUSY || r == EAGAIN) { - time::sleep_microsec(1000); - continue; - } else if (r == ETIMEDOUT) { - return ETIMEDOUT; - } - break; - } + int r MY_ATTRIBUTE((unused)) = mysql_rwlock_destroy(&_rwlock); assert_debug(r == 0); - return r; } -inline void rwlock_t::lock_write(void) { +inline void rwlock_t::lock_read( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + ) { int r; - while ((r = pthread_rwlock_wrlock(&_rwlock)) != 0) { + while ((r = inline_mysql_rwlock_rdlock(&_rwlock +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , + src_file, + src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + )) != 0) { if (r == EBUSY || r == EAGAIN) { time::sleep_microsec(1000); continue; @@ -329,27 +305,33 @@ inline void rwlock_t::lock_write(void) { } assert_debug(r == 0); } -inline int rwlock_t::lock_write(ulonglong microseconds) { +inline void rwlock_t::lock_write( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + ) { int r; - timespec waittime = time::offset_timespec(microseconds); - while ((r = pthread_rwlock_timedwrlock(&_rwlock, &waittime)) != 0) { + while ((r = inline_mysql_rwlock_wrlock(&_rwlock +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , + src_file, + src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + )) != 0) { if (r == EBUSY || r == EAGAIN) { time::sleep_microsec(1000); continue; - } else if (r == ETIMEDOUT) { - return ETIMEDOUT; } break; } assert_debug(r == 0); - return r; } inline void rwlock_t::unlock(void) { - int r = pthread_rwlock_unlock(&_rwlock); + int r MY_ATTRIBUTE((unused)) = mysql_rwlock_unlock(&_rwlock); assert_debug(r == 0); } -inline rwlock_t::rwlock_t(const rwlock_t&) { -} +inline rwlock_t::rwlock_t(const rwlock_t&) {} inline rwlock_t& rwlock_t::operator=(const rwlock_t&) { return *this; } @@ -358,7 +340,7 @@ inline rwlock_t& rwlock_t::operator=(const rwlock_t&) { inline event_t::event_t(bool create_signalled, bool manual_reset) : _manual_reset(manual_reset) { - int r = pthread_mutex_init(&_mutex, NULL); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_init(&_mutex, NULL); assert_debug(r == 0); r = pthread_cond_init(&_cond, NULL); assert_debug(r == 0); @@ -370,13 +352,13 @@ inline event_t::event_t(bool create_signalled, bool manual_reset) : _pulsed = false; } inline event_t::~event_t(void) { - int r = pthread_mutex_destroy(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_destroy(&_mutex); assert_debug(r == 0); r = pthread_cond_destroy(&_cond); assert_debug(r == 0); } inline void event_t::wait(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); while (_signalled == false && _pulsed == false) { r = pthread_cond_wait(&_cond, &_mutex); @@ -413,7 +395,7 @@ inline int event_t::wait(ulonglong microseconds) { return 0; } inline void event_t::signal(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _signalled = true; if (_manual_reset) { @@ -427,7 +409,7 @@ inline void event_t::signal(void) { assert_debug(r == 0); } inline void event_t::pulse(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _pulsed = true; r = pthread_cond_signal(&_cond); @@ -437,7 +419,7 @@ inline void event_t::pulse(void) { } inline bool event_t::signalled(void) { bool ret = false; - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); ret = _signalled; r = pthread_mutex_unlock(&_mutex); @@ -445,7 +427,7 @@ inline bool event_t::signalled(void) { return ret; } inline void event_t::reset(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _signalled = false; _pulsed = false; @@ -467,21 +449,21 @@ inline semaphore_t::semaphore_t( _initial_count(initial_count), _max_count(max_count) { - int r = pthread_mutex_init(&_mutex, NULL); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_init(&_mutex, NULL); assert_debug(r == 0); r = pthread_cond_init(&_cond, NULL); assert_debug(r == 0); _signalled = _initial_count; } inline semaphore_t::~semaphore_t(void) { - int r = pthread_mutex_destroy(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_destroy(&_mutex); assert_debug(r == 0); r = pthread_cond_destroy(&_cond); assert_debug(r == 0); } inline semaphore_t::E_WAIT semaphore_t::wait(void) { E_WAIT ret; - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); while (_signalled == 0 && _interrupted == false) { r = pthread_cond_wait(&_cond, &_mutex); @@ -524,7 +506,7 @@ inline semaphore_t::E_WAIT semaphore_t::wait(ulonglong microseconds) { } inline bool semaphore_t::signal(void) { bool ret = false; - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); if (_signalled < _max_count) { _signalled++; @@ -538,7 +520,7 @@ inline bool semaphore_t::signal(void) { } inline int semaphore_t::signalled(void) { int ret = 0; - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); ret = _signalled; r = pthread_mutex_unlock(&_mutex); @@ -546,7 +528,7 @@ inline int semaphore_t::signalled(void) { return ret; } inline void semaphore_t::reset(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _signalled = 0; r = pthread_mutex_unlock(&_mutex); @@ -554,7 +536,7 @@ inline void semaphore_t::reset(void) { return; } inline void semaphore_t::set_interrupt(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _interrupted = true; r = pthread_cond_broadcast(&_cond); @@ -563,7 +545,7 @@ inline void semaphore_t::set_interrupt(void) { assert_debug(r == 0); } inline void semaphore_t::clear_interrupt(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _interrupted = false; r = pthread_mutex_unlock(&_mutex); -- cgit v1.2.1