Class LockManager

java.lang.Object
io.permazen.kv.simple.LockManager

public class LockManager extends Object
Manager of read/write locks on byte[] key ranges that ensures isolation and serialization while allowing concurrent access by multiple threads to a single underlying byte[] key/value store.

This implementation is straightforward: read locks can overlap, but write locks may not, and all locks owned by the same owner remain in force until all are released at the same time.

Instances are configured with a monitor object which is used for all internal locking and inter-thread wait/notify handshaking (by default, this instance). A user-supplied monitor object may be provided via the constructor.

Two timeout values are supported:

  • The wait timeout (specified as a parameter to lock()) limits how long a thread will wait on a lock held by another thread before giving up
  • The hold timeout limits how long a thread may hold on to a contested lock before being forced to release all its locks; after that, the next call to lock or release will fail

Note that if the hold timeout is set to zero (unlimited), then an application bug that leaks locks will result in those locks never being released.

  • Constructor Details

    • LockManager

      public LockManager()
      Convenience constructor. Equivalent to LockManager(null).
    • LockManager

      public LockManager(Object lockObject)
      Primary constructor.
      Parameters:
      lockObject - Java object used to synchronize field access and inter-thread wait/notify handshake, or null to use this instance
  • Method Details

    • getHoldTimeout

      public long getHoldTimeout()
      Get the hold timeout configured for this instance.

      The hold timeout limits how long a thread may hold on to a contested lock before being forced to release all of its locks; after that, the next call to lock or release will fail.

      Returns:
      hold timeout in milliseconds
    • setHoldTimeout

      public void setHoldTimeout(long holdTimeout)
      Set the hold timeout for this instance. Default is zero (unlimited).
      Parameters:
      holdTimeout - how long a thread may hold a contested lock before LockManager.LockResult.HOLD_TIMEOUT_EXPIRED will be returned by lock() or release() in milliseconds, or zero for unlimited
      Throws:
      IllegalArgumentException - if holdTimeout is negative
    • lock

      public LockManager.LockResult lock(LockOwner owner, byte[] minKey, byte[] maxKey, boolean write, long waitTimeout) throws InterruptedException
      Acquire a lock on behalf of the specified owner.

      This method will block for up to waitTimeout milliseconds if the lock is held by another thread, after which point LockManager.LockResult.WAIT_TIMEOUT_EXPIRED is returned. The configured locking object will be used for inter-thread wait/notify handshaking.

      If owner already holds one or more locks, but the hold timeout has expired, then LockManager.LockResult.HOLD_TIMEOUT_EXPIRED is returned and all of the other locks are will have already been automatically released.

      Once a lock is successfully acquired, it stays acquired until all locks are released together via release().

      Parameters:
      owner - lock owner
      minKey - minimum key (inclusive); must not be null
      maxKey - maximum key (exclusive), or null for no maximum
      write - true for a write lock, false for a read lock
      waitTimeout - how long to wait before returning LockManager.LockResult.WAIT_TIMEOUT_EXPIRED in milliseconds, or zero for unlimited
      Returns:
      a LockManager.LockResult
      Throws:
      InterruptedException - if the current thread is interrupted while waiting for the lock
      IllegalArgumentException - if owner, minKey, or range is null
      IllegalArgumentException - if minKey > maxKey
      IllegalArgumentException - if waitTimeout is negative
    • isLocked

      public boolean isLocked(LockOwner owner, byte[] minKey, byte[] maxKey, boolean write)
      Determine if the given lock owner holds a lock on the specified range.
      Parameters:
      owner - lock owner
      minKey - minimum key (inclusive); must not be null
      maxKey - maximum key (exclusive), or null for no maximum
      write - if range must be write locked; if false, may be either read or write locked
      Returns:
      true if the range is locked for writes by owner
    • release

      public boolean release(LockOwner owner)
      Release all locks held by the specified owner.

      If the owner's hold timeout has already expired, then all locks will have already been released and false is returned.

      Does nothing (and returns true) if owner does not own any locks.

      Parameters:
      owner - lock owner
      Returns:
      true if successful, false if owner's hold timeout expired
      Throws:
      IllegalArgumentException - if owner is null
    • checkHoldTimeout

      public long checkHoldTimeout(LockOwner owner)
      Check whether the hold timeout has expired for the given lock owner and if not return the amount of time remaining.

      If the owner's hold timeout has expired, then -1 is returned and any locks previously held by owner will have been automatically released.

      Parameters:
      owner - lock owner
      Returns:
      milliseconds until owner's hold timeout expires, zero if owner has no hold timeout (e.g., nothing is locked or hold timeout disabled), or -1 if owner's hold timeout has expired
      Throws:
      IllegalArgumentException - if owner is null