d8bd9fc7b3
Summary: This PR has two commits: 1. Modify the code to allow different Lock Managers (of any kind) to be used. It is implied that a LockManager uses its own custom LockTracker. 2. Add definitions for Range Locking (class Endpoint and GetRangeLock() function. cheng-chang, is this what you've had in mind (should the PR have both item 1 and item 2?) Pull Request resolved: https://github.com/facebook/rocksdb/pull/7443 Reviewed By: zhichao-cao Differential Revision: D24123172 Pulled By: cheng-chang fbshipit-source-id: c6548ad6d4cc3c25f68d13b29147bc6fdf357185
210 lines
6.7 KiB
C++
210 lines
6.7 KiB
C++
// 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 <memory>
|
|
|
|
#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
|