Commit d817d01a authored by Rich Prohaska's avatar Rich Prohaska

#81 move the lock wait time to the wait method

parent 7944bc8a
......@@ -99,7 +99,7 @@ PATENT RIGHTS GRANT:
namespace toku {
// initialize a lock request's internals
void lock_request::create(uint64_t wait_time) {
void lock_request::create(void) {
m_txnid = TXNID_NONE;
m_conflicting_txnid = TXNID_NONE;
m_start_time = 0;
......@@ -114,7 +114,6 @@ void lock_request::create(uint64_t wait_time) {
m_complete_r = 0;
m_state = state::UNINITIALIZED;
m_wait_time = wait_time;
toku_cond_init(&m_wait_cond, nullptr);
}
......@@ -236,12 +235,12 @@ int lock_request::start(void) {
return m_state == state::COMPLETE ? m_complete_r : r;
}
void lock_request::calculate_cond_wakeup_time(struct timespec *ts) {
void lock_request::calculate_cond_wakeup_time(struct timespec *ts, uint64_t wait_time) {
struct timeval now;
int r = gettimeofday(&now, NULL);
invariant_zero(r);
int64_t sec = now.tv_sec + (m_wait_time / 1000);
int64_t usec = now.tv_usec + ((m_wait_time % 1000) * 1000);
int64_t sec = now.tv_sec + (wait_time / 1000);
int64_t usec = now.tv_usec + ((wait_time % 1000) * 1000);
int64_t d_sec = usec / 1000000;
int64_t d_usec = usec % 1000000;
ts->tv_sec = sec + d_sec;
......@@ -249,12 +248,12 @@ void lock_request::calculate_cond_wakeup_time(struct timespec *ts) {
}
// sleep on the lock request until it becomes resolved or the wait time has elapsed.
int lock_request::wait(void) {
int lock_request::wait(uint64_t wait_time) {
uint64_t t_start = toku_current_time_microsec();
toku_mutex_lock(&m_info->mutex);
while (m_state == state::PENDING) {
struct timespec ts;
calculate_cond_wakeup_time(&ts);
calculate_cond_wakeup_time(&ts, wait_time);
int r = toku_cond_timedwait(&m_wait_cond, &m_info->mutex, &ts);
invariant(r == 0 || r == ETIMEDOUT);
if (r == ETIMEDOUT && m_state == state::PENDING) {
......
......@@ -125,8 +125,8 @@ public:
WRITE
};
// effect: Initializes a lock request with a given wait time.
void create(uint64_t wait_time);
// effect: Initializes a lock request.
void create(void);
// effect: Destroys a lock request.
void destroy(void);
......@@ -144,7 +144,7 @@ public:
// effect: Sleeps until either the request is granted or the wait time expires.
// returns: The return code of locktree::acquire_[write,read]_lock()
// or simply DB_LOCK_NOTGRANTED if the wait time expired.
int wait(void);
int wait(uint64_t wait_time);
// return: left end-point of the lock range
const DBT *get_left_key(void) const;
......@@ -196,7 +196,6 @@ private:
int m_complete_r;
state m_state;
uint64_t m_wait_time;
toku_cond_t m_wait_cond;
// the lock request info state stored in the
......@@ -235,7 +234,7 @@ private:
void copy_keys(void);
void calculate_cond_wakeup_time(struct timespec *ts);
void calculate_cond_wakeup_time(struct timespec *ts, uint64_t wait_time);
static int find_by_txnid(lock_request * const &request, const TXNID &txnid);
......
......@@ -96,8 +96,7 @@ namespace toku {
// create and set the object's internals, destroy should not crash.
void lock_request_unit_test::test_create_destroy(void) {
lock_request request;
const uint64_t wait_time_magic = 5016342;
request.create(wait_time_magic);
request.create();
invariant(request.m_txnid == TXNID_NONE);
invariant(request.m_left_key == nullptr);
......@@ -112,7 +111,6 @@ void lock_request_unit_test::test_create_destroy(void) {
invariant(request.m_complete_r == 0);
invariant(request.m_state == lock_request::state::UNINITIALIZED);
invariant(request.m_wait_time = wait_time_magic);
request.destroy();
}
......
......@@ -98,8 +98,7 @@ namespace toku {
// when appropriate and plays nice with +/- infinity.
void lock_request_unit_test::test_get_set_keys(void) {
lock_request request;
const uint64_t lock_wait_time = 10;
request.create(lock_wait_time);
request.create();
locktree *const null_lt = nullptr;
......
......@@ -111,9 +111,9 @@ void lock_request_unit_test::test_start_deadlock(void) {
lock_request request_a;
lock_request request_b;
lock_request request_c;
request_a.create(lock_wait_time);
request_b.create(lock_wait_time);
request_c.create(lock_wait_time);
request_a.create();
request_b.create();
request_c.create();
const DBT *one = get_dbt(1);
const DBT *two = get_dbt(2);
......@@ -140,19 +140,19 @@ void lock_request_unit_test::test_start_deadlock(void) {
request_c.set(lt, txnid_c, one, one, lock_request::type::WRITE);
r = request_c.start();
invariant(r == DB_LOCK_NOTGRANTED);
r = request_c.wait();
r = request_c.wait(lock_wait_time);
invariant(r == DB_LOCK_NOTGRANTED);
request_c.set(lt, txnid_c, two, two, lock_request::type::WRITE);
r = request_c.start();
invariant(r == DB_LOCK_NOTGRANTED);
r = request_c.wait();
r = request_c.wait(lock_wait_time);
invariant(r == DB_LOCK_NOTGRANTED);
// release locks for A and B, then wait on A's request which should succeed
// since B just unlocked and should have completed A's pending request.
release_lock_and_retry_requests(lt, txnid_a, one, one);
release_lock_and_retry_requests(lt, txnid_b, two, two);
r = request_a.wait();
r = request_a.wait(lock_wait_time);
invariant_zero(r);
release_lock_and_retry_requests(lt, txnid_a, two, two);
......
......@@ -100,8 +100,6 @@ void lock_request_unit_test::test_start_pending(void) {
locktree::manager mgr;
locktree *lt;
lock_request request;
// bogus, just has to be something.
const uint64_t lock_wait_time = 0;
mgr.create(nullptr, nullptr, nullptr, nullptr);
DICTIONARY_ID dict_id = { 1 };
......@@ -122,7 +120,7 @@ void lock_request_unit_test::test_start_pending(void) {
// start a lock request for 1,1
// it should fail. the request should be stored and in the pending state.
request.create(lock_wait_time);
request.create();
request.set(lt, txnid_a, one, one, lock_request::type::WRITE);
r = request.start();
invariant(r == DB_LOCK_NOTGRANTED);
......
......@@ -135,11 +135,11 @@ void manager_unit_test::test_status(void) {
// txn b tries to write lock one, conflicts, waits, and fails to lock one
lock_request request_b;
request_b.create(1000);
request_b.create();
request_b.set(lt, txnid_b, one, one, lock_request::type::WRITE);
r = request_b.start();
assert(r == DB_LOCK_NOTGRANTED);
r = request_b.wait();
r = request_b.wait(1000);
assert(r == DB_LOCK_NOTGRANTED);
request_b.destroy();
......
......@@ -212,8 +212,7 @@ query_context_base_init(QUERY_CONTEXT_BASE context, DBC *c, uint32_t flag, bool
}
context->do_locking = (context->db->i->lt != nullptr && !(lock_flags & (DB_PRELOCKED | DB_PRELOCKED_WRITE)));
context->r_user_callback = 0;
uint64_t lock_wait_time = context->txn ? context->txn->mgrp->i->ltm.get_lock_wait_time() : 0;
context->request.create(lock_wait_time);
context->request.create();
}
static toku::lock_request::type
......
......@@ -231,10 +231,8 @@ void toku_db_txn_escalate_callback(TXNID txnid, const toku::locktree *lt, const
// Return when the range lock is acquired or the default lock tree timeout has expired.
int toku_db_get_range_lock(DB *db, DB_TXN *txn, const DBT *left_key, const DBT *right_key,
toku::lock_request::type lock_type) {
uint64_t wait_time = txn->mgrp->i->ltm.get_lock_wait_time();
toku::lock_request request;
request.create(wait_time);
request.create();
int r = toku_db_start_range_lock(db, txn, left_key, right_key, lock_type, &request);
if (r == DB_LOCK_NOTGRANTED) {
r = toku_db_wait_range_lock(db, txn, &request);
......@@ -271,7 +269,8 @@ int toku_db_wait_range_lock(DB *db, DB_TXN *txn, toku::lock_request *request) {
const DBT *left_key = request->get_left_key();
const DBT *right_key = request->get_right_key();
const int r = request->wait();
uint64_t wait_time = txn->mgrp->i->ltm.get_lock_wait_time();
const int r = request->wait(wait_time);
if (r == 0) {
db_txn_note_row_lock(db, txn_anc, left_key, right_key);
} else if (r == DB_LOCK_NOTGRANTED) {
......@@ -296,10 +295,8 @@ void toku_db_grab_write_lock (DB *db, DBT *key, TOKUTXN tokutxn) {
TXNID txn_anc_id = txn_anc->id64(txn_anc);
// This lock request must succeed, so we do not want to wait
const uint64_t lock_wait_time = 0;
toku::lock_request request;
request.create(lock_wait_time);
request.create();
request.set(db->i->lt, txn_anc_id, key, key, toku::lock_request::type::WRITE);
int r = request.start();
invariant_zero(r);
......
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