/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * Erdo is a transactional, ordered key/value store. * * An Erdo {@link com.github.geophile.erdo.Database} contains ordered maps. * Each {@link com.github.geophile.erdo.OrderedMap} contains key/value pairs. * Keys are unique within a map. Maps are ordered, so when map contents are traversed, * records are visited in key order, as defined by {@link com.github.geophile.erdo.AbstractKey#compareTo(com.github.geophile.erdo.AbstractKey)}. * * <h2>Usage</h2> * * <p> Erdo is an embedded database. Your application makes calls to the Erdo API, and all database access takes * place in the application's process. A database can only be accessed by one process at a time, but within that * process, multi-threaded access is supported. * * <p>The configuration and state of a {@link com.github.geophile.erdo.Database} is stored in a directory. * The directory is specified when the database * is created or opened. The database directory must not exist prior to database creation. * Database access is permitted after * the database is created or opened, and before the database is closed. * Within a database, ordered maps may be created and opened. All created and opened maps remain open until * the database is closed. * * <h2>Keys and Records</h2> * * <p> An Erdo application provides key and value types by extending * {@link com.github.geophile.erdo.AbstractKey} and {@link com.github.geophile.erdo.AbstractRecord}. A key class must override * methods for hashing the key, comparing keys, serializing, deserializing, and estimating the * size of a serialized key. A record class has to define methods for serializing, deserializing, copying, and * estimating the size of a serialized record. * * <p> Keys are unique within a map. If an application wants to associate multiple values with a key, then the logic * for doing so must be in the application, either by having the record type provide for multiple values, or by * defining a key type with a field for a counter, for example. * * <h2>Transactions</h2> * * <p> Access to a database always takes place within the scope of a transaction. Erdo transactions implement * <a href="http://en.wikipedia.org/wiki/Snapshot_isolation">snapshot isolation</a>, which means that a transaction * operates on the database as it existed at the start of the transaction, modified only by the transaction's own * updates. * * <p> Transactions are not explicitly started. A thread accessing a database is always in a transaction, starting * as soon as the database is open, or as soon as the previous transaction has ended. A transaction is ended by calling * either {@link com.github.geophile.erdo.Database#commitTransaction()} or * {@link com.github.geophile.erdo.Database#rollbackTransaction()}. commitTransactionAsynchronously makes the transaction's updates (if any) * durable and visible to new transactions. rollbackTransaction discards the transaction's updates. * * <p> Transaction state may be written to disk synchronously or asynchronously. Synchronous commits are slower, but * guarantee durability once commitTransactionAsynchronously returns. Asynchronous commits are faster but don't guarantee durability * immediately. An asynchronous commit is performed by calling * {@link com.github.geophile.erdo.Database#commitTransactionAsynchronously(com.github.geophile.erdo.TransactionCallback)}. The callback * {@link com.github.geophile.erdo.TransactionCallback#whenDurable(Object)} is invoked once the updates from the transaction * are made durable. This callback can be used to implement application-level management of committed but * not-yet-durable state. * * <h2>Updates</h2> * * <p> There are four methods for updating an ordered map: * <ul> * <li>{@link com.github.geophile.erdo.OrderedMap#put(com.github.geophile.erdo.AbstractRecord)}: Inserts or updates a record, returning * the previous record associated with the new record's key. * <li>{@link com.github.geophile.erdo.OrderedMap#delete(com.github.geophile.erdo.AbstractKey)}: Deletes a record, returning the previous * record associated with the given key. * <li>{@link com.github.geophile.erdo.OrderedMap#ensurePresent(com.github.geophile.erdo.AbstractRecord)}: Inserts or updates a record without * returning any previous record. * <li>{@link com.github.geophile.erdo.OrderedMap#ensureAbsent(com.github.geophile.erdo.AbstractKey)}: Deletes a record without * returning the record previously associated with the given key. * </ul> * * <p> put and delete return the record being replaced, or null if there is no such record. * They therefore have to locate the previous record in the database. ensurePresent and ensureAbsent do not * have to locate a previous record, and * for this reason, they can often result in improved performance. ensurePresent and ensureAbsent should be used * whenever the application doesn't care about any previous state associated with a key. * * <h2>Retrieval</h2> * * <p> To retrieve the record associated with a key, the simplest thing to do is to call * {@link com.github.geophile.erdo.OrderedMap#find(com.github.geophile.erdo.AbstractKey)}. * * <p> {@link com.github.geophile.erdo.Cursor} objects are used for retrieval of multiple records, starting at a key. * {@link com.github.geophile.erdo.OrderedMap#first()} and {@link com.github.geophile.erdo.OrderedMap#last()} * start at the first and last records of the map, respectively. * {@link com.github.geophile.erdo.OrderedMap#cursor(com.github.geophile.erdo.AbstractKey)} returns a {@link com.github.geophile.erdo.Cursor} * object positioned at a given key, and that can visit neighboring records in either direction. * * <p> The control of a Cursor is simple: {@link com.github.geophile.erdo.Cursor#next()} returns the record with the next * larger key, or null if there is none. {@link com.github.geophile.erdo.Cursor#previous()} goes in the other direction, * finding the record with the next smaller key. A Cursor is considered to be open until next() or previous() returns * null, closed once null has been returned. Once a Cursor is closed, all subsequent calls to next() or previous() * will return null. * A Cursor can also be closed explicitly using {@link com.github.geophile.erdo.Cursor#close()}. * Any cursors open at the end of a transaction will be closed. */ package com.github.geophile.erdo;