Merge branch 'github/10.1' into 10.2

This commit is contained in:
Sergei Golubchik 2018-02-06 14:50:50 +01:00
commit 4771ae4b22
466 changed files with 9384 additions and 3636 deletions

View file

@ -1,7 +1,9 @@
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_VERSION VERSION_LESS "2.8.9")
MESSAGE(STATUS "CMake 2.8.9 or higher is required by TokuDB")
ELSEIF(NOT HAVE_DLOPEN)
MESSAGE(STATUS "dlopen is required by TokuDB")
ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR
CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
# tokudb requires F_NOCACHE or O_DIRECT, and designated initializers

View file

@ -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 ()

View file

@ -445,14 +445,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");

View file

@ -53,7 +53,13 @@ macro(set_cflags_if_supported)
endforeach(flag)
endmacro(set_cflags_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
@ -61,7 +67,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
@ -143,8 +149,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

View file

@ -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;

View file

@ -58,6 +58,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
//
@ -780,18 +799,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; // <CER> Is zero the correct init value?
p->count = 0; // <CER> 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; // <CER> Is zero the correct init value?
p->size_evicting_estimate = 0; // <CER> Is zero the correct init value?
p->ev = ev;
p->list = list;
@ -3230,16 +3256,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);
}
}
@ -3579,9 +3615,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);
}
//
@ -3630,11 +3666,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;
@ -3642,11 +3681,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;
}
@ -4703,7 +4743,7 @@ static_assert(std::is_pod<cachefile_list>::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();

View file

@ -87,8 +87,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;
@ -117,11 +125,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;
}
@ -146,10 +157,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;
}

View file

@ -187,9 +187,35 @@ basement nodes, bulk fetch, and partial fetch:
*/
static toku_mutex_t ft_open_close_lock;
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;
void
toku_ft_get_status(FT_STATUS s) {
// 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;
@ -2644,11 +2670,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);
}
}
@ -2722,7 +2751,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
@ -2934,6 +2963,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) {
@ -2945,7 +2976,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);
@ -4615,20 +4645,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;
@ -4642,7 +4917,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();
}

View file

@ -51,9 +51,10 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#include <toku_assert.h>
#include <portability/toku_atomic.h>
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
@ -101,15 +102,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) {

View file

@ -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);

View file

@ -49,6 +49,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;
@ -276,39 +280,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
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;
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.
// 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);
{
@ -339,14 +348,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);
@ -377,34 +388,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; 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;
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);
@ -431,13 +444,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<void *>(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.

View file

@ -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);
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);
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.

View file

