org.helidb
Interface Database<K,V>

Type Parameters:
K - The type of keys in the database.
V - The type of values in the database.
All Superinterfaces:
Iterable<Record<K,V>>, Map<K,V>
All Known Subinterfaces:
TransactionalDatabase<K,V>
All Known Implementing Classes:
AbstractDatabase, AbstractTransactionalDatabase, LoggingTransactionalDatabase, ShadowCopyTransactionalDatabase, SimpleDatabase

public interface Database<K,V>
extends Map<K,V>, Iterable<Record<K,V>>

This is the interface for a database. The database is a repository for values that can be retrieved by a unique key that it is associated with, just like how a Java Map works. A value and its associated key is represented by a Record object.

The Database interface extends Map, so any database can be used just like a Map. However, many of the operations defined in the Map interface cannot be implemented in an efficient way for a database that is working against persistent storage when efficiency is taken as a measure of how many reads and/or writes to the storage that are required for an operation. The data access methods defined in this interface are designed so that they can be implemented more efficiently.

The Database interface also extends Iterable. The iterator that is returned when iterator() is called iterates over the database's Record:s (its keys and values). keyIterator() returns an iterator for just iterating over the database's keys and valueIterator() returns an iterator for iterating over the database's values. Depending on the backend implementation used and whether an index is used or not, the iterators may or may not return the records in a specific order. If the database is modified while using an iterator, the methods of the iterator will throw ConcurrentModificationException:s if they are invoked after the modification.

There are several different database implementations. Each implementation has its unique set of capabilities, such as for instance transaction support.

A database uses a DatabaseBackend object for reading and writing data to its backing storage. There are different backend implementations that store their data differently. One implementation may be optimized for fast searches and another for efficient storage. The performance test results should be a good guide for selecting an appropriate backend implementation depending on the expected size of the data and how the database is planned to be used.

The DatabaseBackend uses one Serializer object for serializing keys to and interpreting keys in the backing storage and another Serializer object for the values.

Be careful not to modify objects that are used as keys or values in the database if you use a Database or a DatabaseBackend implementation that cache data. Preferably, both key and value objects should be immutable.

After deleting data from the database, its backend may become fragmented. It can be defragmented by calling compact().

The requirements for database keys are the same as for keys in a Map. Specifically, the keys must have equals and hashCode methods that follow Map's contract.

If an I/O error occurs when the database accesses the backing storage, the invoked database method throws an WrappedIOException. This includes methods inherited from Map and Iterable.

Implementations may or may not be thread safe. See each implementation class for details.

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

Nested Class Summary
 
Nested classes/interfaces inherited from interface java.util.Map
Map.Entry<K,V>
 
Method Summary
 void close()
          Close this database and release all resources associated with it.
 boolean compact()
          Defragment the database backend.
 boolean delete(K key)
          Delete the record with the supplied key from the database.
 void fasterInsert(K key, V value)
          This is a faster version of insert(Object, Object) that does not check if the key already exists in the database.
 Cursor<K,V> find(K key)
          Search for the supplied key in the database and return a Cursor at the found record.
 Cursor<K,V> find(K key, SearchMode mode)
          Search for the key in the database using the supplied SearchMode.
 Cursor<K,V> find(K key, SearchMode mode, Comparator<? super K> cmp)
          Search for the key in the database using the supplied SearchMode.
 Cursor<K,V> firstRecord()
          Get a Cursor at the first record in the database.
 void insert(K key, V value)
          Insert a new record in the database.
 boolean insertOrUpdate(K key, V value)
          If the record's key already exists in the database, update the existing record.
 boolean isClosed()
          Is this database closed?
 Iterator<K> keyIterator()
          This method returns an iterator over the keys in the database.
 Cursor<K,V> lastRecord()
          Get a Cursor at the last record in the database.
 void update(K key, V value)
          Update an existing record in the database with a new value.
 Iterator<V> valueIterator()
          Get an iterator over the values in the database.
 
Methods inherited from interface java.util.Map
clear, containsKey, containsValue, entrySet, equals, get, hashCode, isEmpty, keySet, put, putAll, remove, size, values
 
Methods inherited from interface java.lang.Iterable
iterator
 

Method Detail

insert

void insert(K key,
            V value)
            throws KeyExistsException,
                   IllegalStateException,
                   ReadOnlyException
Insert a new record in the database. The record's key must not exist already in the database.

This method makes sure that the supplied key is unique before the record is inserted. The fasterInsert(Object, Object) can be used instead when the client is absolute sure that the key is unique. It should be significantly faster for large databases.

Parameters:
key - The record's key
value - The record's value
Throws:
KeyExistsException - If the record's key already exists in the database.
IllegalStateException - If this database is closed.
ReadOnlyException - If the database is read only.
See Also:
insertOrUpdate(Object, Object), update(Object, Object), Map.put(Object, Object), fasterInsert(Object, Object)

fasterInsert

void fasterInsert(K key,
                  V value)
                  throws IllegalStateException,
                         ReadOnlyException
This is a faster version of insert(Object, Object) that does not check if the key already exists in the database. It is the client's responsibility to avoid key collisions.

The database's behavior if duplicate keys are inserted is unspecified, and it probably varies between different DatabaseBackend implementations.

Parameters:
key - The record's key.
value - The record's value.
Throws:
IllegalStateException - If this database is closed.
ReadOnlyException - If the database is read only.
See Also:
insert(Object, Object), insertOrUpdate(Object, Object), Map.put(Object, Object)

insertOrUpdate

boolean insertOrUpdate(K key,
                       V value)
                       throws IllegalStateException,
                              ReadOnlyException
