// 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 ROCKSDB_LITE #include #include "rocksdb/rocksdb_namespace.h" #include "rocksdb/status.h" #include "rocksdb/types.h" #include "rocksdb/utilities/transaction_db.h" namespace ROCKSDB_NAMESPACE { // Request for locking a single key. struct PointLockRequest { // The id of the key's column family. ColumnFamilyId column_family_id = 0; // The key to lock. std::string key; // The sequence number from which there is no concurrent update to key. SequenceNumber seq = 0; // Whether the lock is acquired only for read. bool read_only = false; // Whether the lock is in exclusive mode. bool exclusive = true; }; // Request for locking a range of keys. struct RangeLockRequest { // The id of the key's column family. ColumnFamilyId column_family_id; // The range to be locked Endpoint start_endp; Endpoint end_endp; }; struct PointLockStatus { // Whether the key is locked. bool locked = false; // Whether the key is locked in exclusive mode. bool exclusive = true; // The sequence number in the tracked PointLockRequest. SequenceNumber seq = 0; }; // Return status when calling LockTracker::Untrack. enum class UntrackStatus { // The lock is not tracked at all, so no lock to untrack. NOT_TRACKED, // The lock is untracked but not removed from the tracker. UNTRACKED, // The lock is removed from the tracker. REMOVED, }; // Tracks the lock requests. // In PessimisticTransaction, it tracks the locks acquired through LockMgr; // In OptimisticTransaction, since there is no LockMgr, it tracks the lock // intention. Not thread-safe. class LockTracker { public: virtual ~LockTracker() {} // Whether supports locking a specific key. virtual bool IsPointLockSupported() const = 0; // Whether supports locking a range of keys. virtual bool IsRangeLockSupported() const = 0; // Tracks the acquirement of a lock on key. // // If this method is not supported, leave it as a no-op. virtual void Track(const PointLockRequest& /*lock_request*/) = 0; // Untracks the lock on a key. // seq and exclusive in lock_request are not used. // // If this method is not supported, leave it as a no-op and // returns NOT_TRACKED. virtual UntrackStatus Untrack(const PointLockRequest& /*lock_request*/) = 0; // Counterpart of Track(const PointLockRequest&) for RangeLockRequest. virtual void Track(const RangeLockRequest& /*lock_request*/) = 0; // Counterpart of Untrack(const PointLockRequest&) for RangeLockRequest. virtual UntrackStatus Untrack(const RangeLockRequest& /*lock_request*/) = 0; // Merges lock requests tracked in the specified tracker into the current // tracker. // // E.g. for point lock, if a key in tracker is not yet tracked, // track this new key; otherwise, merge the tracked information of the key // such as lock's exclusiveness, read/write statistics. // // If this method is not supported, leave it as a no-op. // // REQUIRED: the specified tracker must be of the same concrete class type as // the current tracker. virtual void Merge(const LockTracker& /*tracker*/) = 0; // This is a reverse operation of Merge. // // E.g. for point lock, if a key exists in both current and the sepcified // tracker, then subtract the information (such as read/write statistics) of // the key in the specified tracker from the current tracker. // // If this method is not supported, leave it as a no-op. // // REQUIRED: // The specified tracker must be of the same concrete class type as // the current tracker. // The tracked locks in the specified tracker must be a subset of those // tracked by the current tracker. virtual void Subtract(const LockTracker& /*tracker*/) = 0; // Clears all tracked locks. virtual void Clear() = 0; // Gets the new locks (excluding the locks that have been tracked before the // save point) tracked since the specified save point, the result is stored // in an internally constructed LockTracker and returned. // // save_point_tracker is the tracker used by a SavePoint to track locks // tracked after creating the SavePoint. // // The implementation should document whether point lock, or range lock, or // both are considered in this method. // If this method is not supported, returns nullptr. // // REQUIRED: // The save_point_tracker must be of the same concrete class type as the // current tracker. // The tracked locks in the specified tracker must be a subset of those // tracked by the current tracker. virtual LockTracker* GetTrackedLocksSinceSavePoint( const LockTracker& /*save_point_tracker*/) const = 0; // Gets lock related information of the key. // // If point lock is not supported, always returns LockStatus with // locked=false. virtual PointLockStatus GetPointLockStatus( ColumnFamilyId /*column_family_id*/, const std::string& /*key*/) const = 0; // Gets number of tracked point locks. // // If point lock is not supported, always returns 0. virtual uint64_t GetNumPointLocks() const = 0; class ColumnFamilyIterator { public: virtual ~ColumnFamilyIterator() {} // Whether there are remaining column families. virtual bool HasNext() const = 0; // Gets next column family id. // // If HasNext is false, calling this method has undefined behavior. virtual ColumnFamilyId Next() = 0; }; // Gets an iterator for column families. // // Returned iterator must not be nullptr. // If there is no column family to iterate, // returns an empty non-null iterator. // Caller owns the returned pointer. virtual ColumnFamilyIterator* GetColumnFamilyIterator() const = 0; class KeyIterator { public: virtual ~KeyIterator() {} // Whether there are remaining keys. virtual bool HasNext() const = 0; // Gets the next key. // // If HasNext is false, calling this method has undefined behavior. virtual const std::string& Next() = 0; }; // Gets an iterator for keys with tracked point locks in the column family. // // The column family must exist. // Returned iterator must not be nullptr. // Caller owns the returned pointer. virtual KeyIterator* GetKeyIterator( ColumnFamilyId /*column_family_id*/) const = 0; }; // LockTracker should always be constructed through this factory. // Each LockManager owns a LockTrackerFactory. class LockTrackerFactory { public: // Caller owns the returned pointer. virtual LockTracker* Create() const = 0; virtual ~LockTrackerFactory() {} }; } // namespace ROCKSDB_NAMESPACE #endif // ROCKSDB_LITE