@ -63,21 +63,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;
@ -99,7 +95,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;
}
@ -131,7 +127,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<char *>(file->buffer),
_IOFBF,
file->buffer_size);
if (r != 0) {
result = get_error_errno();
if (newbuffer) {
@ -150,9 +149,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;
@ -196,11 +195,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) {
@ -230,11 +228,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 && i<fi->n_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;
@ -307,20 +306,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);
@ -339,7 +338,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.
@ -635,12 +634,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<void *>(bl));
if (r == 0) {
bl->extractor_live = true;
} else {
} else {
result = r;
(void) toku_ft_loader_internal_destroy(bl, true);
}
@ -659,17 +662,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);
@ -720,31 +723,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;
@ -767,29 +762,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);
@ -800,8 +794,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.
@ -810,24 +805,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 (r<nmemb) {
goto do_error;
} else {
return 0;
}
return toku_os_fread(ptr, size, nmemb, stream);
}
static int bl_write_dbt (DBT *dbt, FILE* datafile, uint64_t *dataoff, struct wbuf *wb, FTLOADER bl)
{
static int bl_write_dbt(DBT *dbt,
TOKU_FILE *datafile,
uint64_t *dataoff,
struct wbuf *wb,
FTLOADER bl) {
int r;
int dlen = dbt->size;
if ((r=bl_fwrite(&dlen, sizeof(dlen), 1, datafile, wb, bl))) return r;
@ -837,8 +822,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;
@ -892,13 +876,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.
@ -916,8 +907,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.
@ -1087,7 +1079,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;
@ -1108,14 +1100,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;
@ -1626,11 +1618,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; i<rows.n_rows; i++) {
DBT skey = make_dbt(rows.data + rows.rows[i].off, rows.rows[i].klen);
DBT sval = make_dbt(rows.data + rows.rows[i].off + rows.rows[i].klen, rows.rows[i].vlen);
TOKU_FILE *sstream = toku_bl_fidx2file(bl, sfile);
for (size_t i = 0; i < rows.n_rows; i++) {
DBT skey = make_dbt(rows.data + rows.rows[i].off, rows.rows[i].klen);
DBT sval = make_dbt(rows.data + rows.rows[i].off + rows.rows[i].klen,
rows.rows[i].vlen);
uint64_t soffset=0; // don't really need this.
r = loader_write_row(&skey, &sval, sfile, sstream, &soffset, &wb, bl);
if (r != 0) {
@ -1727,14 +1720,30 @@ int ft_loader_sort_and_write_rows (struct rowset *rows, struct merge_fileset *fs
return sort_and_write_rows (*rows, fs, bl, which_db, dest_db, compare);
}
int toku_merge_some_files_using_dbufio (const bool to_q, FIDX dest_data, QUEUE q, int n_sources, DBUFIO_FILESET bfs, FIDX srcs_fidxs[/*n_sources*/], FTLOADER bl, int which_db, DB *dest_db, ft_compare_func compare, int progress_allocation)
/* Effect: Given an array of FILE*'s each containing sorted, merge the data and write it to an output. All the files remain open after the merge.
* This merge is performed in one pass, so don't pass too many files in. If you need a tree of merges do it elsewhere.
* If TO_Q is true then we write rowsets into queue Q. Otherwise we write into dest_data.
* Modifies: May modify the arrays of files (but if modified, it must be a permutation so the caller can use that array to close everything.)
* Requires: The number of sources is at least one, and each of the input files must have at least one row in it.
int toku_merge_some_files_using_dbufio(const bool to_q,
FIDX dest_data,
QUEUE q,
int n_sources,
DBUFIO_FILESET bfs,
FIDX srcs_fidxs[/*n_sources*/],
FTLOADER bl,
int which_db,
DB *dest_db,
ft_compare_func compare,
int progress_allocation)
/* Effect: Given an array of FILE*'s each containing sorted, merge the data and
* write it to an output. All the files remain open after the merge.
* This merge is performed in one pass, so don't pass too many files in. If
* you need a tree of merges do it elsewhere.
* If TO_Q is true then we write rowsets into queue Q. Otherwise we write
* into dest_data.
* Modifies: May modify the arrays of files (but if modified, it must be a
* permutation so the caller can use that array to close everything.)
* Requires: The number of sources is at least one, and each of the input files
* must have at least one row in it.
* Arguments:
* to_q boolean indicating that output is queue (true) or a file (false)
* to_q boolean indicating that output is queue (true) or a file
* (false)
* dest_data where to write the sorted data
* q where to write the sorted data
* n_sources how many source files.
@ -1747,9 +1756,10 @@ int toku_merge_some_files_using_dbufio (const bool to_q, FIDX dest_data, QUEUE q
{
int result = 0;
FILE *dest_stream = to_q ? NULL : toku_bl_fidx2file(bl, dest_data);
TOKU_FILE *dest_stream = to_q ? nullptr : toku_bl_fidx2file(bl, dest_data);
//printf(" merge_some_files progress=%d fin at %d\n", bl->progress, 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];
@ -1943,12 +1953,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; i<n_sources; i++) {
int r = fileno(toku_bl_fidx2file(bl, srcs_fidxs[i])); // we rely on the fact that when the files are closed, the fd is also closed.
if (r==-1) {
result=get_error_errno();
if (fds == NULL)
result = get_error_errno();
if (result == 0) {
for (int i = 0; i < n_sources; i++) {
int r = fileno(
toku_bl_fidx2file(bl, srcs_fidxs[i])->file); // 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;
@ -2178,7 +2194,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;
}
@ -2418,7 +2434,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)
@ -2705,21 +2721,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;
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..
)
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]);
@ -2730,10 +2760,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;
@ -2753,24 +2787,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
};
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);
r = toku_pthread_create(*fractal_thread_key,
bl->fractal_threads + which_db,
nullptr,
fractal_thread,
static_cast<void *>(&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;
@ -3107,7 +3144,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++) {
@ -3159,8 +3196,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;
}
@ -3275,8 +3313,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;
@ -3296,7 +3337,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,

View file

@ -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);

View file

@ -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);
}

View file

@ -86,10 +86,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

View file

@ -50,11 +50,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);
@ -132,10 +138,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);
@ -301,10 +310,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);
@ -346,9 +355,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);
}
@ -678,18 +691,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();
}
}
@ -835,10 +858,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
@ -1238,11 +1262,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
@ -1259,10 +1285,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);
first_lsn->lsn=lsn;
if (r != 0) {
return 0;
}
first_lsn->lsn = lsn;
return 0;
}

View file

@ -954,14 +954,14 @@ static int toku_recover_frename(struct logtype_frename *l, RECOVER_ENV renv) {
std::unique_ptr<char[], decltype(&toku_free)> 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);

View file

@ -40,6 +40,7 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#include <string.h>
#include "toku_portability.h"
#include "portability/memory.h"
#include "portability/toku_assert.h"
#include "portability/toku_stdint.h"

View file

@ -55,6 +55,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};
@ -100,8 +105,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
@ -129,7 +136,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);

View file

@ -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"
+

View file

@ -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);

View file

@ -41,6 +41,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#include <toku_list.h>
#include <toku_pthread.h>
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);

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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));

View file

@ -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));

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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<void *>(&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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);
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 ) {
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);
}

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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();
}

View file

@ -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))

View file

@ -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);
}

View file

@ -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,
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.
// 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),
};
.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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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++) {

View file

@ -38,9 +38,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#include <toku_race_tools.h>
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);

View file

@ -8,6 +8,7 @@ set(tokuportability_srcs
portability
toku_assert
toku_crash
toku_instr_mysql
toku_path
toku_pthread
toku_time
@ -53,6 +54,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)

View file

@ -52,9 +52,12 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#include "toku_path.h"
#include <portability/toku_atomic.h>
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_write (ssize_t (*write_fun)(int, const void *, size_t)) {
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)) {
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);
/* Register the result value with the instrumentation system */
toku_instr_file_io_end(io_annotation, bytes_written);
}
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;
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;
}
FILE *
toku_os_fdopen(int fildes, const char *mode) {
FILE * rval;
if (t_fdopen)
rval = t_fdopen(fildes, mode);
else
rval = fdopen(fildes, mode);
return rval;
}
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;
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_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;
}
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;
}
int
toku_os_open(const char *path, int oflag, int mode) {
int rval;
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_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);
}
}
/* Regsiter the returning value with the system */
toku_instr_file_close_end(io_annotation, r);
return r;
}
int toku_os_rename(const char *old_name, const char *new_name) {
return rename(old_name, new_name);
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;
}
int toku_os_unlink(const char *path) { return unlink(path); }
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;
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;
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);

