Class XMLKVDatabase

All Implemented Interfaces:
KVDatabase, Serializable
Direct Known Subclasses:
SpringXMLKVDatabase

public class XMLKVDatabase extends MemoryKVDatabase
A MemoryKVDatabase made persistent by storing its XML content in a file or custom StreamRepository.

The database XML is rewritten in its entirety after each successful commit, so this class should not be used for high-performance applications.

The XML is persisted in a StreamRepository which provides atomicity and any durability. When constructed with a File for persistence, that file gets wrapped in a FileStreamRepository.

Initial Content

At startup, if a FileNotFoundException is caught when trying to read the XML, we assume that the underlying data has not yet been created and so the database is initialized as empty. Alternatively, you can configure some default initial content for this scenario via setInitialContentFile(), or by overriding getInitialContent().

Out-Of-Band Updates

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 "out-of-band" updates are 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.

See Also:
  • Constructor Details

  • Method Details

    • getInitialContent

      protected InputStream getInitialContent() throws IOException
      Get the initial content for an uninitialized database. This method is invoked when, on the first load, the backing XML file is not found. It should return a stream that reads initial content for the database, if any, otherwise null.

      The implementation in XMLKVDatabase opens and returns the File configured by setInitialContentFile(), if any, otherwise null.

      Returns:
      default initial XML database content, or null for none
      Throws:
      IOException - if an error occurs accessing the initial content file
    • setInitialContentFile

      public void setInitialContentFile(File initialContentFile)
      Configure the 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.
      Parameters:
      initialContentFile - file containing default initial XML database content, or null for none
    • start

      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 interface KVDatabase
      Overrides:
      start in class SimpleKVDatabase
    • createTransaction

      public XMLKVTransaction createTransaction()
      Description copied from interface: KVDatabase
      Create a new transaction.
      Specified by:
      createTransaction in interface KVDatabase
      Overrides:
      createTransaction in class SimpleKVDatabase
      Returns:
      newly created transaction
    • reload

      public void reload()
      Forcibly reload this database by re-reading the XML file.

      Any transactions that are in-progress when this method is called immediately become unusable.

    • getGeneration

      public int getGeneration()
      Get the generation number associated with the XML file. The generation number is incremented every time the database is wholesale updated by reading the file into memory, e.g., by invoking reload().
      Returns:
      XML file generation number
      See Also:
    • checkForOutOfBandUpdate

      public 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.
      Returns:
      true if file was updated and re-read, otherwise false
    • checkState

      protected void checkState(SimpleKVTransaction tx)
      Description copied from class: SimpleKVDatabase
      Verify that the given transaction is still usable.

      This method is invoked at the start of the AtomicKVStore 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.

      Overrides:
      checkState in class SimpleKVDatabase
      Parameters:
      tx - the transaction being accessed
    • postCommit

      protected void postCommit(SimpleKVTransaction tx, boolean successful)
      Description copied from class: SimpleKVDatabase
      Invoked during transaction commit just after writing changes to the underlying AtomicKVStore.

      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 AtomicKVStore throws an exception while changes were being written to it. In that case, successful will be false.

      The implementation in SimpleKVDatabase does nothing.

      Overrides:
      postCommit in class SimpleKVDatabase
      Parameters:
      tx - the transaction that was committed
      successful - true if all changes were written back successfully, false if the underlying AtomicKVStore threw an exception during commit update
    • readXML

      protected void readXML()
    • writeXML

      protected void writeXML()