Commit 5b697e7e authored by John Esmet's avatar John Esmet

Merge branch 'releases/tokumx-2.0'

parents db9b01c8 668f1118
......@@ -2514,7 +2514,7 @@ toku_cachetable_minicron_shutdown(CACHETABLE ct) {
void toku_cachetable_prepare_close(CACHETABLE ct UU()) {
extern bool toku_serialize_in_parallel;
toku_serialize_in_parallel = true;
toku_drd_unsafe_set(&toku_serialize_in_parallel, true);
}
/* Requires that it all be flushed. */
......
......@@ -600,8 +600,9 @@ handle_split_of_child(
// We never set the rightmost blocknum to be the root.
// Instead, we wait for the root to split and let promotion initialize the rightmost
// blocknum to be the first non-root leaf node on the right extreme to recieve an insert.
invariant(ft->h->root_blocknum.b != ft->rightmost_blocknum.b);
if (childa->blocknum.b == ft->rightmost_blocknum.b) {
BLOCKNUM rightmost_blocknum = toku_drd_unsafe_fetch(&ft->rightmost_blocknum);
invariant(ft->h->root_blocknum.b != rightmost_blocknum.b);
if (childa->blocknum.b == rightmost_blocknum.b) {
// The rightmost leaf (a) split into (a) and (b). We want (b) to swap pair values
// with (a), now that it is the new rightmost leaf. This keeps the rightmost blocknum
// constant, the same the way we keep the root blocknum constant.
......@@ -1428,7 +1429,8 @@ ft_merge_child(
node->pivotkeys.delete_at(childnuma);
// Handle a merge of the rightmost leaf node.
if (did_merge && childb->blocknum.b == ft->rightmost_blocknum.b) {
BLOCKNUM rightmost_blocknum = toku_drd_unsafe_fetch(&ft->rightmost_blocknum);
if (did_merge && childb->blocknum.b == rightmost_blocknum.b) {
invariant(childb->blocknum.b != ft->h->root_blocknum.b);
toku_ftnode_swap_pair_values(childa, childb);
BP_BLOCKNUM(node, childnuma) = childa->blocknum;
......
......@@ -1200,7 +1200,7 @@ int toku_ftnode_pe_callback(void *ftnode_pv, PAIR_ATTR old_attr, void *write_ext
// We need a function to have something a drd suppression can reference
// see src/tests/drd.suppressions (unsafe_touch_clock)
static void unsafe_touch_clock(FTNODE node, int i) {
BP_TOUCH_CLOCK(node, i);
toku_drd_unsafe_set(&node->bp[i].clock_count, static_cast<unsigned char>(1));
}
// Callback that states if a partial fetch of the node is necessary
......@@ -1620,13 +1620,13 @@ static void inject_message_in_locked_node(
paranoid_invariant(msg_with_msn.msn().msn == node->max_msn_applied_to_node_on_disk.msn);
if (node->blocknum.b == ft->rightmost_blocknum.b) {
if (ft->seqinsert_score < FT_SEQINSERT_SCORE_THRESHOLD) {
if (toku_drd_unsafe_fetch(&ft->seqinsert_score) < FT_SEQINSERT_SCORE_THRESHOLD) {
// we promoted to the rightmost leaf node and the seqinsert score has not yet saturated.
toku_sync_fetch_and_add(&ft->seqinsert_score, 1);
}
} else if (ft->seqinsert_score != 0) {
} else if (toku_drd_unsafe_fetch(&ft->seqinsert_score) != 0) {
// we promoted to something other than the rightmost leaf node and the score should reset
ft->seqinsert_score = 0;
toku_drd_unsafe_set(&ft->seqinsert_score, static_cast<uint32_t>(0));
}
// if we call toku_ft_flush_some_child, then that function unpins the root
......@@ -1785,19 +1785,19 @@ static inline bool should_inject_in_node(seqinsert_loc loc, int height, int dept
return (height == 0 || (loc == NEITHER_EXTREME && (height <= 1 || depth >= 2)));
}
static void ft_set_or_verify_rightmost_blocknum(FT ft, BLOCKNUM b)
static void ft_verify_or_set_rightmost_blocknum(FT ft, BLOCKNUM b)
// Given: 'b', the _definitive_ and constant rightmost blocknum of 'ft'
{
if (ft->rightmost_blocknum.b == RESERVED_BLOCKNUM_NULL) {
if (toku_drd_unsafe_fetch(&ft->rightmost_blocknum.b) == RESERVED_BLOCKNUM_NULL) {
toku_ft_lock(ft);
if (ft->rightmost_blocknum.b == RESERVED_BLOCKNUM_NULL) {
ft->rightmost_blocknum = b;
toku_drd_unsafe_set(&ft->rightmost_blocknum, b);
}
toku_ft_unlock(ft);
}
// The rightmost blocknum only transitions from RESERVED_BLOCKNUM_NULL to non-null.
// If it's already set, verify that the stored value is consistent with 'b'
invariant(ft->rightmost_blocknum.b == b.b);
invariant(toku_drd_unsafe_fetch(&ft->rightmost_blocknum.b) == b.b);
}
bool toku_bnc_should_promote(FT ft, NONLEAF_CHILDINFO bnc) {
......@@ -1859,7 +1859,7 @@ static void push_something_in_subtree(
// otherwise. We explicitly skip the root node because then we don't have
// to worry about changing the rightmost blocknum when the root splits.
if (subtree_root->height == 0 && loc == RIGHT_EXTREME && subtree_root->blocknum.b != ft->h->root_blocknum.b) {
ft_set_or_verify_rightmost_blocknum(ft, subtree_root->blocknum);
ft_verify_or_set_rightmost_blocknum(ft, subtree_root->blocknum);
}
inject_message_in_locked_node(ft, subtree_root, target_childnum, msg, flow_deltas, gc_info);
} else {
......@@ -2276,20 +2276,21 @@ static int ft_maybe_insert_into_rightmost_leaf(FT ft, DBT *key, DBT *val, XIDS m
int r = -1;
uint32_t rightmost_fullhash;
BLOCKNUM rightmost_blocknum = ft->rightmost_blocknum;
BLOCKNUM rightmost_blocknum;
FTNODE rightmost_leaf = nullptr;
// Don't do the optimization if our heurstic suggests that
// insertion pattern is not sequential.
if (ft->seqinsert_score < FT_SEQINSERT_SCORE_THRESHOLD) {
if (toku_drd_unsafe_fetch(&ft->seqinsert_score) < FT_SEQINSERT_SCORE_THRESHOLD) {
goto cleanup;
}
// We know the seqinsert score is high enough that we should
// attemp to directly insert into the right most leaf. Because
// attempt to directly insert into the rightmost leaf. Because
// the score is non-zero, the rightmost blocknum must have been
// set. See inject_message_in_locked_node(), which only increases
// the score if the target node blocknum == rightmost_blocknum
rightmost_blocknum = ft->rightmost_blocknum;
invariant(rightmost_blocknum.b != RESERVED_BLOCKNUM_NULL);
// Pin the rightmost leaf with a write lock.
......
......@@ -572,14 +572,18 @@ toku_logger_make_space_in_inbuf (TOKULOGGER logger, int n_bytes_needed)
release_output(logger, fsynced_lsn);
}
void toku_logger_fsync (TOKULOGGER logger)
void toku_logger_fsync(TOKULOGGER logger)
// Effect: This is the exported fsync used by ydb.c for env_log_flush. Group commit doesn't have to work.
// Entry: Holds no locks
// Exit: Holds no locks
// Implementation note: Acquire the output condition lock, then the output permission, then release the output condition lock, then get the input lock.
// Then release everything.
// Then release everything. Hold the input lock while reading the current max lsn in buf to make drd happy that there is no data race.
{
toku_logger_maybe_fsync(logger, logger->inbuf.max_lsn_in_buf, true, false);
ml_lock(&logger->input_lock);
const LSN max_lsn_in_buf = logger->inbuf.max_lsn_in_buf;
ml_unlock(&logger->input_lock);
toku_logger_maybe_fsync(logger, max_lsn_in_buf, true, false);
}
void toku_logger_fsync_if_lsn_not_fsynced (TOKULOGGER logger, LSN lsn) {
......
......@@ -145,7 +145,7 @@ struct toku_thread_pool *get_ft_pool(void) {
}
void toku_serialize_set_parallel(bool in_parallel) {
toku_serialize_in_parallel = in_parallel;
toku_drd_unsafe_set(&toku_serialize_in_parallel, in_parallel);
}
void toku_ft_serialize_layer_init(void) {
......@@ -852,7 +852,7 @@ toku_serialize_ftnode_to (int fd, BLOCKNUM blocknum, FTNODE node, FTNODE_DISK_DA
ft->h->basementnodesize,
ft->h->compression_method,
do_rebalancing,
toku_serialize_in_parallel, // in_parallel
toku_drd_unsafe_fetch(&toku_serialize_in_parallel),
&n_to_write,
&n_uncompressed_bytes,
&compressed_buf
......
......@@ -325,7 +325,7 @@ toku_txn_manager_get_oldest_living_xid(TXN_MANAGER txn_manager) {
}
TXNID toku_txn_manager_get_oldest_referenced_xid_estimate(TXN_MANAGER txn_manager) {
return txn_manager->last_calculated_oldest_referenced_xid;
return toku_drd_unsafe_fetch(&txn_manager->last_calculated_oldest_referenced_xid);
}
int live_root_txn_list_iter(const TOKUTXN &live_xid, const uint32_t UU(index), TXNID **const referenced_xids);
......@@ -385,7 +385,7 @@ static void set_oldest_referenced_xid(TXN_MANAGER txn_manager) {
oldest_referenced_xid = txn_manager->last_xid;
}
invariant(oldest_referenced_xid != TXNID_MAX);
txn_manager->last_calculated_oldest_referenced_xid = oldest_referenced_xid;
toku_drd_unsafe_set(&txn_manager->last_calculated_oldest_referenced_xid, oldest_referenced_xid);
}
//Heaviside function to find a TOKUTXN by TOKUTXN (used to find the index)
......
......@@ -275,7 +275,7 @@ void locktree::sto_end(void) {
void locktree::sto_end_early_no_accounting(void *prepared_lkr) {
sto_migrate_buffer_ranges_to_tree(prepared_lkr);
sto_end();
m_sto_score = 0;
toku_drd_unsafe_set(&m_sto_score, 0);
}
void locktree::sto_end_early(void *prepared_lkr) {
......@@ -536,11 +536,11 @@ void locktree::remove_overlapping_locks_for_txnid(TXNID txnid,
}
bool locktree::sto_txnid_is_valid_unsafe(void) const {
return m_sto_txnid != TXNID_NONE;
return toku_drd_unsafe_fetch(&m_sto_txnid) != TXNID_NONE;
}
int locktree::sto_get_score_unsafe(void) const {
return m_sto_score;
return toku_drd_unsafe_fetch(&m_sto_score);
}
bool locktree::sto_try_release(TXNID txnid) {
......
......@@ -138,3 +138,22 @@ PATENT RIGHTS GRANT:
# define RUNNING_ON_VALGRIND (0U)
#endif
// Unsafely fetch and return a `T' from src, telling drd to ignore
// racey access to src for the next sizeof(*src) bytes
template <typename T>
T toku_drd_unsafe_fetch(T *src) {
TOKU_DRD_IGNORE_VAR(*src);
T val = *src;
TOKU_DRD_STOP_IGNORING_VAR(*src);
return val;
}
// Unsafely set a `T' value into *dest from src, telling drd to ignore
// racey access to dest for the next sizeof(*dest) bytes
template <typename T>
void toku_drd_unsafe_set(T *dest, const T src) {
TOKU_DRD_IGNORE_VAR(*dest);
*dest = src;
TOKU_DRD_STOP_IGNORING_VAR(*dest);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment