Class SnapshotKVTransaction

java.lang.Object
io.permazen.kv.util.ForwardingKVStore
io.permazen.kv.mvcc.SnapshotKVTransaction
All Implemented Interfaces:
KVStore, KVTransaction, Closeable, AutoCloseable
Direct Known Subclasses:
ArrayKVTransaction, LevelDBKVTransaction, MVStoreKVTransaction

@ThreadSafe public class SnapshotKVTransaction extends ForwardingKVStore implements KVTransaction, Closeable
SnapshotKVDatabase transaction.
  • Constructor Details

    • SnapshotKVTransaction

      protected SnapshotKVTransaction(SnapshotKVDatabase kvdb, MutableView view, long baseVersion)
      Constructor.
      Parameters:
      kvdb - the associated database
      view - mutable view to be used for this transaction
      baseVersion - the database version associated with base
  • Method Details

    • getBaseVersion

      public long getBaseVersion()
      Get the MVCC database version number on which this instance is (or was originally) based.
      Returns:
      transaction base version number
    • getCommitVersion

      public long getCommitVersion()
      Get the MVCC database version number representing this transaction's successful commit, if any.
      Returns:
      transaction commit version number, or zero if transaction is read-only or not committed
    • getMutableView

      public MutableView getMutableView()
      Get the MutableView associated with this instance.
      Returns:
      associated access and mutation state
    • delegate

      protected KVStore delegate()
      Get the underlying KVStore.

      The implementation in SnapshotKVTransaction returns the MutableView associated with this instance.

      Specified by:
      delegate in class ForwardingKVStore
      Returns:
      the underlying KVStore
      Throws:
      StaleTransactionException - if this transaction is no longer valid
      TransactionTimeoutException - if this transaction has timed out
    • getKVDatabase

      public SnapshotKVDatabase getKVDatabase()
      Description copied from interface: KVTransaction
      Get the KVDatabase with which this instance is associated.
      Specified by:
      getKVDatabase in interface KVTransaction
      Returns:
      associated database
    • setTimeout

      public void setTimeout(long timeout)
      Set the transaction timeout.

      SnapshotKVTransactions do not perform any locking while the transaction is open. Therefore, the configured value is used instead as a timeout on the overall transaction duration. If the transaction is kept open for longer than timeout milliseconds, a TransactionTimeoutException will be thrown.

      Specified by:
      setTimeout in interface KVTransaction
      Parameters:
      timeout - transaction timeout in milliseconds, or zero for unlimited
      Throws:
      IllegalArgumentException - if timeout is negative
    • watchKey

      public ListenableFuture<Void> watchKey(byte[] key)
      Description copied from interface: KVTransaction
      Watch a key to monitor for changes in its value.

      When this method is invoked, key's current value (if any) as read by this transaction is remembered. The returned Future completes if and when a different value for key is subsequently committed by some transaction, including possibly this one. This includes creation or deletion of the key.

      Key watches outlive the transaction in which they are created, persisting until they complete or are cancel()'ed. When a KVDatabase is KVDatabase.stop()'ed, all outstanding key watches are implicitly cancel()'ed.

      Caveats

      Key watches are not without overhead; applications should avoid overuse. For example, consider creating a single key that is used to consolidate modifications to some set of keys; at the Permazen layer, modification to multiple objects and/or fields can detected and consolidated using an @OnChange method that increments a single Counter field, whose key is then watched (to determine the key corresponding to a Java model object field, use PermazenField.getKey()).

      Conceptually, detection of changes behaves as if by a background thread that periodically creates a new transaction and reads the key's value (the actual implementation will likely be more efficient). This means a change that is quickly reverted could be missed, and that multiple changes could occur before notification. In addition, spurious notifications may occur, where the key's value has not changed.

      A key watch is only guaranteed to be valid if the transaction in which it was created successfully commits. In particular, nothing is specified about how or whether Futures associated with failed transactions complete, so the Futures returned by this method should not be relied on until after a successful commit (perhaps with the help of a transaction callback).

      Key watch support is optional; instances that don't support key watches throw UnsupportedOperationException. Some implementations may only support watching a key that already exists.

      Note: many KVDatabase implementations actually return a ListenableFuture. However, listeners must not perform any long running or blocking operations. Also, because the semantics of RetryTransactionException allow for the possibility that the transaction actually did commit, "duplicate" listener notifications could occur.

      Key watch Futures that have not completed yet, but are no longer needed, must be cancel()'ed to avoid memory leaks.

      Key watch support is indepdendent of whether the transaction is read-only.

      Specified by:
      watchKey in interface KVTransaction
      Parameters:
      key - the key to watch
      Returns:
      a Future that returns key when the value associated with key is modified
      See Also:
    • isReadOnly

      public boolean isReadOnly()
      Description copied from interface: KVTransaction
      Determine whether this transaction is read-only.

      Default is false.

      Specified by:
      isReadOnly in interface KVTransaction
      Returns:
      true if this instance is read-only
    • setReadOnly

      public void setReadOnly(boolean readOnly)
      Description copied from interface: KVTransaction
      Enable or disable read-only mode.

      Read-only transactions allow mutations, but all changes are discarded on KVTransaction.commit().

      Some implementations may impose one or more of the following restrictions on this method:

      • setReadOnly() may only be invoked prior to accessing data;
      • setReadOnly() may only be invoked prior to mutating data; and/or
      • Once set to read-only, a transaction may not be set back to read-write
      If one of the above constraints is violated, an IllegalStateException is thrown.

      Note: for some implementations, the data read from a transaction that is never KVTransaction.commit()'ed is not guaranteed to be up to date, even if that transaction is read-only.

      Default is false.

      Specified by:
      setReadOnly in interface KVTransaction
      Parameters:
      readOnly - read-only setting
    • commit

      public void commit()
      Description copied from interface: KVTransaction
      Commit this transaction.

      Note that if this method throws a RetryTransactionException, the transaction was either successfully committed or rolled back. In either case, this instance is no longer usable.

      Note also for some implementations, even read-only transactions must be KVTransaction.commit()'ed in order for the data accessed during the transaction to be guaranteed to be up to date.

      Specified by:
      commit in interface KVTransaction
    • rollback

      public void rollback()
      Description copied from interface: KVTransaction
      Cancel this transaction, if not already canceled.

      After this method returns, this instance is no longer usable.

      Note: for some implementations, rolling back a transaction invalidates guarantees about the the data read during the transaction being up to date, even if the transaction was setReadOnly().

      This method may be invoked at any time, even after a previous invocation of KVTransaction.commit() or KVTransaction.rollback(), in which case the invocation will be ignored. In particular, this method must not throw StaleTransactionException.

      Specified by:
      rollback in interface KVTransaction
    • withWeakConsistency

      public void withWeakConsistency(Runnable action)
      Description copied from interface: KVTransaction
      Apply weaker transaction consistency while performing the given action, if supported.

      Some implementations support reads with weaker consistency guarantees. These reads generate fewer transaction conflicts but return possibly out-of-date information. Depending on the implementation, when operating in this mode writes may not be supported and may generate an IllegalStateException or just be ignored.

      The weaker consistency is only applied for the current thread, and it ends when this method returns.

      This method is for experts only; inappropriate use can result in a corrupted database. You should not make any changes to the database after this method returns based on any information read by the action.

      The implementation in KVTransaction just performs action normally.

      Specified by:
      withWeakConsistency in interface KVTransaction
      Parameters:
      action - the action to perform
    • readOnlySnapshot

      public CloseableKVStore readOnlySnapshot()
      Description copied from interface: KVTransaction
      Create a read-only snapshot of the database content represented by this transaction.

      The returned CloseableKVStore should be treated as read-only. It may not actually be read-only, but if it's not, then any changes should have no effect on this instance. The returned CloseableKVStore must be completely independent from this transaction (subsequent changes to either one do not affect the other).

      Note: as with any other information extracted from a KVTransaction, the returned content should not be considered valid until this transaction has been successfully committed.

      The returned CloseableKVStore should be promply close()'d when no longer needed to release any underlying resources. In particular, the caller must ensure that the CloseableKVStore is close()'d even if this transaction's commit fails. This may require adding a transaction synchronization callback, etc.

      This is an optional method; only some underlying key/value store technologies can efficiently support it. Implementations should throw UnsupportedOperationException if not supported.

      Specified by:
      readOnlySnapshot in interface KVTransaction
      Returns:
      independent, read-only copy of this transaction's entire database content
    • close

      public void close()
      Close this instance.

      Equivalent to invoking rollback().

      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • finalize

      protected void finalize() throws Throwable
      Overrides:
      finalize in class Object
      Throws:
      Throwable