public class XMLKVDatabase extends SimpleKVDatabase
KVDatabase
backed by an XML file stored in a StreamRepository
.
The data is kept in memory, and the XML file is rewritten in its entirety after each successful commit.
In normal usage, the XML file is stored in a regular File
using a FileStreamRepository
, which
guarantees (via the use of AtomicUpdateFileOutputStream
) that a partially written XML file can never exist.
If a FileNotFoundException
is caught when trying to read the XML file, we assume that the underlying file has
not yet been created and the database will initially be empty. Alternately, you can configure a file containing
default initial content via setInitialContentFile()
, or override getInitialContent()
to create the initial content more dynamically.
When a FileStreamRepository
is used, instances support "out-of-band" updates of the XML file. In that case,
each time a transaction is accessed the modification timestamp of the XML file is examined. If the XML file has been
updated by some external process since the time the transaction was created, the database will be reloaded from
the XML file and the transaction will fail with a RetryTransactionException
.
Note that two different processes modifying the XML file at the same time is not without race conditions: e.g., it's possible for an external process to update the XML file just as a transaction associated with this instance is being committed and written to the file, which will result in overwriting the external process' changes.
Key watches are supported.
Instances are serializable unless a non-serializable StreamRepository
is provided to the constructor.
DEFAULT_HOLD_TIMEOUT, DEFAULT_WAIT_TIMEOUT, kv, log
Constructor and Description |
---|
XMLKVDatabase(File file)
Constructor.
|
XMLKVDatabase(File file,
long waitTimeout,
long holdTimeout)
Constructor.
|
XMLKVDatabase(StreamRepository repository)
Constructor.
|
XMLKVDatabase(StreamRepository repository,
long waitTimeout,
long holdTimeout)
Constructor.
|
Modifier and Type | Method and Description |
---|---|
boolean |
checkForOutOfBandUpdate()
Check the XML file's timestamp and reload it if it has been modified since the most recent
read or write by this instance.
|
protected void |
checkState(SimpleKVTransaction tx)
Verify that the given transaction is still usable.
|
XMLKVTransaction |
createTransaction()
Create a new transaction.
|
int |
getGeneration()
Get the generation number associated with the XML file.
|
protected InputStream |
getInitialContent()
Get the initial content for an uninitialized database.
|
protected void |
postCommit(SimpleKVTransaction tx,
boolean successful)
Invoked during transaction commit just after writing changes to the underlying
KVStore . |
protected void |
readXML() |
void |
reload()
Forcibly reload this database by re-reading the XML file.
|
void |
setInitialContentFile(File initialContentFile)
Configure the
File containing default initial content for an uninitialized database. |
void |
start()
Start this instance.
|
protected void |
writeXML() |
createTransaction, getHoldTimeout, getWaitTimeout, preCommit, setHoldTimeout, setWaitTimeout, stop
public XMLKVDatabase(File file)
Uses a FileStreamRepository
backed by the specified file, with timeouts set to
SimpleKVDatabase.DEFAULT_WAIT_TIMEOUT
and SimpleKVDatabase.DEFAULT_HOLD_TIMEOUT
.
file
- persistent XML fileIllegalArgumentException
- if file
is nullpublic XMLKVDatabase(File file, long waitTimeout, long holdTimeout)
Uses a FileStreamRepository
backed by the specified file with configurable lock timeouts.
file
- persistent XML filewaitTimeout
- how long a thread will wait for a lock before throwing RetryTransactionException
in milliseconds, or zero for unlimitedholdTimeout
- how long a thread may hold a contestested lock before throwing RetryTransactionException
in milliseconds, or zero for unlimitedIllegalArgumentException
- if waitTimeout
or holdTimeout
is negativeIllegalArgumentException
- if file
is nullpublic XMLKVDatabase(StreamRepository repository)
Allows storage in any user-supplied StreamRepository
, with timeouts set to
SimpleKVDatabase.DEFAULT_WAIT_TIMEOUT
and SimpleKVDatabase.DEFAULT_HOLD_TIMEOUT
.
repository
- XML file storageIllegalArgumentException
- if repository
is nullpublic XMLKVDatabase(StreamRepository repository, long waitTimeout, long holdTimeout)
Allows storage in any user-supplied StreamRepository
with configurable lock timeouts.
repository
- XML file storagewaitTimeout
- how long a thread will wait for a lock before throwing RetryTransactionException
in milliseconds, or zero for unlimitedholdTimeout
- how long a thread may hold a contestested lock before throwing RetryTransactionException
in milliseconds, or zero for unlimitedIllegalArgumentException
- if waitTimeout
or holdTimeout
is negativeIllegalArgumentException
- if repository
is nullprotected InputStream getInitialContent() throws IOException
The implementation in XMLKVDatabase
opens and returns the File
configured by
setInitialContentFile()
, if any, otherwise null.
IOException
- if an error occurs accessing the initial content filepublic void setInitialContentFile(File initialContentFile)
File
containing default initial content for an uninitialized database. This method is invoked
by getInitialContent()
when, on the first load, the backing XML file is not found.initialContentFile
- file containing default initial XML database content, or null for nonepublic void start()
KVDatabase
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.
start
in interface KVDatabase
start
in class SimpleKVDatabase
public XMLKVTransaction createTransaction()
KVDatabase
createTransaction
in interface KVDatabase
createTransaction
in class SimpleKVDatabase
public void reload()
Any transactions that are in-progress when this method is called immediately become unusable.
public int getGeneration()
reload()
.XMLKVTransaction.getGeneration()
public boolean checkForOutOfBandUpdate()
protected void checkState(SimpleKVTransaction tx)
SimpleKVDatabase
This method is invoked at the start of the KVStore
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.
checkState
in class SimpleKVDatabase
tx
- the transaction being accessedprotected void postCommit(SimpleKVTransaction tx, boolean successful)
SimpleKVDatabase
KVStore
.
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 KVStore
throws an exception while changes were being written to it.
In that case, successful
will be false.
The implementation in SimpleKVDatabase
does nothing.
postCommit
in class SimpleKVDatabase
tx
- the transaction that was committedsuccessful
- true if all changes were written back successfully,
false if the underlying KVStore
threw an exception during commit updateprotected void readXML()
protected void writeXML()
Copyright © 2022. All rights reserved.