Interface KVTransaction
- All Superinterfaces:
KVStore
- All Known Implementing Classes:
ArrayKVTransaction
,BerkeleyKVTransaction
,BranchedKVTransaction
,ByteArrayLMDBKVTransaction
,CachingKVTransaction
,FallbackKVTransaction
,FoundationKVTransaction
,LevelDBKVTransaction
,LMDBKVTransaction
,MVStoreKVTransaction
,PrefixKVTransaction
,RaftKVTransaction
,SimpleKVTransaction
,SnapshotKVTransaction
,SpannerKVTransaction
,SQLKVTransaction
,XMLKVTransaction
,XodusKVTransaction
KVDatabase
transaction API.
Provides a transactional view of a KVStore
.
Instances may throw KVTransactionException
during any operation if the transaction cannot be continued.
In particular, StaleKVTransactionException
is thrown by a transaction that is no longer open, and
RetryKVTransactionException
is thrown when the transaction should be retried due to a transient
problem (such as a write conflict with another transaction).
When RetryKVTransactionException
is thrown by commit()
, the transaction may have actually been committed.
Therefore, transactions should be written to be idempotent.
No matter what state it is in, instances must support invoking rollback()
at any time.
If an instance throws a KVTransactionException
, the transaction should be implicitly rolled back.
Any subsequent operation other than rollback()
should throw StaleKVTransactionException
.
Except for rollback()
and methods that just query status, implementations must throw StaleKVTransactionException
if commit()
or rollback()
has already been invoked, or if the KVTransaction
instance is no longer usable
for some other reason. In particular, implementations should throw KVTransactionTimeoutException
if an operation
is attempted on a transaction that has been held open past some maximum allowed time limit.
Implementations are responsible for ensuring modifications to byte[]
arrays after method
invocations do no harm. This usually means byte[]
array parameters and return values must be copied.
Implementations are not required to support accessing keys that start with 0xff
,
and if not may throw IllegalArgumentException
if such keys are accessed.
Note: for some implementations, the data read from a transaction that is never commit()
'ed is
not guaranteed to be up to date.
-
Method Summary
Modifier and TypeMethodDescriptionvoid
commit()
Commit this transaction.Get theKVDatabase
with which this instance is associated.boolean
Determine whether this transaction is read-only.Create a read-only snapshot of the database content represented by this transaction.void
rollback()
Cancel this transaction, if not already canceled.void
setReadOnly
(boolean readOnly) Enable or disable read-only mode.void
setTimeout
(long timeout) Change the timeout for this transaction from its default value (optional operation).watchKey
(byte[] key) Watch a key to monitor for changes in its value.default void
withWeakConsistency
(Runnable action) Apply weaker transaction consistency while performing the given action, if supported.Methods inherited from interface io.permazen.kv.KVStore
adjustCounter, apply, decodeCounter, encodeCounter, get, getAtLeast, getAtMost, getRange, getRange, getRange, put, remove, removeRange, removeRange
-
Method Details
-
getKVDatabase
KVDatabase getKVDatabase()Get theKVDatabase
with which this instance is associated.- Returns:
- associated database
-
setTimeout
void setTimeout(long timeout) Change the timeout for this transaction from its default value (optional operation).- Parameters:
timeout
- transaction timeout in milliseconds, or zero for unlimited- Throws:
UnsupportedOperationException
- if this transaction does not support timeoutsIllegalArgumentException
- iftimeout
is negativeStaleKVTransactionException
- if this transaction is no longer usable
-
isReadOnly
boolean isReadOnly()Determine whether this transaction is read-only.Default is false.
- Returns:
- true if this instance is read-only
- Throws:
StaleKVTransactionException
- if this transaction is no longer usable
-
setReadOnly
void setReadOnly(boolean readOnly) Enable or disable read-only mode.Read-only transactions allow mutations, but all changes are discarded on
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
IllegalStateException
is thrown.Note: for some implementations, the data read from a transaction that is never
commit()
'ed is not guaranteed to be up to date, even if that transaction is read-only.Default is false.
- Parameters:
readOnly
- read-only setting- Throws:
IllegalStateException
- if the implementation doesn't support changing read-only status at this timeStaleKVTransactionException
- if this transaction is no longer usable
-
watchKey
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 returnedFuture
completes if and when a different value forkey
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 aKVDatabase
isKVDatabase.stop()
'ed, all outstanding key watches are implicitlycancel()
'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 singleCounter
field, whose key is then watched (to determine the key corresponding to a Java model object field, usePermazenField.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
Future
s associated with failed transactions complete, so theFuture
s 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 aListenableFuture
. However, listeners must not perform any long running or blocking operations. Also, because the semantics ofRetryKVTransactionException
allow for the possibility that the transaction actually did commit, "duplicate" listener notifications could occur.Key watch
Future
s that have not completed yet, but are no longer needed, must becancel()
'ed to avoid memory leaks.Key watch support is indepdendent of whether the transaction is read-only.
- Parameters:
key
- the key to watch- Returns:
- a
Future
that returnskey
when the value associated withkey
is modified - Throws:
StaleKVTransactionException
- if this transaction is no longer usableRetryKVTransactionException
- if this transaction must be retried and is no longer usableKVDatabaseException
- if an unexpected error occursUnsupportedOperationException
- if this instance does not support key watchesIllegalArgumentException
- ifkey
starts with0xff
and such keys are not supportedIllegalArgumentException
- ifkey
is null- See Also:
-
commit
void commit()Commit this transaction.Note that if this method throws a
RetryKVTransactionException
, 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
commit()
'ed in order for the data accessed during the transaction to be guaranteed to be up to date.- Throws:
StaleKVTransactionException
- if this transaction is no longer usableRetryKVTransactionException
- if this transaction must be retried and is no longer usable
-
rollback
void rollback()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
commit()
orrollback()
, in which case the invocation will be ignored. In particular, this method must not throwStaleKVTransactionException
. -
withWeakConsistency
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 performsaction
normally.- Parameters:
action
- the action to perform- Throws:
IllegalArgumentException
- ifaction
is null
-
readOnlySnapshot
CloseableKVStore readOnlySnapshot()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 returnedCloseableKVStore
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 promplyclose()
'd when no longer needed to release any underlying resources. In particular, the caller must ensure that theCloseableKVStore
isclose()
'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.- Returns:
- independent, read-only copy of this transaction's entire database content
- Throws:
UnsupportedOperationException
- if this method is not supportedStaleKVTransactionException
- if this transaction is no longer usableRetryKVTransactionException
- if this transaction must be retried and is no longer usable
-