/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.internal.ids; import com.db4o.foundation.*; import com.db4o.internal.*; import com.db4o.internal.freespace.*; import com.db4o.internal.slots.*; /** * @exclude */ public class TransactionalIdSystemImpl implements TransactionalIdSystem { private IdSlotChanges _slotChanges; private TransactionalIdSystemImpl _parentIdSystem; private final Closure4<IdSystem> _globalIdSystem; public TransactionalIdSystemImpl(Closure4<FreespaceManager> freespaceManager, Closure4<IdSystem> globalIdSystem, TransactionalIdSystemImpl parentIdSystem){ _globalIdSystem = globalIdSystem; _slotChanges = new IdSlotChanges(this, freespaceManager); _parentIdSystem = parentIdSystem; } public void collectCallBackInfo(final CallbackInfoCollector collector) { if(! _slotChanges.isDirty()){ return; } _slotChanges.traverseSlotChanges(new Visitor4<SlotChange>() { public void visit(SlotChange slotChange) { int id = slotChange._key; if (slotChange.isDeleted()) { if(! slotChange.isNew()){ collector.deleted(id); } } else if (slotChange.isNew()) { collector.added(id); } else { collector.updated(id); } } }); } public boolean isDirty() { return _slotChanges.isDirty(); } public void commit(final FreespaceCommitter freespaceCommitter) { Visitable<SlotChange> slotChangeVisitable = new Visitable<SlotChange>() { public void accept(Visitor4<SlotChange> visitor) { traverseSlotChanges(visitor); } }; freespaceCommitter.transactionalIdSystem(this); accumulateFreeSlots(freespaceCommitter, false); globalIdSystem().commit(slotChangeVisitable, freespaceCommitter); } public void accumulateFreeSlots(FreespaceCommitter accumulator, boolean forFreespace) { _slotChanges.accumulateFreeSlots(accumulator, forFreespace, isSystemIdSystem()); if(_parentIdSystem != null){ _parentIdSystem.accumulateFreeSlots(accumulator, forFreespace); } } private boolean isSystemIdSystem() { return _parentIdSystem == null; } public void completeInterruptedTransaction(int transactionId1, int transactionId2) { globalIdSystem().completeInterruptedTransaction(transactionId1, transactionId2); } public Slot committedSlot(int id) { if (id == 0) { return null; } return globalIdSystem().committedSlot(id); } public Slot currentSlot(int id) { Slot slot = modifiedSlot(id); if(slot != null){ return slot; } return committedSlot(id); } public Slot modifiedSlot(int id) { if (id == 0) { return null; } SlotChange change = _slotChanges.findSlotChange(id); if (change != null) { if(change.slotModified()){ return change.newSlot(); } } return modifiedSlotInParentIdSystem(id); } public final Slot modifiedSlotInParentIdSystem(int id) { if(_parentIdSystem == null){ return null; } return _parentIdSystem.modifiedSlot(id); } public void rollback() { _slotChanges.rollback(); } public void clear() { _slotChanges.clear(); } public boolean isDeleted(int id) { return _slotChanges.isDeleted(id); } public void notifySlotUpdated(int id, Slot slot, SlotChangeFactory slotChangeFactory) { _slotChanges.notifySlotUpdated(id, slot, slotChangeFactory); } private void traverseSlotChanges(Visitor4<SlotChange> visitor){ if(_parentIdSystem != null){ _parentIdSystem.traverseSlotChanges(visitor); } _slotChanges.traverseSlotChanges(visitor); } public int newId(SlotChangeFactory slotChangeFactory) { int id = acquireId(); _slotChanges.produceSlotChange(id, slotChangeFactory).notifySlotCreated(null); return id; } private int acquireId() { return globalIdSystem().newId(); } public int prefetchID() { int id = acquireId(); _slotChanges.addPrefetchedID(id); return id; } public void prefetchedIDConsumed(int id) { _slotChanges.prefetchedIDConsumed(id); } public void notifySlotCreated(int id, Slot slot, SlotChangeFactory slotChangeFactory) { _slotChanges.notifySlotCreated(id, slot, slotChangeFactory); } public void notifySlotDeleted(int id, SlotChangeFactory slotChangeFactory) { _slotChanges.notifySlotDeleted(id, slotChangeFactory); } private IdSystem globalIdSystem() { return _globalIdSystem.run(); } public void close() { _slotChanges.freePrefetchedIDs(globalIdSystem()); } }