Class SimpleKVDatabase

java.lang.Object
io.permazen.kv.simple.SimpleKVDatabase
All Implemented Interfaces:
KVDatabase, Serializable
Direct Known Subclasses:
MemoryKVDatabase

public class SimpleKVDatabase extends Object implements KVDatabase, Serializable
Simple implementation of the KVDatabase interface that provides a concurrent, transactional view of an underlying AtomicKVStore with strong ACID semantics (assuming Atomicity and Durability are provided by the underlying AtomicKVStore).

Transaction isolation is implemented via key range locking using a LockManager. Conflicting access will block, subject to the wait timeout and hold timeout. If the wait timeout is exceeded, a RetryTransactionException is thrown. If the hold timeout is exceeded, a TransactionTimeoutException is thrown.

Instances wrap an underlying AtomicKVStore which from which committed data is read and written. During a transaction, all mutations are recorded in memory; if/when the transaction is committed, those mutations are applied to the AtomicKVStore all at once via AtomicKVStore.apply(). This commit operation is bracketed by calls to preCommit() and postCommit().

Key watches are supported.

Instances implement Serializable if the underlying AtomicKVStore is; this is the case when the default constructor, which uses a MemoryKVStore, is used. However, key watches and open transactions are not remembered across a (de)serialization cycle.

For a simple in-memory implementation, see MemoryKVDatabase.

See Also:
  • Field Details

  • Constructor Details

  • Method Details

    • getWaitTimeout

      public long getWaitTimeout()
      Get the wait timeout for newly created transactions.

      The wait timeout limits how long a thread will wait for a contested lock before giving up and throwing RetryTransactionException.

      Returns:
      wait timeout in milliseconds
    • setWaitTimeout

      public void setWaitTimeout(long waitTimeout)
      Set the wait timeout for newly created transactions. Default is DEFAULT_WAIT_TIMEOUT.
      Parameters:
      waitTimeout - how long a thread will wait for a lock before throwing RetryTransactionException in milliseconds (default), or zero for unlimited
      Throws:
      IllegalArgumentException - if waitTimeout is negative
    • 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 attempted operation will fail with RetryTransactionException.

      Returns:
      hold timeout in milliseconds
    • setHoldTimeout

      public void setHoldTimeout(long holdTimeout)
      Set the hold timeout for this instance. Default is DEFAULT_HOLD_TIMEOUT.
      Parameters:
      holdTimeout - how long a thread may hold a contested lock before throwing RetryTransactionException in milliseconds, or zero for unlimited
      Throws:
      IllegalArgumentException - if holdTimeout is negative
    • start

      @PostConstruct public void start()
      Description copied from interface: KVDatabase
      Start this instance. This method must be called prior to creating any transactions.

      This method is idempotent: if this instance is already started, nothing happens.

      Whether an instance that has been started and stopped can be restarted is implementation-dependent.

      Specified by:
      start in interface KVDatabase
    • stop

      @PreDestroy public void stop()
      Description copied from interface: KVDatabase
      Stop this instance.

      This method is idempotent: if this instance has not been started, or is already stopped, nothing happens.

      Specified by:
      stop in interface KVDatabase
    • createTransaction

      public SimpleKVTransaction createTransaction(Map<String,?> options)
      Description copied from interface: KVDatabase
      Create a new transaction with the specified options.
      Specified by:
      createTransaction in interface KVDatabase
      Parameters:
      options - optional transaction options; may be null
      Returns:
      newly created transaction
    • createTransaction

      public SimpleKVTransaction createTransaction()
      Description copied from interface: KVDatabase
      Create a new transaction.
      Specified by:
      createTransaction in interface KVDatabase
      Returns:
      newly created transaction
    • preCommit

      protected void preCommit(SimpleKVTransaction tx)
      Invoked during transaction commit just prior to writing changes to the underlying AtomicKVStore.

      SimpleKVDatabase guarantees this method and postCommit() will be invoked in matching pairs, and that this instance will be locked when these methods are invoked.

      The implementation in SimpleKVDatabase does nothing.

      Parameters:
      tx - the transaction about to be committed
      Throws:
      RetryTransactionException - if this transaction must be retried and is no longer usable
    • postCommit

      protected void postCommit(SimpleKVTransaction tx, boolean successful)
      Invoked during transaction commit just after writing changes to the underlying AtomicKVStore.

      SimpleKVDatabase guarantees this method and preCommit() will be invoked in matching pairs, and that this instance will be locked when these methods are invoked.

      This method is invoked even if the underlying AtomicKVStore throws an exception while changes were being written to it. In that case, successful will be false.

      The implementation in SimpleKVDatabase does nothing.

      Parameters:
      tx - the transaction that was committed
      successful - true if all changes were written back successfully, false if the underlying AtomicKVStore threw an exception during commit update
    • checkState

      protected void checkState(SimpleKVTransaction tx)
      Verify that the given transaction is still usable.

      This method is invoked at the start of the AtomicKVStore data access and commit() methods of the SimpleKVTransaction associated with this instance. This allows for any checks which depend on a consistent view of the transaction and database together. This instance's lock will be held when this method is invoked. Note: transaction state is also protected by this instance's lock.

      The implementation in SimpleKVDatabase does nothing.

      Parameters:
      tx - the transaction being accessed
      Throws:
      StaleTransactionException - if this instance is no longer usable
      RetryTransactionException - if this transaction should be retried
      TransactionTimeoutException - if the transaction has timed out