revision-id: dd648b42fde54a15675002981c305cf786db8594 (v5.8-1023-gdd648b42f) parent(s): 756b3e44a8b7173993c0076a76c56c6a31d52a8b author: Sergei Petrunia committer: Sergei Petrunia timestamp: 2019-01-04 14:18:04 +0300 message: Range locking: switch to using end-points, not rowkeys. In addition to row comparison function, the user will provide a endpoint-comparison function, and a function to convert rowkey to endpoint. --- include/rocksdb/utilities/transaction_db.h | 12 +++++++- utilities/transactions/transaction_lock_mgr.cc | 41 ++++++++++++++++++++++++-- utilities/transactions/transaction_lock_mgr.h | 26 ++++++++++------ 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/include/rocksdb/utilities/transaction_db.h b/include/rocksdb/utilities/transaction_db.h index 16fa8a4a7..aa68a6243 100644 --- a/include/rocksdb/utilities/transaction_db.h +++ b/include/rocksdb/utilities/transaction_db.h @@ -195,7 +195,17 @@ struct DeadlockPath { // Interface for controlling Range Locking manager class RangeLockMgrControl { -public: + public: + + typedef void (*convert_key_to_endpoint_func)(const rocksdb::Slice &key, + std::string *endpoint); + + typedef int (*compare_endpoints_func)(const char *a, size_t a_len, + const char *b, size_t b_len); + + virtual void set_endpoint_cmp_functions(convert_key_to_endpoint_func cvt_func, + compare_endpoints_func cmp_func)=0; + virtual int set_max_lock_memory(size_t max_lock_memory) = 0; virtual uint64_t get_escalation_count() = 0; }; diff --git a/utilities/transactions/transaction_lock_mgr.cc b/utilities/transactions/transaction_lock_mgr.cc index 561531f7e..53e60679d 100644 --- a/utilities/transactions/transaction_lock_mgr.cc +++ b/utilities/transactions/transaction_lock_mgr.cc @@ -449,7 +449,10 @@ Status RangeLockMgr::TryLock(PessimisticTransaction* txn, uint32_t column_family_id, const std::string& key, Env* env, bool exclusive) { - return TryRangeLock(txn, column_family_id, key, key, exclusive); + std::string endpoint; + convert_key_to_endpoint(rocksdb::Slice(key.data(), key.size()), &endpoint); + rocksdb::Slice endp_slice(endpoint.data(), endpoint.length()); + return TryRangeLock(txn, column_family_id, endp_slice, endp_slice, exclusive); } @@ -854,8 +857,9 @@ void RangeLockMgr::UnLockAll(const PessimisticTransaction* txn, if (txn->owned_locks) { RangeLockList* range_list= (RangeLockList*)txn->owned_locks.get(); - lt->release_locks(txn->GetID(), &range_list->buffer); + lt->release_locks(txn->GetID(), &range_list->buffer, true); range_list->buffer.destroy(); + range_list->buffer.create(); toku::lock_request::retry_all_lock_requests(lt, nullptr /* lock_wait_needed_callback */); } @@ -877,6 +881,39 @@ void RangeLockMgr::UnLockAll(const PessimisticTransaction* txn, #endif } +int RangeLockMgr::compare_dbt_endpoints(__toku_db*, void *arg, + const DBT *a_key, + const DBT *b_key) +{ + RangeLockMgr* mgr= (RangeLockMgr*) arg; + return mgr->compare_endpoints((const char*)a_key->data, a_key->size, + (const char*)b_key->data, b_key->size); +} + + +RangeLockMgr::RangeLockMgr(TransactionDB* txn_db) : my_txn_db(txn_db) +{ + ltm.create(on_create, on_destroy, on_escalate, NULL); + lt= nullptr; +} + +void RangeLockMgr::set_endpoint_cmp_functions(convert_key_to_endpoint_func cvt_func, + compare_endpoints_func cmp_func) +{ + convert_key_to_endpoint= cvt_func; + compare_endpoints= cmp_func; + + // The rest is like a constructor: + assert(!lt); + + toku::comparator cmp; + //cmp.create(toku_builtin_compare_fun, NULL); + cmp.create(compare_dbt_endpoints, (void*)this, NULL); + DICTIONARY_ID dict_id = { .dictid = 1 }; + lt= ltm.get_lt(dict_id, cmp , /* on_create_extra*/nullptr); +} + + uint64_t RangeLockMgr::get_escalation_count() { LTM_STATUS_S ltm_status_test; diff --git a/utilities/transactions/transaction_lock_mgr.h b/utilities/transactions/transaction_lock_mgr.h index 9f7f61db7..59234c26f 100644 --- a/utilities/transactions/transaction_lock_mgr.h +++ b/utilities/transactions/transaction_lock_mgr.h @@ -217,15 +217,7 @@ class RangeLockMgr : void UnLock(PessimisticTransaction* txn, uint32_t column_family_id, const std::string& key, Env* env) override ; - RangeLockMgr(TransactionDB* txn_db) : my_txn_db(txn_db) - { - ltm.create(on_create, on_destroy, on_escalate, NULL); - toku::comparator cmp; - cmp.create(toku_builtin_compare_fun, NULL); - DICTIONARY_ID dict_id = { .dictid = 1 }; - lt= ltm.get_lt(dict_id, cmp , /* on_create_extra*/nullptr); - - } + RangeLockMgr(TransactionDB* txn_db); void KillLockWait(void *cdata); @@ -238,11 +230,27 @@ class RangeLockMgr : TransactionLockMgr::LockStatusData GetLockStatusData(); + using RangeLockMgrControl::convert_key_to_endpoint_func; + using RangeLockMgrControl::compare_endpoints_func; + + void set_endpoint_cmp_functions(convert_key_to_endpoint_func cvt_func, + compare_endpoints_func cmp_func) override; + private: toku::locktree_manager ltm; toku::locktree *lt; // only one tree for now + // Convert rowkey to endpoint (TODO: shouldn't "rowkey=const" translate into + // a pair of [start; end] endpoints in general? They translate into the same + // value in our current encoding, but...) + convert_key_to_endpoint_func convert_key_to_endpoint; + + // User-provided endpoint comparison function + compare_endpoints_func compare_endpoints; + TransactionDB* my_txn_db; + + static int compare_dbt_endpoints(__toku_db*, void *arg, const DBT *a_key, const DBT *b_key); // Callbacks static int on_create(locktree *lt, void *extra) { return 0; /* no error */ }