mirror of
https://github.com/MariaDB/server.git
synced 2026-05-16 20:07:13 +02:00
Merge branch 'github/10.1' into 10.2
This commit is contained in:
commit
4771ae4b22
466 changed files with 9384 additions and 3636 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ()
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
+
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
365
storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc
Normal file
365
storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc
Normal 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
|
||||
249
storage/tokudb/PerconaFT/portability/toku_instr_mysql.h
Normal file
249
storage/tokudb/PerconaFT/portability/toku_instr_mysql.h
Normal 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
|
||||
339
storage/tokudb/PerconaFT/portability/toku_instrumentation.h
Normal file
339
storage/tokudb/PerconaFT/portability/toku_instrumentation.h
Normal 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;
|
||||
|
|
@ -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")));
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue