org.helidb.backend
Interface DatabaseBackend<K,V,P>

Type Parameters:
K - The type of keys in the database.
V - The type of values in the database.
P - The type of the position used to identify and find records in the database.
All Superinterfaces:
Iterable<Record<K,V>>
All Known Implementing Classes:
AbstractDatabaseBackend, AbstractDatabaseBackendProxy, BPlusTreeIndexBackend, ConstantRecordSizeBPlusTreeBackend, ConstantRecordSizeHeapBackend, HeapBackend, LruCacheBackend, MapBackend

public interface DatabaseBackend<K,V,P>
extends Iterable<Record<K,V>>

The DatabaseBackend is responsible for how keys and values are stored and laid out in the underlying storage. A Database uses one DatabaseBackend implementation.

The DatabaseBackend uses one Serializer instance for serializing and interpreting database keys and another Serializer instance for serializing and interpreting database values.

The database client instantiates a backend object when creating the Database, but it should never call the backend's methods directly. All calls to the database should go through the Database object.

If database records are deleted, the backend may become fragmented. It can be defragmented by calling compact(). (Or, for database clients, rather the Database.compact() method.)

The DatabaseBackend interface extends Iterable. The iterator that is returned when iterator() is called iterates over the database's Record:s (its keys and values). Depending on the backend implementation, the iterator may or may not return the records in a specific order. If the database is modified after calling iterator(), the methods of the iterator returned will throw ConcurrentModificationException:s if they are invoked.

Implementation notes:
This interface is designed with the goal that backends should be easy to implement and that backend methods can be implemented as efficient as possible.

Database records (a key and its associated value) are identified by their positions in the backing storage. Exactly what a position is is up to the implementation. A position object is valid until the record it refers to moves. If a client wants to be notified whenever a record moves, it registers a RecordMoveListener with the addRecordMoveListener(RecordMoveListener) method.

Backends never have to bother with locking and transactions. That is the job of the Database layer.

Since:
1.0
Author:
Karl Gustafsson
See Also:
Database, Serializer
In_jar:
helidb-core

Method Summary
 void addRecordMoveListener(RecordMoveListener<? super K,? super V,? super P> l)
          Add a listener that will receive notifications whenever a database record is moved to a new position.
 void clear()
          Wipe out the entire database.
 void close()
          Close this database backend and release all resources associated with it (close files and release locks, for instance).
 boolean compact()
          Compact the backing database file if it has become fragmented.
 boolean delete(K key)
          Delete the record with the supplied key, if it exists.
 P find(Comparable<K> key, SearchMode mode)
          Find the position of the record with the supplied key in the database that matches the search mode.
 P find(K key)
          Find the position of the record with the supplied key in the database backend.
 P find(K key, SearchMode mode, Comparator<? super K> cmp)
          Find the position of the record with the supplied key in the database that matches the search mode.
 void forEachKey(ForEachKeyCallback<K,P> callback)
          For each key in the database, call the callback object.
 int getContentsVersion()
          Get a version number for the contents of the database backend.
 P getFirstPosition()
          Get the position of the "first" record in the backend.
 Set<K> getKeys()
          Return an immutable Set containing all keys in the database.
 P getLastPosition()
          Get the position of the "last" record in the backend.
 P getNextPosition(P pos)
          Get the position of the "next" record in the backend, relative to the record at the supplied position.
 P getPreviousPosition(P pos)
          Get the position of the "previous" record in the backend, relative to the record at the supplied position.
 Set<Record<K,V>> getRecords()
          Return an immutable Set containing all database records (keys and values).
 V getValueFor(K key)
          Get the value for the record with the supplied key.
 Collection<V> getValues()
          Return an immutable Collection containing all values in the database.
 P insert(K key, V value)
          Insert a new record in the database.
 P insertCheckKeyUnique(K key, V value)
          Insert a new record in the database after verifying that the key is unique within the database.
 boolean insertOrUpdate(K key, V value)
          If a record with the supplied key exists, update its value.
 Iterator<K> keyIterator()
          Get an iterator for all keys in the database.
 K readKeyAt(P pos)
          Read the key at the supplied position.
 Record<K,V> readRecordAt(P pos)
          Read the record (key and value) at the specified position.
 V readValueAt(P pos)
          Read the value at the specified position.
 V remove(K key)
          Delete the record with the supplied key and return its value.
 void removeAt(P pos, K key)
          Delete the record at the supplied position.
 void removeRecordMoveListener(RecordMoveListener<? super K,? super V,? super P> l)
          Remove a record move listener.
 void replaceContentsWith(RandomAccess ra, long dataSize)
          Replace the contents of the database with content read from the supplied RandomAccess.
 Pair<P> update(K key, V value)
          Update an existing record with a new value.
 P updateAt(P pos, K key, V value)
          Update the record at the supplied position with the new value.
 Iterator<V> valueIterator()
          Get an iterator for all the values in the database.
 long writeContentsTo(RandomAccess ra)
          Write the contents of the entire database to the current position in the supplied RandomAccess.
 
Methods inherited from interface java.lang.Iterable
iterator
 

Method Detail

getKeys

Set<K> getKeys()
               throws WrappedIOException,
                      IllegalStateException
Return an immutable Set containing all keys in the database.

Returns:
An immutable Set containing all keys in the database. If the database is empty, this method returns an empty Set.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.

getValues

Collection<V> getValues()
                        throws WrappedIOException,
                               IllegalStateException
Return an immutable Collection containing all values in the database.

Returns:
An immutable Collection containing all values in the database. If the database is empty, this method returns an empty Collection.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.

getRecords

Set<Record<K,V>> getRecords()
                            throws WrappedIOException,
                                   IllegalStateException
Return an immutable Set containing all database records (keys and values).

Returns:
An immutable Set containing all database records. If the database is empty, this method returns an empty Set.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.

insert

P insert(K key,
         V value)
         throws WrappedIOException,
                IllegalStateException,
                ReadOnlyException
Insert a new record in the database.

Parameters:
key - The key. It is not verified that this key is unique. Inserting duplicate keys will result in unspecified behavior from the backend.
value - The value.
Returns:
The position of the new record.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

insertCheckKeyUnique

P insertCheckKeyUnique(K key,
                       V value)
                       throws WrappedIOException,
                              IllegalStateException,
                              ReadOnlyException,
                              KeyExistsException
Insert a new record in the database after verifying that the key is unique within the database.

Parameters:
key - The key.
value - The value.
Returns:
The position of the new record.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.
KeyExistsException - If the key already exists in the database.

insertOrUpdate

boolean insertOrUpdate(K key,
                       V value)
                       throws WrappedIOException,
                              IllegalStateException,
                              ReadOnlyException
If a record with the supplied key exists, update its value. If not, insert a new record.

Parameters:
key - The key.
value - The value.
Returns:
true if an existing record was updated, false if a new record was inserted.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

find

P find(K key)
       throws WrappedIOException,
              IllegalStateException
Find the position of the record with the supplied key in the database backend.

Parameters:
key - The key to find.
Returns:
The position of the key, or null if not found.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
See Also:
find(Comparable, SearchMode), find(Object, SearchMode, Comparator)

find

P find(Comparable<K> key,
       SearchMode mode)
       throws WrappedIOException,
              IllegalStateException
Find the position of the record with the supplied key in the database that matches the search mode. The distance between the key to search for and the keys in the database is measured using the distance returned from the Comparable.compareTo(Object) method of the supplied key.

Parameters:
key - The key to find.
mode - The search mode. The backend implementation must support the SearchMode.EXACT_MATCH mode (which makes this method behave exactly like find(Object)). The backend may also support SearchMode.CLOSEST_ABOVE, SearchMode.CLOSEST_BELOW and SearchMode.CLOSEST_MATCH. If not, this method should throw an UnsupportedOperationException when called with any of those search modes. The backend implementation may also invent its own search modes.

The closest match is defined as the match that gives the lowest positive (SearchMode.CLOSEST_ABOVE), negative ( SearchMode.CLOSEST_BELOW) or absolute ( SearchMode.CLOSEST_MATCH) value from the supplied key's Comparable.compareTo(Object) method when comparing the keys in the database with the key to search for.

Returns:
The position of the record that matches the search criteria, or null if no record matching the search criteria is found.
Throws:
UnsupportedOperationException - If this method is called with a SearchMode that is not supported by the backend implementation.
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
Since:
1.1
See Also:
find(Object), find(Object, SearchMode, Comparator)

find

P find(K key,
       SearchMode mode,
       Comparator<? super K> cmp)
       throws UnsupportedOperationException,
              WrappedIOException,
              IllegalStateException
Find the position of the record with the supplied key in the database that matches the search mode. The supplied Comparator is used to compare the distances between the keys in the database and the key to search for.

Parameters:
key - The key to find.
mode - The search mode. The backend implementation must support the SearchMode.EXACT_MATCH mode (which makes this method behave exactly like find(Object)). The backend may also support SearchMode.CLOSEST_ABOVE, SearchMode.CLOSEST_BELOW and SearchMode.CLOSEST_MATCH. If not, this method should throw an UnsupportedOperationException when called with any of those search modes. The backend implementation may also invent its own search modes.

The closest match is defined as the match that gives the lowest positive (SearchMode.CLOSEST_ABOVE), negative ( SearchMode.CLOSEST_BELOW) or absolute ( SearchMode.CLOSEST_MATCH) value from the comparator when comparing the keys in the database with the key to search for.

cmp - The Comparator used to compare keys.
Returns:
The position of the record that matches the search criteria, or null if no record matching the search criteria is found.
Throws:
UnsupportedOperationException - If this method is called with a SearchMode that is not supported by the backend implementation.
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
Since:
1.1
See Also:
find(Object), find(Comparable, SearchMode)

getValueFor

V getValueFor(K key)
              throws WrappedIOException,
                     IllegalStateException
Get the value for the record with the supplied key.

Parameters:
key - The record's key.
Returns:
The record's value or null if no record in the database has the supplied key.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.

updateAt

P updateAt(P pos,
           K key,
           V value)
           throws WrappedIOException,
                  IllegalStateException,
                  ReadOnlyException
Update the record at the supplied position with the new value. The new key is always the same as the previous key.

It is up to the implementation to decide exactly how this is done. It is not required that the record should be located at the same position in the backend after the update. One strategy for implementing this method is to delete the old record and insert a new record with the updated values.

Parameters:
pos - The position of the record to update.
key - The record's key. The key is not modified by the update.
value - The new value.
Returns:
The new position of the record.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

update

Pair<P> update(K key,
               V value)
               throws WrappedIOException,
                      IllegalStateException,
                      ReadOnlyException,
                      KeyNotFoundException
Update an existing record with a new value.

It is up to the implementation to decide exactly how this is done. It is not required that the record should be located at the same position in the backend after the update. One strategy for implementing this method is to delete the old record and insert a new record with the updated values.

Parameters:
key - The record's key.
value - The record's new value.
Returns:
The record's old position (the first object in the pair) and the new position (the second object in the pair).
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.
KeyNotFoundException - If no record with the supplied key was found.

readKeyAt

K readKeyAt(P pos)
            throws WrappedIOException,
                   IllegalStateException
Read the key at the supplied position.

Parameters:
pos - The position of the record containing the key. This must be a valid position in the backend. It it is not, the behavior of this method is unspecified.
Returns:
The key.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
Since:
1.1
See Also:
readValueAt(Object), readRecordAt(Object)

readValueAt

V readValueAt(P pos)
              throws WrappedIOException,
                     IllegalStateException
Read the value at the specified position.

Parameters:
pos - The position of the record containing the value. This must be a valid position in the backend. If it is not, the behavior of this method is unspecified.
Returns:
The value.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
See Also:
readKeyAt(Object), readRecordAt(Object)

readRecordAt

Record<K,V> readRecordAt(P pos)
                         throws WrappedIOException,
                                IllegalStateException
Read the record (key and value) at the specified position.

Parameters:
pos - The position of the record. This must be a valid position in the backend. If it is not, the behavior of this method is unspecified.
Returns:
The record.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
Since:
1.1
See Also:
readKeyAt(Object), readValueAt(Object)

clear

void clear()
           throws WrappedIOException,
                  IllegalStateException,
                  ReadOnlyException
Wipe out the entire database.

Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

removeAt

void removeAt(P pos,
              K key)
              throws WrappedIOException,
                     IllegalStateException,
                     ReadOnlyException
Delete the record at the supplied position.

Parameters:
pos - The position of the record to delete.
key - The key for the record to remove.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

remove

V remove(K key)
         throws WrappedIOException,
                IllegalStateException,
                ReadOnlyException
Delete the record with the supplied key and return its value.

Parameters:
key - The record's key.
Returns:
The record's value or null if no record in the database has the supplied key.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

delete

boolean delete(K key)
               throws WrappedIOException,
                      IllegalStateException,
                      ReadOnlyException
Delete the record with the supplied key, if it exists.

Parameters:
key - The record's key.
Returns:
true if a record was deleted.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

forEachKey

void forEachKey(ForEachKeyCallback<K,P> callback)
                throws IllegalStateException
For each key in the database, call the callback object.

This can for instance be used for building indices for the database.

Parameters:
callback - The callback object to call for each key.
Throws:
IllegalStateException - If the database backend has been closed.

keyIterator

Iterator<K> keyIterator()
Get an iterator for all keys in the database. The iterator may or may not return the keys in a specific order. See the backend implementation documentation.

If the database is modified after calling this method, the methods of the Iterator returned will throw ConcurrentModificationException

Returns:
An Iterator over the database's keys.

valueIterator

Iterator<V> valueIterator()
Get an iterator for all the values in the database.

If the database is modified after calling this method, the methods of the Iterator returned will throw ConcurrentModificationException

Returns:
An Iterator over the database's values.

addRecordMoveListener

void addRecordMoveListener(RecordMoveListener<? super K,? super V,? super P> l)
Add a listener that will receive notifications whenever a database record is moved to a new position.

Parameters:
l - The listener.
See Also:
removeRecordMoveListener(RecordMoveListener)

removeRecordMoveListener

void removeRecordMoveListener(RecordMoveListener<? super K,? super V,? super P> l)
Remove a record move listener.

Parameters:
l - The listener to remove.
See Also:
addRecordMoveListener(RecordMoveListener)

writeContentsTo

long writeContentsTo(RandomAccess ra)
                     throws WrappedIOException,
                            IllegalStateException
Write the contents of the entire database to the current position in the supplied RandomAccess.

After writing, the current position of the RandomAccess should be at the end of the written data.

Parameters:
ra - The RandomAccess to write to. It is not closed after writing.
Returns:
The size of the contents in bytes.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.

replaceContentsWith

void replaceContentsWith(RandomAccess ra,
                         long dataSize)
                         throws WrappedIOException,
                                IllegalStateException,
                                ReadOnlyException
Replace the contents of the database with content read from the supplied RandomAccess. The database contents start at the RandomAccess' current position.

Parameters:
ra - The RandomAccess to read data from. It should not be closed after reading.
dataSize - The total size of the database data in bytes.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

getContentsVersion

int getContentsVersion()
                       throws IllegalStateException
Get a version number for the contents of the database backend. This version number should be updated every time that the backend contents are modified in any way.

The version number is used by database cursors to detect changes in the backend (upon which they throw ConcurrentModificationException:s).

The version number does not have to be persisted. It does not have to be consistent between different backend objects created on the same data.

Returns:
A version number.
Throws:
IllegalStateException - If the database backend has been closed.
Since:
1.1

getFirstPosition

P getFirstPosition()
                   throws WrappedIOException,
                          IllegalStateException
Get the position of the "first" record in the backend. The meaning of "first" is specified by the backend implementation. If the backend sorts the keys, this method returns the position of the first key in the sorted set of keys.

Returns:
The position of the first record in the backend, or null if the backend is empty.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
Since:
1.1
See Also:
getLastPosition(), getNextPosition(Object), getPreviousPosition(Object)

getLastPosition

P getLastPosition()
                  throws WrappedIOException,
                         IllegalStateException,
                         UnsupportedOperationException
Get the position of the "last" record in the backend. The meaning of "last" is specified by the backend implementation. If the backend sorts the keys, this method returns the position of the last key in the sorted set of keys.

Some backend implementations do not support this method. They let this method throw an UnsupportedOperationException.

Returns:
The position of the last record in the backend, or null if the backend is empty.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
UnsupportedOperationException - If this method is not supported by the backend implementation.
Since:
1.1
See Also:
getFirstPosition(), getNextPosition(Object), getPreviousPosition(Object)

getNextPosition

P getNextPosition(P pos)
                  throws WrappedIOException,
                         IllegalStateException
Get the position of the "next" record in the backend, relative to the record at the supplied position. The meaning of "next" is specified by the backend implementation. If the backend sorts the keys, this method returns the position of the next key, relative to the key at the supplied position.

Parameters:
pos - The position to search from. This must be the position of a record in the backend. If it is not, the behavior of this method is unspecified.
Returns:
The position of the next key in the database backend, or null if the supplied position references the last record in the backend (the position returned from getLastPosition()).
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
Since:
1.1
See Also:
getFirstPosition(), getLastPosition(), getPreviousPosition(Object)

getPreviousPosition

P getPreviousPosition(P pos)
                      throws WrappedIOException,
                             IllegalStateException,
                             UnsupportedOperationException
Get the position of the "previous" record in the backend, relative to the record at the supplied position. The meaning of "previous" is specified by the backend implementation. If the backend sorts the keys, this method returns the position of the previous key, relative to the key at the supplied position.

Some backend implementations do not support this method. They let this method throw an UnsupportedOperationException.

Parameters:
pos - The position to search from. This must be the position of a record in the backend. If it is not, the behavior of this method is unspecified.
Returns:
The position of the previous key in the database backend, or null if the supplied position references the first record in the backend (the position returned from getFirstPosition()).
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
UnsupportedOperationException - If this method is not supported by the backend implementation.
Since:
1.1
See Also:
getFirstPosition(), getLastPosition(), getNextPosition(Object)

compact

boolean compact()
                throws WrappedIOException,
                       IllegalStateException,
                       ReadOnlyException
Compact the backing database file if it has become fragmented.

Returns:
true if the backend was modified, false if not.
Throws:
WrappedIOException - On I/O errors.
IllegalStateException - If the database backend has been closed.
ReadOnlyException - If the database backend is read only.

close

void close()
Close this database backend and release all resources associated with it (close files and release locks, for instance).