If the record's key already exists in the database, update the existing record. If not, insert a new record.

This method is quite similar to Map.put(Object, Object), but its implementation should be slightly more efficient since it does not return the record's old value.

Parameters:
key - The record's key.
value - The record's value.
Returns:
true if an existing record was updated, false if a new record was inserted.
Throws:
IllegalStateException - If this database is closed.
ReadOnlyException - If the database is read only.
See Also:
insert(Object, Object), update(Object, Object), Map.put(Object, Object), fasterInsert(Object, Object)

update

void update(K key,
            V value)
            throws KeyNotFoundException,
                   IllegalStateException,
                   ReadOnlyException
Update an existing record in the database with a new value.

Parameters:
key - The record's key.
value - The record's new value.
Throws:
KeyNotFoundException - If no record with the key key exists in the database.
IllegalStateException - If this database is closed.
ReadOnlyException - If the database is read only.
See Also:
insert(Object, Object), fasterInsert(Object, Object), insertOrUpdate(Object, Object), Map.put(Object, Object)

delete

boolean delete(K key)
               throws IllegalStateException,
                      ReadOnlyException
Delete the record with the supplied key from the database. If the key does not exist in the database, this method returns false.

This method should be slightly more efficient than Map.remove(Object) since it does not return the record's previous value.

Parameters:
key - The key of the record to delete.
Returns:
true if a record was deleted, false if there was no record with the supplied key to delete.
Throws:
IllegalStateException - If this database is closed.
ReadOnlyException - If the database is read only.
See Also:
Map.remove(Object)

keyIterator

Iterator<K> keyIterator()
                        throws IllegalStateException
This method returns an iterator over the keys in the database. The order that the keys are returned in is dependent on the DatabaseBackend implementation used by the database and whether the database uses an index or not. (See the class documentation above.)

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

Returns:
An Iterator over the database's keys.
Throws:
IllegalStateException - If this database is closed.

valueIterator

Iterator<V> valueIterator()
                          throws IllegalStateException
Get an iterator over the values in the database. The order that the values are returned in is dependent on the DatabaseBackend implementation used by the database and whether the database uses an index or not. (See the class documentation above.)

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

Returns:
An Iterator over the database's values.
Throws:
IllegalStateException - If this database is closed.

compact

boolean compact()
                throws IllegalStateException,
                       ReadOnlyException
Defragment the database backend. How this is done is up to the backend implementation that is used.

Since defragmenting a database potentially involves modifying the entire database, this method may take a long time to complete depending on the size of the database.

Returns:
true if the database was compacted, or false if there was nothing to compact.
Throws:
IllegalStateException - If this database is closed.
ReadOnlyException - If the database is read only.
See Also:
DatabaseBackend.compact()

find

Cursor<K,V> find(K key)
                 throws IllegalStateException
Search for the supplied key in the database and return a Cursor at the found record.

The returned Cursor is valid until the database is updated.

Parameters:
key - The key to search for.
Returns:
A Cursor at the found record, or null if the key was not in the database.
Throws:
IllegalStateException - If this database is closed.
Since:
1.1
See Also:
find(Object, SearchMode), find(Object, SearchMode, Comparator)

find

Cursor<K,V> find(K key,
                 SearchMode mode)
                 throws IllegalStateException,
                        UnsupportedOperationException
Search for the key in the database using the supplied SearchMode. The natural ordering of the database keys, which must be Comparable, is used to find closest matches.

The returned Cursor is valid until the database is updated.

Parameters:
key - The key to search for.
mode - The search mode. This should be a mode that is supported by the database and its backend.
Returns:
A Cursor at the found record, or null if no matching key was found.
Throws:
IllegalStateException - If this database is closed.
UnsupportedOperationException - If the supplied search mode is not supported by the database or its backend.
Since:
1.1
See Also:
find(Object), find(Object, SearchMode, Comparator)

find

Cursor<K,V> find(K key,
                 SearchMode mode,
                 Comparator<? super K> cmp)
                 throws IllegalStateException
Search for the key in the database using the supplied SearchMode. The supplied Comparator is used to find closest matches.

The returned Cursor is valid until the database is updated.

Parameters:
key - The key to search for.
mode - The search mode. This should be a mode that is supported by the database and its backend.
cmp - A Comparator used for finding closest matches between the search key and the keys in the database.
Returns:
A Cursor at the found record, or null if no matching key was found.
Throws:
IllegalStateException - If this database is closed.
UnsupportedOperationException - If the supplied search mode is not supported by the database or its backend.
Since:
1.1
See Also:
find(Object), find(Object, SearchMode)

firstRecord

Cursor<K,V> firstRecord()
                        throws IllegalStateException
Get a Cursor at the first record in the database. Which record that is and how the Cursor will navigate through the database is determined by the database backend's search order.

The returned Cursor is valid until the database is updated.

Returns:
A Cursor at the database's first record, or null if the database is empty.
Throws:
IllegalStateException - If this database is closed.
Since:
1.1
See Also:
lastRecord()

lastRecord

Cursor<K,V> lastRecord()
                       throws IllegalStateException,
                              UnsupportedOperationException
Get a Cursor at the last record in the database. Which record that is and how the Cursor will navigate through the database is determined by the database backend's search order.

The returned Cursor is valid until the database is updated.

Returns:
A Cursor at the database's last record, or null if the database is empty.
Throws:
IllegalStateException - If this database is closed.
UnsupportedOperationException - If the database backend does not support iteration backwards.
Since:
1.1
See Also:
lastRecord()

close

void close()
Close this database and release all resources associated with it. This method also closes the the database backend.


isClosed

boolean isClosed()
Is this database closed?

Returns:
true if this database is closed.