/* 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.*;
import com.db4o.foundation.*;
import com.db4o.internal.*;
import com.db4o.internal.freespace.*;
import com.db4o.internal.slots.*;
public class IdSlotChanges {
private final LockedTree _slotChanges = new LockedTree();
private final TransactionalIdSystemImpl _idSystem;
private final Closure4<FreespaceManager> _freespaceManager;
private TreeInt _prefetchedIDs;
public IdSlotChanges(TransactionalIdSystemImpl idSystem, Closure4<FreespaceManager> freespaceManager) {
_idSystem = idSystem;
_freespaceManager = freespaceManager;
}
public final void accumulateFreeSlots(final FreespaceCommitter freespaceCommitter, final boolean forFreespace, boolean traverseMutable) {
Visitor4 visitor = new Visitor4() {
public void visit(Object obj) {
((SlotChange)obj).accumulateFreeSlot(_idSystem, freespaceCommitter, forFreespace);
}
};
if(traverseMutable){
_slotChanges.traverseMutable(visitor);
} else {
_slotChanges.traverseLocked(visitor);
}
}
public void clear() {
_slotChanges.clear();
}
public void rollback() {
_slotChanges.traverseLocked(new Visitor4() {
public void visit(Object slotChange) {
((SlotChange) slotChange).rollback(freespaceManager());
}
});
}
public boolean isDeleted(int id) {
SlotChange slot = findSlotChange(id);
if (slot == null) {
return false;
}
return slot.isDeleted();
}
public SlotChange produceSlotChange(int id, SlotChangeFactory slotChangeFactory){
if(DTrace.enabled){
DTrace.PRODUCE_SLOT_CHANGE.log(id);
}
SlotChange slot = slotChangeFactory.newInstance(id);
_slotChanges.add(slot);
return (SlotChange)slot.addedOrExisting();
}
public final SlotChange findSlotChange(int id) {
return (SlotChange)_slotChanges.find(id);
}
public void traverseSlotChanges(Visitor4<SlotChange> visitor){
_slotChanges.traverseLocked(visitor);
}
public boolean isDirty() {
return ! _slotChanges.isEmpty();
}
public void readSlotChanges(ByteArrayBuffer buffer) {
_slotChanges.read(buffer, new SlotChange(0));
}
public void addPrefetchedID(int id) {
_prefetchedIDs = Tree.add(_prefetchedIDs, new TreeInt(id));
}
public void prefetchedIDConsumed(int id) {
_prefetchedIDs = _prefetchedIDs.removeLike(new TreeInt(id));
}
final void freePrefetchedIDs(IdSystem idSystem) {
if (_prefetchedIDs == null) {
return;
}
idSystem.returnUnusedIds(_prefetchedIDs);
_prefetchedIDs = null;
}
public void notifySlotCreated(int id, Slot slot, SlotChangeFactory slotChangeFactory) {
produceSlotChange(id, slotChangeFactory).notifySlotCreated(slot);
}
void notifySlotUpdated(int id, Slot slot, SlotChangeFactory slotChangeFactory) {
produceSlotChange(id, slotChangeFactory).notifySlotUpdated(freespaceManager(), slot);
}
public void notifySlotDeleted(int id, SlotChangeFactory slotChangeFactory) {
produceSlotChange(id, slotChangeFactory).notifyDeleted(freespaceManager());
}
private FreespaceManager freespaceManager() {
return _freespaceManager.run();
}
}