Class SimpleKVDatabase
- All Implemented Interfaces:
KVDatabase
,Serializable
- Direct Known Subclasses:
MemoryKVDatabase
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 RetryKVTransactionException
is thrown. If the hold timeout is exceeded,
a KVTransactionTimeoutException
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 Summary
Modifier and TypeFieldDescriptionstatic final long
Default hold timeout in milliseconds (5000L).static final long
Default wait timeout for newly created transactions in milliseconds (500L).protected final AtomicKVStore
TheAtomicKVStore
for the committed data.protected Logger
-
Constructor Summary
ConstructorDescriptionConstructor.SimpleKVDatabase
(AtomicKVStore kv, long waitTimeout, long holdTimeout) Primary constructor. -
Method Summary
Modifier and TypeMethodDescriptionprotected void
Verify that the given transaction is still usable.Create a new transaction.createTransaction
(Map<String, ?> options) Create a new transaction with the specified options.long
Get the hold timeout configured for this instance.long
Get the wait timeout for newly created transactions.protected void
postCommit
(SimpleKVTransaction tx, boolean successful) Invoked during transaction commit just after writing changes to the underlyingAtomicKVStore
.protected void
Invoked during transaction commit just prior to writing changes to the underlyingAtomicKVStore
.void
setHoldTimeout
(long holdTimeout) Set the hold timeout for this instance.void
setWaitTimeout
(long waitTimeout) Set the wait timeout for newly created transactions.void
start()
Start this instance.void
stop()
Stop this instance.
-
Field Details
-
DEFAULT_WAIT_TIMEOUT
public static final long DEFAULT_WAIT_TIMEOUTDefault wait timeout for newly created transactions in milliseconds (500L).- See Also:
-
DEFAULT_HOLD_TIMEOUT
public static final long DEFAULT_HOLD_TIMEOUTDefault hold timeout in milliseconds (5000L).- See Also:
-
kv
TheAtomicKVStore
for the committed data. -
log
-
-
Constructor Details
-
SimpleKVDatabase
Constructor.Uses the default wait and hold timeouts.
- Parameters:
kv
- storage for the committed data- Throws:
IllegalArgumentException
- ifkv
is null
-
SimpleKVDatabase
Primary constructor.- Parameters:
kv
-AtomicKVStore
for the committed datawaitTimeout
- how long a thread will wait for a lock before throwingRetryKVTransactionException
in milliseconds, or zero for unlimitedholdTimeout
- how long a thread may hold a contestested lock before throwingRetryKVTransactionException
in milliseconds, or zero for unlimited- Throws:
IllegalArgumentException
- ifwaitTimeout
orholdTimeout
is negativeIllegalArgumentException
- ifkv
is null
-
-
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
RetryKVTransactionException
.- Returns:
- wait timeout in milliseconds
-
setWaitTimeout
public void setWaitTimeout(long waitTimeout) Set the wait timeout for newly created transactions. Default isDEFAULT_WAIT_TIMEOUT
.- Parameters:
waitTimeout
- how long a thread will wait for a lock before throwingRetryKVTransactionException
in milliseconds (default), or zero for unlimited- Throws:
IllegalArgumentException
- ifwaitTimeout
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
RetryKVTransactionException
.- Returns:
- hold timeout in milliseconds
-
setHoldTimeout
public void setHoldTimeout(long holdTimeout) Set the hold timeout for this instance. Default isDEFAULT_HOLD_TIMEOUT
.- Parameters:
holdTimeout
- how long a thread may hold a contested lock before throwingRetryKVTransactionException
in milliseconds, or zero for unlimited- Throws:
IllegalArgumentException
- ifholdTimeout
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 interfaceKVDatabase
-
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 interfaceKVDatabase
-
createTransaction
Description copied from interface:KVDatabase
Create a new transaction with the specified options.- Specified by:
createTransaction
in interfaceKVDatabase
- Parameters:
options
- optional transaction options; may be null- Returns:
- newly created transaction
-
createTransaction
Description copied from interface:KVDatabase
Create a new transaction.- Specified by:
createTransaction
in interfaceKVDatabase
- Returns:
- newly created transaction
-
preCommit
Invoked during transaction commit just prior to writing changes to the underlyingAtomicKVStore
.SimpleKVDatabase
guarantees this method andpostCommit()
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:
RetryKVTransactionException
- if this transaction must be retried and is no longer usable
-
postCommit
Invoked during transaction commit just after writing changes to the underlyingAtomicKVStore
.SimpleKVDatabase
guarantees this method andpreCommit()
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 committedsuccessful
- true if all changes were written back successfully, false if the underlyingAtomicKVStore
threw an exception during commit update
-
checkState
Verify that the given transaction is still usable.This method is invoked at the start of the
AtomicKVStore
data access andcommit()
methods of theSimpleKVTransaction
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:
StaleKVTransactionException
- if this instance is no longer usableRetryKVTransactionException
- if this transaction should be retriedKVTransactionTimeoutException
- if the transaction has timed out
-