/*
* 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/.
*/
package com.github.geophile.erdo.apiimpl;
import com.github.geophile.erdo.map.LazyRecord;
import com.github.geophile.erdo.map.MapCursor;
import com.github.geophile.erdo.map.transactionalmap.TransactionalMap;
import com.github.geophile.erdo.util.IdGenerator;
import com.github.geophile.erdo.*;
import java.io.IOException;
public class OrderedMapImpl extends OrderedMap
{
// OrderedMap interface
@Override
public void ensurePresent(AbstractRecord record)
throws IOException,
InterruptedException,
DeadlockException,
TransactionRolledBackException
{
database.checkDatabaseOpen();
// Copy the record so that changes to the record, made by the caller, don't change
// the record in the database.
record = record.copy();
record.key().erdoId(erdoId);
transactionalMap().put(record, false);
}
@Override
public AbstractRecord put(AbstractRecord record)
throws IOException,
InterruptedException,
DeadlockException,
TransactionRolledBackException
{
database.checkDatabaseOpen();
AbstractRecord replaced = null;
// Copy the record so that changes to the record, made by the caller, don't change
// the record in the database.
record = record.copy();
record.key().erdoId(erdoId);
LazyRecord lazyRecord = transactionalMap().put(record, true);
if (lazyRecord != null) {
replaced = lazyRecord.materializeRecord();
if (replaced.deleted()) {
replaced = null;
}
}
return replaced;
}
@Override
public void ensureAbsent(AbstractKey key)
throws IOException,
InterruptedException,
DeadlockException,
TransactionRolledBackException
{
ensurePresent(new DeletedRecord(key));
}
@Override
public AbstractRecord delete(AbstractKey key)
throws IOException,
InterruptedException,
DeadlockException,
TransactionRolledBackException
{
return put(new DeletedRecord(key));
}
@Override
public void lock(AbstractKey key)
throws InterruptedException,
DeadlockException,
TransactionRolledBackException,
IOException
{
database.checkDatabaseOpen();
transactionalMap().lock(key);
}
@Override
public AbstractRecord find(AbstractKey key) throws IOException, InterruptedException
{
database.checkDatabaseOpen();
checkNotNull(key);
key.erdoId(erdoId);
return newCursor(key, true).next();
}
@Override
public Cursor cursor(AbstractKey startKey) throws IOException, InterruptedException
{
database.checkDatabaseOpen();
if (startKey != null) {
startKey.erdoId(erdoId);
}
return newCursor(startKey, false);
}
@Override
public Cursor first() throws IOException, InterruptedException
{
database.checkDatabaseOpen();
return newCursor(lowestKey, false);
}
@Override
public Cursor last() throws IOException, InterruptedException
{
database.checkDatabaseOpen();
return newCursor(highestKey, false);
}
// OrderedMapImpl interface
public OrderedMapImpl(DatabaseImpl database)
{
this(database, (int) erdoIdGenerator.nextId());
}
public OrderedMapImpl(DatabaseImpl database, int erdoId)
{
assert database != null;
this.database = database;
this.erdoId = erdoId;
this.lowestKey = ErdoId.lowest(erdoId);
this.highestKey = ErdoId.highest(erdoId);
}
public int erdoId()
{
return erdoId;
}
// For use by this class
private Cursor newCursor(final AbstractKey key, final boolean singleKey)
throws IOException, InterruptedException
{
MapCursor.Expression mapCursorExpression =
new MapCursor.Expression()
{
@Override
public MapCursor evaluate() throws IOException, InterruptedException
{
return transactionalMap().cursor(key, singleKey);
}
};
return new CursorImpl(database, mapCursorExpression);
}
private TransactionalMap transactionalMap()
{
transactionalMap = database.transactionManager().currentTransaction().transactionalMap();
return transactionalMap;
}
private void checkNotNull(AbstractKey key)
{
if (key == null) {
throw new IllegalArgumentException();
}
}
// Class state
private static final IdGenerator erdoIdGenerator = new IdGenerator(1);
// Object state
private final DatabaseImpl database;
private final int erdoId;
private final ErdoId lowestKey;
private final ErdoId highestKey; // For positioning by last()
private TransactionalMap transactionalMap; // For visibility in debugger
}