fork of https://github.com/rust-rocksdb/rust-rocksdb for nextgraph
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.9 KiB
136 lines
4.9 KiB
1 year ago
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||
|
// This source code is licensed under both the GPLv2 (found in the
|
||
|
// COPYING file in the root directory) and Apache 2.0 License
|
||
|
// (found in the LICENSE.Apache file in the root directory).
|
||
|
|
||
|
#pragma once
|
||
|
#ifndef OS_WIN
|
||
|
|
||
|
// For DeadlockInfoBuffer:
|
||
|
#include "util/thread_local.h"
|
||
|
#include "utilities/transactions/lock/point/point_lock_manager.h"
|
||
|
#include "utilities/transactions/lock/range/range_lock_manager.h"
|
||
|
|
||
|
// Lock Tree library:
|
||
|
#include "utilities/transactions/lock/range/range_tree/lib/locktree/lock_request.h"
|
||
|
#include "utilities/transactions/lock/range/range_tree/lib/locktree/locktree.h"
|
||
|
#include "utilities/transactions/lock/range/range_tree/range_tree_lock_tracker.h"
|
||
|
|
||
|
namespace ROCKSDB_NAMESPACE {
|
||
|
|
||
|
typedef DeadlockInfoBufferTempl<RangeDeadlockPath> RangeDeadlockInfoBuffer;
|
||
|
|
||
|
// A Range Lock Manager that uses PerconaFT's locktree library
|
||
|
class RangeTreeLockManager : public RangeLockManagerBase,
|
||
|
public RangeLockManagerHandle {
|
||
|
public:
|
||
|
LockManager* getLockManager() override { return this; }
|
||
|
|
||
|
void AddColumnFamily(const ColumnFamilyHandle* cfh) override;
|
||
|
void RemoveColumnFamily(const ColumnFamilyHandle* cfh) override;
|
||
|
|
||
|
void Resize(uint32_t) override;
|
||
|
std::vector<DeadlockPath> GetDeadlockInfoBuffer() override;
|
||
|
|
||
|
std::vector<RangeDeadlockPath> GetRangeDeadlockInfoBuffer() override;
|
||
|
void SetRangeDeadlockInfoBufferSize(uint32_t target_size) override;
|
||
|
|
||
|
// Get a lock on a range
|
||
|
// @note only exclusive locks are currently supported (requesting a
|
||
|
// non-exclusive lock will get an exclusive one)
|
||
|
using LockManager::TryLock;
|
||
|
Status TryLock(PessimisticTransaction* txn, ColumnFamilyId column_family_id,
|
||
|
const Endpoint& start_endp, const Endpoint& end_endp, Env* env,
|
||
|
bool exclusive) override;
|
||
|
|
||
|
void UnLock(PessimisticTransaction* txn, const LockTracker& tracker,
|
||
|
Env* env) override;
|
||
|
void UnLock(PessimisticTransaction* txn, ColumnFamilyId column_family_id,
|
||
|
const std::string& key, Env* env) override;
|
||
|
void UnLock(PessimisticTransaction*, ColumnFamilyId, const Endpoint&,
|
||
|
const Endpoint&, Env*) override {
|
||
|
// TODO: range unlock does nothing...
|
||
|
}
|
||
|
|
||
|
explicit RangeTreeLockManager(
|
||
|
std::shared_ptr<TransactionDBMutexFactory> mutex_factory);
|
||
|
|
||
|
~RangeTreeLockManager() override;
|
||
|
|
||
|
int SetMaxLockMemory(size_t max_lock_memory) override {
|
||
|
return ltm_.set_max_lock_memory(max_lock_memory);
|
||
|
}
|
||
|
|
||
|
size_t GetMaxLockMemory() override { return ltm_.get_max_lock_memory(); }
|
||
|
|
||
|
Counters GetStatus() override;
|
||
|
|
||
|
bool IsPointLockSupported() const override {
|
||
|
// One could have acquired a point lock (it is reduced to range lock)
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
PointLockStatus GetPointLockStatus() override;
|
||
|
|
||
|
// This is from LockManager
|
||
|
LockManager::RangeLockStatus GetRangeLockStatus() override;
|
||
|
|
||
|
// This has the same meaning as GetRangeLockStatus but is from
|
||
|
// RangeLockManagerHandle
|
||
|
RangeLockManagerHandle::RangeLockStatus GetRangeLockStatusData() override {
|
||
|
return GetRangeLockStatus();
|
||
|
}
|
||
|
|
||
|
bool IsRangeLockSupported() const override { return true; }
|
||
|
|
||
|
const LockTrackerFactory& GetLockTrackerFactory() const override {
|
||
|
return RangeTreeLockTrackerFactory::Get();
|
||
|
}
|
||
|
|
||
|
// Get the locktree which stores locks for the Column Family with given cf_id
|
||
|
std::shared_ptr<toku::locktree> GetLockTreeForCF(ColumnFamilyId cf_id);
|
||
|
|
||
|
void SetEscalationBarrierFunc(EscalationBarrierFunc func) override {
|
||
|
barrier_func_ = func;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
toku::locktree_manager ltm_;
|
||
|
|
||
|
EscalationBarrierFunc barrier_func_ =
|
||
|
[](const Endpoint&, const Endpoint&) -> bool { return false; };
|
||
|
|
||
|
std::shared_ptr<TransactionDBMutexFactory> mutex_factory_;
|
||
|
|
||
|
// Map from cf_id to locktree*. Can only be accessed while holding the
|
||
|
// ltree_map_mutex_. Must use a custom deleter that calls ltm_.release_lt
|
||
|
using LockTreeMap =
|
||
|
std::unordered_map<ColumnFamilyId, std::shared_ptr<toku::locktree>>;
|
||
|
LockTreeMap ltree_map_;
|
||
|
|
||
|
InstrumentedMutex ltree_map_mutex_;
|
||
|
|
||
|
// Per-thread cache of ltree_map_.
|
||
|
// (uses the same approach as TransactionLockMgr::lock_maps_cache_)
|
||
|
std::unique_ptr<ThreadLocalPtr> ltree_lookup_cache_;
|
||
|
|
||
|
RangeDeadlockInfoBuffer dlock_buffer_;
|
||
|
|
||
|
std::shared_ptr<toku::locktree> MakeLockTreePtr(toku::locktree* lt);
|
||
|
static int CompareDbtEndpoints(void* arg, const DBT* a_key, const DBT* b_key);
|
||
|
|
||
|
// Callbacks
|
||
|
static int on_create(toku::locktree*, void*);
|
||
|
static void on_destroy(toku::locktree*) {}
|
||
|
static void on_escalate(TXNID txnid, const toku::locktree* lt,
|
||
|
const toku::range_buffer& buffer, void* extra);
|
||
|
|
||
|
static bool OnEscalationBarrierCheck(const DBT* a, const DBT* b, void* extra);
|
||
|
};
|
||
|
|
||
|
void serialize_endpoint(const Endpoint& endp, std::string* buf);
|
||
|
void wait_callback_for_locktree(void* cdata, toku::lock_wait_infos* infos);
|
||
|
|
||
|
} // namespace ROCKSDB_NAMESPACE
|
||
|
#endif // OS_WIN
|