@ThreadSafe public class SnapshotKVTransaction extends ForwardingKVStore implements KVTransaction, ReadTracking, Closeable
SnapshotKVDatabase
transaction.Modifier | Constructor and Description |
---|---|
protected |
SnapshotKVTransaction(SnapshotKVDatabase kvdb,
MutableView view,
long baseVersion)
Constructor.
|
Modifier and Type | Method and Description |
---|---|
void |
close()
Close this instance.
|
void |
commit()
Commit this transaction.
|
protected KVStore |
delegate()
Get the underlying
KVStore . |
protected void |
finalize() |
long |
getBaseVersion()
Get the MVCC database version number on which this instance is (or was originally) based.
|
long |
getCommitVersion()
Get the MVCC database version number representing this transaction's successful commit, if any.
|
SnapshotKVDatabase |
getKVDatabase()
Get the
KVDatabase with which this instance is associated. |
MutableView |
getMutableView()
Get the
MutableView associated with this instance. |
AtomicBoolean |
getReadTrackingControl()
Get an
AtomicBoolean that can be used to temporarily pause/un-pause read tracking. |
boolean |
isReadOnly()
Determine whether this transaction is read-only.
|
CloseableKVStore |
mutableSnapshot()
Create a mutable copy 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)
Set the transaction timeout.
|
String |
toString() |
ListenableFuture<Void> |
watchKey(byte[] key)
Watch a key to monitor for changes in its value.
|
adjustCounter, apply, decodeCounter, encodeCounter, get, getAtLeast, getAtMost, getRange, put, remove, removeRange
clone, equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
adjustCounter, apply, decodeCounter, encodeCounter, get, getAtLeast, getAtMost, getRange, getRange, getRange, put, remove, removeRange, removeRange
protected SnapshotKVTransaction(SnapshotKVDatabase kvdb, MutableView view, long baseVersion)
kvdb
- the associated databaseview
- mutable view to be used for this transactionbaseVersion
- the database version associated with base
public long getBaseVersion()
public long getCommitVersion()
public MutableView getMutableView()
MutableView
associated with this instance.public AtomicBoolean getReadTrackingControl()
ReadTracking
AtomicBoolean
that can be used to temporarily pause/un-pause read tracking.
By default the returned control is true. While set to false, read tracking is disabled; setting back to true re-enables read tracking.
For re-entrance safety, this should be done as follows:
final boolean previous = kv.getReadTrackingControl().getAndSet(false);
try {
// do something without tracking reads...
} finally {
kv.getReadTrackingControl().set(previous);
}
getReadTrackingControl
in interface ReadTracking
protected KVStore delegate()
KVStore
.
The implementation in SnapshotKVTransaction
returns the MutableView
associated with this instance.
delegate
in class ForwardingKVStore
KVStore
StaleTransactionException
- if this transaction is no longer validTransactionTimeoutException
- if this transaction has timed outpublic SnapshotKVDatabase getKVDatabase()
KVTransaction
KVDatabase
with which this instance is associated.getKVDatabase
in interface KVTransaction
public void setTimeout(long timeout)
SnapshotKVTransaction
s 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.
setTimeout
in interface KVTransaction
timeout
- transaction timeout in milliseconds, or zero for unlimitedIllegalArgumentException
- if timeout
is negativepublic ListenableFuture<Void> watchKey(byte[] key)
KVTransaction
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
JTransaction.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 the Future
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 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 Future
s 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.
watchKey
in interface KVTransaction
key
- the key to watchFuture
that returns key
when the value associated with key
is modifiedJTransaction.getKey()
public boolean isReadOnly()
KVTransaction
Default is false.
isReadOnly
in interface KVTransaction
public void setReadOnly(boolean readOnly)
KVTransaction
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
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.
setReadOnly
in interface KVTransaction
readOnly
- read-only settingpublic void commit()
KVTransaction
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.
commit
in interface KVTransaction
public void rollback()
KVTransaction
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 should not throw StaleTransactionException
.
rollback
in interface KVTransaction
public CloseableKVStore mutableSnapshot()
KVTransaction
The returned CloseableKVStore
should be mutable, but all changes should remain private until
close()
is invoked, at which time they should be discarded.
That is, the CloseableKVStore
it is completely independent from this transaction
(subsequent changes to either one do not affect the other).
Note that 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.
mutableSnapshot
in interface KVTransaction
public void close()
Equivalent to invoking rollback()
.
close
in interface Closeable
close
in interface AutoCloseable
Copyright © 2022. All rights reserved.