View file

@ -104,7 +104,13 @@ toku_memory_startup(void) {
size_t lg_chunk; // log2 of the mmap threshold
size_t lg_chunk_length = sizeof lg_chunk;
result = mallctl_f("opt.lg_chunk", &lg_chunk, &lg_chunk_length, NULL, 0);
if (result == 0)
if (result)
{
status.mmap_threshold = 1 << 21; // Default value.
// Incompatible jemalloc change.
result = 0;
}
else
status.mmap_threshold = 1 << lg_chunk;
}
}

View file

@ -79,6 +79,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 <portability/toku_atomic.h>
#include <util/partitioned_counter.h>
@ -172,13 +175,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;
}
@ -272,15 +288,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;
}
@ -427,5 +467,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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -53,10 +53,12 @@ int main(void) {
int i;
const int max_threads = 2;
toku_pthread_t tids[max_threads];
for (i=0; i<max_threads; i++) {
r = toku_pthread_create(&tids[i], NULL, f, 0); assert(r == 0);
for (i = 0; i < max_threads; i++) {
r = toku_pthread_create(
toku_uninstrumented, &tids[i], nullptr, f, nullptr);
assert(r == 0);
}
for (i=0; i<max_threads; i++) {
for (i = 0; i < max_threads; i++) {
void *ret;
r = toku_pthread_join(tids[i], &ret); assert(r == 0);
}

View file

@ -53,13 +53,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#error NDEBUG should not be set
#endif
static inline int get_error_errno(void);
inline int get_error_errno(void);
static inline int
get_maybe_error_errno(void)
{
return errno;
}
static inline int get_maybe_error_errno(void) { return errno; }
static inline void
set_errno(int new_errno)
@ -139,12 +135,10 @@ void db_env_do_backtrace(FILE *outf);
#define paranoid_invariant(a) ((void) 0)
#define paranoid_invariant_null(a) ((void) 0)
#define paranoid_invariant_notnull(a) ((void) 0)
#define paranoid_invariant_zero(a) ((void) 0)
#define paranoid_invariant_zero(a) ((void)0)
#endif
static inline int
get_error_errno(void)
{
inline int get_error_errno(void) {
invariant(errno);
return errno;
}

View file

@ -0,0 +1,365 @@
#ifdef MYSQL_TOKUDB_ENGINE
#include "toku_portability.h"
#include "toku_pthread.h"
toku_instr_probe_pfs::toku_instr_probe_pfs(const toku_instr_key &key)
: mutex(new toku_mutex_t) {
toku_mutex_init(key, mutex.get(), nullptr);
}
toku_instr_probe_pfs::~toku_instr_probe_pfs() {
toku_mutex_destroy(mutex.get());
}
// 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) {
#if (MYSQL_VERSION_MAJOR >= 5) && (MYSQL_VERSION_MINOR >= 7)
return PSI_THREAD_CALL(spawn_thread)(
key.id(), reinterpret_cast<my_thread_handle *>(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<PSI_file_operation>(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<PSI_file_operation>(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

View file

@ -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 <memory>
// 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 <mysql/psi/mysql_file.h> // PSI_file
#include <mysql/psi/mysql_thread.h> // 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<toku_mutex_t> 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

View file

@ -0,0 +1,339 @@
#pragma once
#include <stdio.h> // 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 <pthread.h>
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 <toku_instr_mysql.h>
#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;

View file

@ -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")));

View file

@ -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
@ -242,28 +269,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));
@ -273,9 +544,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);
@ -285,28 +558,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)

View file

@ -42,31 +42,62 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#include <time.h>
#include <stdint.h>
#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 <pthread.h>
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
} toku_mutex_t;
};
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
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
#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);
#define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_DEFAULT
#if TOKU_PTHREAD_DEBUG
mutex->locked = false;
invariant(!mutex->valid);
mutex->valid = true;
mutex->owner = 0;
#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
#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, .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
typedef struct toku_cond {
pthread_cond_t pcond;
} toku_cond_t;
#define toku_mutex_lock(M) \
toku_mutex_lock_with_source_location(M, __FILE__, __LINE__)
// Same considerations as for ZERO_MUTEX_INITIALIZER apply
#define ZERO_COND_INITIALIZER {}
#define TOKU_COND_INITIALIZER {PTHREAD_COND_INITIALIZER}
static inline void
toku_cond_init(toku_cond_t *cond, const toku_pthread_condattr_t *attr) {
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);
}
static inline void
toku_cond_destroy(toku_cond_t *cond) {
#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
}
inline int toku_mutex_trylock_with_source_location(toku_mutex_t *mutex,
const char *src_file,
int src_line) {
toku_mutex_instrumentation mutex_instr;
toku_instr_mutex_trylock_start(mutex_instr, *mutex, src_file, src_line);
const int r = pthread_mutex_lock(&mutex->pmutex);
toku_instr_mutex_lock_end(mutex_instr, r);
#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);
}
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);
}

View file

@ -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;

View file

@ -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;
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);
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
//

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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<n_threads; i++) {
ids[i]=i;
{ int chk_r = toku_pthread_create(&thds[i], NULL, start_txns, &ids[i]); CKERR(chk_r); }
int ids[n_threads];
for (int i = 0; i < n_threads; i++) {
ids[i] = i;
{
int chk_r = toku_pthread_create(
toku_uninstrumented, &thds[i], nullptr, start_txns, &ids[i]);
CKERR(chk_r);
}
}
start_checkpoints();

View file

@ -271,24 +271,29 @@ run_test (int iter, int die) {
}
// take checkpoint (all dictionaries)
snapshot(NULL, 1);
snapshot(NULL, 1);
if (die) {
// separate thread will perform random acts on other dictionaries (not 0)
int 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);
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();
// separate thread will perform random acts on other dictionaries (not
// 0)
int r = toku_pthread_create(
toku_uninstrumented, &thread, nullptr,
random_acts, static_cast<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);
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++) {

View file

@ -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);

Some files were not shown because too many files have changed in this diff Show more