Commit 2cb512d0 authored by Yoni Fogel's avatar Yoni Fogel

refs #5149 Fix up ydb layer read-only txn optimizations.

The is_read_only function already took into account children, so we don't need complicated logic.

git-svn-id: file:///svn/toku/tokudb@45205 c7de825b-a66e-492c-adef-691d508d4ae1
parent d88ed42f
...@@ -516,6 +516,8 @@ toku_maybe_log_begin_txn_for_write_operation(TOKUTXN txn) { ...@@ -516,6 +516,8 @@ toku_maybe_log_begin_txn_for_write_operation(TOKUTXN txn) {
bool bool
toku_txn_is_read_only(TOKUTXN txn) { toku_txn_is_read_only(TOKUTXN txn) {
// No need to recursively check children because parents are
// recursively logged before children.
if (!txn->begin_was_logged) { if (!txn->begin_was_logged) {
// Did no work. // Did no work.
invariant(txn->roll_info.num_rollentries == 0); invariant(txn->roll_info.num_rollentries == 0);
......
...@@ -114,6 +114,8 @@ struct tokulogger_preplist { ...@@ -114,6 +114,8 @@ struct tokulogger_preplist {
int toku_logger_recover_txn (TOKULOGGER logger, struct tokulogger_preplist preplist[/*count*/], long count, /*out*/ long *retp, u_int32_t flags); int toku_logger_recover_txn (TOKULOGGER logger, struct tokulogger_preplist preplist[/*count*/], long count, /*out*/ long *retp, u_int32_t flags);
void toku_maybe_log_begin_txn_for_write_operation(TOKUTXN txn); void toku_maybe_log_begin_txn_for_write_operation(TOKUTXN txn);
// Return whether txn (or it's descendents) have done no work.
bool toku_txn_is_read_only(TOKUTXN txn); bool toku_txn_is_read_only(TOKUTXN txn);
#if defined(__cplusplus) || defined(__cilkplusplus) #if defined(__cplusplus) || defined(__cilkplusplus)
......
...@@ -13,11 +13,6 @@ ...@@ -13,11 +13,6 @@
#include <valgrind/helgrind.h> #include <valgrind/helgrind.h>
#include "ft/txn_manager.h" #include "ft/txn_manager.h"
static int toku_txn_commit(DB_TXN * txn, u_int32_t flags, TXN_PROGRESS_POLL_FUNCTION poll,
void *poll_extra, bool release_mo_client_lock_if_held, bool *holds_mo_lock);
static int toku_txn_abort(DB_TXN * txn, TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra,
bool *holds_mo_lock);
static int static int
toku_txn_release_locks(DB_TXN* txn) { toku_txn_release_locks(DB_TXN* txn) {
assert(txn); assert(txn);
...@@ -60,20 +55,12 @@ toku_txn_destroy(DB_TXN *txn) { ...@@ -60,20 +55,12 @@ toku_txn_destroy(DB_TXN *txn) {
static int static int
toku_txn_commit(DB_TXN * txn, u_int32_t flags, toku_txn_commit(DB_TXN * txn, u_int32_t flags,
TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra, TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra,
bool release_mo_lock_if_held, bool release_mo_lock) {
bool *holds_mo_lock) {
HANDLE_PANICKED_ENV(txn->mgrp); HANDLE_PANICKED_ENV(txn->mgrp);
// Don't take multi-operation lock until we see a non-readonly txn.
if (!*holds_mo_lock &&
!toku_txn_is_read_only(db_txn_struct_i(txn)->tokutxn)) {
toku_multi_operation_client_lock();
*holds_mo_lock = true;
}
//Recursively kill off children //Recursively kill off children
if (db_txn_struct_i(txn)->child) { if (db_txn_struct_i(txn)->child) {
//commit of child sets the child pointer to NULL //commit of child sets the child pointer to NULL
int r_child = toku_txn_commit(db_txn_struct_i(txn)->child, int r_child = toku_txn_commit(db_txn_struct_i(txn)->child, flags, NULL, NULL, false);
flags, NULL, NULL, false, holds_mo_lock);
if (r_child !=0 && !toku_env_is_panicked(txn->mgrp)) { if (r_child !=0 && !toku_env_is_panicked(txn->mgrp)) {
env_panic(txn->mgrp, r_child, "Recursive child commit failed during parent commit.\n"); env_panic(txn->mgrp, r_child, "Recursive child commit failed during parent commit.\n");
} }
...@@ -125,7 +112,7 @@ toku_txn_commit(DB_TXN * txn, u_int32_t flags, ...@@ -125,7 +112,7 @@ toku_txn_commit(DB_TXN * txn, u_int32_t flags,
// this lock must be held until the references to the open FTs is released // this lock must be held until the references to the open FTs is released
// begin checkpoint logs these associations, so we must be protect // begin checkpoint logs these associations, so we must be protect
// the changing of these associations with checkpointing // the changing of these associations with checkpointing
if (release_mo_lock_if_held && *holds_mo_lock) { if (release_mo_lock) {
toku_multi_operation_client_unlock(); toku_multi_operation_client_unlock();
} }
toku_txn_maybe_fsync_log(logger, do_fsync_lsn, do_fsync); toku_txn_maybe_fsync_log(logger, do_fsync_lsn, do_fsync);
...@@ -154,20 +141,12 @@ toku_txn_id64(DB_TXN * txn) { ...@@ -154,20 +141,12 @@ toku_txn_id64(DB_TXN * txn) {
static int static int
toku_txn_abort(DB_TXN * txn, toku_txn_abort(DB_TXN * txn,
TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra, TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra) {
bool *holds_mo_lock) {
HANDLE_PANICKED_ENV(txn->mgrp); HANDLE_PANICKED_ENV(txn->mgrp);
// Don't take multi-operation lock until we see a non-readonly txn.
if (!*holds_mo_lock &&
!toku_txn_is_read_only(db_txn_struct_i(txn)->tokutxn)) {
toku_multi_operation_client_lock();
*holds_mo_lock = true;
}
//Recursively kill off children (abort or commit are both correct, commit is cheaper) //Recursively kill off children (abort or commit are both correct, commit is cheaper)
if (db_txn_struct_i(txn)->child) { if (db_txn_struct_i(txn)->child) {
//commit of child sets the child pointer to NULL //commit of child sets the child pointer to NULL
int r_child = toku_txn_commit(db_txn_struct_i(txn)->child, int r_child = toku_txn_commit(db_txn_struct_i(txn)->child, DB_TXN_NOSYNC, NULL, NULL, false);
DB_TXN_NOSYNC, NULL, NULL, false, holds_mo_lock);
if (r_child !=0 && !toku_env_is_panicked(txn->mgrp)) { if (r_child !=0 && !toku_env_is_panicked(txn->mgrp)) {
env_panic(txn->mgrp, r_child, "Recursive child commit failed during parent abort.\n"); env_panic(txn->mgrp, r_child, "Recursive child commit failed during parent abort.\n");
} }
...@@ -216,7 +195,7 @@ toku_txn_xa_prepare (DB_TXN *txn, TOKU_XA_XID *xid) { ...@@ -216,7 +195,7 @@ toku_txn_xa_prepare (DB_TXN *txn, TOKU_XA_XID *xid) {
//commit of child sets the child pointer to NULL //commit of child sets the child pointer to NULL
// toku_txn_commit will take the mo_lock if not held and a non-readonly txn is found. // toku_txn_commit will take the mo_lock if not held and a non-readonly txn is found.
int r_child = toku_txn_commit(db_txn_struct_i(txn)->child, 0, NULL, NULL, false, &holds_mo_lock); int r_child = toku_txn_commit(db_txn_struct_i(txn)->child, 0, NULL, NULL, false);
if (r_child !=0 && !toku_env_is_panicked(txn->mgrp)) { if (r_child !=0 && !toku_env_is_panicked(txn->mgrp)) {
env_panic(txn->mgrp, r_child, "Recursive child commit failed during parent commit.\n"); env_panic(txn->mgrp, r_child, "Recursive child commit failed during parent commit.\n");
} }
...@@ -278,12 +257,16 @@ locked_txn_commit_with_progress(DB_TXN *txn, u_int32_t flags, ...@@ -278,12 +257,16 @@ locked_txn_commit_with_progress(DB_TXN *txn, u_int32_t flags,
toku_checkpoint(txn->mgrp->i->cachetable, txn->mgrp->i->logger, NULL, NULL, NULL, NULL, TXN_COMMIT_CHECKPOINT); toku_checkpoint(txn->mgrp->i->cachetable, txn->mgrp->i->logger, NULL, NULL, NULL, NULL, TXN_COMMIT_CHECKPOINT);
} }
bool holds_mo_lock = false; bool holds_mo_lock = false;
if (!toku_txn_is_read_only(db_txn_struct_i(txn)->tokutxn)) {
toku_multi_operation_client_lock();
holds_mo_lock = true;
}
// cannot begin a checkpoint. // cannot begin a checkpoint.
// the multi operation lock is taken the first time we // the multi operation lock is taken the first time we
// see a non-readonly txn in the recursive commit. // see a non-readonly txn in the recursive commit.
// But released in the first-level toku_txn_commit (if taken), // But released in the first-level toku_txn_commit (if taken),
// this way, we don't hold it while we fsync the log. // this way, we don't hold it while we fsync the log.
int r = toku_txn_commit(txn, flags, poll, poll_extra, true, &holds_mo_lock); int r = toku_txn_commit(txn, flags, poll, poll_extra, holds_mo_lock);
return r; return r;
} }
...@@ -295,7 +278,11 @@ locked_txn_abort_with_progress(DB_TXN *txn, ...@@ -295,7 +278,11 @@ locked_txn_abort_with_progress(DB_TXN *txn,
// see a non-readonly txn in the abort (or recursive commit). // see a non-readonly txn in the abort (or recursive commit).
// But released here so we don't have to hold additional state. // But released here so we don't have to hold additional state.
bool holds_mo_lock = false; bool holds_mo_lock = false;
int r = toku_txn_abort(txn, poll, poll_extra, &holds_mo_lock); if (!toku_txn_is_read_only(db_txn_struct_i(txn)->tokutxn)) {
toku_multi_operation_client_lock();
holds_mo_lock = true;
}
int r = toku_txn_abort(txn, poll, poll_extra);
if (holds_mo_lock) { if (holds_mo_lock) {
toku_multi_operation_client_unlock(); toku_multi_operation_client_unlock();
} }
......
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