/* * 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.map.transactionalmap; import com.github.geophile.erdo.*; import com.github.geophile.erdo.forest.ForestSnapshot; import com.github.geophile.erdo.map.LazyRecord; import com.github.geophile.erdo.map.MapCursor; import com.github.geophile.erdo.map.OpenMapBase; import com.github.geophile.erdo.map.forestmap.ForestMapCursor; import com.github.geophile.erdo.map.privatemap.PrivateMap; import com.github.geophile.erdo.transaction.TransactionUpdates; import java.io.IOException; /* * A TransactionalMap is an updatable map for use by a single transaction. Updates are tracked in a * PrivateMap which is invisible outside of this object. On commit, the PrivateMap is transferred * to the ForestMap. Those updates are then visible to other transactions. */ public class TransactionalMap extends OpenMapBase { // OpenMapBase interface @Override public LazyRecord put(AbstractRecord record, boolean returnReplaced) throws IOException, InterruptedException, DeadlockException, TransactionRolledBackException { lock(record.key()); if (record.key().deleted()) { factory.testObserver().writeDeletedKey(); } LazyRecord replaced; LazyRecord uncommitted = updateMap().put(record, returnReplaced); if (returnReplaced && uncommitted == null) { AbstractKey key = record.key(); MapCursor cursor = ForestMapCursor.newCursor(forestSnapshot, key, true); LazyRecord committed = cursor.next(); cursor.close(); replaced = committed; } else { replaced = uncommitted; } return returnReplaced ? replaced : null; } public void lock(AbstractKey key) throws InterruptedException, DeadlockException, TransactionRolledBackException { database.lock(key); } @Override public MapCursor cursor(AbstractKey key, boolean singleKey) throws IOException, InterruptedException { return new TransactionalMapCursor(this, key, singleKey); } // TransactionalMap interface public TransactionUpdates takeUpdates() { PrivateMap takeUpdates = updateMap(); updates = null; return takeUpdates; } public TransactionalMap(ForestSnapshot forestSnapshot) { super(forestSnapshot.database().factory()); this.database = forestSnapshot.database(); this.forestSnapshot = forestSnapshot; } public void cleanup() { forestSnapshot.cleanup(); } // For use by this class private PrivateMap updateMap() { if (updates == null) { updates = new PrivateMap(factory); } return updates; } // Object State private final Database database; final ForestSnapshot forestSnapshot; PrivateMap updates; }