/* 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.filestats;
import java.util.*;
import com.db4o.foundation.*;
import com.db4o.internal.*;
import com.db4o.internal.slots.*;
/**
* @exclude
*/
@decaf.Ignore(decaf.Platform.JDK11)
public class SlotMapImpl implements SlotMap {
private TreeIntObject<Slot> _slots = null;
private final long _fileLength;
public SlotMapImpl(long fileLength) {
_fileLength = fileLength;
}
public void add(Slot slot) {
_slots = Tree.add(_slots, new TreeIntObject<Slot>(slot.address(), slot));
}
public List<Slot> merged() {
final List<Slot> mergedSlots = new ArrayList<Slot>();
final ByRef<Slot> mergedSlot = ByRef.newInstance(new Slot(0,0));
Tree.traverse(_slots, new Visitor4<TreeIntObject<Slot>>() {
public void visit(TreeIntObject<Slot> node) {
Slot curSlot = node._object;
if(mergedSlot.value.address() + mergedSlot.value.length() == curSlot.address()) {
mergedSlot.value = new Slot(mergedSlot.value.address(), mergedSlot.value.length() + curSlot.length());
}
else {
mergedSlots.add(mergedSlot.value);
mergedSlot.value = curSlot;
}
}
});
mergedSlots.add(mergedSlot.value);
return mergedSlots;
}
public List<Slot> gaps(long length) {
List<Slot> merged = merged();
List<Slot> gaps = new ArrayList<Slot>();
if(merged.size() == 0) {
return gaps;
}
boolean isFirst = true;
Slot prevSlot = null;
for (Slot curSlot : merged) {
if(isFirst) {
prevSlot = curSlot;
if(prevSlot.address() > 0) {
gaps.add(new Slot(0, prevSlot.address()));
}
isFirst = false;
}
else {
int gapStart = prevSlot.address() + prevSlot.length();
gaps.add(new Slot(gapStart, curSlot.address() - gapStart));
prevSlot = curSlot;
}
}
int afterlast = prevSlot.address() + prevSlot.length();
if(afterlast < length) {
gaps.add(new Slot(afterlast, (int)(length - afterlast)));
}
return gaps;
}
@Override
public String toString() {
StringBuffer str = new StringBuffer();
str.append("SLOTS:\n");
logSlots(merged(), str);
str.append("GAPS:");
logSlots(gaps(_fileLength), str);
return str.toString();
}
private void logSlots(Iterable<Slot> slots, StringBuffer str) {
int totalLength = 0;
for (Slot gap : slots) {
totalLength += gap.length();
str.append(gap).append("\n");
}
str.append("TOTAL: ").append(totalLength).append("\n");
}
}