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