1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #pragma once
7 #ifndef ROCKSDB_LITE
8 #ifndef OS_WIN
9 
10 // For DeadlockInfoBuffer:
11 #include "util/thread_local.h"
12 #include "utilities/transactions/lock/point/point_lock_manager.h"
13 #include "utilities/transactions/lock/range/range_lock_manager.h"
14 
15 // Lock Tree library:
16 #include "utilities/transactions/lock/range/range_tree/lib/locktree/lock_request.h"
17 #include "utilities/transactions/lock/range/range_tree/lib/locktree/locktree.h"
18 #include "utilities/transactions/lock/range/range_tree/range_tree_lock_tracker.h"
19 
20 namespace ROCKSDB_NAMESPACE {
21 
22 using namespace toku;
23 
24 typedef DeadlockInfoBufferTempl<RangeDeadlockPath> RangeDeadlockInfoBuffer;
25 
26 // A Range Lock Manager that uses PerconaFT's locktree library
27 class RangeTreeLockManager : public RangeLockManagerBase,
28                              public RangeLockManagerHandle {
29  public:
getLockManager()30   LockManager* getLockManager() override { return this; }
31 
32   void AddColumnFamily(const ColumnFamilyHandle* cfh) override;
33   void RemoveColumnFamily(const ColumnFamilyHandle* cfh) override;
34 
35   void Resize(uint32_t) override;
36   std::vector<DeadlockPath> GetDeadlockInfoBuffer() override;
37 
38   std::vector<RangeDeadlockPath> GetRangeDeadlockInfoBuffer() override;
39   void SetRangeDeadlockInfoBufferSize(uint32_t target_size) override;
40 
41   // Get a lock on a range
42   //  @note only exclusive locks are currently supported (requesting a
43   //  non-exclusive lock will get an exclusive one)
44   using LockManager::TryLock;
45   Status TryLock(PessimisticTransaction* txn, ColumnFamilyId column_family_id,
46                  const Endpoint& start_endp, const Endpoint& end_endp, Env* env,
47                  bool exclusive) override;
48 
49   void UnLock(PessimisticTransaction* txn, const LockTracker& tracker,
50               Env* env) override;
51   void UnLock(PessimisticTransaction* txn, ColumnFamilyId column_family_id,
52               const std::string& key, Env* env) override;
UnLock(PessimisticTransaction *,ColumnFamilyId,const Endpoint &,const Endpoint &,Env *)53   void UnLock(PessimisticTransaction*, ColumnFamilyId, const Endpoint&,
54               const Endpoint&, Env*) override {
55     // TODO: range unlock does nothing...
56   }
57 
58   explicit RangeTreeLockManager(
59       std::shared_ptr<TransactionDBMutexFactory> mutex_factory);
60 
61   ~RangeTreeLockManager() override;
62 
SetMaxLockMemory(size_t max_lock_memory)63   int SetMaxLockMemory(size_t max_lock_memory) override {
64     return ltm_.set_max_lock_memory(max_lock_memory);
65   }
66 
GetMaxLockMemory()67   size_t GetMaxLockMemory() override { return ltm_.get_max_lock_memory(); }
68 
69   Counters GetStatus() override;
70 
IsPointLockSupported()71   bool IsPointLockSupported() const override {
72     // One could have acquired a point lock (it is reduced to range lock)
73     return true;
74   }
75 
76   PointLockStatus GetPointLockStatus() override;
77 
78   // This is from LockManager
79   LockManager::RangeLockStatus GetRangeLockStatus() override;
80 
81   // This has the same meaning as GetRangeLockStatus but is from
82   // RangeLockManagerHandle
GetRangeLockStatusData()83   RangeLockManagerHandle::RangeLockStatus GetRangeLockStatusData() override {
84     return GetRangeLockStatus();
85   }
86 
IsRangeLockSupported()87   bool IsRangeLockSupported() const override { return true; }
88 
GetLockTrackerFactory()89   const LockTrackerFactory& GetLockTrackerFactory() const override {
90     return RangeTreeLockTrackerFactory::Get();
91   }
92 
93   // Get the locktree which stores locks for the Column Family with given cf_id
94   std::shared_ptr<locktree> GetLockTreeForCF(ColumnFamilyId cf_id);
95 
96  private:
97   toku::locktree_manager ltm_;
98 
99   std::shared_ptr<TransactionDBMutexFactory> mutex_factory_;
100 
101   // Map from cf_id to locktree*. Can only be accessed while holding the
102   // ltree_map_mutex_. Must use a custom deleter that calls ltm_.release_lt
103   using LockTreeMap =
104       std::unordered_map<ColumnFamilyId, std::shared_ptr<locktree>>;
105   LockTreeMap ltree_map_;
106 
107   InstrumentedMutex ltree_map_mutex_;
108 
109   // Per-thread cache of ltree_map_.
110   // (uses the same approach as TransactionLockMgr::lock_maps_cache_)
111   std::unique_ptr<ThreadLocalPtr> ltree_lookup_cache_;
112 
113   RangeDeadlockInfoBuffer dlock_buffer_;
114 
115   std::shared_ptr<locktree> MakeLockTreePtr(locktree* lt);
116   static int CompareDbtEndpoints(void* arg, const DBT* a_key, const DBT* b_key);
117 
118   // Callbacks
on_create(locktree *,void *)119   static int on_create(locktree*, void*) { return 0; /* no error */ }
on_destroy(locktree *)120   static void on_destroy(locktree*) {}
121   static void on_escalate(TXNID txnid, const locktree* lt,
122                           const range_buffer& buffer, void* extra);
123 };
124 
125 void serialize_endpoint(const Endpoint& endp, std::string* buf);
126 void wait_callback_for_locktree(void* cdata, lock_wait_infos* infos);
127 
128 }  // namespace ROCKSDB_NAMESPACE
129 #endif  // OS_WIN
130 #endif  // ROCKSDB_LITE
131